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"
24 static uint32_t xorshift32_state
= 123456789;
26 static uint32_t xorshift32(uint32_t limit
) {
27 xorshift32_state
^= xorshift32_state
<< 13;
28 xorshift32_state
^= xorshift32_state
>> 17;
29 xorshift32_state
^= xorshift32_state
<< 5;
30 return xorshift32_state
% limit
;
33 static RTLIL::Wire
*getw(std::vector
<RTLIL::Wire
*> &wires
, RTLIL::Wire
*w
)
36 int idx
= xorshift32(SIZE(wires
));
37 if (wires
[idx
] != w
&& !wires
[idx
]->port_output
)
42 static void test_abcloop()
44 log("Rng seed value: %u\n", int(xorshift32_state
));
46 RTLIL::Design
*design
= new RTLIL::Design
;
47 RTLIL::Module
*module
= nullptr;
48 RTLIL::SigSpec in_sig
, out_sig
;
51 int create_cycles
= 0;
55 module
= design
->addModule("\\uut");
61 std::vector
<RTLIL::Wire
*> wires
;
63 for (int i
= 0; i
< 4; i
++) {
64 RTLIL::Wire
*w
= module
->addWire(stringf("\\i%d", i
));
70 for (int i
= 0; i
< 4; i
++) {
71 RTLIL::Wire
*w
= module
->addWire(stringf("\\o%d", i
));
72 w
->port_output
= true;
77 for (int i
= 0; i
< 16; i
++) {
78 RTLIL::Wire
*w
= module
->addWire(stringf("\\t%d", i
));
84 switch (xorshift32(12))
87 module
->addNotGate(w
->name
.str() + "g", getw(wires
, w
), w
);
90 module
->addAndGate(w
->name
.str() + "g", getw(wires
, w
), getw(wires
, w
), w
);
93 module
->addNandGate(w
->name
.str() + "g", getw(wires
, w
), getw(wires
, w
), w
);
96 module
->addOrGate(w
->name
.str() + "g", getw(wires
, w
), getw(wires
, w
), w
);
99 module
->addNorGate(w
->name
.str() + "g", getw(wires
, w
), getw(wires
, w
), w
);
102 module
->addXorGate(w
->name
.str() + "g", getw(wires
, w
), getw(wires
, w
), w
);
105 module
->addXnorGate(w
->name
.str() + "g", getw(wires
, w
), getw(wires
, w
), w
);
108 module
->addMuxGate(w
->name
.str() + "g", getw(wires
, w
), getw(wires
, w
), getw(wires
, w
), w
);
111 module
->addAoi3Gate(w
->name
.str() + "g", getw(wires
, w
), getw(wires
, w
), getw(wires
, w
), w
);
114 module
->addOai3Gate(w
->name
.str() + "g", getw(wires
, w
), getw(wires
, w
), getw(wires
, w
), w
);
117 module
->addAoi4Gate(w
->name
.str() + "g", getw(wires
, w
), getw(wires
, w
), getw(wires
, w
), getw(wires
, w
), w
);
120 module
->addOai4Gate(w
->name
.str() + "g", getw(wires
, w
), getw(wires
, w
), getw(wires
, w
), getw(wires
, w
), w
);
124 module
->fixup_ports();
125 Pass::call(design
, "clean");
128 SigMap
sigmap(module
);
129 SatGen
satgen(&ez
, &sigmap
);
131 for (auto c
: module
->cells()) {
132 bool ok
= satgen
.importCell(c
);
136 std::vector
<int> in_vec
= satgen
.importSigSpec(in_sig
);
137 std::vector
<int> inverse_in_vec
= ez
.vec_not(in_vec
);
139 std::vector
<int> out_vec
= satgen
.importSigSpec(out_sig
);
141 for (int i
= 0; i
< 16; i
++)
143 std::vector
<int> assumptions
;
144 for (int j
= 0; j
< SIZE(in_vec
); j
++)
145 assumptions
.push_back((i
& (1 << j
)) ? in_vec
.at(j
) : inverse_in_vec
.at(j
));
147 std::vector
<bool> results
;
148 if (!ez
.solve(out_vec
, results
, assumptions
)) {
149 log("No stable solution for input %d found -> recreate module.\n", i
);
150 goto recreate_module
;
153 for (int j
= 0; j
< 4; j
++)
154 truthtab
[i
][j
] = results
[j
];
156 assumptions
.push_back(ez
.vec_ne(out_vec
, ez
.vec_const(results
)));
158 std::vector
<bool> results2
;
159 if (ez
.solve(out_vec
, results2
, assumptions
)) {
160 log("Two stable solutions for input %d found -> recreate module.\n", i
);
161 goto recreate_module
;
167 design
->remove(module
);
170 log("Found viable UUT after %d cycles:\n", create_cycles
);
171 Pass::call(design
, "write_ilang");
172 Pass::call(design
, "abc");
175 log("Pre- and post-abc truth table:\n");
178 SigMap
sigmap(module
);
179 SatGen
satgen(&ez
, &sigmap
);
181 for (auto c
: module
->cells()) {
182 bool ok
= satgen
.importCell(c
);
186 std::vector
<int> in_vec
= satgen
.importSigSpec(in_sig
);
187 std::vector
<int> inverse_in_vec
= ez
.vec_not(in_vec
);
189 std::vector
<int> out_vec
= satgen
.importSigSpec(out_sig
);
191 bool found_error
= false;
192 bool truthtab2
[16][4];
194 for (int i
= 0; i
< 16; i
++)
196 std::vector
<int> assumptions
;
197 for (int j
= 0; j
< SIZE(in_vec
); j
++)
198 assumptions
.push_back((i
& (1 << j
)) ? in_vec
.at(j
) : inverse_in_vec
.at(j
));
200 for (int j
= 0; j
< 4; j
++)
201 truthtab2
[i
][j
] = truthtab
[i
][j
];
203 std::vector
<bool> results
;
204 if (!ez
.solve(out_vec
, results
, assumptions
)) {
205 log("No stable solution for input %d found.\n", i
);
210 for (int j
= 0; j
< 4; j
++)
211 truthtab2
[i
][j
] = results
[j
];
213 assumptions
.push_back(ez
.vec_ne(out_vec
, ez
.vec_const(results
)));
215 std::vector
<bool> results2
;
216 if (ez
.solve(out_vec
, results2
, assumptions
)) {
217 log("Two stable solutions for input %d found -> recreate module.\n", i
);
222 for (int i
= 0; i
< 16; i
++) {
224 for (int j
= 0; j
< 4; j
++)
225 log("%c", truthtab
[i
][j
] ? '1' : '0');
227 for (int j
= 0; j
< 4; j
++)
228 log("%c", truthtab2
[i
][j
] ? '1' : '0');
229 for (int j
= 0; j
< 4; j
++)
230 if (truthtab
[i
][j
] != truthtab2
[i
][j
]) {
238 log_assert(found_error
== false);
242 struct TestAbcloopPass
: public Pass
{
243 TestAbcloopPass() : Pass("test_abcloop", "automatically test handling of loops in abc command") { }
246 // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
248 log(" test_abcloop [options]\n");
250 log("Test handling of logic loops in ABC.\n");
252 log(" -n {integer}\n");
253 log(" create this number of circuits and test them (default = 100).\n");
255 log(" -s {positive_integer}\n");
256 log(" use this value as rng seed value (default = unix time).\n");
259 virtual void execute(std::vector
<std::string
> args
, RTLIL::Design
*)
262 xorshift32_state
= 0;
265 for (argidx
= 1; argidx
< SIZE(args
); argidx
++)
267 if (args
[argidx
] == "-n" && argidx
+1 < SIZE(args
)) {
268 num_iter
= atoi(args
[++argidx
].c_str());
271 if (args
[argidx
] == "-s" && argidx
+1 < SIZE(args
)) {
272 xorshift32_state
= atoi(args
[++argidx
].c_str());
278 if (xorshift32_state
== 0)
279 xorshift32_state
= time(NULL
) & 0x7fffffff;
281 for (int i
= 0; i
< num_iter
; i
++)