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"
28 PRIVATE_NAMESPACE_BEGIN
30 static uint32_t xorshift32_state
= 123456789;
32 static uint32_t xorshift32(uint32_t limit
) {
33 xorshift32_state
^= xorshift32_state
<< 13;
34 xorshift32_state
^= xorshift32_state
>> 17;
35 xorshift32_state
^= xorshift32_state
<< 5;
36 return xorshift32_state
% limit
;
39 static void create_gold_module(RTLIL::Design
*design
, RTLIL::IdString cell_type
, std::string cell_type_flags
, bool constmode
)
41 RTLIL::Module
*module
= design
->addModule("\\gold");
42 RTLIL::Cell
*cell
= module
->addCell("\\UUT", cell_type
);
45 if (cell_type
== "$fa")
47 int width
= 1 + xorshift32(8);
49 wire
= module
->addWire("\\A");
51 wire
->port_input
= true;
52 cell
->setPort("\\A", wire
);
54 wire
= module
->addWire("\\B");
56 wire
->port_input
= true;
57 cell
->setPort("\\B", wire
);
59 wire
= module
->addWire("\\C");
61 wire
->port_input
= true;
62 cell
->setPort("\\C", wire
);
64 wire
= module
->addWire("\\X");
66 wire
->port_output
= true;
67 cell
->setPort("\\X", wire
);
69 wire
= module
->addWire("\\Y");
71 wire
->port_output
= true;
72 cell
->setPort("\\Y", wire
);
75 if (cell_type
== "$lcu")
77 int width
= 1 + xorshift32(8);
79 wire
= module
->addWire("\\P");
81 wire
->port_input
= true;
82 cell
->setPort("\\P", wire
);
84 wire
= module
->addWire("\\G");
86 wire
->port_input
= true;
87 cell
->setPort("\\G", wire
);
89 wire
= module
->addWire("\\CI");
90 wire
->port_input
= true;
91 cell
->setPort("\\CI", wire
);
93 wire
= module
->addWire("\\CO");
95 wire
->port_output
= true;
96 cell
->setPort("\\CO", wire
);
99 if (cell_type
== "$macc")
102 int width
= 1 + xorshift32(8);
103 int depth
= 1 + xorshift32(6);
104 int mulbits_a
= 0, mulbits_b
= 0;
106 RTLIL::Wire
*wire_a
= module
->addWire("\\A");
108 wire_a
->port_input
= true;
110 for (int i
= 0; i
< depth
; i
++)
112 int size_a
= xorshift32(width
) + 1;
113 int size_b
= depth
> 4 ? 0 : xorshift32(width
) + 1;
115 if (mulbits_a
+ size_a
*size_b
<= 96 && mulbits_b
+ size_a
+ size_b
<= 16 && xorshift32(2) == 1) {
116 mulbits_a
+= size_a
* size_b
;
117 mulbits_b
+= size_a
+ size_b
;
121 Macc::port_t this_port
;
123 wire_a
->width
+= size_a
;
124 this_port
.in_a
= RTLIL::SigSpec(wire_a
, wire_a
->width
- size_a
, size_a
);
126 wire_a
->width
+= size_b
;
127 this_port
.in_b
= RTLIL::SigSpec(wire_a
, wire_a
->width
- size_b
, size_b
);
129 this_port
.is_signed
= xorshift32(2) == 1;
130 this_port
.do_subtract
= xorshift32(2) == 1;
131 macc
.ports
.push_back(this_port
);
134 wire
= module
->addWire("\\B");
135 wire
->width
= xorshift32(mulbits_a
? xorshift32(4)+1 : xorshift32(16)+1);
136 wire
->port_input
= true;
137 macc
.bit_ports
= wire
;
139 wire
= module
->addWire("\\Y");
141 wire
->port_output
= true;
142 cell
->setPort("\\Y", wire
);
147 if (cell_type
== "$lut")
149 int width
= 1 + xorshift32(6);
151 wire
= module
->addWire("\\A");
153 wire
->port_input
= true;
154 cell
->setPort("\\A", wire
);
156 wire
= module
->addWire("\\Y");
157 wire
->port_output
= true;
158 cell
->setPort("\\Y", wire
);
160 RTLIL::SigSpec config
;
161 for (int i
= 0; i
< (1 << width
); i
++)
162 config
.append(xorshift32(2) ? RTLIL::S1
: RTLIL::S0
);
164 cell
->setParam("\\LUT", config
.as_const());
167 if (cell_type_flags
.find('A') != std::string::npos
) {
168 wire
= module
->addWire("\\A");
169 wire
->width
= 1 + xorshift32(8);
170 wire
->port_input
= true;
171 cell
->setPort("\\A", wire
);
174 if (cell_type_flags
.find('B') != std::string::npos
) {
175 wire
= module
->addWire("\\B");
176 if (cell_type_flags
.find('h') != std::string::npos
)
177 wire
->width
= 1 + xorshift32(6);
179 wire
->width
= 1 + xorshift32(8);
180 wire
->port_input
= true;
181 cell
->setPort("\\B", wire
);
184 if (cell_type_flags
.find('S') != std::string::npos
&& xorshift32(2)) {
185 if (cell_type_flags
.find('A') != std::string::npos
)
186 cell
->parameters
["\\A_SIGNED"] = true;
187 if (cell_type_flags
.find('B') != std::string::npos
)
188 cell
->parameters
["\\B_SIGNED"] = true;
191 if (cell_type_flags
.find('s') != std::string::npos
) {
192 if (cell_type_flags
.find('A') != std::string::npos
&& xorshift32(2))
193 cell
->parameters
["\\A_SIGNED"] = true;
194 if (cell_type_flags
.find('B') != std::string::npos
&& xorshift32(2))
195 cell
->parameters
["\\B_SIGNED"] = true;
198 if (cell_type_flags
.find('Y') != std::string::npos
) {
199 wire
= module
->addWire("\\Y");
200 wire
->width
= 1 + xorshift32(8);
201 wire
->port_output
= true;
202 cell
->setPort("\\Y", wire
);
205 if (cell_type
== "$alu")
207 wire
= module
->addWire("\\CI");
208 wire
->port_input
= true;
209 cell
->setPort("\\CI", wire
);
211 wire
= module
->addWire("\\BI");
212 wire
->port_input
= true;
213 cell
->setPort("\\BI", wire
);
215 wire
= module
->addWire("\\X");
216 wire
->width
= SIZE(cell
->getPort("\\Y"));
217 wire
->port_output
= true;
218 cell
->setPort("\\X", wire
);
220 wire
= module
->addWire("\\CO");
221 wire
->width
= SIZE(cell
->getPort("\\Y"));
222 wire
->port_output
= true;
223 cell
->setPort("\\CO", wire
);
228 auto conn_list
= cell
->connections();
229 for (auto &conn
: conn_list
)
231 RTLIL::SigSpec sig
= conn
.second
;
233 if (SIZE(sig
) == 0 || sig
[0].wire
== nullptr || sig
[0].wire
->port_output
)
237 switch (xorshift32(5))
240 n
= xorshift32(SIZE(sig
) + 1);
241 for (int i
= 0; i
< n
; i
++)
242 sig
[i
] = xorshift32(2) == 1 ? RTLIL::S1
: RTLIL::S0
;
245 n
= xorshift32(SIZE(sig
) + 1);
246 for (int i
= n
; i
< SIZE(sig
); i
++)
247 sig
[i
] = xorshift32(2) == 1 ? RTLIL::S1
: RTLIL::S0
;
250 n
= xorshift32(SIZE(sig
));
251 m
= xorshift32(SIZE(sig
));
252 for (int i
= std::min(n
, m
); i
< std::max(n
, m
); i
++)
253 sig
[i
] = xorshift32(2) == 1 ? RTLIL::S1
: RTLIL::S0
;
257 cell
->setPort(conn
.first
, sig
);
261 module
->fixup_ports();
262 cell
->fixup_parameters();
266 static void run_eval_test(RTLIL::Design
*design
, bool verbose
, bool nosat
, std::string uut_name
, std::ofstream
&vlog_file
)
268 log("Eval testing:%c", verbose
? '\n' : ' ');
270 RTLIL::Module
*gold_mod
= design
->module("\\gold");
271 RTLIL::Module
*gate_mod
= design
->module("\\gate");
272 ConstEval
gold_ce(gold_mod
), gate_ce(gate_mod
);
274 ezDefaultSAT ez1
, ez2
;
275 SigMap
sigmap(gold_mod
);
276 SatGen
satgen1(&ez1
, &sigmap
);
277 SatGen
satgen2(&ez2
, &sigmap
);
278 satgen2
.model_undef
= true;
281 for (auto cell
: gold_mod
->cells()) {
282 satgen1
.importCell(cell
);
283 satgen2
.importCell(cell
);
286 if (vlog_file
.is_open())
288 vlog_file
<< stringf("\nmodule %s;\n", uut_name
.c_str());
290 for (auto port
: gold_mod
->ports
) {
291 RTLIL::Wire
*wire
= gold_mod
->wire(port
);
292 if (wire
->port_input
)
293 vlog_file
<< stringf(" reg [%d:0] %s;\n", SIZE(wire
)-1, log_id(wire
));
295 vlog_file
<< stringf(" wire [%d:0] %s_expr, %s_noexpr;\n", SIZE(wire
)-1, log_id(wire
), log_id(wire
));
298 vlog_file
<< stringf(" %s_expr uut_expr(", uut_name
.c_str());
299 for (int i
= 0; i
< SIZE(gold_mod
->ports
); i
++)
300 vlog_file
<< stringf("%s.%s(%s%s)", i
? ", " : "", log_id(gold_mod
->ports
[i
]), log_id(gold_mod
->ports
[i
]),
301 gold_mod
->wire(gold_mod
->ports
[i
])->port_input
? "" : "_expr");
302 vlog_file
<< stringf(");\n");
304 vlog_file
<< stringf(" %s_expr uut_noexpr(", uut_name
.c_str());
305 for (int i
= 0; i
< SIZE(gold_mod
->ports
); i
++)
306 vlog_file
<< stringf("%s.%s(%s%s)", i
? ", " : "", log_id(gold_mod
->ports
[i
]), log_id(gold_mod
->ports
[i
]),
307 gold_mod
->wire(gold_mod
->ports
[i
])->port_input
? "" : "_noexpr");
308 vlog_file
<< stringf(");\n");
310 vlog_file
<< stringf(" task run;\n");
311 vlog_file
<< stringf(" begin\n");
312 vlog_file
<< stringf(" $display(\"%s\");\n", uut_name
.c_str());
315 for (int i
= 0; i
< 64; i
++)
317 log(verbose
? "\n" : ".");
321 RTLIL::SigSpec in_sig
, in_val
;
322 RTLIL::SigSpec out_sig
, out_val
;
323 std::string vlog_pattern_info
;
325 for (auto port
: gold_mod
->ports
)
327 RTLIL::Wire
*gold_wire
= gold_mod
->wire(port
);
328 RTLIL::Wire
*gate_wire
= gate_mod
->wire(port
);
330 log_assert(gold_wire
!= nullptr);
331 log_assert(gate_wire
!= nullptr);
332 log_assert(gold_wire
->port_input
== gate_wire
->port_input
);
333 log_assert(SIZE(gold_wire
) == SIZE(gate_wire
));
335 if (!gold_wire
->port_input
)
338 RTLIL::Const in_value
;
339 for (int i
= 0; i
< SIZE(gold_wire
); i
++)
340 in_value
.bits
.push_back(xorshift32(2) ? RTLIL::S1
: RTLIL::S0
);
342 if (xorshift32(4) == 0) {
343 int inv_chance
= 1 + xorshift32(8);
344 for (int i
= 0; i
< SIZE(gold_wire
); i
++)
345 if (xorshift32(inv_chance
) == 0)
346 in_value
.bits
[i
] = RTLIL::Sx
;
350 log("%s: %s\n", log_id(gold_wire
), log_signal(in_value
));
352 in_sig
.append(gold_wire
);
353 in_val
.append(in_value
);
355 gold_ce
.set(gold_wire
, in_value
);
356 gate_ce
.set(gate_wire
, in_value
);
358 if (vlog_file
.is_open() && SIZE(in_value
) > 0) {
359 vlog_file
<< stringf(" %s = 'b%s;\n", log_id(gold_wire
), in_value
.as_string().c_str());
360 if (!vlog_pattern_info
.empty())
361 vlog_pattern_info
+= " ";
362 vlog_pattern_info
+= stringf("%s=%s", log_id(gold_wire
), log_signal(in_value
));
366 if (vlog_file
.is_open())
367 vlog_file
<< stringf(" #1;\n");
369 for (auto port
: gold_mod
->ports
)
371 RTLIL::Wire
*gold_wire
= gold_mod
->wire(port
);
372 RTLIL::Wire
*gate_wire
= gate_mod
->wire(port
);
374 log_assert(gold_wire
!= nullptr);
375 log_assert(gate_wire
!= nullptr);
376 log_assert(gold_wire
->port_output
== gate_wire
->port_output
);
377 log_assert(SIZE(gold_wire
) == SIZE(gate_wire
));
379 if (!gold_wire
->port_output
)
382 RTLIL::SigSpec
gold_outval(gold_wire
);
383 RTLIL::SigSpec
gate_outval(gate_wire
);
385 if (!gold_ce
.eval(gold_outval
))
386 log_error("Failed to eval %s in gold module.\n", log_id(gold_wire
));
388 if (!gate_ce
.eval(gate_outval
))
389 log_error("Failed to eval %s in gate module.\n", log_id(gate_wire
));
391 bool gold_gate_mismatch
= false;
392 for (int i
= 0; i
< SIZE(gold_wire
); i
++) {
393 if (gold_outval
[i
] == RTLIL::Sx
)
395 if (gold_outval
[i
] == gate_outval
[i
])
397 gold_gate_mismatch
= true;
401 if (gold_gate_mismatch
)
402 log_error("Mismatch in output %s: gold:%s != gate:%s\n", log_id(gate_wire
), log_signal(gold_outval
), log_signal(gate_outval
));
405 log("%s: %s\n", log_id(gold_wire
), log_signal(gold_outval
));
407 out_sig
.append(gold_wire
);
408 out_val
.append(gold_outval
);
410 if (vlog_file
.is_open()) {
411 vlog_file
<< stringf(" $display(\"[%s] %s expected: %%b, expr: %%b, noexpr: %%b\", %d'b%s, %s_expr, %s_noexpr);\n",
412 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
));
413 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());
414 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());
419 log("EVAL: %s\n", out_val
.as_string().c_str());
423 std::vector
<int> sat1_in_sig
= satgen1
.importSigSpec(in_sig
);
424 std::vector
<int> sat1_in_val
= satgen1
.importSigSpec(in_val
);
426 std::vector
<int> sat1_model
= satgen1
.importSigSpec(out_sig
);
427 std::vector
<bool> sat1_model_value
;
429 if (!ez1
.solve(sat1_model
, sat1_model_value
, ez1
.vec_eq(sat1_in_sig
, sat1_in_val
)))
430 log_error("Evaluating sat model 1 (no undef modeling) failed!\n");
434 for (int i
= SIZE(out_sig
)-1; i
>= 0; i
--)
435 log("%c", sat1_model_value
.at(i
) ? '1' : '0');
439 for (int i
= 0; i
< SIZE(out_sig
); i
++) {
440 if (out_val
[i
] != RTLIL::S0
&& out_val
[i
] != RTLIL::S1
)
442 if (out_val
[i
] == RTLIL::S0
&& sat1_model_value
.at(i
) == false)
444 if (out_val
[i
] == RTLIL::S1
&& sat1_model_value
.at(i
) == true)
446 log_error("Mismatch in sat model 1 (no undef modeling) output!\n");
449 std::vector
<int> sat2_in_def_sig
= satgen2
.importDefSigSpec(in_sig
);
450 std::vector
<int> sat2_in_def_val
= satgen2
.importDefSigSpec(in_val
);
452 std::vector
<int> sat2_in_undef_sig
= satgen2
.importUndefSigSpec(in_sig
);
453 std::vector
<int> sat2_in_undef_val
= satgen2
.importUndefSigSpec(in_val
);
455 std::vector
<int> sat2_model_def_sig
= satgen2
.importDefSigSpec(out_sig
);
456 std::vector
<int> sat2_model_undef_sig
= satgen2
.importUndefSigSpec(out_sig
);
458 std::vector
<int> sat2_model
;
459 sat2_model
.insert(sat2_model
.end(), sat2_model_def_sig
.begin(), sat2_model_def_sig
.end());
460 sat2_model
.insert(sat2_model
.end(), sat2_model_undef_sig
.begin(), sat2_model_undef_sig
.end());
462 std::vector
<bool> sat2_model_value
;
464 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
)))
465 log_error("Evaluating sat model 2 (undef modeling) failed!\n");
469 for (int i
= SIZE(out_sig
)-1; i
>= 0; i
--)
470 log("%c", sat2_model_value
.at(SIZE(out_sig
) + i
) ? 'x' : sat2_model_value
.at(i
) ? '1' : '0');
474 for (int i
= 0; i
< SIZE(out_sig
); i
++) {
475 if (sat2_model_value
.at(SIZE(out_sig
) + i
)) {
476 if (out_val
[i
] != RTLIL::S0
&& out_val
[i
] != RTLIL::S1
)
479 if (out_val
[i
] == RTLIL::S0
&& sat2_model_value
.at(i
) == false)
481 if (out_val
[i
] == RTLIL::S1
&& sat2_model_value
.at(i
) == true)
484 log_error("Mismatch in sat model 2 (undef modeling) output!\n");
489 if (vlog_file
.is_open()) {
490 vlog_file
<< stringf(" end\n");
491 vlog_file
<< stringf(" endtask\n");
492 vlog_file
<< stringf("endmodule\n");
499 struct TestCellPass
: public Pass
{
500 TestCellPass() : Pass("test_cell", "automatically test the implementation of a cell type") { }
503 // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
505 log(" test_cell [options] {cell-types}\n");
507 log("Tests the internal implementation of the given cell type (for example '$add')\n");
508 log("by comparing SAT solver, EVAL and TECHMAP implementations of the cell types..\n");
510 log("Run with 'all' instead of a cell type to run the test on all supported\n");
511 log("cell types.\n");
513 log(" -n {integer}\n");
514 log(" create this number of cell instances and test them (default = 100).\n");
516 log(" -s {positive_integer}\n");
517 log(" use this value as rng seed value (default = unix time).\n");
519 log(" -f {ilang_file}\n");
520 log(" don't generate circuits. instead load the specified ilang file.\n");
522 log(" -map {filename}\n");
523 log(" pass this option to techmap.\n");
526 log(" use \"techmap -map +/simlib.v -max_iter 2 -autoproc\"\n");
528 log(" -script {script_file}\n");
529 log(" instead of calling \"techmap\", call \"script {script_file}\".\n");
532 log(" set some input bits to random constant values\n");
535 log(" do not check SAT model or run SAT equivalence checking\n");
538 log(" print additional debug information to the console\n");
540 log(" -vlog {filename}\n");
541 log(" create a verilog test bench to test simlib and write_verilog\n");
544 virtual void execute(std::vector
<std::string
> args
, RTLIL::Design
*)
547 std::string techmap_cmd
= "techmap -assert";
548 std::string ilang_file
;
549 xorshift32_state
= 0;
550 std::ofstream vlog_file
;
551 bool verbose
= false;
552 bool constmode
= false;
556 for (argidx
= 1; argidx
< SIZE(args
); argidx
++)
558 if (args
[argidx
] == "-n" && argidx
+1 < SIZE(args
)) {
559 num_iter
= atoi(args
[++argidx
].c_str());
562 if (args
[argidx
] == "-s" && argidx
+1 < SIZE(args
)) {
563 xorshift32_state
= atoi(args
[++argidx
].c_str());
566 if (args
[argidx
] == "-map" && argidx
+1 < SIZE(args
)) {
567 techmap_cmd
+= " -map " + args
[++argidx
];
570 if (args
[argidx
] == "-f" && argidx
+1 < SIZE(args
)) {
571 ilang_file
= args
[++argidx
];
575 if (args
[argidx
] == "-script" && argidx
+1 < SIZE(args
)) {
576 techmap_cmd
= "script " + args
[++argidx
];
579 if (args
[argidx
] == "-simlib") {
580 techmap_cmd
= "techmap -map +/simlib.v -max_iter 2 -autoproc";
583 if (args
[argidx
] == "-const") {
587 if (args
[argidx
] == "-nosat") {
591 if (args
[argidx
] == "-v") {
595 if (args
[argidx
] == "-vlog" && argidx
+1 < SIZE(args
)) {
596 vlog_file
.open(args
[++argidx
], std::ios_base::trunc
);
597 if (!vlog_file
.is_open())
598 log_cmd_error("Failed to open output file `%s'.\n", args
[argidx
].c_str());
604 if (xorshift32_state
== 0) {
605 xorshift32_state
= time(NULL
) & 0x7fffffff;
606 log("Rng seed value: %d\n", int(xorshift32_state
));
609 std::map
<std::string
, std::string
> cell_types
;
610 std::vector
<std::string
> selected_cell_types
;
612 cell_types
["$not"] = "ASY";
613 cell_types
["$pos"] = "ASY";
614 cell_types
["$neg"] = "ASY";
616 cell_types
["$and"] = "ABSY";
617 cell_types
["$or"] = "ABSY";
618 cell_types
["$xor"] = "ABSY";
619 cell_types
["$xnor"] = "ABSY";
621 cell_types
["$reduce_and"] = "ASY";
622 cell_types
["$reduce_or"] = "ASY";
623 cell_types
["$reduce_xor"] = "ASY";
624 cell_types
["$reduce_xnor"] = "ASY";
625 cell_types
["$reduce_bool"] = "ASY";
627 cell_types
["$shl"] = "ABshY";
628 cell_types
["$shr"] = "ABshY";
629 cell_types
["$sshl"] = "ABshY";
630 cell_types
["$sshr"] = "ABshY";
631 cell_types
["$shift"] = "ABshY";
632 cell_types
["$shiftx"] = "ABshY";
634 cell_types
["$lt"] = "ABSY";
635 cell_types
["$le"] = "ABSY";
636 cell_types
["$eq"] = "ABSY";
637 cell_types
["$ne"] = "ABSY";
638 // cell_types["$eqx"] = "ABSY";
639 // cell_types["$nex"] = "ABSY";
640 cell_types
["$ge"] = "ABSY";
641 cell_types
["$gt"] = "ABSY";
643 cell_types
["$add"] = "ABSY";
644 cell_types
["$sub"] = "ABSY";
645 cell_types
["$mul"] = "ABSY";
646 cell_types
["$div"] = "ABSY";
647 cell_types
["$mod"] = "ABSY";
648 // cell_types["$pow"] = "ABsY";
650 cell_types
["$logic_not"] = "ASY";
651 cell_types
["$logic_and"] = "ABSY";
652 cell_types
["$logic_or"] = "ABSY";
654 // cell_types["$mux"] = "A";
655 // cell_types["$pmux"] = "A";
656 // cell_types["$slice"] = "A";
657 // cell_types["$concat"] = "A";
658 // cell_types["$assert"] = "A";
660 cell_types
["$lut"] = "*";
661 cell_types
["$alu"] = "ABSY";
662 cell_types
["$lcu"] = "*";
663 cell_types
["$macc"] = "*";
664 cell_types
["$fa"] = "*";
666 for (; argidx
< SIZE(args
); argidx
++)
668 if (args
[argidx
].rfind("-", 0) == 0)
669 log_cmd_error("Unexpected option: %s\n", args
[argidx
].c_str());
671 if (args
[argidx
] == "all") {
672 for (auto &it
: cell_types
)
673 if (std::count(selected_cell_types
.begin(), selected_cell_types
.end(), it
.first
) == 0)
674 selected_cell_types
.push_back(it
.first
);
678 if (cell_types
.count(args
[argidx
]) == 0) {
679 std::string cell_type_list
;
681 for (auto &it
: cell_types
) {
682 if (charcount
> 60) {
683 cell_type_list
+= "\n" + it
.first
;
686 cell_type_list
+= " " + it
.first
;
687 charcount
+= SIZE(it
.first
);
689 log_cmd_error("The cell type `%s' is currently not supported. Try one of these:%s\n",
690 args
[argidx
].c_str(), cell_type_list
.c_str());
693 if (std::count(selected_cell_types
.begin(), selected_cell_types
.end(), args
[argidx
]) == 0)
694 selected_cell_types
.push_back(args
[argidx
]);
697 if (!ilang_file
.empty()) {
698 if (!selected_cell_types
.empty())
699 log_cmd_error("Do not specify any cell types when using -f.\n");
700 selected_cell_types
.push_back("ilang");
703 if (selected_cell_types
.empty())
704 log_cmd_error("No cell type to test specified.\n");
706 std::vector
<std::string
> uut_names
;
708 for (auto cell_type
: selected_cell_types
)
709 for (int i
= 0; i
< num_iter
; i
++)
711 RTLIL::Design
*design
= new RTLIL::Design
;
712 if (cell_type
== "ilang")
713 Frontend::frontend_call(design
, NULL
, std::string(), "ilang " + ilang_file
);
715 create_gold_module(design
, cell_type
, cell_types
.at(cell_type
), constmode
);
716 Pass::call(design
, stringf("copy gold gate; cd gate; %s; cd ..; opt -fast gate", techmap_cmd
.c_str()));
718 Pass::call(design
, "miter -equiv -flatten -make_outputs -ignore_gold_x gold gate miter");
720 Pass::call(design
, "dump gate");
721 Pass::call(design
, "dump gold");
723 Pass::call(design
, "sat -verify -enable_undef -prove trigger 0 -show-inputs -show-outputs miter");
724 std::string uut_name
= stringf("uut_%s_%d", cell_type
.substr(1).c_str(), i
);
725 if (vlog_file
.is_open()) {
726 Pass::call(design
, stringf("copy gold %s_expr; select %s_expr", uut_name
.c_str(), uut_name
.c_str()));
727 Backend::backend_call(design
, &vlog_file
, "<test_cell -vlog>", "verilog -selected");
728 Pass::call(design
, stringf("copy gold %s_noexpr; select %s_noexpr", uut_name
.c_str(), uut_name
.c_str()));
729 Backend::backend_call(design
, &vlog_file
, "<test_cell -vlog>", "verilog -selected -noexpr");
730 uut_names
.push_back(uut_name
);
732 run_eval_test(design
, verbose
, nosat
, uut_name
, vlog_file
);
736 if (vlog_file
.is_open()) {
737 vlog_file
<< "\nmodule testbench;\n";
738 for (auto &uut
: uut_names
)
739 vlog_file
<< stringf(" %s %s ();\n", uut
.c_str(), uut
.c_str());
740 vlog_file
<< " initial begin\n";
741 for (auto &uut
: uut_names
)
742 vlog_file
<< " " << uut
<< ".run;\n";
743 vlog_file
<< " end\n";
744 vlog_file
<< "endmodule\n";
749 PRIVATE_NAMESPACE_END