2 * yosys -- Yosys Open SYnthesis Suite
4 * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20 #include "kernel/yosys.h"
21 #include "kernel/sigtools.h"
22 #include "kernel/consteval.h"
25 PRIVATE_NAMESPACE_BEGIN
27 struct ExtractFaConfig
29 bool enable_fa
= false;
30 bool enable_ha
= false;
36 // http://svn.clifford.at/handicraft/2016/bindec/bindec.c
37 int bindec(unsigned char v
)
40 r
+= (~((v
& 2) - 1)) & 10;
41 r
+= (~((v
& 4) - 1)) & 100;
42 r
+= (~((v
& 8) - 1)) & 1000;
43 r
+= (~((v
& 16) - 1)) & 10000;
44 r
+= (~((v
& 32) - 1)) & 100000;
45 r
+= (~((v
& 64) - 1)) & 1000000;
46 r
+= (~((v
& 128) - 1)) & 10000000;
50 struct ExtractFaWorker
52 const ExtractFaConfig
&config
;
57 dict
<SigBit
, Cell
*> driver
;
58 pool
<SigBit
> handled_bits
;
60 const int xor2_func
= 0x6, xnor2_func
= 0x9;
61 const int xor3_func
= 0x96, xnor3_func
= 0x69;
63 pool
<tuple
<SigBit
, SigBit
>> xorxnor2
;
64 pool
<tuple
<SigBit
, SigBit
, SigBit
>> xorxnor3
;
66 dict
<tuple
<SigBit
, SigBit
>, dict
<int, pool
<SigBit
>>> func2
;
67 dict
<tuple
<SigBit
, SigBit
, SigBit
>, dict
<int, pool
<SigBit
>>> func3
;
72 struct func2_and_info_t
{
73 bool inv_a
, inv_b
, inv_y
;
76 struct func3_maj_info_t
{
77 bool inv_a
, inv_b
, inv_c
, inv_y
;
80 dict
<int, func2_and_info_t
> func2_and_info
;
81 dict
<int, func3_maj_info_t
> func3_maj_info
;
83 ExtractFaWorker(const ExtractFaConfig
&config
, Module
*module
) :
84 config(config
), module(module
), ce(module
), sigmap(ce
.assign_map
)
86 for (auto cell
: module
->selected_cells())
88 if (cell
->type
.in( "$_BUF_", "$_NOT_", "$_AND_", "$_NAND_", "$_OR_", "$_NOR_",
89 "$_XOR_", "$_XNOR_", "$_ANDNOT_", "$_ORNOT_", "$_MUX_", "$_NMUX_",
90 "$_AOI3_", "$_OAI3_", "$_AOI4_", "$_OAI4_"))
92 SigBit y
= sigmap(SigBit(cell
->getPort("\\Y")));
93 log_assert(driver
.count(y
) == 0);
98 for (int ia
= 0; ia
< 2; ia
++)
99 for (int ib
= 0; ib
< 2; ib
++)
101 func2_and_info_t f2i
;
108 for (int i
= 0; i
< 4; i
++)
110 bool a
= (i
& 1) ? !f2i
.inv_a
: f2i
.inv_a
;
111 bool b
= (i
& 2) ? !f2i
.inv_b
: f2i
.inv_b
;
112 if (a
&& b
) func
|= 1 << i
;
115 log_assert(func2_and_info
.count(func
) == 0);
116 func2_and_info
[func
] = f2i
;
121 log_assert(func2_and_info
.count(func
) == 0);
122 func2_and_info
[func
] = f2i
;
125 for (int ia
= 0; ia
< 2; ia
++)
126 for (int ib
= 0; ib
< 2; ib
++)
127 for (int ic
= 0; ic
< 2; ic
++)
129 func3_maj_info_t f3i
;
137 for (int i
= 0; i
< 8; i
++)
139 bool a
= (i
& 1) ? !f3i
.inv_a
: f3i
.inv_a
;
140 bool b
= (i
& 2) ? !f3i
.inv_b
: f3i
.inv_b
;
141 bool c
= (i
& 4) ? !f3i
.inv_c
: f3i
.inv_c
;
142 if ((a
&& b
) || (a
&& c
) || (b
&&c
)) func
|= 1 << i
;
145 log_assert(func3_maj_info
.count(func
) == 0);
146 func3_maj_info
[func
] = f3i
;
151 // log_assert(func3_maj_info.count(func) == 0);
152 // func3_maj_info[func] = f3i;
156 void check_partition(SigBit root
, pool
<SigBit
> &leaves
, IdString cell_type
)
158 if (config
.enable_ha
&& GetSize(leaves
) == 2)
160 if (!cell_type
.in("$_ANDNOT_", "$_ORNOT_"))
163 SigBit A
= SigSpec(leaves
)[0];
164 SigBit B
= SigSpec(leaves
)[1];
167 for (int i
= 0; i
< 4; i
++)
169 bool a_value
= (i
& 1) != 0;
170 bool b_value
= (i
& 2) != 0;
173 ce
.set(A
, a_value
? State::S1
: State::S0
);
174 ce
.set(B
, b_value
? State::S1
: State::S0
);
183 if (sig
== State::S1
)
189 // log("%04d %s %s -> %s\n", bindec(func), log_signal(A), log_signal(B), log_signal(root));
191 if (func
== xor2_func
|| func
== xnor2_func
)
192 xorxnor2
.insert(tuple
<SigBit
, SigBit
>(A
, B
));
195 func2
[tuple
<SigBit
, SigBit
>(A
, B
)][func
].insert(root
);
198 if (config
.enable_fa
&& GetSize(leaves
) == 3)
202 SigBit A
= SigSpec(leaves
)[0];
203 SigBit B
= SigSpec(leaves
)[1];
204 SigBit C
= SigSpec(leaves
)[2];
207 for (int i
= 0; i
< 8; i
++)
209 bool a_value
= (i
& 1) != 0;
210 bool b_value
= (i
& 2) != 0;
211 bool c_value
= (i
& 4) != 0;
214 ce
.set(A
, a_value
? State::S1
: State::S0
);
215 ce
.set(B
, b_value
? State::S1
: State::S0
);
216 ce
.set(C
, c_value
? State::S1
: State::S0
);
225 if (sig
== State::S1
)
231 // log("%08d %s %s %s -> %s\n", bindec(func), log_signal(A), log_signal(B), log_signal(C), log_signal(root));
233 if (func
== xor3_func
|| func
== xnor3_func
)
234 xorxnor3
.insert(tuple
<SigBit
, SigBit
, SigBit
>(A
, B
, C
));
237 func3
[tuple
<SigBit
, SigBit
, SigBit
>(A
, B
, C
)][func
].insert(root
);
241 void find_partitions(SigBit root
, pool
<SigBit
> &leaves
, pool
<pool
<SigBit
>> &cache
, int maxdepth
, int maxbreadth
, IdString cell_type
)
243 if (cache
.count(leaves
))
246 // log("%*s[%d] %s:", 20-maxdepth, "", maxdepth, log_signal(root));
247 // for (auto bit : leaves)
248 // log(" %s", log_signal(bit));
251 cache
.insert(leaves
);
252 check_partition(root
, leaves
, cell_type
);
257 for (SigBit bit
: leaves
)
259 if (driver
.count(bit
) == 0)
262 Cell
*cell
= driver
.at(bit
);
263 pool
<SigBit
> new_leaves
= leaves
;
265 new_leaves
.erase(bit
);
266 if (cell
->hasPort("\\A")) new_leaves
.insert(sigmap(SigBit(cell
->getPort("\\A"))));
267 if (cell
->hasPort("\\B")) new_leaves
.insert(sigmap(SigBit(cell
->getPort("\\B"))));
268 if (cell
->hasPort("\\C")) new_leaves
.insert(sigmap(SigBit(cell
->getPort("\\C"))));
269 if (cell
->hasPort("\\D")) new_leaves
.insert(sigmap(SigBit(cell
->getPort("\\D"))));
271 if (GetSize(new_leaves
) > maxbreadth
)
274 find_partitions(root
, new_leaves
, cache
, maxdepth
-1, maxbreadth
, cell_type
);
278 void assign_new_driver(SigBit bit
, SigBit new_driver
)
280 Cell
*cell
= driver
.at(bit
);
281 if (sigmap(cell
->getPort("\\Y")) == bit
) {
282 cell
->setPort("\\Y", module
->addWire(NEW_ID
));
283 module
->connect(bit
, new_driver
);
289 log("Extracting full/half adders from %s:\n", log_id(module
));
291 for (auto it
: driver
)
293 if (it
.second
->type
.in("$_BUF_", "$_NOT_"))
296 SigBit root
= it
.first
;
297 pool
<SigBit
> leaves
= { root
};
298 pool
<pool
<SigBit
>> cache
;
301 log(" checking %s\n", log_signal(it
.first
));
306 find_partitions(root
, leaves
, cache
, config
.maxdepth
, config
.maxbreadth
, it
.second
->type
);
308 if (config
.verbose
&& count_func2
> 0)
309 log(" extracted %d two-input functions\n", count_func2
);
311 if (config
.verbose
&& count_func3
> 0)
312 log(" extracted %d three-input functions\n", count_func3
);
315 for (auto &key
: xorxnor3
)
317 SigBit A
= get
<0>(key
);
318 SigBit B
= get
<1>(key
);
319 SigBit C
= get
<2>(key
);
321 log(" 3-Input XOR/XNOR %s %s %s:\n", log_signal(A
), log_signal(B
), log_signal(C
));
323 for (auto &it
: func3
.at(key
))
325 if (it
.first
!= xor3_func
&& it
.first
!= xnor3_func
)
328 log(" %08d ->", bindec(it
.first
));
329 for (auto bit
: it
.second
)
330 log(" %s", log_signal(bit
));
334 dict
<int, tuple
<SigBit
, SigBit
, Cell
*>> facache
;
336 for (auto &it
: func3_maj_info
)
339 auto f3i
= it
.second
;
341 if (func3
.at(key
).count(func
) == 0)
344 if (func3
.at(key
).count(xor3_func
) == 0 && func3
.at(key
).count(xnor3_func
) != 0) {
345 f3i
.inv_a
= !f3i
.inv_a
;
346 f3i
.inv_b
= !f3i
.inv_b
;
347 f3i
.inv_c
= !f3i
.inv_c
;
348 f3i
.inv_y
= !f3i
.inv_y
;
351 if (!f3i
.inv_a
&& !f3i
.inv_b
&& !f3i
.inv_c
&& !f3i
.inv_y
) {
352 log(" Majority without inversions:\n");
354 log(" Majority with inverted");
355 if (f3i
.inv_a
) log(" A");
356 if (f3i
.inv_b
) log(" B");
357 if (f3i
.inv_c
) log(" C");
358 if (f3i
.inv_y
) log(" Y");
362 log(" %08d ->", bindec(func
));
363 for (auto bit
: func3
.at(key
).at(func
))
364 log(" %s", log_signal(bit
));
368 if (f3i
.inv_a
) fakey
|= 1;
369 if (f3i
.inv_b
) fakey
|= 2;
370 if (f3i
.inv_c
) fakey
|= 4;
372 int fakey_inv
= fakey
^ 7;
373 bool invert_xy
= false;
376 if (facache
.count(fakey
))
378 auto &fa
= facache
.at(fakey
);
381 log(" Reusing $fa cell %s.\n", log_id(get
<2>(fa
)));
384 if (facache
.count(fakey_inv
))
386 auto &fa
= facache
.at(fakey_inv
);
390 log(" Reusing $fa cell %s.\n", log_id(get
<2>(fa
)));
394 Cell
*cell
= module
->addCell(NEW_ID
, "$fa");
395 cell
->setParam("\\WIDTH", 1);
397 log(" Created $fa cell %s.\n", log_id(cell
));
399 cell
->setPort("\\A", f3i
.inv_a
? module
->NotGate(NEW_ID
, A
) : A
);
400 cell
->setPort("\\B", f3i
.inv_b
? module
->NotGate(NEW_ID
, B
) : B
);
401 cell
->setPort("\\C", f3i
.inv_c
? module
->NotGate(NEW_ID
, C
) : C
);
403 X
= module
->addWire(NEW_ID
);
404 Y
= module
->addWire(NEW_ID
);
406 cell
->setPort("\\X", X
);
407 cell
->setPort("\\Y", Y
);
409 facache
[fakey
] = make_tuple(X
, Y
, cell
);
412 if (func3
.at(key
).count(xor3_func
)) {
413 SigBit YY
= invert_xy
? module
->NotGate(NEW_ID
, Y
) : Y
;
414 for (auto bit
: func3
.at(key
).at(xor3_func
))
415 assign_new_driver(bit
, YY
);
418 if (func3
.at(key
).count(xnor3_func
)) {
419 SigBit YY
= invert_xy
? Y
: module
->NotGate(NEW_ID
, Y
);
420 for (auto bit
: func3
.at(key
).at(xnor3_func
))
421 assign_new_driver(bit
, YY
);
424 SigBit XX
= invert_xy
!= f3i
.inv_y
? module
->NotGate(NEW_ID
, X
) : X
;
426 for (auto bit
: func3
.at(key
).at(func
))
427 assign_new_driver(bit
, XX
);
431 for (auto &key
: xorxnor2
)
433 SigBit A
= get
<0>(key
);
434 SigBit B
= get
<1>(key
);
436 log(" 2-Input XOR/XNOR %s %s:\n", log_signal(A
), log_signal(B
));
438 for (auto &it
: func2
.at(key
))
440 if (it
.first
!= xor2_func
&& it
.first
!= xnor2_func
)
443 log(" %04d ->", bindec(it
.first
));
444 for (auto bit
: it
.second
)
445 log(" %s", log_signal(bit
));
449 dict
<int, tuple
<SigBit
, SigBit
, Cell
*>> facache
;
451 for (auto &it
: func2_and_info
)
454 auto &f2i
= it
.second
;
456 if (func2
.at(key
).count(func
) == 0)
459 if (!f2i
.inv_a
&& !f2i
.inv_b
&& !f2i
.inv_y
) {
460 log(" AND without inversions:\n");
462 log(" AND with inverted");
463 if (f2i
.inv_a
) log(" A");
464 if (f2i
.inv_b
) log(" B");
465 if (f2i
.inv_y
) log(" Y");
469 log(" %04d ->", bindec(func
));
470 for (auto bit
: func2
.at(key
).at(func
))
471 log(" %s", log_signal(bit
));
475 if (f2i
.inv_a
) fakey
|= 1;
476 if (f2i
.inv_b
) fakey
|= 2;
478 int fakey_inv
= fakey
^ 3;
479 bool invert_xy
= false;
482 if (facache
.count(fakey
))
484 auto &fa
= facache
.at(fakey
);
487 log(" Reusing $fa cell %s.\n", log_id(get
<2>(fa
)));
490 if (facache
.count(fakey_inv
))
492 auto &fa
= facache
.at(fakey_inv
);
496 log(" Reusing $fa cell %s.\n", log_id(get
<2>(fa
)));
500 Cell
*cell
= module
->addCell(NEW_ID
, "$fa");
501 cell
->setParam("\\WIDTH", 1);
503 log(" Created $fa cell %s.\n", log_id(cell
));
505 cell
->setPort("\\A", f2i
.inv_a
? module
->NotGate(NEW_ID
, A
) : A
);
506 cell
->setPort("\\B", f2i
.inv_b
? module
->NotGate(NEW_ID
, B
) : B
);
507 cell
->setPort("\\C", State::S0
);
509 X
= module
->addWire(NEW_ID
);
510 Y
= module
->addWire(NEW_ID
);
512 cell
->setPort("\\X", X
);
513 cell
->setPort("\\Y", Y
);
516 if (func2
.at(key
).count(xor2_func
)) {
517 SigBit YY
= invert_xy
? module
->NotGate(NEW_ID
, Y
) : Y
;
518 for (auto bit
: func2
.at(key
).at(xor2_func
))
519 assign_new_driver(bit
, YY
);
522 if (func2
.at(key
).count(xnor2_func
)) {
523 SigBit YY
= invert_xy
? Y
: module
->NotGate(NEW_ID
, Y
);
524 for (auto bit
: func2
.at(key
).at(xnor2_func
))
525 assign_new_driver(bit
, YY
);
528 SigBit XX
= invert_xy
!= f2i
.inv_y
? module
->NotGate(NEW_ID
, X
) : X
;
530 for (auto bit
: func2
.at(key
).at(func
))
531 assign_new_driver(bit
, XX
);
537 struct ExtractFaPass
: public Pass
{
538 ExtractFaPass() : Pass("extract_fa", "find and extract full/half adders") { }
539 void help() YS_OVERRIDE
541 // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
543 log(" extract_fa [options] [selection]\n");
545 log("This pass extracts full/half adders from a gate-level design.\n");
548 log(" Enable cell types (fa=full adder, ha=half adder)\n");
549 log(" All types are enabled if none of this options is used\n");
552 log(" Set maximum depth for extracted logic cones (default=20)\n");
555 log(" Set maximum breadth for extracted logic cones (default=6)\n");
558 log(" Verbose output\n");
561 void execute(std::vector
<std::string
> args
, RTLIL::Design
*design
) YS_OVERRIDE
563 ExtractFaConfig config
;
565 log_header(design
, "Executing EXTRACT_FA pass (find and extract full/half adders).\n");
569 for (argidx
= 1; argidx
< args
.size(); argidx
++)
571 if (args
[argidx
] == "-fa") {
572 config
.enable_fa
= true;
575 if (args
[argidx
] == "-ha") {
576 config
.enable_ha
= true;
579 if (args
[argidx
] == "-v") {
580 config
.verbose
= true;
583 if (args
[argidx
] == "-d" && argidx
+2 < args
.size()) {
584 config
.maxdepth
= atoi(args
[++argidx
].c_str());
587 if (args
[argidx
] == "-b" && argidx
+2 < args
.size()) {
588 config
.maxbreadth
= atoi(args
[++argidx
].c_str());
593 extra_args(args
, argidx
, design
);
595 if (!config
.enable_fa
&& !config
.enable_ha
) {
596 config
.enable_fa
= true;
597 config
.enable_ha
= true;
600 for (auto module
: design
->selected_modules())
602 ExtractFaWorker
worker(config
, module
);
610 PRIVATE_NAMESPACE_END