diff --git a/backends/rtlil/rtlil_backend.cc b/backends/rtlil/rtlil_backend.cc index 057edc584..d47bebf82 100644 --- a/backends/rtlil/rtlil_backend.cc +++ b/backends/rtlil/rtlil_backend.cc @@ -61,7 +61,9 @@ void RTLIL_BACKEND::dump_const(std::ostream &f, const RTLIL::Const &data, int wi return; } } - f << stringf("%d'", width); + if ((data.flags & RTLIL::CONST_FLAG_UNSIZED) == 0) { + f << stringf("%d'", width); + } if (data.flags & RTLIL::CONST_FLAG_SIGNED) { f << stringf("s"); } @@ -173,9 +175,10 @@ void RTLIL_BACKEND::dump_cell(std::ostream &f, std::string indent, const RTLIL:: dump_attributes(f, indent, cell); f << stringf("%s" "cell %s %s\n", indent, cell->type, cell->name); for (const auto& [name, param] : reversed(cell->parameters)) { - f << stringf("%s parameter%s%s %s ", indent, + f << stringf("%s parameter%s%s%s %s ", indent, (param.flags & RTLIL::CONST_FLAG_SIGNED) != 0 ? " signed" : "", (param.flags & RTLIL::CONST_FLAG_REAL) != 0 ? " real" : "", + (param.flags & RTLIL::CONST_FLAG_UNSIZED) != 0 ? " unsized" : "", name); dump_const(f, param); f << stringf("\n"); diff --git a/frontends/ast/ast.cc b/frontends/ast/ast.cc index 4a16abee9..984c4294c 100644 --- a/frontends/ast/ast.cc +++ b/frontends/ast/ast.cc @@ -993,6 +993,8 @@ RTLIL::Const AstNode::asParaConst() const RTLIL::Const val = asAttrConst(); if (is_signed) val.flags |= RTLIL::CONST_FLAG_SIGNED; + if (is_unsized) + val.flags |= RTLIL::CONST_FLAG_UNSIZED; return val; } @@ -1766,7 +1768,10 @@ static std::string serialize_param_value(const RTLIL::Const &val) { res.push_back('s'); if (val.flags & RTLIL::ConstFlags::CONST_FLAG_REAL) res.push_back('r'); - res += stringf("%d", GetSize(val)); + if (val.flags & RTLIL::ConstFlags::CONST_FLAG_UNSIZED) + res.push_back('u'); + else + res += stringf("%d", GetSize(val)); res.push_back('\''); res.append(val.as_string("?")); return res; @@ -1860,7 +1865,7 @@ std::string AstModule::derive_common(RTLIL::Design *design, const dictsecond.flags & RTLIL::CONST_FLAG_STRING) != 0) child->children[0] = AstNode::mkconst_str(loc, it->second.decode_string()); else - child->children[0] = AstNode::mkconst_bits(loc, it->second.to_bits(), (it->second.flags & RTLIL::CONST_FLAG_SIGNED) != 0); + child->children[0] = AstNode::mkconst_bits(loc, it->second.to_bits(), (it->second.flags & RTLIL::CONST_FLAG_SIGNED) != 0, (it->second.flags & RTLIL::CONST_FLAG_UNSIZED) != 0); rewritten.insert(it->first); } diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index 308406591..83174e963 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -2265,9 +2265,13 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin } if (children[0]->type == AST_CONSTANT) { if (width != int(children[0]->bits.size())) { - RTLIL::SigSpec sig(children[0]->bits); - sig.extend_u0(width, children[0]->is_signed); - children[0] = mkconst_bits(location, sig.as_const().to_bits(), is_signed); + RTLIL::Const val; + if (children[0]->is_unsized) { + val = children[0]->bitsAsUnsizedConst(width); + } else { + val = children[0]->bitsAsConst(width); + } + children[0] = mkconst_bits(location, val.to_bits(), is_signed); fixup_hierarchy_flags(); } children[0]->is_signed = is_signed; diff --git a/frontends/rtlil/rtlil_frontend.cc b/frontends/rtlil/rtlil_frontend.cc index 04d01fc93..271962725 100644 --- a/frontends/rtlil/rtlil_frontend.cc +++ b/frontends/rtlil/rtlil_frontend.cc @@ -567,10 +567,13 @@ struct RTLILFrontendWorker { if (try_parse_keyword("parameter")) { bool is_signed = false; bool is_real = false; + bool is_unsized = false; if (try_parse_keyword("signed")) { is_signed = true; } else if (try_parse_keyword("real")) { is_real = true; + } else if (try_parse_keyword("unsized")) { + is_unsized = true; } RTLIL::IdString param_name = parse_id(); RTLIL::Const val = parse_const(); @@ -578,6 +581,8 @@ struct RTLILFrontendWorker { val.flags |= RTLIL::CONST_FLAG_SIGNED; if (is_real) val.flags |= RTLIL::CONST_FLAG_REAL; + if (is_unsized) + val.flags |= RTLIL::CONST_FLAG_UNSIZED; cell->parameters.insert({std::move(param_name), std::move(val)}); expect_eol(); } else if (try_parse_keyword("connect")) { diff --git a/kernel/rtlil.h b/kernel/rtlil.h index 79cc73e45..27f610f85 100644 --- a/kernel/rtlil.h +++ b/kernel/rtlil.h @@ -53,10 +53,11 @@ namespace RTLIL // Semantic metadata - how can this constant be interpreted? // Values may be generally non-exclusive enum ConstFlags : unsigned char { - CONST_FLAG_NONE = 0, - CONST_FLAG_STRING = 1, - CONST_FLAG_SIGNED = 2, // only used for parameters - CONST_FLAG_REAL = 4 // only used for parameters + CONST_FLAG_NONE = 0, + CONST_FLAG_STRING = 1, + CONST_FLAG_SIGNED = 2, // only used for parameters + CONST_FLAG_REAL = 4, // only used for parameters + CONST_FLAG_UNSIZED = 8, // only used for parameters }; enum SelectPartials : unsigned char { diff --git a/tests/rtlil/everything.v b/tests/rtlil/everything.v index 666d630c2..c4f8c348a 100644 --- a/tests/rtlil/everything.v +++ b/tests/rtlil/everything.v @@ -38,3 +38,20 @@ module foo( assign b = bb; assign y = a + bb; endmodule + +module set_param #( + parameter [3:0] VALUE = 1'bx +) ( + output logic [3:0] out +); + assign out = VALUE; +endmodule + +module use_param ( + output logic [3:0] a, b, c, d +); + set_param #($signed(1)) spa (a); + set_param #('1) spb (b); + set_param #(1.1) spc (c); + set_param #(1'b1) spd (d); +endmodule diff --git a/tests/verilog/unbased_unsized.sv b/tests/verilog/unbased_unsized.sv index 1d0c5a72c..62f7d41ff 100644 --- a/tests/verilog/unbased_unsized.sv +++ b/tests/verilog/unbased_unsized.sv @@ -5,7 +5,20 @@ module pass_through( assign out = inp; endmodule +module set_param #( + parameter logic [63:0] VALUE +) ( + output logic [63:0] out +); + assign out = VALUE; +endmodule + module top; + localparam logic [63:0] + l01 = '0, + l02 = '1, + l03 = 'x, + l04 = 'z; logic [63:0] o01, o02, o03, o04, o05, o06, o07, o08, @@ -23,6 +36,10 @@ module top; pass_through pt10('1, o10); pass_through pt11('x, o11); pass_through pt12('z, o12); + set_param #('0) sp13(o13); + set_param #('1) sp14(o14); + set_param #('x) sp15(o15); + set_param #('z) sp16(o16); always @* begin assert (o01 === {64 {1'b0}}); assert (o02 === {64 {1'b1}}); @@ -36,5 +53,13 @@ module top; assert (o10 === {64 {1'b1}}); assert (o11 === {64 {1'bx}}); assert (o12 === {64 {1'bz}}); + assert (l01 === {64 {1'b0}}); + assert (l02 === {64 {1'b1}}); + assert (l03 === {64 {1'bx}}); + assert (l04 === {64 {1'bz}}); + assert (o13 === {64 {1'b0}}); + assert (o14 === {64 {1'b1}}); + assert (o15 === {64 {1'bx}}); + assert (o16 === {64 {1'bz}}); end endmodule diff --git a/tests/verilog/unbased_unsized.ys b/tests/verilog/unbased_unsized.ys index 3290650d5..851866140 100644 --- a/tests/verilog/unbased_unsized.ys +++ b/tests/verilog/unbased_unsized.ys @@ -1,5 +1,5 @@ read_verilog -sv unbased_unsized.sv -hierarchy +hierarchy -top top proc flatten opt -full