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;
33 // http://svn.clifford.at/handicraft/2016/bindec/bindec.c
34 int bindec(unsigned char v
)
37 r
+= (~((v
& 2) - 1)) & 10;
38 r
+= (~((v
& 4) - 1)) & 100;
39 r
+= (~((v
& 8) - 1)) & 1000;
40 r
+= (~((v
& 16) - 1)) & 10000;
41 r
+= (~((v
& 32) - 1)) & 100000;
42 r
+= (~((v
& 64) - 1)) & 1000000;
43 r
+= (~((v
& 128) - 1)) & 10000000;
47 struct ExtractFaWorker
49 const ExtractFaConfig
&config
;
54 dict
<SigBit
, Cell
*> driver
;
55 pool
<SigBit
> handled_bits
;
57 pool
<tuple
<SigBit
, SigBit
>> xorxnor2
;
58 pool
<tuple
<SigBit
, SigBit
, SigBit
>> xorxnor3
;
60 dict
<tuple
<SigBit
, SigBit
>, dict
<int, pool
<SigBit
>>> func2
;
61 dict
<tuple
<SigBit
, SigBit
, SigBit
>, dict
<int, pool
<SigBit
>>> func3
;
63 ExtractFaWorker(const ExtractFaConfig
&config
, Module
*module
) :
64 config(config
), module(module
), ce(module
), sigmap(ce
.assign_map
)
66 for (auto cell
: module
->selected_cells())
68 if (cell
->type
.in( "$_BUF_", "$_NOT_", "$_AND_", "$_NAND_", "$_OR_", "$_NOR_",
69 "$_XOR_", "$_XNOR_", "$_ANDNOT_", "$_ORNOT_", "$_MUX_",
70 "$_AOI3_", "$_OAI3_", "$_AOI4_", "$_OAI4_"))
72 SigBit y
= sigmap(SigBit(cell
->getPort("\\Y")));
73 log_assert(driver
.count(y
) == 0);
79 void check_partition(SigBit root
, pool
<SigBit
> &leaves
)
81 if (GetSize(leaves
) == 2)
85 SigBit A
= SigSpec(leaves
)[0];
86 SigBit B
= SigSpec(leaves
)[1];
89 for (int i
= 0; i
< 4; i
++)
91 bool a_value
= (i
& 1) != 0;
92 bool b_value
= (i
& 2) != 0;
95 ce
.set(A
, a_value
? State::S1
: State::S0
);
96 ce
.set(B
, b_value
? State::S1
: State::S0
);
103 if (sig
== State::S1
)
109 // log("%04d %s %s -> %s\n", bindec(func), log_signal(A), log_signal(B), log_signal(root));
111 if (func
== 0x6 || func
== 0x9)
112 xorxnor2
.insert(tuple
<SigBit
, SigBit
>(A
, B
));
114 func2
[tuple
<SigBit
, SigBit
>(A
, B
)][func
].insert(root
);
117 if (GetSize(leaves
) == 3)
121 SigBit A
= SigSpec(leaves
)[0];
122 SigBit B
= SigSpec(leaves
)[1];
123 SigBit C
= SigSpec(leaves
)[2];
126 for (int i
= 0; i
< 8; i
++)
128 bool a_value
= (i
& 1) != 0;
129 bool b_value
= (i
& 2) != 0;
130 bool c_value
= (i
& 4) != 0;
133 ce
.set(A
, a_value
? State::S1
: State::S0
);
134 ce
.set(B
, b_value
? State::S1
: State::S0
);
135 ce
.set(C
, c_value
? State::S1
: State::S0
);
142 if (sig
== State::S1
)
148 // log("%08d %s %s %s -> %s\n", bindec(func), log_signal(A), log_signal(B), log_signal(C), log_signal(root));
150 if (func
== 0x69 || func
== 0x96)
151 xorxnor3
.insert(tuple
<SigBit
, SigBit
, SigBit
>(A
, B
, C
));
153 func3
[tuple
<SigBit
, SigBit
, SigBit
>(A
, B
, C
)][func
].insert(root
);
157 void find_partitions(SigBit root
, pool
<SigBit
> &leaves
, pool
<pool
<SigBit
>> &cache
, int maxdepth
, int maxbreadth
)
159 if (cache
.count(leaves
))
162 cache
.insert(leaves
);
163 check_partition(root
, leaves
);
168 for (SigBit bit
: leaves
)
170 if (driver
.count(bit
) == 0)
173 Cell
*cell
= driver
.at(bit
);
174 pool
<SigBit
> new_leaves
= leaves
;
176 new_leaves
.erase(bit
);
177 if (cell
->hasPort("\\A")) new_leaves
.insert(sigmap(SigBit(cell
->getPort("\\A"))));
178 if (cell
->hasPort("\\B")) new_leaves
.insert(sigmap(SigBit(cell
->getPort("\\B"))));
179 if (cell
->hasPort("\\C")) new_leaves
.insert(sigmap(SigBit(cell
->getPort("\\C"))));
180 if (cell
->hasPort("\\D")) new_leaves
.insert(sigmap(SigBit(cell
->getPort("\\D"))));
182 if (GetSize(new_leaves
) > maxbreadth
)
185 find_partitions(root
, new_leaves
, cache
, maxdepth
-1, maxbreadth
);
191 for (auto it
: driver
)
193 SigBit root
= it
.first
;
194 pool
<SigBit
> leaves
= { root
};
195 pool
<pool
<SigBit
>> cache
;
197 find_partitions(root
, leaves
, cache
, 5, 10);
200 for (auto &key
: xorxnor3
)
202 SigBit A
= get
<0>(key
);
203 SigBit B
= get
<1>(key
);
204 SigBit C
= get
<2>(key
);
206 log("3-Input XOR/XNOR %s %s %s:\n", log_signal(A
), log_signal(B
), log_signal(C
));
208 for (auto &it
: func3
.at(key
)) {
209 log(" %08d ->", bindec(it
.first
));
210 for (auto bit
: it
.second
)
211 log(" %s", log_signal(bit
));
216 for (auto &key
: xorxnor2
)
218 SigBit A
= get
<0>(key
);
219 SigBit B
= get
<1>(key
);
221 log("2-Input XOR/XNOR %s %s:\n", log_signal(A
), log_signal(B
));
223 for (auto &it
: func2
.at(key
)) {
224 log(" %04d ->", bindec(it
.first
));
225 for (auto bit
: it
.second
)
226 log(" %s", log_signal(bit
));
233 struct ExtractFaPass
: public Pass
{
234 ExtractFaPass() : Pass("extract_fa", "find and extract full/half adders") { }
237 // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
239 log(" extract_fa [options] [selection]\n");
241 log("This pass extracts full/half adders from a gate-level design.\n");
244 log(" Enable cell types (fa=full adder, ha=half adder)\n");
245 log(" All types are enabled if none of this options is used\n");
248 virtual void execute(std::vector
<std::string
> args
, RTLIL::Design
*design
)
250 ExtractFaConfig config
;
252 log_header(design
, "Executing EXTRACT_FA pass (find and extract full/half adders).\n");
256 for (argidx
= 1; argidx
< args
.size(); argidx
++)
258 if (args
[argidx
] == "-fa") {
259 config
.enable_fa
= true;
262 if (args
[argidx
] == "-ha") {
263 config
.enable_ha
= true;
268 extra_args(args
, argidx
, design
);
270 if (!config
.enable_fa
&& !config
.enable_ha
) {
271 config
.enable_fa
= true;
272 config
.enable_ha
= true;
275 for (auto module
: design
->selected_modules())
277 ExtractFaWorker
worker(config
, module
);
285 PRIVATE_NAMESPACE_END