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"
23 #include "kernel/consteval.h"
24 #include "kernel/macc.h"
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 void create_gold_module(RTLIL::Design
*design
, RTLIL::IdString cell_type
, std::string cell_type_flags
, bool constmode
)
38 RTLIL::Module
*module
= design
->addModule("\\gold");
39 RTLIL::Cell
*cell
= module
->addCell("\\UUT", cell_type
);
42 if (cell_type
== "$macc")
45 int width
= 1 + xorshift32(8);
46 int depth
= 1 + xorshift32(6);
47 int mulbits_a
= 0, mulbits_b
= 0;
49 RTLIL::Wire
*wire_a
= module
->addWire("\\A");
51 wire_a
->port_input
= true;
53 for (int i
= 0; i
< depth
; i
++)
55 int size_a
= xorshift32(width
) + 1;
56 int size_b
= depth
> 4 ? 0 : xorshift32(width
) + 1;
58 if (mulbits_a
+ size_a
*size_b
<= 96 && mulbits_b
+ size_a
+ size_b
<= 16 && xorshift32(2) == 1) {
59 mulbits_a
+= size_a
* size_b
;
60 mulbits_b
+= size_a
+ size_b
;
64 Macc::port_t this_port
;
66 wire_a
->width
+= size_a
;
67 this_port
.in_a
= RTLIL::SigSpec(wire_a
, wire_a
->width
- size_a
, size_a
);
69 wire_a
->width
+= size_b
;
70 this_port
.in_b
= RTLIL::SigSpec(wire_a
, wire_a
->width
- size_b
, size_b
);
72 this_port
.is_signed
= xorshift32(2) == 1;
73 this_port
.do_subtract
= xorshift32(2) == 1;
74 macc
.ports
.push_back(this_port
);
77 wire
= module
->addWire("\\B");
78 wire
->width
= xorshift32(mulbits_a
? xorshift32(4)+1 : xorshift32(16)+1);
79 wire
->port_input
= true;
80 macc
.bit_ports
= wire
;
82 wire
= module
->addWire("\\Y");
84 wire
->port_output
= true;
85 cell
->setPort("\\Y", wire
);
90 if (cell_type
== "$lut")
92 int width
= 1 + xorshift32(6);
94 wire
= module
->addWire("\\A");
96 wire
->port_input
= true;
97 cell
->setPort("\\A", wire
);
99 wire
= module
->addWire("\\Y");
100 wire
->port_output
= true;
101 cell
->setPort("\\Y", wire
);
103 RTLIL::SigSpec config
;
104 for (int i
= 0; i
< (1 << width
); i
++)
105 config
.append(xorshift32(2) ? RTLIL::S1
: RTLIL::S0
);
107 cell
->setParam("\\LUT", config
.as_const());
110 if (cell_type_flags
.find('A') != std::string::npos
) {
111 wire
= module
->addWire("\\A");
112 wire
->width
= 1 + xorshift32(8);
113 wire
->port_input
= true;
114 cell
->setPort("\\A", wire
);
117 if (cell_type_flags
.find('B') != std::string::npos
) {
118 wire
= module
->addWire("\\B");
119 if (cell_type_flags
.find('h') != std::string::npos
)
120 wire
->width
= 1 + xorshift32(6);
122 wire
->width
= 1 + xorshift32(8);
123 wire
->port_input
= true;
124 cell
->setPort("\\B", wire
);
127 if (cell_type_flags
.find('S') != std::string::npos
&& xorshift32(2)) {
128 if (cell_type_flags
.find('A') != std::string::npos
)
129 cell
->parameters
["\\A_SIGNED"] = true;
130 if (cell_type_flags
.find('B') != std::string::npos
)
131 cell
->parameters
["\\B_SIGNED"] = true;
134 if (cell_type_flags
.find('s') != std::string::npos
) {
135 if (cell_type_flags
.find('A') != std::string::npos
&& xorshift32(2))
136 cell
->parameters
["\\A_SIGNED"] = true;
137 if (cell_type_flags
.find('B') != std::string::npos
&& xorshift32(2))
138 cell
->parameters
["\\B_SIGNED"] = true;
141 if (cell_type_flags
.find('Y') != std::string::npos
) {
142 wire
= module
->addWire("\\Y");
143 wire
->width
= 1 + xorshift32(8);
144 wire
->port_output
= true;
145 cell
->setPort("\\Y", wire
);
148 if (cell_type
== "$alu")
150 wire
= module
->addWire("\\CI");
151 wire
->port_input
= true;
152 cell
->setPort("\\CI", wire
);
154 wire
= module
->addWire("\\BI");
155 wire
->port_input
= true;
156 cell
->setPort("\\BI", wire
);
158 wire
= module
->addWire("\\X");
159 wire
->width
= SIZE(cell
->getPort("\\Y"));
160 wire
->port_output
= true;
161 cell
->setPort("\\X", wire
);
163 wire
= module
->addWire("\\CO");
164 wire
->width
= SIZE(cell
->getPort("\\Y"));
165 wire
->port_output
= true;
166 cell
->setPort("\\CO", wire
);
171 auto conn_list
= cell
->connections();
172 for (auto &conn
: conn_list
)
174 RTLIL::SigSpec sig
= conn
.second
;
176 if (SIZE(sig
) == 0 || sig
[0].wire
== nullptr || sig
[0].wire
->port_output
)
180 switch (xorshift32(5))
183 n
= xorshift32(SIZE(sig
) + 1);
184 for (int i
= 0; i
< n
; i
++)
185 sig
[i
] = xorshift32(2) == 1 ? RTLIL::S1
: RTLIL::S0
;
188 n
= xorshift32(SIZE(sig
) + 1);
189 for (int i
= n
; i
< SIZE(sig
); i
++)
190 sig
[i
] = xorshift32(2) == 1 ? RTLIL::S1
: RTLIL::S0
;
193 n
= xorshift32(SIZE(sig
));
194 m
= xorshift32(SIZE(sig
));
195 for (int i
= std::min(n
, m
); i
< std::max(n
, m
); i
++)
196 sig
[i
] = xorshift32(2) == 1 ? RTLIL::S1
: RTLIL::S0
;
200 cell
->setPort(conn
.first
, sig
);
204 module
->fixup_ports();
205 cell
->fixup_parameters();
209 static void run_eval_test(RTLIL::Design
*design
, bool verbose
, bool nosat
, std::string uut_name
, std::ofstream
&vlog_file
)
211 log("Eval testing:%c", verbose
? '\n' : ' ');
213 RTLIL::Module
*gold_mod
= design
->module("\\gold");
214 RTLIL::Module
*gate_mod
= design
->module("\\gate");
215 ConstEval
gold_ce(gold_mod
), gate_ce(gate_mod
);
217 ezDefaultSAT ez1
, ez2
;
218 SigMap
sigmap(gold_mod
);
219 SatGen
satgen1(&ez1
, &sigmap
);
220 SatGen
satgen2(&ez2
, &sigmap
);
221 satgen2
.model_undef
= true;
224 for (auto cell
: gold_mod
->cells()) {
225 satgen1
.importCell(cell
);
226 satgen2
.importCell(cell
);
229 if (vlog_file
.is_open())
231 vlog_file
<< stringf("\nmodule %s;\n", uut_name
.c_str());
233 for (auto port
: gold_mod
->ports
) {
234 RTLIL::Wire
*wire
= gold_mod
->wire(port
);
235 if (wire
->port_input
)
236 vlog_file
<< stringf(" reg [%d:0] %s;\n", SIZE(wire
)-1, log_id(wire
));
238 vlog_file
<< stringf(" wire [%d:0] %s_expr, %s_noexpr;\n", SIZE(wire
)-1, log_id(wire
), log_id(wire
));
241 vlog_file
<< stringf(" %s_expr uut_expr(", uut_name
.c_str());
242 for (int i
= 0; i
< SIZE(gold_mod
->ports
); i
++)
243 vlog_file
<< stringf("%s.%s(%s%s)", i
? ", " : "", log_id(gold_mod
->ports
[i
]), log_id(gold_mod
->ports
[i
]),
244 gold_mod
->wire(gold_mod
->ports
[i
])->port_input
? "" : "_expr");
245 vlog_file
<< stringf(");\n");
247 vlog_file
<< stringf(" %s_expr uut_noexpr(", uut_name
.c_str());
248 for (int i
= 0; i
< SIZE(gold_mod
->ports
); i
++)
249 vlog_file
<< stringf("%s.%s(%s%s)", i
? ", " : "", log_id(gold_mod
->ports
[i
]), log_id(gold_mod
->ports
[i
]),
250 gold_mod
->wire(gold_mod
->ports
[i
])->port_input
? "" : "_noexpr");
251 vlog_file
<< stringf(");\n");
253 vlog_file
<< stringf(" task run;\n");
254 vlog_file
<< stringf(" begin\n");
255 vlog_file
<< stringf(" $display(\"%s\");\n", uut_name
.c_str());
258 for (int i
= 0; i
< 64; i
++)
260 log(verbose
? "\n" : ".");
264 RTLIL::SigSpec in_sig
, in_val
;
265 RTLIL::SigSpec out_sig
, out_val
;
266 std::string vlog_pattern_info
;
268 for (auto port
: gold_mod
->ports
)
270 RTLIL::Wire
*gold_wire
= gold_mod
->wire(port
);
271 RTLIL::Wire
*gate_wire
= gate_mod
->wire(port
);
273 log_assert(gold_wire
!= nullptr);
274 log_assert(gate_wire
!= nullptr);
275 log_assert(gold_wire
->port_input
== gate_wire
->port_input
);
276 log_assert(SIZE(gold_wire
) == SIZE(gate_wire
));
278 if (!gold_wire
->port_input
)
281 RTLIL::Const in_value
;
282 for (int i
= 0; i
< SIZE(gold_wire
); i
++)
283 in_value
.bits
.push_back(xorshift32(2) ? RTLIL::S1
: RTLIL::S0
);
285 if (xorshift32(4) == 0) {
286 int inv_chance
= 1 + xorshift32(8);
287 for (int i
= 0; i
< SIZE(gold_wire
); i
++)
288 if (xorshift32(inv_chance
) == 0)
289 in_value
.bits
[i
] = RTLIL::Sx
;
293 log("%s: %s\n", log_id(gold_wire
), log_signal(in_value
));
295 in_sig
.append(gold_wire
);
296 in_val
.append(in_value
);
298 gold_ce
.set(gold_wire
, in_value
);
299 gate_ce
.set(gate_wire
, in_value
);
301 if (vlog_file
.is_open() && SIZE(in_value
) > 0) {
302 vlog_file
<< stringf(" %s = 'b%s;\n", log_id(gold_wire
), in_value
.as_string().c_str());
303 if (!vlog_pattern_info
.empty())
304 vlog_pattern_info
+= " ";
305 vlog_pattern_info
+= stringf("%s=%s", log_id(gold_wire
), log_signal(in_value
));
309 if (vlog_file
.is_open())
310 vlog_file
<< stringf(" #1;\n");
312 for (auto port
: gold_mod
->ports
)
314 RTLIL::Wire
*gold_wire
= gold_mod
->wire(port
);
315 RTLIL::Wire
*gate_wire
= gate_mod
->wire(port
);
317 log_assert(gold_wire
!= nullptr);
318 log_assert(gate_wire
!= nullptr);
319 log_assert(gold_wire
->port_output
== gate_wire
->port_output
);
320 log_assert(SIZE(gold_wire
) == SIZE(gate_wire
));
322 if (!gold_wire
->port_output
)
325 RTLIL::SigSpec
gold_outval(gold_wire
);
326 RTLIL::SigSpec
gate_outval(gate_wire
);
328 if (!gold_ce
.eval(gold_outval
))
329 log_error("Failed to eval %s in gold module.\n", log_id(gold_wire
));
331 if (!gate_ce
.eval(gate_outval
))
332 log_error("Failed to eval %s in gate module.\n", log_id(gate_wire
));
334 bool gold_gate_mismatch
= false;
335 for (int i
= 0; i
< SIZE(gold_wire
); i
++) {
336 if (gold_outval
[i
] == RTLIL::Sx
)
338 if (gold_outval
[i
] == gate_outval
[i
])
340 gold_gate_mismatch
= true;
344 if (gold_gate_mismatch
)
345 log_error("Mismatch in output %s: gold:%s != gate:%s\n", log_id(gate_wire
), log_signal(gold_outval
), log_signal(gate_outval
));
348 log("%s: %s\n", log_id(gold_wire
), log_signal(gold_outval
));
350 out_sig
.append(gold_wire
);
351 out_val
.append(gold_outval
);
353 if (vlog_file
.is_open()) {
354 vlog_file
<< stringf(" $display(\"[%s] %s expected: %%b, expr: %%b, noexpr: %%b\", %d'b%s, %s_expr, %s_noexpr);\n",
355 vlog_pattern_info
.c_str(), log_id(gold_wire
), SIZE(gold_outval
), gold_outval
.as_string().c_str(), log_id(gold_wire
), log_id(gold_wire
));
356 vlog_file
<< stringf(" if (%s_expr !== %d'b%s) begin $display(\"ERROR\"); $finish; end\n", log_id(gold_wire
), SIZE(gold_outval
), gold_outval
.as_string().c_str());
357 vlog_file
<< stringf(" if (%s_noexpr !== %d'b%s) begin $display(\"ERROR\"); $finish; end\n", log_id(gold_wire
), SIZE(gold_outval
), gold_outval
.as_string().c_str());
362 log("EVAL: %s\n", out_val
.as_string().c_str());
366 std::vector
<int> sat1_in_sig
= satgen1
.importSigSpec(in_sig
);
367 std::vector
<int> sat1_in_val
= satgen1
.importSigSpec(in_val
);
369 std::vector
<int> sat1_model
= satgen1
.importSigSpec(out_sig
);
370 std::vector
<bool> sat1_model_value
;
372 if (!ez1
.solve(sat1_model
, sat1_model_value
, ez1
.vec_eq(sat1_in_sig
, sat1_in_val
)))
373 log_error("Evaluating sat model 1 (no undef modeling) failed!\n");
377 for (int i
= SIZE(out_sig
)-1; i
>= 0; i
--)
378 log("%c", sat1_model_value
.at(i
) ? '1' : '0');
382 for (int i
= 0; i
< SIZE(out_sig
); i
++) {
383 if (out_val
[i
] != RTLIL::S0
&& out_val
[i
] != RTLIL::S1
)
385 if (out_val
[i
] == RTLIL::S0
&& sat1_model_value
.at(i
) == false)
387 if (out_val
[i
] == RTLIL::S1
&& sat1_model_value
.at(i
) == true)
389 log_error("Mismatch in sat model 1 (no undef modeling) output!\n");
392 std::vector
<int> sat2_in_def_sig
= satgen2
.importDefSigSpec(in_sig
);
393 std::vector
<int> sat2_in_def_val
= satgen2
.importDefSigSpec(in_val
);
395 std::vector
<int> sat2_in_undef_sig
= satgen2
.importUndefSigSpec(in_sig
);
396 std::vector
<int> sat2_in_undef_val
= satgen2
.importUndefSigSpec(in_val
);
398 std::vector
<int> sat2_model_def_sig
= satgen2
.importDefSigSpec(out_sig
);
399 std::vector
<int> sat2_model_undef_sig
= satgen2
.importUndefSigSpec(out_sig
);
401 std::vector
<int> sat2_model
;
402 sat2_model
.insert(sat2_model
.end(), sat2_model_def_sig
.begin(), sat2_model_def_sig
.end());
403 sat2_model
.insert(sat2_model
.end(), sat2_model_undef_sig
.begin(), sat2_model_undef_sig
.end());
405 std::vector
<bool> sat2_model_value
;
407 if (!ez2
.solve(sat2_model
, sat2_model_value
, ez2
.vec_eq(sat2_in_def_sig
, sat2_in_def_val
), ez2
.vec_eq(sat2_in_undef_sig
, sat2_in_undef_val
)))
408 log_error("Evaluating sat model 2 (undef modeling) failed!\n");
412 for (int i
= SIZE(out_sig
)-1; i
>= 0; i
--)
413 log("%c", sat2_model_value
.at(SIZE(out_sig
) + i
) ? 'x' : sat2_model_value
.at(i
) ? '1' : '0');
417 for (int i
= 0; i
< SIZE(out_sig
); i
++) {
418 if (sat2_model_value
.at(SIZE(out_sig
) + i
)) {
419 if (out_val
[i
] != RTLIL::S0
&& out_val
[i
] != RTLIL::S1
)
422 if (out_val
[i
] == RTLIL::S0
&& sat2_model_value
.at(i
) == false)
424 if (out_val
[i
] == RTLIL::S1
&& sat2_model_value
.at(i
) == true)
427 log_error("Mismatch in sat model 2 (undef modeling) output!\n");
432 if (vlog_file
.is_open()) {
433 vlog_file
<< stringf(" end\n");
434 vlog_file
<< stringf(" endtask\n");
435 vlog_file
<< stringf("endmodule\n");
442 struct TestCellPass
: public Pass
{
443 TestCellPass() : Pass("test_cell", "automatically test the implementation of a cell type") { }
446 // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
448 log(" test_cell [options] {cell-types}\n");
450 log("Tests the internal implementation of the given cell type (for example '$mux')\n");
451 log("by comparing SAT solver, EVAL and TECHMAP implementations of the cell types..\n");
453 log("Run with 'all' instead of a cell type to run the test on all supported\n");
454 log("cell types.\n");
456 log(" -n {integer}\n");
457 log(" create this number of cell instances and test them (default = 100).\n");
459 log(" -s {positive_integer}\n");
460 log(" use this value as rng seed value (default = unix time).\n");
462 log(" -f {ilang_file}\n");
463 log(" don't generate circuits. instead load the specified ilang file.\n");
465 log(" -map {filename}\n");
466 log(" pass this option to techmap.\n");
469 log(" use \"techmap -map +/simlib.v -max_iter 2 -autoproc\"\n");
471 log(" -script {script_file}\n");
472 log(" instead of calling \"techmap\", call \"script {script_file}\".\n");
475 log(" set some input bits to random constant values\n");
478 log(" do not check SAT model or run SAT equivalence checking\n");
481 log(" print additional debug information to the console\n");
483 log(" -vlog {filename}\n");
484 log(" create a verilog test bench to test simlib and write_verilog\n");
487 virtual void execute(std::vector
<std::string
> args
, RTLIL::Design
*)
490 std::string techmap_cmd
= "techmap -assert";
491 std::string ilang_file
;
492 xorshift32_state
= 0;
493 std::ofstream vlog_file
;
494 bool verbose
= false;
495 bool constmode
= false;
499 for (argidx
= 1; argidx
< SIZE(args
); argidx
++)
501 if (args
[argidx
] == "-n" && argidx
+1 < SIZE(args
)) {
502 num_iter
= atoi(args
[++argidx
].c_str());
505 if (args
[argidx
] == "-s" && argidx
+1 < SIZE(args
)) {
506 xorshift32_state
= atoi(args
[++argidx
].c_str());
509 if (args
[argidx
] == "-map" && argidx
+1 < SIZE(args
)) {
510 techmap_cmd
+= " -map " + args
[++argidx
];
513 if (args
[argidx
] == "-f" && argidx
+1 < SIZE(args
)) {
514 ilang_file
= args
[++argidx
];
518 if (args
[argidx
] == "-script" && argidx
+1 < SIZE(args
)) {
519 techmap_cmd
= "script " + args
[++argidx
];
522 if (args
[argidx
] == "-simlib") {
523 techmap_cmd
= "techmap -map +/simlib.v -max_iter 2 -autoproc";
526 if (args
[argidx
] == "-const") {
530 if (args
[argidx
] == "-nosat") {
534 if (args
[argidx
] == "-v") {
538 if (args
[argidx
] == "-vlog" && argidx
+1 < SIZE(args
)) {
539 vlog_file
.open(args
[++argidx
], std::ios_base::trunc
);
540 if (!vlog_file
.is_open())
541 log_cmd_error("Failed to open output file `%s'.\n", args
[argidx
].c_str());
547 if (xorshift32_state
== 0) {
548 xorshift32_state
= time(NULL
) & 0x7fffffff;
549 log("Rng seed value: %d\n", int(xorshift32_state
));
552 std::map
<std::string
, std::string
> cell_types
;
553 std::vector
<std::string
> selected_cell_types
;
555 cell_types
["$not"] = "ASY";
556 cell_types
["$pos"] = "ASY";
557 cell_types
["$neg"] = "ASY";
559 cell_types
["$and"] = "ABSY";
560 cell_types
["$or"] = "ABSY";
561 cell_types
["$xor"] = "ABSY";
562 cell_types
["$xnor"] = "ABSY";
564 cell_types
["$reduce_and"] = "ASY";
565 cell_types
["$reduce_or"] = "ASY";
566 cell_types
["$reduce_xor"] = "ASY";
567 cell_types
["$reduce_xnor"] = "ASY";
568 cell_types
["$reduce_bool"] = "ASY";
570 cell_types
["$shl"] = "ABshY";
571 cell_types
["$shr"] = "ABshY";
572 cell_types
["$sshl"] = "ABshY";
573 cell_types
["$sshr"] = "ABshY";
574 cell_types
["$shift"] = "ABshY";
575 cell_types
["$shiftx"] = "ABshY";
577 cell_types
["$lt"] = "ABSY";
578 cell_types
["$le"] = "ABSY";
579 cell_types
["$eq"] = "ABSY";
580 cell_types
["$ne"] = "ABSY";
581 // cell_types["$eqx"] = "ABSY";
582 // cell_types["$nex"] = "ABSY";
583 cell_types
["$ge"] = "ABSY";
584 cell_types
["$gt"] = "ABSY";
586 cell_types
["$add"] = "ABSY";
587 cell_types
["$sub"] = "ABSY";
588 cell_types
["$mul"] = "ABSY";
589 cell_types
["$div"] = "ABSY";
590 cell_types
["$mod"] = "ABSY";
591 // cell_types["$pow"] = "ABsY";
593 cell_types
["$logic_not"] = "ASY";
594 cell_types
["$logic_and"] = "ABSY";
595 cell_types
["$logic_or"] = "ABSY";
597 // cell_types["$mux"] = "A";
598 // cell_types["$pmux"] = "A";
599 // cell_types["$slice"] = "A";
600 // cell_types["$concat"] = "A";
601 // cell_types["$assert"] = "A";
603 cell_types
["$lut"] = "*";
604 cell_types
["$alu"] = "ABSY";
605 cell_types
["$macc"] = "*";
607 for (; argidx
< SIZE(args
); argidx
++)
609 if (args
[argidx
].rfind("-", 0) == 0)
610 log_cmd_error("Unexpected option: %s\n", args
[argidx
].c_str());
612 if (args
[argidx
] == "all") {
613 for (auto &it
: cell_types
)
614 if (std::count(selected_cell_types
.begin(), selected_cell_types
.end(), it
.first
) == 0)
615 selected_cell_types
.push_back(it
.first
);
619 if (cell_types
.count(args
[argidx
]) == 0) {
620 std::string cell_type_list
;
622 for (auto &it
: cell_types
) {
623 if (charcount
> 60) {
624 cell_type_list
+= "\n" + it
.first
;
627 cell_type_list
+= " " + it
.first
;
628 charcount
+= SIZE(it
.first
);
630 log_cmd_error("The cell type `%s' is currently not supported. Try one of these:%s\n",
631 args
[argidx
].c_str(), cell_type_list
.c_str());
634 if (std::count(selected_cell_types
.begin(), selected_cell_types
.end(), args
[argidx
]) == 0)
635 selected_cell_types
.push_back(args
[argidx
]);
638 if (!ilang_file
.empty()) {
639 if (!selected_cell_types
.empty())
640 log_cmd_error("Do not specify any cell types when using -f.\n");
641 selected_cell_types
.push_back("ilang");
644 if (selected_cell_types
.empty())
645 log_cmd_error("No cell type to test specified.\n");
647 std::vector
<std::string
> uut_names
;
649 for (auto cell_type
: selected_cell_types
)
650 for (int i
= 0; i
< num_iter
; i
++)
652 RTLIL::Design
*design
= new RTLIL::Design
;
653 if (cell_type
== "ilang")
654 Frontend::frontend_call(design
, NULL
, std::string(), "ilang " + ilang_file
);
656 create_gold_module(design
, cell_type
, cell_types
.at(cell_type
), constmode
);
657 Pass::call(design
, stringf("copy gold gate; cd gate; %s; cd ..; opt -fast gate", techmap_cmd
.c_str()));
659 Pass::call(design
, "miter -equiv -flatten -make_outputs -ignore_gold_x gold gate miter");
661 Pass::call(design
, "dump gate");
662 Pass::call(design
, "dump gold");
664 Pass::call(design
, "sat -verify -enable_undef -prove trigger 0 -show-inputs -show-outputs miter");
665 std::string uut_name
= stringf("uut_%s_%d", cell_type
.substr(1).c_str(), i
);
666 if (vlog_file
.is_open()) {
667 Pass::call(design
, stringf("copy gold %s_expr; select %s_expr", uut_name
.c_str(), uut_name
.c_str()));
668 Backend::backend_call(design
, &vlog_file
, "<test_cell -vlog>", "verilog -selected");
669 Pass::call(design
, stringf("copy gold %s_noexpr; select %s_noexpr", uut_name
.c_str(), uut_name
.c_str()));
670 Backend::backend_call(design
, &vlog_file
, "<test_cell -vlog>", "verilog -selected -noexpr");
671 uut_names
.push_back(uut_name
);
673 run_eval_test(design
, verbose
, nosat
, uut_name
, vlog_file
);
677 if (vlog_file
.is_open()) {
678 vlog_file
<< "\nmodule testbench;\n";
679 for (auto &uut
: uut_names
)
680 vlog_file
<< stringf(" %s %s ();\n", uut
.c_str(), uut
.c_str());
681 vlog_file
<< " initial begin\n";
682 for (auto &uut
: uut_names
)
683 vlog_file
<< " " << uut
<< ".run;\n";
684 vlog_file
<< " end\n";
685 vlog_file
<< "endmodule\n";