2 * yosys -- Yosys Open SYnthesis Suite
4 * Copyright (C) 2014 Clifford Wolf <clifford@clifford.at>
5 * Copyright (C) 2014 Johann Glaser <Johann.Glaser@gmx.at>
7 * Permission to use, copy, modify, and/or distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21 #include "kernel/yosys.h"
22 #include "kernel/satgen.h"
25 PRIVATE_NAMESPACE_BEGIN
27 static uint32_t xorshift32_state
= 123456789;
29 static uint32_t xorshift32(uint32_t limit
) {
30 xorshift32_state
^= xorshift32_state
<< 13;
31 xorshift32_state
^= xorshift32_state
>> 17;
32 xorshift32_state
^= xorshift32_state
<< 5;
33 return xorshift32_state
% limit
;
36 static RTLIL::Wire
*getw(std::vector
<RTLIL::Wire
*> &wires
, RTLIL::Wire
*w
)
39 int idx
= xorshift32(GetSize(wires
));
40 if (wires
[idx
] != w
&& !wires
[idx
]->port_output
)
45 static void test_abcloop()
47 log("Rng seed value: %u\n", int(xorshift32_state
));
49 RTLIL::Design
*design
= new RTLIL::Design
;
50 RTLIL::Module
*module
= nullptr;
51 RTLIL::SigSpec in_sig
, out_sig
;
54 int create_cycles
= 0;
58 module
= design
->addModule("\\uut");
64 std::vector
<RTLIL::Wire
*> wires
;
66 for (int i
= 0; i
< 4; i
++) {
67 RTLIL::Wire
*w
= module
->addWire(stringf("\\i%d", i
));
73 for (int i
= 0; i
< 4; i
++) {
74 RTLIL::Wire
*w
= module
->addWire(stringf("\\o%d", i
));
75 w
->port_output
= true;
80 for (int i
= 0; i
< 16; i
++) {
81 RTLIL::Wire
*w
= module
->addWire(stringf("\\t%d", i
));
87 switch (xorshift32(12))
90 module
->addNotGate(w
->name
.str() + "g", getw(wires
, w
), w
);
93 module
->addAndGate(w
->name
.str() + "g", getw(wires
, w
), getw(wires
, w
), w
);
96 module
->addNandGate(w
->name
.str() + "g", getw(wires
, w
), getw(wires
, w
), w
);
99 module
->addOrGate(w
->name
.str() + "g", getw(wires
, w
), getw(wires
, w
), w
);
102 module
->addNorGate(w
->name
.str() + "g", getw(wires
, w
), getw(wires
, w
), w
);
105 module
->addXorGate(w
->name
.str() + "g", getw(wires
, w
), getw(wires
, w
), w
);
108 module
->addXnorGate(w
->name
.str() + "g", getw(wires
, w
), getw(wires
, w
), w
);
111 module
->addMuxGate(w
->name
.str() + "g", getw(wires
, w
), getw(wires
, w
), getw(wires
, w
), w
);
114 module
->addAoi3Gate(w
->name
.str() + "g", getw(wires
, w
), getw(wires
, w
), getw(wires
, w
), w
);
117 module
->addOai3Gate(w
->name
.str() + "g", getw(wires
, w
), getw(wires
, w
), getw(wires
, w
), w
);
120 module
->addAoi4Gate(w
->name
.str() + "g", getw(wires
, w
), getw(wires
, w
), getw(wires
, w
), getw(wires
, w
), w
);
123 module
->addOai4Gate(w
->name
.str() + "g", getw(wires
, w
), getw(wires
, w
), getw(wires
, w
), getw(wires
, w
), w
);
127 module
->fixup_ports();
128 Pass::call(design
, "clean");
131 SigMap
sigmap(module
);
132 SatGen
satgen(ez
.get(), &sigmap
);
134 for (auto c
: module
->cells()) {
135 bool ok
YS_ATTRIBUTE(unused
) = satgen
.importCell(c
);
139 std::vector
<int> in_vec
= satgen
.importSigSpec(in_sig
);
140 std::vector
<int> inverse_in_vec
= ez
->vec_not(in_vec
);
142 std::vector
<int> out_vec
= satgen
.importSigSpec(out_sig
);
144 for (int i
= 0; i
< 16; i
++)
146 std::vector
<int> assumptions
;
147 for (int j
= 0; j
< GetSize(in_vec
); j
++)
148 assumptions
.push_back((i
& (1 << j
)) ? in_vec
.at(j
) : inverse_in_vec
.at(j
));
150 std::vector
<bool> results
;
151 if (!ez
->solve(out_vec
, results
, assumptions
)) {
152 log("No stable solution for input %d found -> recreate module.\n", i
);
153 goto recreate_module
;
156 for (int j
= 0; j
< 4; j
++)
157 truthtab
[i
][j
] = results
[j
];
159 assumptions
.push_back(ez
->vec_ne(out_vec
, ez
->vec_const(results
)));
161 std::vector
<bool> results2
;
162 if (ez
->solve(out_vec
, results2
, assumptions
)) {
163 log("Two stable solutions for input %d found -> recreate module.\n", i
);
164 goto recreate_module
;
170 design
->remove(module
);
173 log("Found viable UUT after %d cycles:\n", create_cycles
);
174 Pass::call(design
, "write_ilang");
175 Pass::call(design
, "abc");
178 log("Pre- and post-abc truth table:\n");
181 SigMap
sigmap(module
);
182 SatGen
satgen(ez
.get(), &sigmap
);
184 for (auto c
: module
->cells()) {
185 bool ok
YS_ATTRIBUTE(unused
) = satgen
.importCell(c
);
189 std::vector
<int> in_vec
= satgen
.importSigSpec(in_sig
);
190 std::vector
<int> inverse_in_vec
= ez
->vec_not(in_vec
);
192 std::vector
<int> out_vec
= satgen
.importSigSpec(out_sig
);
194 bool found_error
= false;
195 bool truthtab2
[16][4];
197 for (int i
= 0; i
< 16; i
++)
199 std::vector
<int> assumptions
;
200 for (int j
= 0; j
< GetSize(in_vec
); j
++)
201 assumptions
.push_back((i
& (1 << j
)) ? in_vec
.at(j
) : inverse_in_vec
.at(j
));
203 for (int j
= 0; j
< 4; j
++)
204 truthtab2
[i
][j
] = truthtab
[i
][j
];
206 std::vector
<bool> results
;
207 if (!ez
->solve(out_vec
, results
, assumptions
)) {
208 log("No stable solution for input %d found.\n", i
);
213 for (int j
= 0; j
< 4; j
++)
214 truthtab2
[i
][j
] = results
[j
];
216 assumptions
.push_back(ez
->vec_ne(out_vec
, ez
->vec_const(results
)));
218 std::vector
<bool> results2
;
219 if (ez
->solve(out_vec
, results2
, assumptions
)) {
220 log("Two stable solutions for input %d found -> recreate module.\n", i
);
225 for (int i
= 0; i
< 16; i
++) {
227 for (int j
= 0; j
< 4; j
++)
228 log("%c", truthtab
[i
][j
] ? '1' : '0');
230 for (int j
= 0; j
< 4; j
++)
231 log("%c", truthtab2
[i
][j
] ? '1' : '0');
232 for (int j
= 0; j
< 4; j
++)
233 if (truthtab
[i
][j
] != truthtab2
[i
][j
]) {
241 log_assert(found_error
== false);
245 struct TestAbcloopPass
: public Pass
{
246 TestAbcloopPass() : Pass("test_abcloop", "automatically test handling of loops in abc command") { }
247 void help() YS_OVERRIDE
249 // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
251 log(" test_abcloop [options]\n");
253 log("Test handling of logic loops in ABC.\n");
255 log(" -n {integer}\n");
256 log(" create this number of circuits and test them (default = 100).\n");
258 log(" -s {positive_integer}\n");
259 log(" use this value as rng seed value (default = unix time).\n");
262 void execute(std::vector
<std::string
> args
, RTLIL::Design
*) YS_OVERRIDE
265 xorshift32_state
= 0;
268 for (argidx
= 1; argidx
< GetSize(args
); argidx
++)
270 if (args
[argidx
] == "-n" && argidx
+1 < GetSize(args
)) {
271 num_iter
= atoi(args
[++argidx
].c_str());
274 if (args
[argidx
] == "-s" && argidx
+1 < GetSize(args
)) {
275 xorshift32_state
= atoi(args
[++argidx
].c_str());
281 if (xorshift32_state
== 0)
282 xorshift32_state
= time(NULL
) & 0x7fffffff;
284 for (int i
= 0; i
< num_iter
; i
++)
289 PRIVATE_NAMESPACE_END