yosys-master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
test_cell.cc File Reference
#include "kernel/yosys.h"
#include "kernel/satgen.h"
#include "kernel/consteval.h"
#include "kernel/macc.h"
#include <algorithm>
+ Include dependency graph for test_cell.cc:

Go to the source code of this file.

Data Structures

struct  TestCellPass
 

Functions

static uint32_t xorshift32 (uint32_t limit)
 
static void create_gold_module (RTLIL::Design *design, RTLIL::IdString cell_type, std::string cell_type_flags, bool constmode)
 
static void run_eval_test (RTLIL::Design *design, bool verbose, bool nosat, std::string uut_name, std::ofstream &vlog_file)
 

Variables

USING_YOSYS_NAMESPACE static
PRIVATE_NAMESPACE_BEGIN
uint32_t 
xorshift32_state = 123456789
 
TestCellPass TestCellPass
 

Function Documentation

static void create_gold_module ( RTLIL::Design design,
RTLIL::IdString  cell_type,
std::string  cell_type_flags,
bool  constmode 
)
static

Definition at line 39 of file test_cell.cc.

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 }
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::SigSpec bit_ports
Definition: macc.h:35
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
void setPort(RTLIL::IdString portname, RTLIL::SigSpec signal)
Definition: rtlil.cc:1789
bool port_input
Definition: rtlil.h:827
int width
Definition: rtlil.h:826
std::vector< port_t > ports
Definition: macc.h:34
RTLIL::Module * module
Definition: abc.cc:94
std::map< RTLIL::IdString, RTLIL::Const > parameters
Definition: rtlil.h:856
tuple n
Definition: fsm/generate.py:59
if(!(yy_init))
Definition: ilang_lexer.cc:846
bool port_output
Definition: rtlil.h:827
RTLIL::SigSpec in_b
Definition: macc.h:30
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
RTLIL::Wire * addWire(RTLIL::IdString name, int width=1)
Definition: rtlil.cc:1331
bool is_signed
Definition: macc.h:31
RTLIL::Module * addModule(RTLIL::IdString name)
Definition: rtlil.cc:270
void check()
Definition: rtlil.cc:1839
RTLIL::SigSpec in_a
Definition: macc.h:30
void append(const RTLIL::SigSpec &signal)
Definition: rtlil.cc:2523
const std::map< RTLIL::IdString, RTLIL::SigSpec > & connections() const
Definition: rtlil.cc:1814
bool do_subtract
Definition: macc.h:31

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static void run_eval_test ( RTLIL::Design design,
bool  verbose,
bool  nosat,
std::string  uut_name,
std::ofstream &  vlog_file 
)
static

Definition at line 266 of file test_cell.cc.

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 }
RTLIL::Wire * wire(RTLIL::IdString id)
Definition: rtlil.h:637
std::string stringf(const char *fmt,...)
Definition: yosys.cc:58
const char * log_signal(const RTLIL::SigSpec &sig, bool autoint)
Definition: log.cc:269
bool port_input
Definition: rtlil.h:827
void log_error(const char *format,...)
Definition: log.cc:204
bool port_output
Definition: rtlil.h:827
YOSYS_NAMESPACE_BEGIN typedef ezMiniSAT ezDefaultSAT
Definition: satgen.h:32
std::vector< RTLIL::IdString > ports
Definition: rtlil.h:617
std::string as_string() const
Definition: rtlil.cc:116
static uint32_t xorshift32(uint32_t limit)
Definition: test_cell.cc:32
int GetSize(RTLIL::Wire *wire)
Definition: yosys.cc:334
#define log_assert(_assert_expr_)
Definition: log.h:85
Definition: satgen.h:34
RTLIL::Module * module(RTLIL::IdString name)
Definition: rtlil.cc:254
RTLIL::ObjRange< RTLIL::Cell * > cells()
Definition: rtlil.h:641
void log(const char *format,...)
Definition: log.cc:180
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
const char * log_id(RTLIL::IdString str)
Definition: log.cc:283

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static uint32_t xorshift32 ( uint32_t  limit)
static

Definition at line 32 of file test_cell.cc.

32  {
36  return xorshift32_state % limit;
37 }
USING_YOSYS_NAMESPACE static PRIVATE_NAMESPACE_BEGIN uint32_t xorshift32_state
Definition: test_cell.cc:30

+ Here is the caller graph for this function:

Variable Documentation

USING_YOSYS_NAMESPACE static PRIVATE_NAMESPACE_BEGIN uint32_t xorshift32_state = 123456789
static

Definition at line 30 of file test_cell.cc.