From 25ff27e37fcb12c6a298267eda2464431304d713 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 19 Jul 2019 12:34:04 -0700 Subject: [PATCH 01/29] SigSpec::extract to take negative lengths --- kernel/rtlil.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index a09f4a0d1..85b013bdc 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -3353,7 +3353,7 @@ RTLIL::SigSpec RTLIL::SigSpec::extract(int offset, int length) const { unpack(); cover("kernel.rtlil.sigspec.extract_pos"); - return std::vector(bits_.begin() + offset, bits_.begin() + offset + length); + return std::vector(bits_.begin() + offset, length >= 0 ? bits_.begin() + offset + length : bits_.end() + length + 1); } void RTLIL::SigSpec::append(const RTLIL::SigSpec &signal) From 3839bd50f28a16f1253a56d5871465763e72180c Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 19 Jul 2019 12:43:02 -0700 Subject: [PATCH 02/29] Add test --- tests/various/wreduce.ys | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 tests/various/wreduce.ys diff --git a/tests/various/wreduce.ys b/tests/various/wreduce.ys new file mode 100644 index 000000000..0b5403fa1 --- /dev/null +++ b/tests/various/wreduce.ys @@ -0,0 +1,22 @@ + +read_verilog < Date: Fri, 19 Jul 2019 12:50:11 -0700 Subject: [PATCH 03/29] Add tests for sub too --- tests/various/wreduce.ys | 49 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 48 insertions(+), 1 deletion(-) diff --git a/tests/various/wreduce.ys b/tests/various/wreduce.ys index 0b5403fa1..ee03e008d 100644 --- a/tests/various/wreduce.ys +++ b/tests/various/wreduce.ys @@ -5,7 +5,7 @@ module wreduce_add_test(input [3:0] i, input [7:0] j, output [7:0] o); endmodule EOT -hierarchy -top wreduce_add_test +hierarchy -auto-top proc design -save gold @@ -20,3 +20,50 @@ design -import gate -as gate miter -equiv -flatten -make_assert -make_outputs gold gate miter sat -verify -prove-asserts -show-ports miter + + +### X - 0 +read_verilog < Date: Fri, 19 Jul 2019 12:50:21 -0700 Subject: [PATCH 04/29] wreduce for $sub --- passes/opt/wreduce.cc | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/passes/opt/wreduce.cc b/passes/opt/wreduce.cc index 1fbc41082..e8c2cb726 100644 --- a/passes/opt/wreduce.cc +++ b/passes/opt/wreduce.cc @@ -365,6 +365,29 @@ struct WreduceWorker } } + if (cell->type.in("$add", "$sub")) { + SigSpec A = cell->getPort("\\A"); + SigSpec B = cell->getPort("\\B"); + bool sub = cell->type == "$sub"; + + int i; + for (i = 0; i < GetSize(sig); i++) { + if (B[i] != S0 && (sub || A[i] != S0)) + break; + if (B[i] == S0) + module->connect(sig[i], A[i]); + else if (A[i] == S0) + module->connect(sig[i], B[i]); + else log_abort(); + } + if (i > 0) { + cell->setPort("\\A", A.extract(i, -1)); + cell->setPort("\\B", B.extract(i, -1)); + sig.remove(0, i); + bits_removed += i; + } + } + if (GetSize(sig) == 0) { log("Removed cell %s.%s (%s).\n", log_id(module), log_id(cell), log_id(cell->type)); module->remove(cell); From 415a2716df8c41193650804158281ef73e7fc655 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 19 Jul 2019 12:53:18 -0700 Subject: [PATCH 05/29] Be more explicit --- tests/various/wreduce.ys | 35 +++++++++++++++++++++++++++++------ 1 file changed, 29 insertions(+), 6 deletions(-) diff --git a/tests/various/wreduce.ys b/tests/various/wreduce.ys index ee03e008d..f9e5ed4e3 100644 --- a/tests/various/wreduce.ys +++ b/tests/various/wreduce.ys @@ -1,6 +1,6 @@ read_verilog < Date: Fri, 19 Jul 2019 13:11:30 -0700 Subject: [PATCH 06/29] Add one more test with trimming Y_WIDTH of $sub --- tests/various/wreduce.ys | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/tests/various/wreduce.ys b/tests/various/wreduce.ys index f9e5ed4e3..8030c005e 100644 --- a/tests/various/wreduce.ys +++ b/tests/various/wreduce.ys @@ -9,7 +9,7 @@ hierarchy -auto-top proc design -save gold -prep +prep # calls wreduce select -assert-count 1 t:$add r:A_WIDTH=4 r:B_WIDTH=4 r:Y_WIDTH=5 %i %i %i @@ -21,8 +21,8 @@ design -import gate -as gate miter -equiv -flatten -make_assert -make_outputs gold gate miter sat -verify -prove-asserts -show-ports miter +########## -### X - 0 read_verilog <> 4) - i; endmodule EOT @@ -79,9 +81,10 @@ hierarchy -auto-top proc design -save gold -prep +prep # calls wreduce -select -assert-count 1 t:$sub r:A_WIDTH=8 r:B_WIDTH=8 r:Y_WIDTH=9 %i %i %i +dump +select -assert-count 1 t:$sub r:A_WIDTH=4 r:B_WIDTH=4 r:Y_WIDTH=5 %i %i %i design -stash gate From bcd802718256efbacaf0a73f99347af40b61e464 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 19 Jul 2019 13:11:48 -0700 Subject: [PATCH 07/29] Also optimise MSB of $sub --- passes/opt/wreduce.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/passes/opt/wreduce.cc b/passes/opt/wreduce.cc index e8c2cb726..dff1c5370 100644 --- a/passes/opt/wreduce.cc +++ b/passes/opt/wreduce.cc @@ -342,9 +342,9 @@ struct WreduceWorker } } - if (cell->type.in("$pos", "$add", "$mul", "$and", "$or", "$xor")) + if (cell->type.in("$pos", "$add", "$mul", "$and", "$or", "$xor", "$sub")) { - bool is_signed = cell->getParam("\\A_SIGNED").as_bool(); + bool is_signed = cell->getParam("\\A_SIGNED").as_bool() || cell->type == "$sub"; int a_size = 0, b_size = 0; if (cell->hasPort("\\A")) a_size = GetSize(cell->getPort("\\A")); @@ -352,7 +352,7 @@ struct WreduceWorker int max_y_size = max(a_size, b_size); - if (cell->type == "$add") + if (cell->type.in("$add", "$sub")) max_y_size++; if (cell->type == "$mul") From 31b0002e8c0e1b7a8ad054e02b1200c03461b581 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 19 Jul 2019 13:20:45 -0700 Subject: [PATCH 08/29] Remove "top" from message --- passes/opt/wreduce.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/passes/opt/wreduce.cc b/passes/opt/wreduce.cc index dff1c5370..23e14f7f5 100644 --- a/passes/opt/wreduce.cc +++ b/passes/opt/wreduce.cc @@ -395,7 +395,7 @@ struct WreduceWorker } if (bits_removed) { - log("Removed top %d bits (of %d) from port Y of cell %s.%s (%s).\n", + log("Removed %d bits (of %d) from port Y of cell %s.%s (%s).\n", bits_removed, GetSize(sig) + bits_removed, log_id(module), log_id(cell), log_id(cell->type)); cell->setPort("\\Y", sig); did_something = true; From 3a87dc35242598b6951fb70d4302ede60c2a96b2 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 19 Jul 2019 13:23:07 -0700 Subject: [PATCH 09/29] Wrap A and B in sigmap --- passes/opt/wreduce.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/passes/opt/wreduce.cc b/passes/opt/wreduce.cc index 23e14f7f5..294f0d57e 100644 --- a/passes/opt/wreduce.cc +++ b/passes/opt/wreduce.cc @@ -366,8 +366,8 @@ struct WreduceWorker } if (cell->type.in("$add", "$sub")) { - SigSpec A = cell->getPort("\\A"); - SigSpec B = cell->getPort("\\B"); + SigSpec A = mi.sigmap(cell->getPort("\\A")); + SigSpec B = mi.sigmap(cell->getPort("\\B")); bool sub = cell->type == "$sub"; int i; From 54708dfbd786032e841f48f15af4875c1eabbbfe Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 19 Jul 2019 13:54:57 -0700 Subject: [PATCH 10/29] Add an SigSpec::at(offset, defval) convenience method --- kernel/rtlil.h | 1 + 1 file changed, 1 insertion(+) diff --git a/kernel/rtlil.h b/kernel/rtlil.h index 82cbfaf28..f9412e776 100644 --- a/kernel/rtlil.h +++ b/kernel/rtlil.h @@ -818,6 +818,7 @@ public: operator std::vector() const { return chunks(); } operator std::vector() const { return bits(); } + RTLIL::SigBit at(int offset, const RTLIL::SigBit &defval) { return offset < width_ ? (*this)[offset] : defval; } unsigned int hash() const { if (!hash_) updhash(); return hash_; }; From cb0fd0521531a69632102f5fad8cdc9996ed4dee Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 19 Jul 2019 13:58:50 -0700 Subject: [PATCH 11/29] Do not access beyond bounds --- passes/opt/wreduce.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/passes/opt/wreduce.cc b/passes/opt/wreduce.cc index 294f0d57e..908a85d5b 100644 --- a/passes/opt/wreduce.cc +++ b/passes/opt/wreduce.cc @@ -372,7 +372,7 @@ struct WreduceWorker int i; for (i = 0; i < GetSize(sig); i++) { - if (B[i] != S0 && (sub || A[i] != S0)) + if (B.at(i, Sx) != S0 && (sub || A.at(i, Sx) != S0)) break; if (B[i] == S0) module->connect(sig[i], A[i]); From c926eeb43a9c42a0ecc34871f383f4181b7a45f9 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 19 Jul 2019 14:02:46 -0700 Subject: [PATCH 12/29] Add another test --- tests/various/wreduce.ys | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/tests/various/wreduce.ys b/tests/various/wreduce.ys index 8030c005e..deb99304d 100644 --- a/tests/various/wreduce.ys +++ b/tests/various/wreduce.ys @@ -83,7 +83,6 @@ design -save gold prep # calls wreduce -dump select -assert-count 1 t:$sub r:A_WIDTH=4 r:B_WIDTH=4 r:Y_WIDTH=5 %i %i %i design -stash gate @@ -93,3 +92,27 @@ design -import gate -as gate miter -equiv -flatten -make_assert -make_outputs gold gate miter sat -verify -prove-asserts -show-ports miter + +########## + +read_verilog < Date: Fri, 19 Jul 2019 14:40:57 -0700 Subject: [PATCH 13/29] Try and fix again --- passes/opt/wreduce.cc | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/passes/opt/wreduce.cc b/passes/opt/wreduce.cc index 908a85d5b..22af0bd8b 100644 --- a/passes/opt/wreduce.cc +++ b/passes/opt/wreduce.cc @@ -372,13 +372,12 @@ struct WreduceWorker int i; for (i = 0; i < GetSize(sig); i++) { - if (B.at(i, Sx) != S0 && (sub || A.at(i, Sx) != S0)) - break; - if (B[i] == S0) + if (B.at(i, Sx) == S0 && A.at(i, Sx) != Sx) module->connect(sig[i], A[i]); - else if (A[i] == S0) + else if (!sub && A.at(i, Sx) == S0 && B.at(i, Sx) != Sx) module->connect(sig[i], B[i]); - else log_abort(); + else + break; } if (i > 0) { cell->setPort("\\A", A.extract(i, -1)); From 3b8c917025e1be9695468588082e9175e918c9e9 Mon Sep 17 00:00:00 2001 From: Jim Lawson Date: Wed, 31 Jul 2019 09:27:38 -0700 Subject: [PATCH 14/29] Support explicit FIRRTL properties for better accommodation of FIRRTL/Verilog semantic differences. Use FIRRTL spec vlaues for definition of FIRRTL widths. Added support for '$pos`, `$pow` and `$xnor` cells. Enable tests/simple/operators.v since all operators tested there are now supported. Disable FIRRTL tests of tests/simple/{defvalue.sv,implicit_ports.v,wandwor.v} since they currently generate FIRRTL compilation errors. --- backends/firrtl/firrtl.cc | 302 ++++++++++++++++++++++++++------------ tests/simple/xfirrtl | 4 +- 2 files changed, 209 insertions(+), 97 deletions(-) diff --git a/backends/firrtl/firrtl.cc b/backends/firrtl/firrtl.cc index 1c7a7351f..9ef6e311a 100644 --- a/backends/firrtl/firrtl.cc +++ b/backends/firrtl/firrtl.cc @@ -381,10 +381,10 @@ struct FirrtlWorker // Given an expression for a shift amount, and a maximum width, // generate the FIRRTL expression for equivalent dynamic shift taking into account FIRRTL shift semantics. - std::string gen_dshl(const string b_expr, const int b_padded_width) + std::string gen_dshl(const string b_expr, const int b_width) { string result = b_expr; - if (b_padded_width >= FIRRTL_MAX_DSH_WIDTH_ERROR) { + if (b_width >= FIRRTL_MAX_DSH_WIDTH_ERROR) { int max_shift_width_bits = FIRRTL_MAX_DSH_WIDTH_ERROR - 1; string max_shift_string = stringf("UInt<%d>(%d)", max_shift_width_bits, (1<cells()) { - bool extract_y_bits = false; // Assume no extraction of final bits will be required. + static Const ndef(0, 0); + // Is this cell is a module instance? if (cell->type[0] != '$') { process_instance(cell, wire_exprs); continue; } + // Not a module instance. Set up cell properties + bool extract_y_bits = false; // Assume no extraction of final bits will be required. + int a_width = cell->parameters.at("\\A_WIDTH", ndef).as_int(); // The width of "A" + int b_width = cell->parameters.at("\\B_WIDTH", ndef).as_int(); // The width of "A" + const int y_width = cell->parameters.at("\\Y_WIDTH", ndef).as_int(); // The width of the result + const bool a_signed = cell->parameters.at("\\A_SIGNED", ndef).as_bool(); + const bool b_signed = cell->parameters.at("\\B_SIGNED", ndef).as_bool(); + bool firrtl_is_signed = a_signed; // The result is signed (subsequent code may change this). + int firrtl_width = 0; + string primop; + bool always_uint = false; + string y_id = make_id(cell->name); + if (cell->type.in("$not", "$logic_not", "$neg", "$reduce_and", "$reduce_or", "$reduce_xor", "$reduce_bool", "$reduce_xnor")) { - string y_id = make_id(cell->name); - bool is_signed = cell->parameters.at("\\A_SIGNED").as_bool(); - int y_width = cell->parameters.at("\\Y_WIDTH").as_int(); string a_expr = make_expr(cell->getPort("\\A")); wire_decls.push_back(stringf(" wire %s: UInt<%d>\n", y_id.c_str(), y_width)); - if (cell->parameters.at("\\A_SIGNED").as_bool()) { + if (a_signed) { a_expr = "asSInt(" + a_expr + ")"; } @@ -446,12 +457,13 @@ struct FirrtlWorker a_expr = stringf("pad(%s, %d)", a_expr.c_str(), y_width); } - string primop; - bool always_uint = false; + // Assume the FIRRTL width is a single bit. + firrtl_width = 1; if (cell->type == "$not") primop = "not"; else if (cell->type == "$neg") { primop = "neg"; - is_signed = true; // Result of "neg" is signed (an SInt). + firrtl_is_signed = true; // Result of "neg" is signed (an SInt). + firrtl_width = a_width; } else if (cell->type == "$logic_not") { primop = "eq"; a_expr = stringf("%s, UInt(0)", a_expr.c_str()); @@ -466,14 +478,12 @@ struct FirrtlWorker else if (cell->type == "$reduce_bool") { primop = "neq"; // Use the sign of the a_expr and its width as the type (UInt/SInt) and width of the comparand. - bool a_signed = cell->parameters.at("\\A_SIGNED").as_bool(); - int a_width = cell->parameters.at("\\A_WIDTH").as_int(); a_expr = stringf("%s, %cInt<%d>(0)", a_expr.c_str(), a_signed ? 'S' : 'U', a_width); } string expr = stringf("%s(%s)", primop.c_str(), a_expr.c_str()); - if ((is_signed && !always_uint)) + if ((firrtl_is_signed && !always_uint)) expr = stringf("asUInt(%s)", expr.c_str()); cell_exprs.push_back(stringf(" %s <= %s\n", y_id.c_str(), expr.c_str())); @@ -481,81 +491,121 @@ struct FirrtlWorker continue; } - if (cell->type.in("$add", "$sub", "$mul", "$div", "$mod", "$xor", "$and", "$or", "$eq", "$eqx", + if (cell->type.in("$add", "$sub", "$mul", "$div", "$mod", "$xor", "$xnor", "$and", "$or", "$eq", "$eqx", "$gt", "$ge", "$lt", "$le", "$ne", "$nex", "$shr", "$sshr", "$sshl", "$shl", - "$logic_and", "$logic_or")) + "$logic_and", "$logic_or", "$pow")) { - string y_id = make_id(cell->name); - bool is_signed = cell->parameters.at("\\A_SIGNED").as_bool(); - int y_width = cell->parameters.at("\\Y_WIDTH").as_int(); string a_expr = make_expr(cell->getPort("\\A")); string b_expr = make_expr(cell->getPort("\\B")); - int b_padded_width = cell->parameters.at("\\B_WIDTH").as_int(); wire_decls.push_back(stringf(" wire %s: UInt<%d>\n", y_id.c_str(), y_width)); - if (cell->parameters.at("\\A_SIGNED").as_bool()) { + if (a_signed) { a_expr = "asSInt(" + a_expr + ")"; - } - // Shift amount is always unsigned, and needn't be padded to result width. - if (!cell->type.in("$shr", "$sshr", "$shl", "$sshl")) { - if (cell->parameters.at("\\B_SIGNED").as_bool()) { - b_expr = "asSInt(" + b_expr + ")"; + // Expand the "A" operand to the result width + if (a_width < y_width) { + a_expr = stringf("pad(%s, %d)", a_expr.c_str(), y_width); + a_width = y_width; } - if (b_padded_width < y_width) { - auto b_sig = cell->getPort("\\B"); - b_padded_width = y_width; + } + // Shift amount is always unsigned, and needn't be padded to result width, + // otherwise, we need to cast the b_expr appropriately + if (b_signed && !cell->type.in("$shr", "$sshr", "$shl", "$sshl", "$pow")) { + b_expr = "asSInt(" + b_expr + ")"; + // Expand the "B" operand to the result width + if (b_width < y_width) { + b_expr = stringf("pad(%s, %d)", b_expr.c_str(), y_width); + b_width = y_width; } } + // For the arithmetic ops, expand operand widths to result widths befor performing the operation. + // This corresponds (according to iverilog) to what verilog compilers implement. + if (cell->type.in("$add", "$sub", "$mul", "$div", "$mod", "$xor", "$xnor", "$and", "$or")) + { + if (a_width < y_width) { + a_expr = stringf("pad(%s, %d)", a_expr.c_str(), y_width); + a_width = y_width; + } + if (b_width < y_width) { + b_expr = stringf("pad(%s, %d)", b_expr.c_str(), y_width); + b_width = y_width; + } + } + // Assume the FIRRTL width is the width of "A" + firrtl_width = a_width; auto a_sig = cell->getPort("\\A"); - if (cell->parameters.at("\\A_SIGNED").as_bool() & (cell->type == "$shr")) { - a_expr = "asUInt(" + a_expr + ")"; + if (cell->type == "$add") { + primop = "add"; + firrtl_is_signed = a_signed | b_signed; + firrtl_width = max(a_width, b_width); + } else if (cell->type == "$sub") { + primop = "sub"; + firrtl_is_signed = true; + int a_widthInc = (!a_signed && b_signed) ? 2 : (a_signed && !b_signed) ? 1 : 0; + int b_widthInc = (a_signed && !b_signed) ? 2 : (!a_signed && b_signed) ? 1 : 0; + firrtl_width = max(a_width + a_widthInc, b_width + b_widthInc); + } else if (cell->type == "$mul") { + primop = "mul"; + firrtl_is_signed = a_signed | b_signed; + firrtl_width = a_width + b_width; + } else if (cell->type == "$div") { + primop = "div"; + firrtl_is_signed = a_signed | b_signed; + firrtl_width = a_width; + } else if (cell->type == "$mod") { + primop = "rem"; + firrtl_width = min(a_width, b_width); + } else if (cell->type == "$and") { + primop = "and"; + always_uint = true; + firrtl_width = max(a_width, b_width); } - - string primop; - bool always_uint = false; - if (cell->type == "$add") primop = "add"; - else if (cell->type == "$sub") primop = "sub"; - else if (cell->type == "$mul") primop = "mul"; - else if (cell->type == "$div") primop = "div"; - else if (cell->type == "$mod") primop = "rem"; - else if (cell->type == "$and") { - primop = "and"; - always_uint = true; - } else if (cell->type == "$or" ) { - primop = "or"; - always_uint = true; - } + primop = "or"; + always_uint = true; + firrtl_width = max(a_width, b_width); + } else if (cell->type == "$xor") { - primop = "xor"; - always_uint = true; - } + primop = "xor"; + always_uint = true; + firrtl_width = max(a_width, b_width); + } + else if (cell->type == "$xnor") { + primop = "xnor"; + always_uint = true; + firrtl_width = max(a_width, b_width); + } else if ((cell->type == "$eq") | (cell->type == "$eqx")) { - primop = "eq"; - always_uint = true; - } + primop = "eq"; + always_uint = true; + firrtl_width = 1; + } else if ((cell->type == "$ne") | (cell->type == "$nex")) { - primop = "neq"; - always_uint = true; - } + primop = "neq"; + always_uint = true; + firrtl_width = 1; + } else if (cell->type == "$gt") { - primop = "gt"; - always_uint = true; - } + primop = "gt"; + always_uint = true; + firrtl_width = 1; + } else if (cell->type == "$ge") { - primop = "geq"; - always_uint = true; - } + primop = "geq"; + always_uint = true; + firrtl_width = 1; + } else if (cell->type == "$lt") { - primop = "lt"; - always_uint = true; - } + primop = "lt"; + always_uint = true; + firrtl_width = 1; + } else if (cell->type == "$le") { - primop = "leq"; - always_uint = true; - } + primop = "leq"; + always_uint = true; + firrtl_width = 1; + } else if ((cell->type == "$shl") | (cell->type == "$sshl")) { // FIRRTL will widen the result (y) by the amount of the shift. // We'll need to offset this by extracting the un-widened portion as Verilog would do. @@ -564,11 +614,14 @@ struct FirrtlWorker auto b_sig = cell->getPort("\\B"); if (b_sig.is_fully_const()) { primop = "shl"; - b_expr = std::to_string(b_sig.as_int()); + int shift_amount = b_sig.as_int(); + b_expr = std::to_string(shift_amount); + firrtl_width = a_width + shift_amount; } else { primop = "dshl"; // Convert from FIRRTL left shift semantics. - b_expr = gen_dshl(b_expr, b_padded_width); + b_expr = gen_dshl(b_expr, b_width); + firrtl_width = a_width + (1 << b_width) - 1; } } else if ((cell->type == "$shr") | (cell->type == "$sshr")) { @@ -578,36 +631,86 @@ struct FirrtlWorker auto b_sig = cell->getPort("\\B"); if (b_sig.is_fully_const()) { primop = "shr"; - b_expr = std::to_string(b_sig.as_int()); + int shift_amount = b_sig.as_int(); + b_expr = std::to_string(shift_amount); + firrtl_width = max(1, a_width - shift_amount); } else { primop = "dshr"; + firrtl_width = a_width; + } + // We'll need to do some special fixups if the source (and thus result) is signed. + if (firrtl_is_signed) { + // If this is a "logical" shift right, pretend the source is unsigned. + if (cell->type == "$shr") { + a_expr = "asUInt(" + a_expr + ")"; + } } } else if ((cell->type == "$logic_and")) { - primop = "and"; - a_expr = "neq(" + a_expr + ", UInt(0))"; - b_expr = "neq(" + b_expr + ", UInt(0))"; - always_uint = true; - } + primop = "and"; + a_expr = "neq(" + a_expr + ", UInt(0))"; + b_expr = "neq(" + b_expr + ", UInt(0))"; + always_uint = true; + firrtl_width = 1; + } else if ((cell->type == "$logic_or")) { - primop = "or"; - a_expr = "neq(" + a_expr + ", UInt(0))"; - b_expr = "neq(" + b_expr + ", UInt(0))"; - always_uint = true; - } + primop = "or"; + a_expr = "neq(" + a_expr + ", UInt(0))"; + b_expr = "neq(" + b_expr + ", UInt(0))"; + always_uint = true; + firrtl_width = 1; + } + else if ((cell->type == "$pow")) { + if (a_sig.is_fully_const() && a_sig.as_int() == 2) { + // We'll convert this to a shift. To simplify things, change the a_expr to "1" + // so we can use b_expr directly as a shift amount. + // Only support 2 ** N (i.e., shift left) + // FIRRTL will widen the result (y) by the amount of the shift. + // We'll need to offset this by extracting the un-widened portion as Verilog would do. + a_expr = firrtl_is_signed ? "SInt(1)" : "UInt(1)"; + extract_y_bits = true; + // Is the shift amount constant? + auto b_sig = cell->getPort("\\B"); + if (b_sig.is_fully_const()) { + primop = "shl"; + int shiftAmount = b_sig.as_int(); + if (shiftAmount < 0) { + log_error("Negative power exponent - %d: %s.%s\n", shiftAmount, log_id(module), log_id(cell)); + } + b_expr = std::to_string(shiftAmount); + firrtl_width = a_width + shiftAmount; + } else { + primop = "dshl"; + // Convert from FIRRTL left shift semantics. + b_expr = gen_dshl(b_expr, b_width); + firrtl_width = a_width + (1 << b_width) - 1; + } + } else { + log_error("Non power 2: %s.%s\n", log_id(module), log_id(cell)); + } + } if (!cell->parameters.at("\\B_SIGNED").as_bool()) { b_expr = "asUInt(" + b_expr + ")"; } - string expr = stringf("%s(%s, %s)", primop.c_str(), a_expr.c_str(), b_expr.c_str()); - - // Deal with FIRRTL's "shift widens" semantics - if (extract_y_bits) { - expr = stringf("bits(%s, %d, 0)", expr.c_str(), y_width - 1); + string expr; + // Deal with $xnor == ~^ (not xor) + if (primop == "xnor") { + expr = stringf("not(xor(%s, %s))", a_expr.c_str(), b_expr.c_str()); + } else { + expr = stringf("%s(%s, %s)", primop.c_str(), a_expr.c_str(), b_expr.c_str()); } - if ((is_signed && !always_uint) || cell->type.in("$sub")) + // Deal with FIRRTL's "shift widens" semantics, or the need to widen the FIRRTL result. + // If the operation is signed, the FIRRTL width will be 1 one bit larger. + if (extract_y_bits) { + expr = stringf("bits(%s, %d, 0)", expr.c_str(), y_width - 1); + } else if (firrtl_is_signed && (firrtl_width + 1) < y_width) { + expr = stringf("pad(%s, %d)", expr.c_str(), y_width); + } + + if ((firrtl_is_signed && !always_uint)) expr = stringf("asUInt(%s)", expr.c_str()); cell_exprs.push_back(stringf(" %s <= %s\n", y_id.c_str(), expr.c_str())); @@ -618,7 +721,6 @@ struct FirrtlWorker if (cell->type.in("$mux")) { - string y_id = make_id(cell->name); int width = cell->parameters.at("\\WIDTH").as_int(); string a_expr = make_expr(cell->getPort("\\A")); string b_expr = make_expr(cell->getPort("\\B")); @@ -762,15 +864,14 @@ struct FirrtlWorker if (clkpol == false) log_error("Negative edge clock on FF %s.%s.\n", log_id(module), log_id(cell)); - string q_id = make_id(cell->name); int width = cell->parameters.at("\\WIDTH").as_int(); string expr = make_expr(cell->getPort("\\D")); string clk_expr = "asClock(" + make_expr(cell->getPort("\\CLK")) + ")"; - wire_decls.push_back(stringf(" reg %s: UInt<%d>, %s\n", q_id.c_str(), width, clk_expr.c_str())); + wire_decls.push_back(stringf(" reg %s: UInt<%d>, %s\n", y_id.c_str(), width, clk_expr.c_str())); - cell_exprs.push_back(stringf(" %s <= %s\n", q_id.c_str(), expr.c_str())); - register_reverse_wire_map(q_id, cell->getPort("\\Q")); + cell_exprs.push_back(stringf(" %s <= %s\n", y_id.c_str(), expr.c_str())); + register_reverse_wire_map(y_id, cell->getPort("\\Q")); continue; } @@ -785,8 +886,6 @@ struct FirrtlWorker // assign y = a[b +: y_width]; // We'll extract the correct bits as part of the primop. - string y_id = make_id(cell->name); - int y_width = cell->parameters.at("\\Y_WIDTH").as_int(); string a_expr = make_expr(cell->getPort("\\A")); // Get the initial bit selector string b_expr = make_expr(cell->getPort("\\B")); @@ -808,18 +907,15 @@ struct FirrtlWorker // assign y = a >> b; // where b may be negative - string y_id = make_id(cell->name); - int y_width = cell->parameters.at("\\Y_WIDTH").as_int(); string a_expr = make_expr(cell->getPort("\\A")); string b_expr = make_expr(cell->getPort("\\B")); auto b_string = b_expr.c_str(); - int b_padded_width = cell->parameters.at("\\B_WIDTH").as_int(); string expr; wire_decls.push_back(stringf(" wire %s: UInt<%d>\n", y_id.c_str(), y_width)); if (cell->getParam("\\B_SIGNED").as_bool()) { // We generate a left or right shift based on the sign of b. - std::string dshl = stringf("bits(dshl(%s, %s), 0, %d)", a_expr.c_str(), gen_dshl(b_expr, b_padded_width).c_str(), y_width); + std::string dshl = stringf("bits(dshl(%s, %s), 0, %d)", a_expr.c_str(), gen_dshl(b_expr, b_width).c_str(), y_width); std::string dshr = stringf("dshr(%s, %s)", a_expr.c_str(), b_string); expr = stringf("mux(%s < 0, %s, %s)", b_string, @@ -833,6 +929,20 @@ struct FirrtlWorker register_reverse_wire_map(y_id, cell->getPort("\\Y")); continue; } + if (cell->type == "$pos") { + // assign y = a; +// printCell(cell); + string a_expr = make_expr(cell->getPort("\\A")); + // Verilog appears to treat the result as signed, so if the result is wider than "A", + // we need to pad. + if (a_width < y_width) { + a_expr = stringf("pad(%s, %d)", a_expr.c_str(), y_width); + } + wire_decls.push_back(stringf(" wire %s: UInt<%d>\n", y_id.c_str(), y_width)); + cell_exprs.push_back(stringf(" %s <= %s\n", y_id.c_str(), a_expr.c_str())); + register_reverse_wire_map(y_id, cell->getPort("\\Y")); + continue; + } log_warning("Cell type not supported: %s (%s.%s)\n", log_id(cell->type), log_id(module), log_id(cell)); } diff --git a/tests/simple/xfirrtl b/tests/simple/xfirrtl index ba61a4476..10063d2c2 100644 --- a/tests/simple/xfirrtl +++ b/tests/simple/xfirrtl @@ -1,10 +1,12 @@ # This file contains the names of verilog files to exclude from verilog to FIRRTL regression tests due to known failures. arraycells.v inst id[0] of +defvalue.sv Initial value not supported dff_different_styles.v dff_init.v Initial value not supported generate.v combinational loop hierdefparam.v inst id[0] of i2c_master_tests.v $adff +implicit_ports.v not fully initialized macros.v drops modules mem2reg.v drops modules mem_arst.v $adff @@ -12,7 +14,6 @@ memory.v $adff multiplier.v inst id[0] of muxtree.v drops modules omsp_dbg_uart.v $adff -operators.v $pow partsel.v drops modules process.v drops modules realexpr.v drops modules @@ -23,5 +24,6 @@ specify.v no code (empty module generates error subbytes.v $adff task_func.v drops modules values.v combinational loop +wandwor.v Invalid connect to an expression that is not a reference or a WritePort. vloghammer.v combinational loop wreduce.v original verilog issues ( -x where x isn't declared signed) From 15fae357f6c7a5c205d2733cd0b2640eecd17a2d Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 1 Aug 2019 12:34:52 +0200 Subject: [PATCH 15/29] Implement improved JSON attr/param encoding Signed-off-by: Clifford Wolf --- backends/json/json.cc | 50 ++++++++++++++++++++++++++++++++----------- 1 file changed, 37 insertions(+), 13 deletions(-) diff --git a/backends/json/json.cc b/backends/json/json.cc index dda4dfedd..107009ee4 100644 --- a/backends/json/json.cc +++ b/backends/json/json.cc @@ -83,20 +83,43 @@ struct JsonWriter return str + " ]"; } + void write_parameter_value(const Const &value) + { + if ((value.flags & RTLIL::ConstFlags::CONST_FLAG_STRING) != 0) { + string str = value.decode_string(); + int state = 0; + for (char c : str) { + if (state == 0) { + if (c == '0' || c == '1' || c == 'x' || c == 'z') + state = 0; + else if (c == ' ') + state = 1; + else + state = 2; + } else if (state == 1 && c != ' ') + state = 2; + } + if (state < 2) + str += " "; + f << get_string(str); + } else + if (GetSize(value) == 32 && value.is_fully_def()) { + if ((value.flags & RTLIL::ConstFlags::CONST_FLAG_SIGNED) != 0) + f << stringf("%d", value.as_int()); + else + f << stringf("%u", value.as_int()); + } else { + f << get_string(value.as_string()); + } + } + void write_parameters(const dict ¶meters, bool for_module=false) { bool first = true; for (auto ¶m : parameters) { f << stringf("%s\n", first ? "" : ","); f << stringf(" %s%s: ", for_module ? "" : " ", get_name(param.first).c_str()); - if ((param.second.flags & RTLIL::ConstFlags::CONST_FLAG_STRING) != 0) - f << get_string(param.second.decode_string()); - else if (GetSize(param.second.bits) > 32) - f << get_string(param.second.as_string()); - else if ((param.second.flags & RTLIL::ConstFlags::CONST_FLAG_SIGNED) != 0) - f << stringf("%d", param.second.as_int()); - else - f << stringf("%u", param.second.as_int()); + write_parameter_value(param.second); first = false; } } @@ -342,12 +365,13 @@ struct JsonBackend : public Backend { log("Module and cell ports and nets can be single bit wide or vectors of multiple\n"); log("bits. Each individual signal bit is assigned a unique integer. The \n"); log("values referenced above are vectors of this integers. Signal bits that are\n"); - log("connected to a constant driver are denoted as string \"0\" or \"1\" instead of\n"); - log("a number.\n"); + log("connected to a constant driver are denoted as string \"0\", \"1\", \"x\", or\n"); + log("\"z\" instead of a number.\n"); log("\n"); - log("Numeric parameter and attribute values up to 32 bits are written as decimal\n"); - log("values. Numbers larger than that are written as string holding the binary\n"); - log("representation of the value.\n"); + log("Numeric 32-bit parameter and attribute values are written as decimal values.\n"); + log("Bit verctors of different sizes, or ones containing 'x' or 'z' bits, are written\n"); + log("as string holding the binary representation of the value. Strings are written\n"); + log("as strings, with an appended blank in cases of strings of the form /[01xz]* */.\n"); log("\n"); log("For example the following Verilog code:\n"); log("\n"); From 292f03355a425ede48051c79d5bf619591531080 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 1 Aug 2019 12:48:22 +0200 Subject: [PATCH 16/29] Update JSON front-end to process new attr/param encoding Signed-off-by: Clifford Wolf --- frontends/json/jsonparse.cc | 57 ++++++++++++++++++++++--------------- 1 file changed, 34 insertions(+), 23 deletions(-) diff --git a/frontends/json/jsonparse.cc b/frontends/json/jsonparse.cc index f5ae8eb72..7aceffbfc 100644 --- a/frontends/json/jsonparse.cc +++ b/frontends/json/jsonparse.cc @@ -25,7 +25,7 @@ struct JsonNode { char type; // S=String, N=Number, A=Array, D=Dict string data_string; - int data_number; + int64_t data_number; vector data_array; dict data_dict; vector data_dict_keys; @@ -206,6 +206,38 @@ struct JsonNode } }; +Const json_parse_attr_param_value(JsonNode *node) +{ + Const value; + + if (node->type == 'S') { + string &s = node->data_string; + size_t cursor = s.find_first_not_of("01xz"); + if (cursor == string::npos) { + value = Const::from_string(s); + } else if (s.find_first_not_of(' ', cursor) == string::npos) { + value = Const(s.substr(0, GetSize(s)-1)); + } else { + value = Const(s); + } + } else + if (node->type == 'N') { + value = Const(node->data_number, 32); + if (node->data_number < 0) + value.flags |= RTLIL::CONST_FLAG_SIGNED; + } else + if (node->type == 'A') { + log_error("JSON attribute or parameter value is an array.\n"); + } else + if (node->type == 'D') { + log_error("JSON attribute or parameter value is a dict.\n"); + } else { + log_abort(); + } + + return value; +} + void json_parse_attr_param(dict &results, JsonNode *node) { if (node->type != 'D') @@ -214,28 +246,7 @@ void json_parse_attr_param(dict &results, JsonNode *node) for (auto it : node->data_dict) { IdString key = RTLIL::escape_id(it.first.c_str()); - JsonNode *value_node = it.second; - Const value; - - if (value_node->type == 'S') { - string &s = value_node->data_string; - if (s.find_first_not_of("01xz") == string::npos) - value = Const::from_string(s); - else - value = Const(s); - } else - if (value_node->type == 'N') { - value = Const(value_node->data_number, 32); - } else - if (value_node->type == 'A') { - log_error("JSON attribute or parameter value is an array.\n"); - } else - if (value_node->type == 'D') { - log_error("JSON attribute or parameter value is a dict.\n"); - } else { - log_abort(); - } - + Const value = json_parse_attr_param_value(it.second); results[key] = value; } } From 837cb0a1b9c9a774512481d0812c28f927985e7b Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Sat, 3 Aug 2019 14:47:33 +0200 Subject: [PATCH 17/29] anlogic : Fix alu mapping --- techlibs/anlogic/arith_map.v | 24 ++++++++---------------- 1 file changed, 8 insertions(+), 16 deletions(-) diff --git a/techlibs/anlogic/arith_map.v b/techlibs/anlogic/arith_map.v index 11cd140ec..6d6a7ca37 100644 --- a/techlibs/anlogic/arith_map.v +++ b/techlibs/anlogic/arith_map.v @@ -42,10 +42,9 @@ module _80_anlogic_alu (A, B, CI, BI, X, Y, CO); wire [Y_WIDTH-1:0] AA = A_buf; wire [Y_WIDTH-1:0] BB = BI ? ~B_buf : B_buf; wire [Y_WIDTH+1:0] COx; - wire [Y_WIDTH+1:0] C = {COx, CI}; + wire [Y_WIDTH+2:0] C = {COx, CI}; wire dummy; - (* keep *) AL_MAP_ADDER #( .ALUTYPE("ADD_CARRY")) adder_cin ( @@ -55,19 +54,6 @@ module _80_anlogic_alu (A, B, CI, BI, X, Y, CO); genvar i; generate for (i = 0; i < Y_WIDTH; i = i + 1) begin: slice - if(i==Y_WIDTH-1) begin - (* keep *) - AL_MAP_ADDER #( - .ALUTYPE("ADD")) - adder_cout ( - .c(C[Y_WIDTH]), - .o(COx[Y_WIDTH]) - ); - assign CO = COx[Y_WIDTH]; - end - else - begin - (* keep *) AL_MAP_ADDER #( .ALUTYPE("ADD") ) adder_i ( @@ -76,9 +62,15 @@ module _80_anlogic_alu (A, B, CI, BI, X, Y, CO); .c(C[i+1]), .o({COx[i+1],Y[i]}) ); - end end: slice endgenerate /* End implementation */ + AL_MAP_ADDER #( + .ALUTYPE("ADD")) + adder_cout ( + .c(C[Y_WIDTH+1]), + .o(COx[Y_WIDTH+1]) + ); + assign CO = COx[Y_WIDTH+1]; assign X = AA ^ BB; endmodule \ No newline at end of file From f1f5b4e375f6347424cf7877ed6415bf9c71420e Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Tue, 6 Aug 2019 18:06:14 +0200 Subject: [PATCH 18/29] Fix handling of functions/tasks without top-level begin-end block, fixes #1231 Signed-off-by: Clifford Wolf --- frontends/ast/simplify.cc | 17 ++--------------- 1 file changed, 2 insertions(+), 15 deletions(-) diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index e947125bf..6fb94d80b 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -3439,19 +3439,11 @@ AstNode *AstNode::eval_const_function(AstNode *fcall) { std::map backup_scope; std::map variables; - bool delete_temp_block = false; - AstNode *block = NULL; + AstNode *block = new AstNode(AST_BLOCK); size_t argidx = 0; for (auto child : children) { - if (child->type == AST_BLOCK) - { - log_assert(block == NULL); - block = child; - continue; - } - if (child->type == AST_WIRE) { while (child->simplify(true, false, false, 1, -1, false, true)) { } @@ -3468,13 +3460,9 @@ AstNode *AstNode::eval_const_function(AstNode *fcall) continue; } - log_assert(block == NULL); - delete_temp_block = true; - block = new AstNode(AST_BLOCK); block->children.push_back(child->clone()); } - log_assert(block != NULL); log_assert(variables.count(str) != 0); while (!block->children.empty()) @@ -3642,8 +3630,7 @@ AstNode *AstNode::eval_const_function(AstNode *fcall) log_abort(); } - if (delete_temp_block) - delete block; + delete block; for (auto &it : backup_scope) if (it.second == NULL) From 95a6582f342537d387063be10cba55c001ed19f5 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Tue, 6 Aug 2019 19:21:37 +0200 Subject: [PATCH 19/29] Be less aggressive with running design->check() Signed-off-by: Clifford Wolf --- kernel/driver.cc | 6 ++++++ kernel/register.cc | 10 +++------- kernel/yosys.cc | 10 ++++++++-- 3 files changed, 17 insertions(+), 9 deletions(-) diff --git a/kernel/driver.cc b/kernel/driver.cc index f273057dd..70a97c4b9 100644 --- a/kernel/driver.cc +++ b/kernel/driver.cc @@ -522,6 +522,12 @@ int main(int argc, char **argv) if (!backend_command.empty()) run_backend(output_filename, backend_command); + yosys_design->check(); + for (auto it : saved_designs) + it.second->check(); + for (auto it : pushed_designs) + it->check(); + if (!depsfile.empty()) { FILE *f = fopen(depsfile.c_str(), "wt"); diff --git a/kernel/register.cc b/kernel/register.cc index 4c6e3591f..8f8f2c971 100644 --- a/kernel/register.cc +++ b/kernel/register.cc @@ -256,8 +256,6 @@ void Pass::call(RTLIL::Design *design, std::vector args) pass_register[args[0]]->post_execute(state); while (design->selection_stack.size() > orig_sel_stack_pos) design->selection_stack.pop_back(); - - design->check(); } void Pass::call_on_selection(RTLIL::Design *design, const RTLIL::Selection &selection, std::string command) @@ -339,8 +337,10 @@ void ScriptPass::run(std::string command, std::string info) log(" %s\n", command.c_str()); else log(" %s %s\n", command.c_str(), info.c_str()); - } else + } else { Pass::call(active_design, command); + active_design->check(); + } } void ScriptPass::run_script(RTLIL::Design *design, std::string run_from, std::string run_to) @@ -534,8 +534,6 @@ void Frontend::frontend_call(RTLIL::Design *design, std::istream *f, std::string args.push_back(filename); frontend_register[args[0]]->execute(args, design); } - - design->check(); } Backend::Backend(std::string name, std::string short_help) : @@ -645,8 +643,6 @@ void Backend::backend_call(RTLIL::Design *design, std::ostream *f, std::string f while (design->selection_stack.size() > orig_sel_stack_pos) design->selection_stack.pop_back(); - - design->check(); } static struct CellHelpMessages { diff --git a/kernel/yosys.cc b/kernel/yosys.cc index 191b6d5c7..a4cc53f1a 100644 --- a/kernel/yosys.cc +++ b/kernel/yosys.cc @@ -964,14 +964,18 @@ void run_frontend(std::string filename, std::string command, std::string *backen command += next_line; } handle_label(command, from_to_active, run_from, run_to); - if (from_to_active) + if (from_to_active) { Pass::call(design, command); + design->check(); + } } if (!command.empty()) { handle_label(command, from_to_active, run_from, run_to); - if (from_to_active) + if (from_to_active) { Pass::call(design, command); + design->check(); + } } } catch (...) { @@ -1000,6 +1004,7 @@ void run_frontend(std::string filename, std::string command, std::string *backen Pass::call(design, vector({command, filename})); else Frontend::frontend_call(design, NULL, filename, command); + design->check(); } void run_frontend(std::string filename, std::string command, RTLIL::Design *design) @@ -1183,6 +1188,7 @@ void shell(RTLIL::Design *design) design->selection_stack.pop_back(); log_reset_stack(); } + design->check(); } if (command == NULL) printf("exit\n"); From 51b39219cda35e782fe4372409edf5432f86741f Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 6 Aug 2019 15:24:49 -0700 Subject: [PATCH 20/29] Move LSB tests from wreduce to opt_expr --- tests/various/opt_expr.ys | 98 ++++++++++++++++++++++++++++++++++++ tests/various/wreduce.ys | 102 ++------------------------------------ 2 files changed, 101 insertions(+), 99 deletions(-) create mode 100644 tests/various/opt_expr.ys diff --git a/tests/various/opt_expr.ys b/tests/various/opt_expr.ys new file mode 100644 index 000000000..2165802d6 --- /dev/null +++ b/tests/various/opt_expr.ys @@ -0,0 +1,98 @@ + +read_verilog <> 4) - i; endmodule EOT @@ -81,7 +8,8 @@ hierarchy -auto-top proc design -save gold -prep # calls wreduce +opt_expr +wreduce select -assert-count 1 t:$sub r:A_WIDTH=4 r:B_WIDTH=4 r:Y_WIDTH=5 %i %i %i @@ -92,27 +20,3 @@ design -import gate -as gate miter -equiv -flatten -make_assert -make_outputs gold gate miter sat -verify -prove-asserts -show-ports miter - -########## - -read_verilog < Date: Tue, 6 Aug 2019 15:24:55 -0700 Subject: [PATCH 21/29] Restore original SigSpec::extract() --- kernel/rtlil.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index f2c81db72..ba8472ec1 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -3355,7 +3355,7 @@ RTLIL::SigSpec RTLIL::SigSpec::extract(int offset, int length) const { unpack(); cover("kernel.rtlil.sigspec.extract_pos"); - return std::vector(bits_.begin() + offset, length >= 0 ? bits_.begin() + offset + length : bits_.end() + length + 1); + return std::vector(bits_.begin() + offset, bits_.begin() + offset + length); } void RTLIL::SigSpec::append(const RTLIL::SigSpec &signal) From 84f52aee0d01378796792c9a2f068a22d955f586 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 6 Aug 2019 15:25:11 -0700 Subject: [PATCH 22/29] Add SigSpec::extract_end() convenience function --- kernel/rtlil.h | 1 + 1 file changed, 1 insertion(+) diff --git a/kernel/rtlil.h b/kernel/rtlil.h index 633cb51d6..c07d39c65 100644 --- a/kernel/rtlil.h +++ b/kernel/rtlil.h @@ -788,6 +788,7 @@ public: RTLIL::SigSpec extract(const RTLIL::SigSpec &pattern, const RTLIL::SigSpec *other = NULL) const; RTLIL::SigSpec extract(const pool &pattern, const RTLIL::SigSpec *other = NULL) const; RTLIL::SigSpec extract(int offset, int length = 1) const; + RTLIL::SigSpec extract_end(int offset) const { return extract(offset, width_ - offset); } void append(const RTLIL::SigSpec &signal); void append_bit(const RTLIL::SigBit &bit); From bfc7164af7bf64cb2fe5d00e87bbfead841a4dc2 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 6 Aug 2019 15:25:50 -0700 Subject: [PATCH 23/29] Move LSB-trimming functionality from wreduce to opt_expr --- passes/opt/opt_expr.cc | 25 +++++++++++++++++++++++++ passes/opt/wreduce.cc | 24 +----------------------- 2 files changed, 26 insertions(+), 23 deletions(-) diff --git a/passes/opt/opt_expr.cc b/passes/opt/opt_expr.cc index 512ef0cbf..acdc39937 100644 --- a/passes/opt/opt_expr.cc +++ b/passes/opt/opt_expr.cc @@ -641,6 +641,31 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons did_something = true; } } + + if (cell->type.in("$add", "$sub")) { + RTLIL::SigSpec sig_a = assign_map(cell->getPort("\\A")); + RTLIL::SigSpec sig_b = assign_map(cell->getPort("\\B")); + RTLIL::SigSpec sig_y = cell->getPort("\\Y"); + bool sub = cell->type == "$sub"; + + int i; + for (i = 0; i < GetSize(sig_y); i++) { + if (sig_b.at(i, State::Sx) == State::S0 && sig_a.at(i, State::Sx) != State::Sx) + module->connect(sig_y[i], sig_a[i]); + else if (!sub && sig_a.at(i, State::Sx) == State::S0 && sig_b.at(i, State::Sx) != State::Sx) + module->connect(sig_y[i], sig_b[i]); + else + break; + } + if (i > 0) { + cover_list("opt.opt_expr.fine", "$add", "$sub", cell->type.str()); + cell->setPort("\\A", sig_a.extract_end(i)); + cell->setPort("\\B", sig_b.extract_end(i)); + cell->setPort("\\Y", sig_y.extract_end(i)); + cell->fixup_parameters(); + did_something = true; + } + } } if (cell->type == "$reduce_xor" || cell->type == "$reduce_xnor" || cell->type == "$shift" || cell->type == "$shiftx" || diff --git a/passes/opt/wreduce.cc b/passes/opt/wreduce.cc index 22af0bd8b..1eeca2748 100644 --- a/passes/opt/wreduce.cc +++ b/passes/opt/wreduce.cc @@ -365,28 +365,6 @@ struct WreduceWorker } } - if (cell->type.in("$add", "$sub")) { - SigSpec A = mi.sigmap(cell->getPort("\\A")); - SigSpec B = mi.sigmap(cell->getPort("\\B")); - bool sub = cell->type == "$sub"; - - int i; - for (i = 0; i < GetSize(sig); i++) { - if (B.at(i, Sx) == S0 && A.at(i, Sx) != Sx) - module->connect(sig[i], A[i]); - else if (!sub && A.at(i, Sx) == S0 && B.at(i, Sx) != Sx) - module->connect(sig[i], B[i]); - else - break; - } - if (i > 0) { - cell->setPort("\\A", A.extract(i, -1)); - cell->setPort("\\B", B.extract(i, -1)); - sig.remove(0, i); - bits_removed += i; - } - } - if (GetSize(sig) == 0) { log("Removed cell %s.%s (%s).\n", log_id(module), log_id(cell), log_id(cell->type)); module->remove(cell); @@ -394,7 +372,7 @@ struct WreduceWorker } if (bits_removed) { - log("Removed %d bits (of %d) from port Y of cell %s.%s (%s).\n", + log("Removed top %d bits (of %d) from port Y of cell %s.%s (%s).\n", bits_removed, GetSize(sig) + bits_removed, log_id(module), log_id(cell), log_id(cell->type)); cell->setPort("\\Y", sig); did_something = true; From 769c750c226cfde5efcd1f75940b25f51330d67b Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 6 Aug 2019 15:38:43 -0700 Subject: [PATCH 24/29] Add signed test --- tests/various/wreduce.ys | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/tests/various/wreduce.ys b/tests/various/wreduce.ys index 7e4f1765a..4257292f5 100644 --- a/tests/various/wreduce.ys +++ b/tests/various/wreduce.ys @@ -20,3 +20,29 @@ design -import gate -as gate miter -equiv -flatten -make_assert -make_outputs gold gate miter sat -verify -prove-asserts -show-ports miter + +########## + +read_verilog <>> 4) - i; +endmodule +EOT + +hierarchy -auto-top +proc +design -save gold + +opt_expr +wreduce + +dump +select -assert-count 1 t:$sub r:A_WIDTH=4 r:B_WIDTH=4 r:Y_WIDTH=5 %i %i %i + +design -stash gate + +design -import gold -as gold +design -import gate -as gate + +miter -equiv -flatten -make_assert -make_outputs gold gate miter +sat -verify -prove-asserts -show-ports miter From 2d1b517b01b6cd1ec35018d4c63aaa091fcc1917 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 6 Aug 2019 15:40:30 -0700 Subject: [PATCH 25/29] Add signed opt_expr tests --- tests/various/opt_expr.ys | 50 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/tests/various/opt_expr.ys b/tests/various/opt_expr.ys index 2165802d6..0c61ac881 100644 --- a/tests/various/opt_expr.ys +++ b/tests/various/opt_expr.ys @@ -24,6 +24,31 @@ sat -verify -prove-asserts -show-ports miter ########## +read_verilog < Date: Wed, 7 Aug 2019 01:12:14 +0200 Subject: [PATCH 26/29] Redesign of cell cost API Signed-off-by: Clifford Wolf --- kernel/cost.h | 158 ++++++++++++++++++++++-------------------- passes/techmap/abc.cc | 42 ++++++----- 2 files changed, 102 insertions(+), 98 deletions(-) diff --git a/kernel/cost.h b/kernel/cost.h index e8e077ff5..7ff11eba2 100644 --- a/kernel/cost.h +++ b/kernel/cost.h @@ -24,86 +24,92 @@ YOSYS_NAMESPACE_BEGIN -int get_cell_cost(RTLIL::Cell *cell, dict *mod_cost_cache = nullptr, bool cmos_cost = false); - -inline int get_cell_cost(RTLIL::IdString type, const dict ¶meters = dict(), - RTLIL::Design *design = nullptr, dict *mod_cost_cache = nullptr, bool cmos_cost = false) +struct CellCosts { - static dict gate_cost = { - { "$_BUF_", 1 }, - { "$_NOT_", 2 }, - { "$_AND_", 4 }, - { "$_NAND_", 4 }, - { "$_OR_", 4 }, - { "$_NOR_", 4 }, - { "$_ANDNOT_", 4 }, - { "$_ORNOT_", 4 }, - { "$_XOR_", 8 }, - { "$_XNOR_", 8 }, - { "$_AOI3_", 6 }, - { "$_OAI3_", 6 }, - { "$_AOI4_", 8 }, - { "$_OAI4_", 8 }, - { "$_MUX_", 4 }, - { "$_NMUX_", 4 } - }; - - // match costs in "stat -tech cmos" - static dict cmos_gate_cost = { - { "$_BUF_", 1 }, - { "$_NOT_", 2 }, - { "$_AND_", 6 }, - { "$_NAND_", 4 }, - { "$_OR_", 6 }, - { "$_NOR_", 4 }, - { "$_ANDNOT_", 6 }, - { "$_ORNOT_", 6 }, - { "$_XOR_", 12 }, - { "$_XNOR_", 12 }, - { "$_AOI3_", 6 }, - { "$_OAI3_", 6 }, - { "$_AOI4_", 8 }, - { "$_OAI4_", 8 }, - { "$_MUX_", 12 }, - { "$_NMUX_", 10 } - }; - - if (cmos_cost && cmos_gate_cost.count(type)) - return cmos_gate_cost.at(type); - - if (gate_cost.count(type)) - return gate_cost.at(type); - - if (parameters.empty() && design && design->module(type)) - { - RTLIL::Module *mod = design->module(type); - - if (mod->attributes.count("\\cost")) - return mod->attributes.at("\\cost").as_int(); - - dict local_mod_cost_cache; - if (mod_cost_cache == nullptr) - mod_cost_cache = &local_mod_cost_cache; - - if (mod_cost_cache->count(mod->name)) - return mod_cost_cache->at(mod->name); - - int module_cost = 1; - for (auto c : mod->cells()) - module_cost += get_cell_cost(c, mod_cost_cache); - - (*mod_cost_cache)[mod->name] = module_cost; - return module_cost; + static const dict& default_gate_cost() { + static const dict db = { + { "$_BUF_", 1 }, + { "$_NOT_", 2 }, + { "$_AND_", 4 }, + { "$_NAND_", 4 }, + { "$_OR_", 4 }, + { "$_NOR_", 4 }, + { "$_ANDNOT_", 4 }, + { "$_ORNOT_", 4 }, + { "$_XOR_", 6 }, + { "$_XNOR_", 6 }, + { "$_AOI3_", 6 }, + { "$_OAI3_", 6 }, + { "$_AOI4_", 8 }, + { "$_OAI4_", 8 }, + { "$_MUX_", 4 }, + { "$_NMUX_", 4 } + }; + return db; } - log_warning("Can't determine cost of %s cell (%d parameters).\n", log_id(type), GetSize(parameters)); - return 1; -} + static const dict& cmos_gate_cost() { + static const dict db = { + { "$_BUF_", 1 }, + { "$_NOT_", 2 }, + { "$_AND_", 6 }, + { "$_NAND_", 4 }, + { "$_OR_", 6 }, + { "$_NOR_", 4 }, + { "$_ANDNOT_", 6 }, + { "$_ORNOT_", 6 }, + { "$_XOR_", 12 }, + { "$_XNOR_", 12 }, + { "$_AOI3_", 6 }, + { "$_OAI3_", 6 }, + { "$_AOI4_", 8 }, + { "$_OAI4_", 8 }, + { "$_MUX_", 12 }, + { "$_NMUX_", 10 } + }; + return db; + } -inline int get_cell_cost(RTLIL::Cell *cell, dict *mod_cost_cache, bool cmos_cost) -{ - return get_cell_cost(cell->type, cell->parameters, cell->module->design, mod_cost_cache, cmos_cost); -} + dict mod_cost_cache; + const dict *gate_cost = nullptr; + Design *design = nullptr; + + int get(RTLIL::IdString type) const + { + if (gate_cost && gate_cost->count(type)) + return gate_cost->at(type); + + log_warning("Can't determine cost of %s cell.\n", log_id(type)); + return 1; + } + + int get(RTLIL::Cell *cell) + { + if (gate_cost && gate_cost->count(cell->type)) + return gate_cost->at(cell->type); + + if (design && design->module(cell->type) && cell->parameters.empty()) + { + RTLIL::Module *mod = design->module(cell->type); + + if (mod->attributes.count("\\cost")) + return mod->attributes.at("\\cost").as_int(); + + if (mod_cost_cache.count(mod->name)) + return mod_cost_cache.at(mod->name); + + int module_cost = 1; + for (auto c : mod->cells()) + module_cost += get(c); + + mod_cost_cache[mod->name] = module_cost; + return module_cost; + } + + log_warning("Can't determine cost of %s cell (%d parameters).\n", log_id(cell->type), GetSize(cell->parameters)); + return 1; + } +}; YOSYS_NAMESPACE_END diff --git a/passes/techmap/abc.cc b/passes/techmap/abc.cc index 41a05c619..c0cfe2f36 100644 --- a/passes/techmap/abc.cc +++ b/passes/techmap/abc.cc @@ -931,9 +931,7 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin { log_header(design, "Executing ABC.\n"); - auto cell_cost = [](IdString cell_type) { - return get_cell_cost(cell_type, dict(), nullptr, nullptr, cmos_cost); - }; + auto &cell_cost = cmos_cost ? CellCosts::cmos_gate_cost() : CellCosts::default_gate_cost(); buffer = stringf("%s/stdcells.genlib", tempdir_name.c_str()); f = fopen(buffer.c_str(), "wt"); @@ -941,42 +939,42 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin log_error("Opening %s for writing failed: %s\n", buffer.c_str(), strerror(errno)); fprintf(f, "GATE ZERO 1 Y=CONST0;\n"); fprintf(f, "GATE ONE 1 Y=CONST1;\n"); - fprintf(f, "GATE BUF %d Y=A; PIN * NONINV 1 999 1 0 1 0\n", cell_cost("$_BUF_")); - fprintf(f, "GATE NOT %d Y=!A; PIN * INV 1 999 1 0 1 0\n", cell_cost("$_NOT_")); + fprintf(f, "GATE BUF %d Y=A; PIN * NONINV 1 999 1 0 1 0\n", cell_cost.at("$_BUF_")); + fprintf(f, "GATE NOT %d Y=!A; PIN * INV 1 999 1 0 1 0\n", cell_cost.at("$_NOT_")); if (enabled_gates.empty() || enabled_gates.count("AND")) - fprintf(f, "GATE AND %d Y=A*B; PIN * NONINV 1 999 1 0 1 0\n", cell_cost("$_AND_")); + fprintf(f, "GATE AND %d Y=A*B; PIN * NONINV 1 999 1 0 1 0\n", cell_cost.at("$_AND_")); if (enabled_gates.empty() || enabled_gates.count("NAND")) - fprintf(f, "GATE NAND %d Y=!(A*B); PIN * INV 1 999 1 0 1 0\n", cell_cost("$_NAND_")); + fprintf(f, "GATE NAND %d Y=!(A*B); PIN * INV 1 999 1 0 1 0\n", cell_cost.at("$_NAND_")); if (enabled_gates.empty() || enabled_gates.count("OR")) - fprintf(f, "GATE OR %d Y=A+B; PIN * NONINV 1 999 1 0 1 0\n", cell_cost("$_OR_")); + fprintf(f, "GATE OR %d Y=A+B; PIN * NONINV 1 999 1 0 1 0\n", cell_cost.at("$_OR_")); if (enabled_gates.empty() || enabled_gates.count("NOR")) - fprintf(f, "GATE NOR %d Y=!(A+B); PIN * INV 1 999 1 0 1 0\n", cell_cost("$_NOR_")); + fprintf(f, "GATE NOR %d Y=!(A+B); PIN * INV 1 999 1 0 1 0\n", cell_cost.at("$_NOR_")); if (enabled_gates.empty() || enabled_gates.count("XOR")) - fprintf(f, "GATE XOR %d Y=(A*!B)+(!A*B); PIN * UNKNOWN 1 999 1 0 1 0\n", cell_cost("$_XOR_")); + fprintf(f, "GATE XOR %d Y=(A*!B)+(!A*B); PIN * UNKNOWN 1 999 1 0 1 0\n", cell_cost.at("$_XOR_")); if (enabled_gates.empty() || enabled_gates.count("XNOR")) - fprintf(f, "GATE XNOR %d Y=(A*B)+(!A*!B); PIN * UNKNOWN 1 999 1 0 1 0\n", cell_cost("$_XNOR_")); + fprintf(f, "GATE XNOR %d Y=(A*B)+(!A*!B); PIN * UNKNOWN 1 999 1 0 1 0\n", cell_cost.at("$_XNOR_")); if (enabled_gates.empty() || enabled_gates.count("ANDNOT")) - fprintf(f, "GATE ANDNOT %d Y=A*!B; PIN * UNKNOWN 1 999 1 0 1 0\n", cell_cost("$_ANDNOT_")); + fprintf(f, "GATE ANDNOT %d Y=A*!B; PIN * UNKNOWN 1 999 1 0 1 0\n", cell_cost.at("$_ANDNOT_")); if (enabled_gates.empty() || enabled_gates.count("ORNOT")) - fprintf(f, "GATE ORNOT %d Y=A+!B; PIN * UNKNOWN 1 999 1 0 1 0\n", cell_cost("$_ORNOT_")); + fprintf(f, "GATE ORNOT %d Y=A+!B; PIN * UNKNOWN 1 999 1 0 1 0\n", cell_cost.at("$_ORNOT_")); if (enabled_gates.empty() || enabled_gates.count("AOI3")) - fprintf(f, "GATE AOI3 %d Y=!((A*B)+C); PIN * INV 1 999 1 0 1 0\n", cell_cost("$_AOI3_")); + fprintf(f, "GATE AOI3 %d Y=!((A*B)+C); PIN * INV 1 999 1 0 1 0\n", cell_cost.at("$_AOI3_")); if (enabled_gates.empty() || enabled_gates.count("OAI3")) - fprintf(f, "GATE OAI3 %d Y=!((A+B)*C); PIN * INV 1 999 1 0 1 0\n", cell_cost("$_OAI3_")); + fprintf(f, "GATE OAI3 %d Y=!((A+B)*C); PIN * INV 1 999 1 0 1 0\n", cell_cost.at("$_OAI3_")); if (enabled_gates.empty() || enabled_gates.count("AOI4")) - fprintf(f, "GATE AOI4 %d Y=!((A*B)+(C*D)); PIN * INV 1 999 1 0 1 0\n", cell_cost("$_AOI4_")); + fprintf(f, "GATE AOI4 %d Y=!((A*B)+(C*D)); PIN * INV 1 999 1 0 1 0\n", cell_cost.at("$_AOI4_")); if (enabled_gates.empty() || enabled_gates.count("OAI4")) - fprintf(f, "GATE OAI4 %d Y=!((A+B)*(C+D)); PIN * INV 1 999 1 0 1 0\n", cell_cost("$_OAI4_")); + fprintf(f, "GATE OAI4 %d Y=!((A+B)*(C+D)); PIN * INV 1 999 1 0 1 0\n", cell_cost.at("$_OAI4_")); if (enabled_gates.empty() || enabled_gates.count("MUX")) - fprintf(f, "GATE MUX %d Y=(A*B)+(S*B)+(!S*A); PIN * UNKNOWN 1 999 1 0 1 0\n", cell_cost("$_MUX_")); + fprintf(f, "GATE MUX %d Y=(A*B)+(S*B)+(!S*A); PIN * UNKNOWN 1 999 1 0 1 0\n", cell_cost.at("$_MUX_")); if (enabled_gates.empty() || enabled_gates.count("NMUX")) - fprintf(f, "GATE NMUX %d Y=!((A*B)+(S*B)+(!S*A)); PIN * UNKNOWN 1 999 1 0 1 0\n", cell_cost("$_NMUX_")); + fprintf(f, "GATE NMUX %d Y=!((A*B)+(S*B)+(!S*A)); PIN * UNKNOWN 1 999 1 0 1 0\n", cell_cost.at("$_NMUX_")); if (map_mux4) - fprintf(f, "GATE MUX4 %d Y=(!S*!T*A)+(S*!T*B)+(!S*T*C)+(S*T*D); PIN * UNKNOWN 1 999 1 0 1 0\n", 2*cell_cost("$_MUX_")); + fprintf(f, "GATE MUX4 %d Y=(!S*!T*A)+(S*!T*B)+(!S*T*C)+(S*T*D); PIN * UNKNOWN 1 999 1 0 1 0\n", 2*cell_cost.at("$_MUX_")); if (map_mux8) - fprintf(f, "GATE MUX8 %d Y=(!S*!T*!U*A)+(S*!T*!U*B)+(!S*T*!U*C)+(S*T*!U*D)+(!S*!T*U*E)+(S*!T*U*F)+(!S*T*U*G)+(S*T*U*H); PIN * UNKNOWN 1 999 1 0 1 0\n", 4*cell_cost("$_MUX_")); + fprintf(f, "GATE MUX8 %d Y=(!S*!T*!U*A)+(S*!T*!U*B)+(!S*T*!U*C)+(S*T*!U*D)+(!S*!T*U*E)+(S*!T*U*F)+(!S*T*U*G)+(S*T*U*H); PIN * UNKNOWN 1 999 1 0 1 0\n", 4*cell_cost.at("$_MUX_")); if (map_mux16) - fprintf(f, "GATE MUX16 %d Y=(!S*!T*!U*!V*A)+(S*!T*!U*!V*B)+(!S*T*!U*!V*C)+(S*T*!U*!V*D)+(!S*!T*U*!V*E)+(S*!T*U*!V*F)+(!S*T*U*!V*G)+(S*T*U*!V*H)+(!S*!T*!U*V*I)+(S*!T*!U*V*J)+(!S*T*!U*V*K)+(S*T*!U*V*L)+(!S*!T*U*V*M)+(S*!T*U*V*N)+(!S*T*U*V*O)+(S*T*U*V*P); PIN * UNKNOWN 1 999 1 0 1 0\n", 8*cell_cost("$_MUX_")); + fprintf(f, "GATE MUX16 %d Y=(!S*!T*!U*!V*A)+(S*!T*!U*!V*B)+(!S*T*!U*!V*C)+(S*T*!U*!V*D)+(!S*!T*U*!V*E)+(S*!T*U*!V*F)+(!S*T*U*!V*G)+(S*T*U*!V*H)+(!S*!T*!U*V*I)+(S*!T*!U*V*J)+(!S*T*!U*V*K)+(S*T*!U*V*L)+(!S*!T*U*V*M)+(S*!T*U*V*N)+(!S*T*U*V*O)+(S*T*U*V*P); PIN * UNKNOWN 1 999 1 0 1 0\n", 8*cell_cost.at("$_MUX_")); fclose(f); if (!lut_costs.empty()) { From 338f6765ebeb6bd07197dbef8e22fa077bf2d043 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Wed, 7 Aug 2019 10:25:51 +0200 Subject: [PATCH 27/29] Tweak default gate costs, cleanup "stat -tech cmos" Signed-off-by: Clifford Wolf --- kernel/cost.h | 8 ++++---- passes/cmds/stat.cc | 22 ++++++---------------- 2 files changed, 10 insertions(+), 20 deletions(-) diff --git a/kernel/cost.h b/kernel/cost.h index 7ff11eba2..10fa50fb3 100644 --- a/kernel/cost.h +++ b/kernel/cost.h @@ -36,12 +36,12 @@ struct CellCosts { "$_NOR_", 4 }, { "$_ANDNOT_", 4 }, { "$_ORNOT_", 4 }, - { "$_XOR_", 6 }, - { "$_XNOR_", 6 }, + { "$_XOR_", 5 }, + { "$_XNOR_", 5 }, { "$_AOI3_", 6 }, { "$_OAI3_", 6 }, - { "$_AOI4_", 8 }, - { "$_OAI4_", 8 }, + { "$_AOI4_", 7 }, + { "$_OAI4_", 7 }, { "$_MUX_", 4 }, { "$_NMUX_", 4 } }; diff --git a/passes/cmds/stat.cc b/passes/cmds/stat.cc index 89920ed55..c8e4f3981 100644 --- a/passes/cmds/stat.cc +++ b/passes/cmds/stat.cc @@ -17,11 +17,10 @@ * */ -#include "kernel/register.h" +#include "kernel/yosys.h" #include "kernel/celltypes.h" #include "passes/techmap/libparse.h" - -#include "kernel/log.h" +#include "kernel/cost.h" USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN @@ -228,25 +227,16 @@ struct statdata_t { int tran_cnt = 0; bool tran_cnt_exact = true; + auto &gate_costs = CellCosts::cmos_gate_cost(); for (auto it : num_cells_by_type) { auto ctype = it.first; auto cnum = it.second; - if (ctype == "$_NOT_") - tran_cnt += 2*cnum; - else if (ctype.in("$_NAND_", "$_NOR_")) - tran_cnt += 4*cnum; - else if (ctype.in("$_AOI3_", "$_OAI3_")) - tran_cnt += 6*cnum; - else if (ctype.in("$_AOI4_", "$_OAI4_")) - tran_cnt += 8*cnum; - else if (ctype.in("$_NMUX_")) - tran_cnt += 10*cnum; - else if (ctype.in("$_MUX_", "$_XOR_", "$_XNOR_")) - tran_cnt += 12*cnum; + if (gate_costs.count(ctype)) + tran_cnt += cnum * gate_costs.at(ctype); else if (ctype.in("$_DFF_P_", "$_DFF_N_")) - tran_cnt += 16*cnum; + tran_cnt += cnum * 16; else tran_cnt_exact = false; } From 607c7fa7e15f2d64685d2aab2c9c9f860037da17 Mon Sep 17 00:00:00 2001 From: David Shah Date: Wed, 7 Aug 2019 10:56:32 +0100 Subject: [PATCH 28/29] Update CHANGELOG Signed-off-by: David Shah --- CHANGELOG | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG b/CHANGELOG index 661581433..638c36121 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -17,6 +17,8 @@ Yosys 0.9 .. Yosys 0.9-dev - Added automatic gzip decompression for frontends - Added $_NMUX_ cell type - Added automatic gzip compression (based on filename extension) for backends + - Improve attribute and parameter encoding in JSON to avoid ambiguities between + bit vectors and strings containing [01xz]* Yosys 0.8 .. Yosys 0.8-dev -------------------------- From a36fd8582e52524a292702fa88b94ee40fc8acc4 Mon Sep 17 00:00:00 2001 From: David Shah Date: Wed, 7 Aug 2019 14:19:31 +0100 Subject: [PATCH 29/29] ecp5: Make cells_sim.v consistent with nextpnr Signed-off-by: David Shah --- techlibs/ecp5/cells_sim.v | 331 +++++++++++++++++++++++++++----------- 1 file changed, 237 insertions(+), 94 deletions(-) diff --git a/techlibs/ecp5/cells_sim.v b/techlibs/ecp5/cells_sim.v index ca88d0a5b..3d343b315 100644 --- a/techlibs/ecp5/cells_sim.v +++ b/techlibs/ecp5/cells_sim.v @@ -333,6 +333,31 @@ module TRELLIS_SLICE( parameter [127:0] CCU2_INJECT1_0 = "NO"; parameter [127:0] CCU2_INJECT1_1 = "NO"; parameter WREMUX = "WRE"; + parameter WCKMUX = "WCK"; + + parameter A0MUX = "A0"; + parameter A1MUX = "A1"; + parameter B0MUX = "B0"; + parameter B1MUX = "B1"; + parameter C0MUX = "C0"; + parameter C1MUX = "C1"; + parameter D0MUX = "D0"; + parameter D1MUX = "D1"; + + wire A0m, B0m, C0m, D0m; + wire A1m, B1m, C1m, D1m; + + generate + if (A0MUX == "1") assign A0m = 1'b1; else assign A0m = A0; + if (B0MUX == "1") assign B0m = 1'b1; else assign B0m = B0; + if (C0MUX == "1") assign C0m = 1'b1; else assign C0m = C0; + if (D0MUX == "1") assign D0m = 1'b1; else assign D0m = D0; + if (A1MUX == "1") assign A1m = 1'b1; else assign A1m = A1; + if (B1MUX == "1") assign B1m = 1'b1; else assign B1m = B1; + if (C1MUX == "1") assign C1m = 1'b1; else assign C1m = C1; + if (D1MUX == "1") assign D1m = 1'b1; else assign D1m = D1; + + endgenerate function [15:0] permute_initval; input [15:0] initval; @@ -350,13 +375,13 @@ module TRELLIS_SLICE( LUT4 #( .INIT(LUT0_INITVAL) ) lut4_0 ( - .A(A0), .B(B0), .C(C0), .D(D0), + .A(A0m), .B(B0m), .C(C0m), .D(D0m), .Z(F0) ); LUT4 #( .INIT(LUT1_INITVAL) ) lut4_1 ( - .A(A1), .B(B1), .C(C1), .D(D1), + .A(A1m), .B(B1m), .C(C1m), .D(D1m), .Z(F1) ); // LUT expansion muxes @@ -370,20 +395,20 @@ module TRELLIS_SLICE( .INJECT1_1(CCU2_INJECT1_1) ) ccu2c_i ( .CIN(FCI), - .A0(A0), .B0(B0), .C0(C0), .D0(D0), - .A1(A1), .B1(B1), .C1(C1), .D1(D1), + .A0(A0m), .B0(B0m), .C0(C0m), .D0(D0m), + .A1(A1m), .B1(B1m), .C1(C1m), .D1(D1m), .S0(F0), .S1(F1), .COUT(FCO) ); end else if (MODE == "RAMW") begin - assign WDO0 = C1; - assign WDO1 = A1; - assign WDO2 = D1; - assign WDO3 = B1; - assign WADO0 = D0; - assign WADO1 = B0; - assign WADO2 = C0; - assign WADO3 = A0; + assign WDO0 = C1m; + assign WDO1 = A1m; + assign WDO2 = D1m; + assign WDO3 = B1m; + assign WADO0 = D0m; + assign WADO1 = B0m; + assign WADO2 = C0m; + assign WADO3 = A0m; end else if (MODE == "DPRAM") begin TRELLIS_RAM16X2 #( .INITVAL_0(permute_initval(LUT0_INITVAL)), @@ -393,17 +418,19 @@ module TRELLIS_SLICE( .DI0(WD0), .DI1(WD1), .WAD0(WAD0), .WAD1(WAD1), .WAD2(WAD2), .WAD3(WAD3), .WRE(WRE), .WCK(WCK), - .RAD0(D0), .RAD1(B0), .RAD2(C0), .RAD3(A0), + .RAD0(D0m), .RAD1(B0m), .RAD2(C0m), .RAD3(A0m), .DO0(F0), .DO1(F1) ); // TODO: confirm RAD and INITVAL ordering // DPRAM mode contract? +`ifdef FORMAL always @(*) begin - assert(A0==A1); - assert(B0==B1); - assert(C0==C1); - assert(D0==D1); + assert(A0m==A1m); + assert(B0m==B1m); + assert(C0m==C1m); + assert(D0m==D1m); end +`endif end else begin ERROR_UNKNOWN_SLICE_MODE error(); end @@ -455,90 +482,206 @@ module DP16KD( input CSB2, CSB1, CSB0, output DOB17, DOB16, DOB15, DOB14, DOB13, DOB12, DOB11, DOB10, DOB9, DOB8, DOB7, DOB6, DOB5, DOB4, DOB3, DOB2, DOB1, DOB0 ); - parameter DATA_WIDTH_A = 18; - parameter DATA_WIDTH_B = 18; + parameter DATA_WIDTH_A = 18; + parameter DATA_WIDTH_B = 18; - parameter REGMODE_A = "NOREG"; - parameter REGMODE_B = "NOREG"; + parameter REGMODE_A = "NOREG"; + parameter REGMODE_B = "NOREG"; - parameter RESETMODE = "SYNC"; - parameter ASYNC_RESET_RELEASE = "SYNC"; + parameter RESETMODE = "SYNC"; + parameter ASYNC_RESET_RELEASE = "SYNC"; - parameter CSDECODE_A = "0b000"; - parameter CSDECODE_B = "0b000"; + parameter CSDECODE_A = "0b000"; + parameter CSDECODE_B = "0b000"; - parameter WRITEMODE_A = "NORMAL"; - parameter WRITEMODE_B = "NORMAL"; + parameter WRITEMODE_A = "NORMAL"; + parameter WRITEMODE_B = "NORMAL"; - parameter CLKAMUX = "CLKA"; - parameter CLKBMUX = "CLKB"; + parameter DIA17MUX = "DIA17"; + parameter DIA16MUX = "DIA16"; + parameter DIA15MUX = "DIA15"; + parameter DIA14MUX = "DIA14"; + parameter DIA13MUX = "DIA13"; + parameter DIA12MUX = "DIA12"; + parameter DIA11MUX = "DIA11"; + parameter DIA10MUX = "DIA10"; + parameter DIA9MUX = "DIA9"; + parameter DIA8MUX = "DIA8"; + parameter DIA7MUX = "DIA7"; + parameter DIA6MUX = "DIA6"; + parameter DIA5MUX = "DIA5"; + parameter DIA4MUX = "DIA4"; + parameter DIA3MUX = "DIA3"; + parameter DIA2MUX = "DIA2"; + parameter DIA1MUX = "DIA1"; + parameter DIA0MUX = "DIA0"; + parameter ADA13MUX = "ADA13"; + parameter ADA12MUX = "ADA12"; + parameter ADA11MUX = "ADA11"; + parameter ADA10MUX = "ADA10"; + parameter ADA9MUX = "ADA9"; + parameter ADA8MUX = "ADA8"; + parameter ADA7MUX = "ADA7"; + parameter ADA6MUX = "ADA6"; + parameter ADA5MUX = "ADA5"; + parameter ADA4MUX = "ADA4"; + parameter ADA3MUX = "ADA3"; + parameter ADA2MUX = "ADA2"; + parameter ADA1MUX = "ADA1"; + parameter ADA0MUX = "ADA0"; + parameter CEAMUX = "CEA"; + parameter OCEAMUX = "OCEA"; + parameter CLKAMUX = "CLKA"; + parameter WEAMUX = "WEA"; + parameter RSTAMUX = "RSTA"; + parameter CSA2MUX = "CSA2"; + parameter CSA1MUX = "CSA1"; + parameter CSA0MUX = "CSA0"; + parameter DOA17MUX = "DOA17"; + parameter DOA16MUX = "DOA16"; + parameter DOA15MUX = "DOA15"; + parameter DOA14MUX = "DOA14"; + parameter DOA13MUX = "DOA13"; + parameter DOA12MUX = "DOA12"; + parameter DOA11MUX = "DOA11"; + parameter DOA10MUX = "DOA10"; + parameter DOA9MUX = "DOA9"; + parameter DOA8MUX = "DOA8"; + parameter DOA7MUX = "DOA7"; + parameter DOA6MUX = "DOA6"; + parameter DOA5MUX = "DOA5"; + parameter DOA4MUX = "DOA4"; + parameter DOA3MUX = "DOA3"; + parameter DOA2MUX = "DOA2"; + parameter DOA1MUX = "DOA1"; + parameter DOA0MUX = "DOA0"; + parameter DIB17MUX = "DIB17"; + parameter DIB16MUX = "DIB16"; + parameter DIB15MUX = "DIB15"; + parameter DIB14MUX = "DIB14"; + parameter DIB13MUX = "DIB13"; + parameter DIB12MUX = "DIB12"; + parameter DIB11MUX = "DIB11"; + parameter DIB10MUX = "DIB10"; + parameter DIB9MUX = "DIB9"; + parameter DIB8MUX = "DIB8"; + parameter DIB7MUX = "DIB7"; + parameter DIB6MUX = "DIB6"; + parameter DIB5MUX = "DIB5"; + parameter DIB4MUX = "DIB4"; + parameter DIB3MUX = "DIB3"; + parameter DIB2MUX = "DIB2"; + parameter DIB1MUX = "DIB1"; + parameter DIB0MUX = "DIB0"; + parameter ADB13MUX = "ADB13"; + parameter ADB12MUX = "ADB12"; + parameter ADB11MUX = "ADB11"; + parameter ADB10MUX = "ADB10"; + parameter ADB9MUX = "ADB9"; + parameter ADB8MUX = "ADB8"; + parameter ADB7MUX = "ADB7"; + parameter ADB6MUX = "ADB6"; + parameter ADB5MUX = "ADB5"; + parameter ADB4MUX = "ADB4"; + parameter ADB3MUX = "ADB3"; + parameter ADB2MUX = "ADB2"; + parameter ADB1MUX = "ADB1"; + parameter ADB0MUX = "ADB0"; + parameter CEBMUX = "CEB"; + parameter OCEBMUX = "OCEB"; + parameter CLKBMUX = "CLKB"; + parameter WEBMUX = "WEB"; + parameter RSTBMUX = "RSTB"; + parameter CSB2MUX = "CSB2"; + parameter CSB1MUX = "CSB1"; + parameter CSB0MUX = "CSB0"; + parameter DOB17MUX = "DOB17"; + parameter DOB16MUX = "DOB16"; + parameter DOB15MUX = "DOB15"; + parameter DOB14MUX = "DOB14"; + parameter DOB13MUX = "DOB13"; + parameter DOB12MUX = "DOB12"; + parameter DOB11MUX = "DOB11"; + parameter DOB10MUX = "DOB10"; + parameter DOB9MUX = "DOB9"; + parameter DOB8MUX = "DOB8"; + parameter DOB7MUX = "DOB7"; + parameter DOB6MUX = "DOB6"; + parameter DOB5MUX = "DOB5"; + parameter DOB4MUX = "DOB4"; + parameter DOB3MUX = "DOB3"; + parameter DOB2MUX = "DOB2"; + parameter DOB1MUX = "DOB1"; + parameter DOB0MUX = "DOB0"; - parameter GSR = "ENABLED"; + parameter WID = 0; - parameter INITVAL_00 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; - parameter INITVAL_01 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; - parameter INITVAL_02 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; - parameter INITVAL_03 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; - parameter INITVAL_04 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; - parameter INITVAL_05 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; - parameter INITVAL_06 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; - parameter INITVAL_07 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; - parameter INITVAL_08 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; - parameter INITVAL_09 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; - parameter INITVAL_0A = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; - parameter INITVAL_0B = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; - parameter INITVAL_0C = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; - parameter INITVAL_0D = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; - parameter INITVAL_0E = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; - parameter INITVAL_0F = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; - parameter INITVAL_10 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; - parameter INITVAL_11 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; - parameter INITVAL_12 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; - parameter INITVAL_13 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; - parameter INITVAL_14 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; - parameter INITVAL_15 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; - parameter INITVAL_16 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; - parameter INITVAL_17 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; - parameter INITVAL_18 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; - parameter INITVAL_19 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; - parameter INITVAL_1A = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; - parameter INITVAL_1B = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; - parameter INITVAL_1C = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; - parameter INITVAL_1D = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; - parameter INITVAL_1E = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; - parameter INITVAL_1F = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; - parameter INITVAL_20 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; - parameter INITVAL_21 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; - parameter INITVAL_22 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; - parameter INITVAL_23 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; - parameter INITVAL_24 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; - parameter INITVAL_25 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; - parameter INITVAL_26 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; - parameter INITVAL_27 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; - parameter INITVAL_28 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; - parameter INITVAL_29 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; - parameter INITVAL_2A = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; - parameter INITVAL_2B = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; - parameter INITVAL_2C = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; - parameter INITVAL_2D = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; - parameter INITVAL_2E = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; - parameter INITVAL_2F = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; - parameter INITVAL_30 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; - parameter INITVAL_31 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; - parameter INITVAL_32 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; - parameter INITVAL_33 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; - parameter INITVAL_34 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; - parameter INITVAL_35 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; - parameter INITVAL_36 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; - parameter INITVAL_37 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; - parameter INITVAL_38 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; - parameter INITVAL_39 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; - parameter INITVAL_3A = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; - parameter INITVAL_3B = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; - parameter INITVAL_3C = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; - parameter INITVAL_3D = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; - parameter INITVAL_3E = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; - parameter INITVAL_3F = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; + parameter GSR = "ENABLED"; + + parameter INITVAL_00 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; + parameter INITVAL_01 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; + parameter INITVAL_02 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; + parameter INITVAL_03 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; + parameter INITVAL_04 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; + parameter INITVAL_05 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; + parameter INITVAL_06 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; + parameter INITVAL_07 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; + parameter INITVAL_08 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; + parameter INITVAL_09 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; + parameter INITVAL_0A = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; + parameter INITVAL_0B = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; + parameter INITVAL_0C = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; + parameter INITVAL_0D = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; + parameter INITVAL_0E = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; + parameter INITVAL_0F = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; + parameter INITVAL_10 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; + parameter INITVAL_11 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; + parameter INITVAL_12 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; + parameter INITVAL_13 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; + parameter INITVAL_14 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; + parameter INITVAL_15 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; + parameter INITVAL_16 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; + parameter INITVAL_17 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; + parameter INITVAL_18 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; + parameter INITVAL_19 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; + parameter INITVAL_1A = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; + parameter INITVAL_1B = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; + parameter INITVAL_1C = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; + parameter INITVAL_1D = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; + parameter INITVAL_1E = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; + parameter INITVAL_1F = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; + parameter INITVAL_20 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; + parameter INITVAL_21 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; + parameter INITVAL_22 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; + parameter INITVAL_23 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; + parameter INITVAL_24 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; + parameter INITVAL_25 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; + parameter INITVAL_26 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; + parameter INITVAL_27 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; + parameter INITVAL_28 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; + parameter INITVAL_29 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; + parameter INITVAL_2A = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; + parameter INITVAL_2B = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; + parameter INITVAL_2C = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; + parameter INITVAL_2D = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; + parameter INITVAL_2E = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; + parameter INITVAL_2F = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; + parameter INITVAL_30 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; + parameter INITVAL_31 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; + parameter INITVAL_32 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; + parameter INITVAL_33 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; + parameter INITVAL_34 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; + parameter INITVAL_35 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; + parameter INITVAL_36 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; + parameter INITVAL_37 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; + parameter INITVAL_38 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; + parameter INITVAL_39 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; + parameter INITVAL_3A = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; + parameter INITVAL_3B = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; + parameter INITVAL_3C = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; + parameter INITVAL_3D = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; + parameter INITVAL_3E = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; + parameter INITVAL_3F = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000; endmodule // TODO: Diamond flip-flops