yosys-master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
test_cell.cc
Go to the documentation of this file.
1 /*
2  * yosys -- Yosys Open SYnthesis Suite
3  *
4  * Copyright (C) 2014 Clifford Wolf <clifford@clifford.at>
5  * Copyright (C) 2014 Johann Glaser <Johann.Glaser@gmx.at>
6  *
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.
10  *
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.
18  *
19  */
20 
21 #include "kernel/yosys.h"
22 #include "kernel/satgen.h"
23 #include "kernel/consteval.h"
24 #include "kernel/macc.h"
25 #include <algorithm>
26 
29 
30 static uint32_t xorshift32_state = 123456789;
31 
32 static uint32_t xorshift32(uint32_t limit) {
36  return xorshift32_state % limit;
37 }
38 
39 static void create_gold_module(RTLIL::Design *design, RTLIL::IdString cell_type, std::string cell_type_flags, bool constmode)
40 {
41  RTLIL::Module *module = design->addModule("\\gold");
42  RTLIL::Cell *cell = module->addCell("\\UUT", cell_type);
43  RTLIL::Wire *wire;
44 
45  if (cell_type == "$fa")
46  {
47  int width = 1 + xorshift32(8);
48 
49  wire = module->addWire("\\A");
50  wire->width = width;
51  wire->port_input = true;
52  cell->setPort("\\A", wire);
53 
54  wire = module->addWire("\\B");
55  wire->width = width;
56  wire->port_input = true;
57  cell->setPort("\\B", wire);
58 
59  wire = module->addWire("\\C");
60  wire->width = width;
61  wire->port_input = true;
62  cell->setPort("\\C", wire);
63 
64  wire = module->addWire("\\X");
65  wire->width = width;
66  wire->port_output = true;
67  cell->setPort("\\X", wire);
68 
69  wire = module->addWire("\\Y");
70  wire->width = width;
71  wire->port_output = true;
72  cell->setPort("\\Y", wire);
73  }
74 
75  if (cell_type == "$lcu")
76  {
77  int width = 1 + xorshift32(8);
78 
79  wire = module->addWire("\\P");
80  wire->width = width;
81  wire->port_input = true;
82  cell->setPort("\\P", wire);
83 
84  wire = module->addWire("\\G");
85  wire->width = width;
86  wire->port_input = true;
87  cell->setPort("\\G", wire);
88 
89  wire = module->addWire("\\CI");
90  wire->port_input = true;
91  cell->setPort("\\CI", wire);
92 
93  wire = module->addWire("\\CO");
94  wire->width = width;
95  wire->port_output = true;
96  cell->setPort("\\CO", wire);
97  }
98 
99  if (cell_type == "$macc")
100  {
101  Macc macc;
102  int width = 1 + xorshift32(8);
103  int depth = 1 + xorshift32(6);
104  int mulbits_a = 0, mulbits_b = 0;
105 
106  RTLIL::Wire *wire_a = module->addWire("\\A");
107  wire_a->width = 0;
108  wire_a->port_input = true;
109 
110  for (int i = 0; i < depth; i++)
111  {
112  int size_a = xorshift32(width) + 1;
113  int size_b = depth > 4 ? 0 : xorshift32(width) + 1;
114 
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;
118  } else
119  size_b = 0;
120 
121  Macc::port_t this_port;
122 
123  wire_a->width += size_a;
124  this_port.in_a = RTLIL::SigSpec(wire_a, wire_a->width - size_a, size_a);
125 
126  wire_a->width += size_b;
127  this_port.in_b = RTLIL::SigSpec(wire_a, wire_a->width - size_b, size_b);
128 
129  this_port.is_signed = xorshift32(2) == 1;
130  this_port.do_subtract = xorshift32(2) == 1;
131  macc.ports.push_back(this_port);
132  }
133 
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;
138 
139  wire = module->addWire("\\Y");
140  wire->width = width;
141  wire->port_output = true;
142  cell->setPort("\\Y", wire);
143 
144  macc.to_cell(cell);
145  }
146 
147  if (cell_type == "$lut")
148  {
149  int width = 1 + xorshift32(6);
150 
151  wire = module->addWire("\\A");
152  wire->width = width;
153  wire->port_input = true;
154  cell->setPort("\\A", wire);
155 
156  wire = module->addWire("\\Y");
157  wire->port_output = true;
158  cell->setPort("\\Y", wire);
159 
160  RTLIL::SigSpec config;
161  for (int i = 0; i < (1 << width); i++)
162  config.append(xorshift32(2) ? RTLIL::S1 : RTLIL::S0);
163 
164  cell->setParam("\\LUT", config.as_const());
165  }
166 
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);
172  }
173 
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);
178  else
179  wire->width = 1 + xorshift32(8);
180  wire->port_input = true;
181  cell->setPort("\\B", wire);
182  }
183 
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;
189  }
190 
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;
196  }
197 
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);
203  }
204 
205  if (cell_type == "$alu")
206  {
207  wire = module->addWire("\\CI");
208  wire->port_input = true;
209  cell->setPort("\\CI", wire);
210 
211  wire = module->addWire("\\BI");
212  wire->port_input = true;
213  cell->setPort("\\BI", wire);
214 
215  wire = module->addWire("\\X");
216  wire->width = GetSize(cell->getPort("\\Y"));
217  wire->port_output = true;
218  cell->setPort("\\X", wire);
219 
220  wire = module->addWire("\\CO");
221  wire->width = GetSize(cell->getPort("\\Y"));
222  wire->port_output = true;
223  cell->setPort("\\CO", wire);
224  }
225 
226  if (constmode)
227  {
228  auto conn_list = cell->connections();
229  for (auto &conn : conn_list)
230  {
231  RTLIL::SigSpec sig = conn.second;
232 
233  if (GetSize(sig) == 0 || sig[0].wire == nullptr || sig[0].wire->port_output)
234  continue;
235 
236  int n, m;
237  switch (xorshift32(5))
238  {
239  case 0:
240  n = xorshift32(GetSize(sig) + 1);
241  for (int i = 0; i < n; i++)
242  sig[i] = xorshift32(2) == 1 ? RTLIL::S1 : RTLIL::S0;
243  break;
244  case 1:
245  n = xorshift32(GetSize(sig) + 1);
246  for (int i = n; i < GetSize(sig); i++)
247  sig[i] = xorshift32(2) == 1 ? RTLIL::S1 : RTLIL::S0;
248  break;
249  case 2:
250  n = xorshift32(GetSize(sig));
251  m = xorshift32(GetSize(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;
254  break;
255  }
256 
257  cell->setPort(conn.first, sig);
258  }
259  }
260 
261  module->fixup_ports();
262  cell->fixup_parameters();
263  cell->check();
264 }
265 
266 static void run_eval_test(RTLIL::Design *design, bool verbose, bool nosat, std::string uut_name, std::ofstream &vlog_file)
267 {
268  log("Eval testing:%c", verbose ? '\n' : ' ');
269 
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);
273 
274  ezDefaultSAT ez1, ez2;
275  SigMap sigmap(gold_mod);
276  SatGen satgen1(&ez1, &sigmap);
277  SatGen satgen2(&ez2, &sigmap);
278  satgen2.model_undef = true;
279 
280  if (!nosat)
281  for (auto cell : gold_mod->cells()) {
282  satgen1.importCell(cell);
283  satgen2.importCell(cell);
284  }
285 
286  if (vlog_file.is_open())
287  {
288  vlog_file << stringf("\nmodule %s;\n", uut_name.c_str());
289 
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", GetSize(wire)-1, log_id(wire));
294  else
295  vlog_file << stringf(" wire [%d:0] %s_expr, %s_noexpr;\n", GetSize(wire)-1, log_id(wire), log_id(wire));
296  }
297 
298  vlog_file << stringf(" %s_expr uut_expr(", uut_name.c_str());
299  for (int i = 0; i < GetSize(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");
303 
304  vlog_file << stringf(" %s_expr uut_noexpr(", uut_name.c_str());
305  for (int i = 0; i < GetSize(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");
309 
310  vlog_file << stringf(" task run;\n");
311  vlog_file << stringf(" begin\n");
312  vlog_file << stringf(" $display(\"%s\");\n", uut_name.c_str());
313  }
314 
315  for (int i = 0; i < 64; i++)
316  {
317  log(verbose ? "\n" : ".");
318  gold_ce.clear();
319  gate_ce.clear();
320 
321  RTLIL::SigSpec in_sig, in_val;
322  RTLIL::SigSpec out_sig, out_val;
323  std::string vlog_pattern_info;
324 
325  for (auto port : gold_mod->ports)
326  {
327  RTLIL::Wire *gold_wire = gold_mod->wire(port);
328  RTLIL::Wire *gate_wire = gate_mod->wire(port);
329 
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(GetSize(gold_wire) == GetSize(gate_wire));
334 
335  if (!gold_wire->port_input)
336  continue;
337 
338  RTLIL::Const in_value;
339  for (int i = 0; i < GetSize(gold_wire); i++)
340  in_value.bits.push_back(xorshift32(2) ? RTLIL::S1 : RTLIL::S0);
341 
342  if (xorshift32(4) == 0) {
343  int inv_chance = 1 + xorshift32(8);
344  for (int i = 0; i < GetSize(gold_wire); i++)
345  if (xorshift32(inv_chance) == 0)
346  in_value.bits[i] = RTLIL::Sx;
347  }
348 
349  if (verbose)
350  log("%s: %s\n", log_id(gold_wire), log_signal(in_value));
351 
352  in_sig.append(gold_wire);
353  in_val.append(in_value);
354 
355  gold_ce.set(gold_wire, in_value);
356  gate_ce.set(gate_wire, in_value);
357 
358  if (vlog_file.is_open() && GetSize(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));
363  }
364  }
365 
366  if (vlog_file.is_open())
367  vlog_file << stringf(" #1;\n");
368 
369  for (auto port : gold_mod->ports)
370  {
371  RTLIL::Wire *gold_wire = gold_mod->wire(port);
372  RTLIL::Wire *gate_wire = gate_mod->wire(port);
373 
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(GetSize(gold_wire) == GetSize(gate_wire));
378 
379  if (!gold_wire->port_output)
380  continue;
381 
382  RTLIL::SigSpec gold_outval(gold_wire);
383  RTLIL::SigSpec gate_outval(gate_wire);
384 
385  if (!gold_ce.eval(gold_outval))
386  log_error("Failed to eval %s in gold module.\n", log_id(gold_wire));
387 
388  if (!gate_ce.eval(gate_outval))
389  log_error("Failed to eval %s in gate module.\n", log_id(gate_wire));
390 
391  bool gold_gate_mismatch = false;
392  for (int i = 0; i < GetSize(gold_wire); i++) {
393  if (gold_outval[i] == RTLIL::Sx)
394  continue;
395  if (gold_outval[i] == gate_outval[i])
396  continue;
397  gold_gate_mismatch = true;
398  break;
399  }
400 
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));
403 
404  if (verbose)
405  log("%s: %s\n", log_id(gold_wire), log_signal(gold_outval));
406 
407  out_sig.append(gold_wire);
408  out_val.append(gold_outval);
409 
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), GetSize(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), GetSize(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), GetSize(gold_outval), gold_outval.as_string().c_str());
415  }
416  }
417 
418  if (verbose)
419  log("EVAL: %s\n", out_val.as_string().c_str());
420 
421  if (!nosat)
422  {
423  std::vector<int> sat1_in_sig = satgen1.importSigSpec(in_sig);
424  std::vector<int> sat1_in_val = satgen1.importSigSpec(in_val);
425 
426  std::vector<int> sat1_model = satgen1.importSigSpec(out_sig);
427  std::vector<bool> sat1_model_value;
428 
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");
431 
432  if (verbose) {
433  log("SAT 1: ");
434  for (int i = GetSize(out_sig)-1; i >= 0; i--)
435  log("%c", sat1_model_value.at(i) ? '1' : '0');
436  log("\n");
437  }
438 
439  for (int i = 0; i < GetSize(out_sig); i++) {
440  if (out_val[i] != RTLIL::S0 && out_val[i] != RTLIL::S1)
441  continue;
442  if (out_val[i] == RTLIL::S0 && sat1_model_value.at(i) == false)
443  continue;
444  if (out_val[i] == RTLIL::S1 && sat1_model_value.at(i) == true)
445  continue;
446  log_error("Mismatch in sat model 1 (no undef modeling) output!\n");
447  }
448 
449  std::vector<int> sat2_in_def_sig = satgen2.importDefSigSpec(in_sig);
450  std::vector<int> sat2_in_def_val = satgen2.importDefSigSpec(in_val);
451 
452  std::vector<int> sat2_in_undef_sig = satgen2.importUndefSigSpec(in_sig);
453  std::vector<int> sat2_in_undef_val = satgen2.importUndefSigSpec(in_val);
454 
455  std::vector<int> sat2_model_def_sig = satgen2.importDefSigSpec(out_sig);
456  std::vector<int> sat2_model_undef_sig = satgen2.importUndefSigSpec(out_sig);
457 
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());
461 
462  std::vector<bool> sat2_model_value;
463 
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");
466 
467  if (verbose) {
468  log("SAT 2: ");
469  for (int i = GetSize(out_sig)-1; i >= 0; i--)
470  log("%c", sat2_model_value.at(GetSize(out_sig) + i) ? 'x' : sat2_model_value.at(i) ? '1' : '0');
471  log("\n");
472  }
473 
474  for (int i = 0; i < GetSize(out_sig); i++) {
475  if (sat2_model_value.at(GetSize(out_sig) + i)) {
476  if (out_val[i] != RTLIL::S0 && out_val[i] != RTLIL::S1)
477  continue;
478  } else {
479  if (out_val[i] == RTLIL::S0 && sat2_model_value.at(i) == false)
480  continue;
481  if (out_val[i] == RTLIL::S1 && sat2_model_value.at(i) == true)
482  continue;
483  }
484  log_error("Mismatch in sat model 2 (undef modeling) output!\n");
485  }
486  }
487  }
488 
489  if (vlog_file.is_open()) {
490  vlog_file << stringf(" end\n");
491  vlog_file << stringf(" endtask\n");
492  vlog_file << stringf("endmodule\n");
493  }
494 
495  if (!verbose)
496  log(" ok.\n");
497 }
498 
499 struct TestCellPass : public Pass {
500  TestCellPass() : Pass("test_cell", "automatically test the implementation of a cell type") { }
501  virtual void help()
502  {
503  // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
504  log("\n");
505  log(" test_cell [options] {cell-types}\n");
506  log("\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");
509  log("\n");
510  log("Run with 'all' instead of a cell type to run the test on all supported\n");
511  log("cell types.\n");
512  log("\n");
513  log(" -n {integer}\n");
514  log(" create this number of cell instances and test them (default = 100).\n");
515  log("\n");
516  log(" -s {positive_integer}\n");
517  log(" use this value as rng seed value (default = unix time).\n");
518  log("\n");
519  log(" -f {ilang_file}\n");
520  log(" don't generate circuits. instead load the specified ilang file.\n");
521  log("\n");
522  log(" -map {filename}\n");
523  log(" pass this option to techmap.\n");
524  log("\n");
525  log(" -simlib\n");
526  log(" use \"techmap -map +/simlib.v -max_iter 2 -autoproc\"\n");
527  log("\n");
528  log(" -script {script_file}\n");
529  log(" instead of calling \"techmap\", call \"script {script_file}\".\n");
530  log("\n");
531  log(" -const\n");
532  log(" set some input bits to random constant values\n");
533  log("\n");
534  log(" -nosat\n");
535  log(" do not check SAT model or run SAT equivalence checking\n");
536  log("\n");
537  log(" -v\n");
538  log(" print additional debug information to the console\n");
539  log("\n");
540  log(" -vlog {filename}\n");
541  log(" create a verilog test bench to test simlib and write_verilog\n");
542  log("\n");
543  }
544  virtual void execute(std::vector<std::string> args, RTLIL::Design*)
545  {
546  int num_iter = 100;
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;
553  bool nosat = false;
554 
555  int argidx;
556  for (argidx = 1; argidx < GetSize(args); argidx++)
557  {
558  if (args[argidx] == "-n" && argidx+1 < GetSize(args)) {
559  num_iter = atoi(args[++argidx].c_str());
560  continue;
561  }
562  if (args[argidx] == "-s" && argidx+1 < GetSize(args)) {
563  xorshift32_state = atoi(args[++argidx].c_str());
564  continue;
565  }
566  if (args[argidx] == "-map" && argidx+1 < GetSize(args)) {
567  techmap_cmd += " -map " + args[++argidx];
568  continue;
569  }
570  if (args[argidx] == "-f" && argidx+1 < GetSize(args)) {
571  ilang_file = args[++argidx];
572  num_iter = 1;
573  continue;
574  }
575  if (args[argidx] == "-script" && argidx+1 < GetSize(args)) {
576  techmap_cmd = "script " + args[++argidx];
577  continue;
578  }
579  if (args[argidx] == "-simlib") {
580  techmap_cmd = "techmap -map +/simlib.v -max_iter 2 -autoproc";
581  continue;
582  }
583  if (args[argidx] == "-const") {
584  constmode = true;
585  continue;
586  }
587  if (args[argidx] == "-nosat") {
588  nosat = true;
589  continue;
590  }
591  if (args[argidx] == "-v") {
592  verbose = true;
593  continue;
594  }
595  if (args[argidx] == "-vlog" && argidx+1 < GetSize(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());
599  continue;
600  }
601  break;
602  }
603 
604  if (xorshift32_state == 0) {
605  xorshift32_state = time(NULL) & 0x7fffffff;
606  log("Rng seed value: %d\n", int(xorshift32_state));
607  }
608 
609  std::map<std::string, std::string> cell_types;
610  std::vector<std::string> selected_cell_types;
611 
612  cell_types["$not"] = "ASY";
613  cell_types["$pos"] = "ASY";
614  cell_types["$neg"] = "ASY";
615 
616  cell_types["$and"] = "ABSY";
617  cell_types["$or"] = "ABSY";
618  cell_types["$xor"] = "ABSY";
619  cell_types["$xnor"] = "ABSY";
620 
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";
626 
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";
633 
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";
642 
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";
649 
650  cell_types["$logic_not"] = "ASY";
651  cell_types["$logic_and"] = "ABSY";
652  cell_types["$logic_or"] = "ABSY";
653 
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";
659 
660  cell_types["$lut"] = "*";
661  cell_types["$alu"] = "ABSY";
662  cell_types["$lcu"] = "*";
663  cell_types["$macc"] = "*";
664  cell_types["$fa"] = "*";
665 
666  for (; argidx < GetSize(args); argidx++)
667  {
668  if (args[argidx].rfind("-", 0) == 0)
669  log_cmd_error("Unexpected option: %s\n", args[argidx].c_str());
670 
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);
675  continue;
676  }
677 
678  if (cell_types.count(args[argidx]) == 0) {
679  std::string cell_type_list;
680  int charcount = 100;
681  for (auto &it : cell_types) {
682  if (charcount > 60) {
683  cell_type_list += "\n" + it.first;
684  charcount = 0;
685  } else
686  cell_type_list += " " + it.first;
687  charcount += GetSize(it.first);
688  }
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());
691  }
692 
693  if (std::count(selected_cell_types.begin(), selected_cell_types.end(), args[argidx]) == 0)
694  selected_cell_types.push_back(args[argidx]);
695  }
696 
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");
701  }
702 
703  if (selected_cell_types.empty())
704  log_cmd_error("No cell type to test specified.\n");
705 
706  std::vector<std::string> uut_names;
707 
708  for (auto cell_type : selected_cell_types)
709  for (int i = 0; i < num_iter; i++)
710  {
711  RTLIL::Design *design = new RTLIL::Design;
712  if (cell_type == "ilang")
713  Frontend::frontend_call(design, NULL, std::string(), "ilang " + ilang_file);
714  else
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()));
717  if (!nosat)
718  Pass::call(design, "miter -equiv -flatten -make_outputs -ignore_gold_x gold gate miter");
719  if (verbose)
720  Pass::call(design, "dump gate");
721  Pass::call(design, "dump gold");
722  if (!nosat)
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);
731  }
732  run_eval_test(design, verbose, nosat, uut_name, vlog_file);
733  delete design;
734  }
735 
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";
745  }
746  }
747 } TestCellPass;
748 
void to_cell(RTLIL::Cell *cell) const
Definition: macc.h:152
void fixup_parameters(bool set_a_signed=false, bool set_b_signed=false)
Definition: rtlil.cc:1847
RTLIL::Wire * wire(RTLIL::IdString id)
Definition: rtlil.h:637
RTLIL::SigSpec bit_ports
Definition: macc.h:35
std::string stringf(const char *fmt,...)
Definition: yosys.cc:58
Definition: macc.h:27
RTLIL::Cell * addCell(RTLIL::IdString name, RTLIL::IdString type)
Definition: rtlil.cc:1353
void setParam(RTLIL::IdString paramname, RTLIL::Const value)
Definition: rtlil.cc:1829
RTLIL::Const as_const() const
Definition: rtlil.cc:2857
const char * log_signal(const RTLIL::SigSpec &sig, bool autoint)
Definition: log.cc:269
static void frontend_call(RTLIL::Design *design, std::istream *f, std::string filename, std::string command)
Definition: register.cc:375
void setPort(RTLIL::IdString portname, RTLIL::SigSpec signal)
Definition: rtlil.cc:1789
bool port_input
Definition: rtlil.h:827
bool eval(RTLIL::Cell *cell, RTLIL::SigSpec &undef)
Definition: consteval.h:89
int width
Definition: rtlil.h:826
std::vector< int > importSigSpec(RTLIL::SigSpec sig, int timestep=-1)
Definition: satgen.h:78
std::vector< port_t > ports
Definition: macc.h:34
void log_error(const char *format,...)
Definition: log.cc:204
RTLIL::Module * module
Definition: abc.cc:94
std::map< RTLIL::IdString, RTLIL::Const > parameters
Definition: rtlil.h:856
void clear()
Definition: consteval.h:55
bool model_undef
Definition: satgen.h:43
tuple n
Definition: fsm/generate.py:59
if(!(yy_init))
Definition: ilang_lexer.cc:846
std::vector< int > importUndefSigSpec(RTLIL::SigSpec sig, int timestep=-1)
Definition: satgen.h:92
bool port_output
Definition: rtlil.h:827
RTLIL::SigSpec in_b
Definition: macc.h:30
USING_YOSYS_NAMESPACE static PRIVATE_NAMESPACE_BEGIN uint32_t xorshift32_state
Definition: test_cell.cc:30
YOSYS_NAMESPACE_BEGIN typedef ezMiniSAT ezDefaultSAT
Definition: satgen.h:32
static void run_eval_test(RTLIL::Design *design, bool verbose, bool nosat, std::string uut_name, std::ofstream &vlog_file)
Definition: test_cell.cc:266
std::vector< RTLIL::IdString > ports
Definition: rtlil.h:617
static void backend_call(RTLIL::Design *design, std::ostream *f, std::string filename, std::string command)
Definition: register.cc:479
std::vector< int > importDefSigSpec(RTLIL::SigSpec sig, int timestep=-1)
Definition: satgen.h:85
std::string as_string() const
Definition: rtlil.cc:116
#define PRIVATE_NAMESPACE_BEGIN
Definition: yosys.h:97
const RTLIL::SigSpec & getPort(RTLIL::IdString portname) const
Definition: rtlil.cc:1809
static uint32_t xorshift32(uint32_t limit)
Definition: test_cell.cc:32
int GetSize(RTLIL::Wire *wire)
Definition: yosys.cc:334
void fixup_ports()
Definition: rtlil.cc:1312
#define log_assert(_assert_expr_)
Definition: log.h:85
RTLIL::Wire * addWire(RTLIL::IdString name, int width=1)
Definition: rtlil.cc:1331
bool is_signed
Definition: macc.h:31
#define PRIVATE_NAMESPACE_END
Definition: yosys.h:98
Definition: satgen.h:34
Definition: register.h:27
void log_cmd_error(const char *format,...)
Definition: log.cc:211
virtual void execute(std::vector< std::string > args, RTLIL::Design *)
Definition: test_cell.cc:544
RTLIL::Module * addModule(RTLIL::IdString name)
Definition: rtlil.cc:270
RTLIL::Module * module(RTLIL::IdString name)
Definition: rtlil.cc:254
void check()
Definition: rtlil.cc:1839
#define USING_YOSYS_NAMESPACE
Definition: yosys.h:102
RTLIL::ObjRange< RTLIL::Cell * > cells()
Definition: rtlil.h:641
RTLIL::SigSpec in_a
Definition: macc.h:30
#define NULL
virtual void help()
Definition: test_cell.cc:501
static void create_gold_module(RTLIL::Design *design, RTLIL::IdString cell_type, std::string cell_type_flags, bool constmode)
Definition: test_cell.cc:39
void log(const char *format,...)
Definition: log.cc:180
bool importCell(RTLIL::Cell *cell, int timestep=-1)
Definition: satgen.h:203
std::vector< RTLIL::State > bits
Definition: rtlil.h:438
std::string as_string() const
Definition: rtlil.cc:2840
void append(const RTLIL::SigSpec &signal)
Definition: rtlil.cc:2523
TestCellPass TestCellPass
void set(RTLIL::SigSpec sig, RTLIL::Const value)
Definition: consteval.h:72
static void call(RTLIL::Design *design, std::string command)
Definition: register.cc:146
const std::map< RTLIL::IdString, RTLIL::SigSpec > & connections() const
Definition: rtlil.cc:1814
bool do_subtract
Definition: macc.h:31
const char * log_id(RTLIL::IdString str)
Definition: log.cc:283