2 * yosys -- Yosys Open SYnthesis Suite
4 * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20 // [[CITE]] VlogHammer Verilog Regression Test Suite
21 // http://www.clifford.at/yosys/vloghammer.html
23 #include "kernel/register.h"
24 #include "kernel/celltypes.h"
25 #include "kernel/consteval.h"
26 #include "kernel/sigtools.h"
27 #include "kernel/satgen.h"
28 #include "kernel/log.h"
36 /* this should only be used for regression testing of ConstEval -- see vloghammer */
37 struct BruteForceEquivChecker
39 RTLIL::Module
*mod1
, *mod2
;
40 RTLIL::SigSpec mod1_inputs
, mod1_outputs
;
41 RTLIL::SigSpec mod2_inputs
, mod2_outputs
;
45 void run_checker(RTLIL::SigSpec
&inputs
)
47 if (inputs
.size() < mod1_inputs
.size()) {
48 RTLIL::SigSpec inputs0
= inputs
, inputs1
= inputs
;
49 inputs0
.append(RTLIL::Const(0, 1));
50 inputs1
.append(RTLIL::Const(1, 1));
58 ConstEval
ce1(mod1
), ce2(mod2
);
59 ce1
.set(mod1_inputs
, inputs
.as_const());
60 ce2
.set(mod2_inputs
, inputs
.as_const());
62 RTLIL::SigSpec sig1
= mod1_outputs
, undef1
;
63 RTLIL::SigSpec sig2
= mod2_outputs
, undef2
;
65 if (!ce1
.eval(sig1
, undef1
))
66 log("Failed ConstEval of module 1 outputs at signal %s (input: %s = %s).\n",
67 log_signal(undef1
), log_signal(mod1_inputs
), log_signal(inputs
));
68 if (!ce2
.eval(sig2
, undef2
))
69 log("Failed ConstEval of module 2 outputs at signal %s (input: %s = %s).\n",
70 log_signal(undef2
), log_signal(mod1_inputs
), log_signal(inputs
));
73 sig1
.expand(), sig2
.expand();
74 for (size_t i
= 0; i
< sig1
.chunks().size(); i
++)
75 if (sig1
.chunks().at(i
) == RTLIL::SigChunk(RTLIL::State::Sx
))
76 sig2
.chunks_rw().at(i
) = RTLIL::SigChunk(RTLIL::State::Sx
);
77 sig1
.optimize(), sig2
.optimize();
81 log("Found counter-example (ignore_x_mod1 = %s):\n", ignore_x_mod1
? "active" : "inactive");
82 log(" Module 1: %s = %s => %s = %s\n", log_signal(mod1_inputs
), log_signal(inputs
), log_signal(mod1_outputs
), log_signal(sig1
));
83 log(" Module 2: %s = %s => %s = %s\n", log_signal(mod2_inputs
), log_signal(inputs
), log_signal(mod2_outputs
), log_signal(sig2
));
90 BruteForceEquivChecker(RTLIL::Module
*mod1
, RTLIL::Module
*mod2
, bool ignore_x_mod1
) :
91 mod1(mod1
), mod2(mod2
), counter(0), errors(0), ignore_x_mod1(ignore_x_mod1
)
93 log("Checking for equivialence (brute-force): %s vs %s\n", mod1
->name
.c_str(), mod2
->name
.c_str());
94 for (auto &w
: mod1
->wires
)
96 RTLIL::Wire
*wire1
= w
.second
;
97 if (wire1
->port_id
== 0)
100 if (mod2
->wires
.count(wire1
->name
) == 0)
101 log_cmd_error("Port %s in module 1 has no counterpart in module 2!\n", wire1
->name
.c_str());
103 RTLIL::Wire
*wire2
= mod2
->wires
.at(wire1
->name
);
104 if (wire1
->width
!= wire2
->width
|| wire1
->port_input
!= wire2
->port_input
|| wire1
->port_output
!= wire2
->port_output
)
105 log_cmd_error("Port %s in module 1 does not match its counterpart in module 2!\n", wire1
->name
.c_str());
107 if (wire1
->port_input
) {
108 mod1_inputs
.append(wire1
);
109 mod2_inputs
.append(wire2
);
111 mod1_outputs
.append(wire1
);
112 mod2_outputs
.append(wire2
);
116 RTLIL::SigSpec inputs
;
121 /* this should only be used for regression testing of ConstEval -- see vloghammer */
122 struct VlogHammerReporter
124 RTLIL::Design
*design
;
125 std::vector
<RTLIL::Module
*> modules
;
126 std::vector
<std::string
> module_names
;
127 std::vector
<RTLIL::IdString
> inputs
;
128 std::vector
<int> input_widths
;
129 std::vector
<RTLIL::Const
> patterns
;
130 int total_input_width
;
132 std::vector
<std::string
> split(std::string text
, const char *delim
)
134 std::vector
<std::string
> list
;
135 char *p
= strdup(text
.c_str());
136 char *t
= strtok(p
, delim
);
139 t
= strtok(NULL
, delim
);
145 void sat_check(RTLIL::Module
*module
, RTLIL::SigSpec recorded_set_vars
, RTLIL::Const recorded_set_vals
, RTLIL::SigSpec expected_y
, bool model_undef
)
147 log("Verifying SAT model (%s)..\n", model_undef
? "with undef" : "without undef");
150 SigMap
sigmap(module
);
151 SatGen
satgen(&ez
, &sigmap
);
152 satgen
.model_undef
= model_undef
;
154 for (auto &c
: module
->cells
)
155 if (!satgen
.importCell(c
.second
))
156 log_error("Failed to import cell %s (type %s) to SAT database.\n", RTLIL::id2cstr(c
.first
), RTLIL::id2cstr(c
.second
->type
));
158 ez
.assume(satgen
.signals_eq(recorded_set_vars
, recorded_set_vals
));
160 std::vector
<int> y_vec
= satgen
.importDefSigSpec(module
->wires
.at("\\y"));
161 std::vector
<bool> y_values
;
164 std::vector
<int> y_undef_vec
= satgen
.importUndefSigSpec(module
->wires
.at("\\y"));
165 y_vec
.insert(y_vec
.end(), y_undef_vec
.begin(), y_undef_vec
.end());
168 log(" Created SAT problem with %d variables and %d clauses.\n",
169 ez
.numCnfVariables(), ez
.numCnfClauses());
171 if (!ez
.solve(y_vec
, y_values
))
172 log_error("Failed to find solution to SAT problem.\n");
175 for (int i
= 0; i
< expected_y
.size(); i
++) {
176 RTLIL::State solution_bit
= y_values
.at(i
) ? RTLIL::State::S1
: RTLIL::State::S0
;
177 RTLIL::State expected_bit
= expected_y
.chunks().at(i
).data
.bits
.at(0);
179 if (y_values
.at(expected_y
.size()+i
))
180 solution_bit
= RTLIL::State::Sx
;
182 if (expected_bit
== RTLIL::State::Sx
)
185 if (solution_bit
!= expected_bit
) {
186 std::string sat_bits
, rtl_bits
;
187 for (int k
= expected_y
.size()-1; k
>= 0; k
--) {
188 if (model_undef
&& y_values
.at(expected_y
.size()+k
))
191 sat_bits
+= y_values
.at(k
) ? "1" : "0";
192 rtl_bits
+= expected_y
.chunks().at(k
).data
.bits
.at(0) == RTLIL::State::Sx
? "x" :
193 expected_y
.chunks().at(k
).data
.bits
.at(0) == RTLIL::State::S1
? "1" : "0";
195 log_error("Found error in SAT model: y[%d] = %s, should be %s:\n SAT: %s\n RTL: %s\n %*s^\n",
196 int(i
), log_signal(solution_bit
), log_signal(expected_bit
),
197 sat_bits
.c_str(), rtl_bits
.c_str(), expected_y
.size()-i
-1, "");
203 std::vector
<int> cmp_vars
;
204 std::vector
<bool> cmp_vals
;
206 std::vector
<bool> y_undef(y_values
.begin() + expected_y
.size(), y_values
.end());
208 for (int i
= 0; i
< expected_y
.size(); i
++)
211 log(" Toggling undef bit %d to test undef gating.\n", i
);
212 if (!ez
.solve(y_vec
, y_values
, ez
.IFF(y_vec
.at(i
), y_values
.at(i
) ? ez
.FALSE
: ez
.TRUE
)))
213 log_error("Failed to find solution with toggled bit!\n");
215 cmp_vars
.push_back(y_vec
.at(expected_y
.size() + i
));
216 cmp_vals
.push_back(true);
220 cmp_vars
.push_back(y_vec
.at(i
));
221 cmp_vals
.push_back(y_values
.at(i
));
223 cmp_vars
.push_back(y_vec
.at(expected_y
.size() + i
));
224 cmp_vals
.push_back(false);
227 log(" Testing if SAT solution is unique.\n");
228 ez
.assume(ez
.vec_ne(cmp_vars
, ez
.vec_const(cmp_vals
)));
229 if (ez
.solve(y_vec
, y_values
))
230 log_error("Found two distinct solutions to SAT problem.\n");
234 log(" Testing if SAT solution is unique.\n");
235 ez
.assume(ez
.vec_ne(y_vec
, ez
.vec_const(y_values
)));
236 if (ez
.solve(y_vec
, y_values
))
237 log_error("Found two distinct solutions to SAT problem.\n");
240 log(" SAT model verified.\n");
245 for (int idx
= 0; idx
< int(patterns
.size()); idx
++)
247 log("Creating report for pattern %d: %s\n", idx
, log_signal(patterns
[idx
]));
248 std::string input_pattern_list
;
249 RTLIL::SigSpec rtl_sig
;
251 for (int mod
= 0; mod
< int(modules
.size()); mod
++)
253 RTLIL::SigSpec recorded_set_vars
;
254 RTLIL::Const recorded_set_vals
;
255 RTLIL::Module
*module
= modules
[mod
];
256 std::string module_name
= module_names
[mod
].c_str();
257 ConstEval
ce(module
);
259 std::vector
<RTLIL::State
> bits(patterns
[idx
].bits
.begin(), patterns
[idx
].bits
.begin() + total_input_width
);
260 for (int i
= 0; i
< int(inputs
.size()); i
++) {
261 RTLIL::Wire
*wire
= module
->wires
.at(inputs
[i
]);
262 for (int j
= input_widths
[i
]-1; j
>= 0; j
--) {
263 ce
.set(RTLIL::SigSpec(wire
, 1, j
), bits
.back());
264 recorded_set_vars
.append(RTLIL::SigSpec(wire
, 1, j
));
265 recorded_set_vals
.bits
.push_back(bits
.back());
268 if (module
== modules
.front()) {
269 RTLIL::SigSpec
sig(wire
);
271 log_error("Can't read back value for port %s!\n", RTLIL::id2cstr(inputs
[i
]));
272 input_pattern_list
+= stringf(" %s", sig
.as_const().as_string().c_str());
273 log("++PAT++ %d %s %s #\n", idx
, RTLIL::id2cstr(inputs
[i
]), sig
.as_const().as_string().c_str());
277 if (module
->wires
.count("\\y") == 0)
278 log_error("No output wire (y) found in module %s!\n", RTLIL::id2cstr(module
->name
));
280 RTLIL::SigSpec
sig(module
->wires
.at("\\y"));
281 RTLIL::SigSpec undef
;
283 while (!ce
.eval(sig
, undef
)) {
284 // log_error("Evaluation of y in module %s failed: sig=%s, undef=%s\n", RTLIL::id2cstr(module->name), log_signal(sig), log_signal(undef));
285 log("Warning: Setting signal %s in module %s to undef.\n", log_signal(undef
), RTLIL::id2cstr(module
->name
));
286 ce
.set(undef
, RTLIL::Const(RTLIL::State::Sx
, undef
.size()));
289 log("++VAL++ %d %s %s #\n", idx
, module_name
.c_str(), sig
.as_const().as_string().c_str());
291 if (module_name
== "rtl") {
294 sat_check(module
, recorded_set_vars
, recorded_set_vals
, sig
, false);
295 sat_check(module
, recorded_set_vars
, recorded_set_vals
, sig
, true);
296 } else if (rtl_sig
.size() > 0) {
298 if (rtl_sig
.size() != sig
.size())
299 log_error("Output (y) has a different width in module %s compared to rtl!\n", RTLIL::id2cstr(module
->name
));
300 for (int i
= 0; i
< sig
.size(); i
++)
301 if (rtl_sig
.chunks().at(i
).data
.bits
.at(0) == RTLIL::State::Sx
)
302 sig
.chunks_rw().at(i
).data
.bits
.at(0) = RTLIL::State::Sx
;
305 log("++RPT++ %d%s %s %s\n", idx
, input_pattern_list
.c_str(), sig
.as_const().as_string().c_str(), module_name
.c_str());
308 log("++RPT++ ----\n");
313 VlogHammerReporter(RTLIL::Design
*design
, std::string module_prefix
, std::string module_list
, std::string input_list
, std::string pattern_list
) : design(design
)
315 for (auto name
: split(module_list
, ",")) {
316 RTLIL::IdString esc_name
= RTLIL::escape_id(module_prefix
+ name
);
317 if (design
->modules
.count(esc_name
) == 0)
318 log_error("Can't find module %s in current design!\n", name
.c_str());
319 log("Using module %s (%s).\n", esc_name
.c_str(), name
.c_str());
320 modules
.push_back(design
->modules
.at(esc_name
));
321 module_names
.push_back(name
);
324 total_input_width
= 0;
325 for (auto name
: split(input_list
, ",")) {
327 RTLIL::IdString esc_name
= RTLIL::escape_id(name
);
328 for (auto mod
: modules
) {
329 if (mod
->wires
.count(esc_name
) == 0)
330 log_error("Can't find input %s in module %s!\n", name
.c_str(), RTLIL::id2cstr(mod
->name
));
331 RTLIL::Wire
*port
= mod
->wires
.at(esc_name
);
332 if (!port
->port_input
|| port
->port_output
)
333 log_error("Wire %s in module %s is not an input!\n", name
.c_str(), RTLIL::id2cstr(mod
->name
));
334 if (width
>= 0 && width
!= port
->width
)
335 log_error("Port %s has different sizes in the different modules!\n", name
.c_str());
338 log("Using input port %s with width %d.\n", esc_name
.c_str(), width
);
339 inputs
.push_back(esc_name
);
340 input_widths
.push_back(width
);
341 total_input_width
+= width
;
344 for (auto pattern
: split(pattern_list
, ",")) {
346 bool invert_pattern
= false;
347 if (pattern
.size() > 0 && pattern
[0] == '~') {
348 invert_pattern
= true;
349 pattern
= pattern
.substr(1);
351 if (!RTLIL::SigSpec::parse(sig
, NULL
, pattern
) || !sig
.is_fully_const())
352 log_error("Failed to parse pattern %s!\n", pattern
.c_str());
353 if (sig
.size() < total_input_width
)
354 log_error("Pattern %s is to short!\n", pattern
.c_str());
355 patterns
.push_back(sig
.as_const());
356 if (invert_pattern
) {
357 for (auto &bit
: patterns
.back().bits
)
358 if (bit
== RTLIL::State::S0
)
359 bit
= RTLIL::State::S1
;
360 else if (bit
== RTLIL::State::S1
)
361 bit
= RTLIL::State::S0
;
363 log("Using pattern %s.\n", patterns
.back().as_string().c_str());
370 struct EvalPass
: public Pass
{
371 EvalPass() : Pass("eval", "evaluate the circuit given an input") { }
374 // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
376 log(" eval [options] [selection]\n");
378 log("This command evaluates the value of a signal given the value of all required\n");
381 log(" -set <signal> <value>\n");
382 log(" set the specified signal to the specified value.\n");
384 log(" -set-undef\n");
385 log(" set all unspecified source signals to undef (x)\n");
387 log(" -table <signal>\n");
388 log(" create a truth table using the specified input signals\n");
390 log(" -show <signal>\n");
391 log(" show the value for the specified signal. if no -show option is passed\n");
392 log(" then all output ports of the current module are used.\n");
395 virtual void execute(std::vector
<std::string
> args
, RTLIL::Design
*design
)
397 std::vector
<std::pair
<std::string
, std::string
>> sets
;
398 std::vector
<std::string
> shows
, tables
;
399 bool set_undef
= false;
401 log_header("Executing EVAL pass (evaluate the circuit given an input).\n");
404 for (argidx
= 1; argidx
< args
.size(); argidx
++) {
405 if (args
[argidx
] == "-set" && argidx
+2 < args
.size()) {
406 std::string lhs
= args
[++argidx
].c_str();
407 std::string rhs
= args
[++argidx
].c_str();
408 sets
.push_back(std::pair
<std::string
, std::string
>(lhs
, rhs
));
411 if (args
[argidx
] == "-set-undef") {
415 if (args
[argidx
] == "-show" && argidx
+1 < args
.size()) {
416 shows
.push_back(args
[++argidx
]);
419 if (args
[argidx
] == "-table" && argidx
+1 < args
.size()) {
420 tables
.push_back(args
[++argidx
]);
423 if ((args
[argidx
] == "-brute_force_equiv_checker" || args
[argidx
] == "-brute_force_equiv_checker_x") && argidx
+3 == args
.size()) {
424 /* this should only be used for regression testing of ConstEval -- see vloghammer */
425 std::string mod1_name
= RTLIL::escape_id(args
[++argidx
]);
426 std::string mod2_name
= RTLIL::escape_id(args
[++argidx
]);
427 if (design
->modules
.count(mod1_name
) == 0)
428 log_error("Can't find module `%s'!\n", mod1_name
.c_str());
429 if (design
->modules
.count(mod2_name
) == 0)
430 log_error("Can't find module `%s'!\n", mod2_name
.c_str());
431 BruteForceEquivChecker
checker(design
->modules
.at(mod1_name
), design
->modules
.at(mod2_name
), args
[argidx
-2] == "-brute_force_equiv_checker_x");
432 if (checker
.errors
> 0)
433 log_cmd_error("Modules are not equivialent!\n");
434 log("Verified %s = %s (using brute-force check on %d cases).\n",
435 mod1_name
.c_str(), mod2_name
.c_str(), checker
.counter
);
438 if (args
[argidx
] == "-vloghammer_report" && argidx
+5 == args
.size()) {
439 /* this should only be used for regression testing of ConstEval -- see vloghammer */
440 std::string module_prefix
= args
[++argidx
];
441 std::string module_list
= args
[++argidx
];
442 std::string input_list
= args
[++argidx
];
443 std::string pattern_list
= args
[++argidx
];
444 VlogHammerReporter
reporter(design
, module_prefix
, module_list
, input_list
, pattern_list
);
450 extra_args(args
, argidx
, design
);
452 RTLIL::Module
*module
= NULL
;
453 for (auto &mod_it
: design
->modules
)
454 if (design
->selected(mod_it
.second
)) {
456 log_cmd_error("Only one module must be selected for the EVAL pass! (selected: %s and %s)\n",
457 RTLIL::id2cstr(module
->name
), RTLIL::id2cstr(mod_it
.first
));
458 module
= mod_it
.second
;
461 log_cmd_error("Can't perform EVAL on an empty selection!\n");
463 ConstEval
ce(module
);
465 for (auto &it
: sets
) {
466 RTLIL::SigSpec lhs
, rhs
;
467 if (!RTLIL::SigSpec::parse_sel(lhs
, design
, module
, it
.first
))
468 log_cmd_error("Failed to parse lhs set expression `%s'.\n", it
.first
.c_str());
469 if (!RTLIL::SigSpec::parse_rhs(lhs
, rhs
, module
, it
.second
))
470 log_cmd_error("Failed to parse rhs set expression `%s'.\n", it
.second
.c_str());
471 if (!rhs
.is_fully_const())
472 log_cmd_error("Right-hand-side set expression `%s' is not constant.\n", it
.second
.c_str());
473 if (lhs
.size() != rhs
.size())
474 log_cmd_error("Set expression with different lhs and rhs sizes: %s (%s, %d bits) vs. %s (%s, %d bits)\n",
475 it
.first
.c_str(), log_signal(lhs
), lhs
.size(), it
.second
.c_str(), log_signal(rhs
), rhs
.size());
476 ce
.set(lhs
, rhs
.as_const());
479 if (shows
.size() == 0) {
480 for (auto &it
: module
->wires
)
481 if (it
.second
->port_output
)
482 shows
.push_back(it
.second
->name
);
487 for (auto &it
: shows
) {
488 RTLIL::SigSpec signal
, value
, undef
;
489 if (!RTLIL::SigSpec::parse_sel(signal
, design
, module
, it
))
490 log_cmd_error("Failed to parse show expression `%s'.\n", it
.c_str());
494 while (!ce
.eval(value
, undef
)) {
495 log("Failed to evaluate signal %s: Missing value for %s. -> setting to undef\n", log_signal(signal
), log_signal(undef
));
496 ce
.set(undef
, RTLIL::Const(RTLIL::State::Sx
, undef
.size()));
497 undef
= RTLIL::SigSpec();
499 log("Eval result: %s = %s.\n", log_signal(signal
), log_signal(value
));
501 if (!ce
.eval(value
, undef
))
502 log("Failed to evaluate signal %s: Missing value for %s.\n", log_signal(signal
), log_signal(undef
));
504 log("Eval result: %s = %s.\n", log_signal(signal
), log_signal(value
));
510 RTLIL::SigSpec tabsigs
, signal
, value
, undef
;
511 std::vector
<std::vector
<std::string
>> tab
;
512 int tab_sep_colidx
= 0;
514 for (auto &it
: shows
) {
516 if (!RTLIL::SigSpec::parse_sel(sig
, design
, module
, it
))
517 log_cmd_error("Failed to parse show expression `%s'.\n", it
.c_str());
521 for (auto &it
: tables
) {
523 if (!RTLIL::SigSpec::parse_sel(sig
, design
, module
, it
))
524 log_cmd_error("Failed to parse table expression `%s'.\n", it
.c_str());
528 std::vector
<std::string
> tab_line
;
529 for (auto &c
: tabsigs
.chunks())
530 tab_line
.push_back(log_signal(c
));
531 tab_sep_colidx
= tab_line
.size();
532 for (auto &c
: signal
.chunks())
533 tab_line
.push_back(log_signal(c
));
534 tab
.push_back(tab_line
);
537 RTLIL::Const
tabvals(0, tabsigs
.size());
541 ce
.set(tabsigs
, tabvals
);
544 RTLIL::SigSpec this_undef
;
545 while (!ce
.eval(value
, this_undef
)) {
547 log("Failed to evaluate signal %s at %s = %s: Missing value for %s.\n", log_signal(signal
),
548 log_signal(tabsigs
), log_signal(tabvals
), log_signal(this_undef
));
551 ce
.set(this_undef
, RTLIL::Const(RTLIL::State::Sx
, this_undef
.size()));
552 undef
.append(this_undef
);
553 this_undef
= RTLIL::SigSpec();
557 for (auto &c
: tabsigs
.chunks()) {
558 tab_line
.push_back(log_signal(RTLIL::SigSpec(tabvals
).extract(pos
, c
.width
)));
563 for (auto &c
: signal
.chunks()) {
564 tab_line
.push_back(log_signal(value
.extract(pos
, c
.width
)));
568 tab
.push_back(tab_line
);
572 tabvals
= RTLIL::const_add(tabvals
, RTLIL::Const(1), false, false, tabvals
.bits
.size());
574 while (tabvals
.as_bool());
576 std::vector
<int> tab_column_width
;
577 for (auto &row
: tab
) {
578 if (tab_column_width
.size() < row
.size())
579 tab_column_width
.resize(row
.size());
580 for (size_t i
= 0; i
< row
.size(); i
++)
581 tab_column_width
[i
] = std::max(tab_column_width
[i
], int(row
[i
].size()));
586 for (auto &row
: tab
) {
587 for (size_t i
= 0; i
< row
.size(); i
++) {
588 int k
= int(i
) < tab_sep_colidx
? tab_sep_colidx
- i
- 1 : i
;
589 log(" %s%*s", k
== tab_sep_colidx
? "| " : "", tab_column_width
[k
], row
[k
].c_str());
593 for (size_t i
= 0; i
< row
.size(); i
++) {
594 int k
= int(i
) < tab_sep_colidx
? tab_sep_colidx
- i
- 1 : i
;
595 log(" %s", k
== tab_sep_colidx
? "| " : "");
596 for (int j
= 0; j
< tab_column_width
[k
]; j
++)
605 if (undef
.size() > 0) {
606 undef
.sort_and_unify();
607 log("Assumend undef (x) value for the following singals: %s\n\n", log_signal(undef
));