3
0
Fork 0
mirror of https://github.com/YosysHQ/yosys synced 2025-11-15 18:35:45 +00:00

Merge pull request #5473 from YosysHQ/krys/unsized_params

Handle unsized params
This commit is contained in:
KrystalDelusion 2025-11-12 07:14:44 +13:00 committed by GitHub
commit 529886f7fb
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 72 additions and 12 deletions

View file

@ -61,7 +61,9 @@ void RTLIL_BACKEND::dump_const(std::ostream &f, const RTLIL::Const &data, int wi
return; return;
} }
} }
f << stringf("%d'", width); if ((data.flags & RTLIL::CONST_FLAG_UNSIZED) == 0) {
f << stringf("%d'", width);
}
if (data.flags & RTLIL::CONST_FLAG_SIGNED) { if (data.flags & RTLIL::CONST_FLAG_SIGNED) {
f << stringf("s"); 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); dump_attributes(f, indent, cell);
f << stringf("%s" "cell %s %s\n", indent, cell->type, cell->name); f << stringf("%s" "cell %s %s\n", indent, cell->type, cell->name);
for (const auto& [name, param] : reversed(cell->parameters)) { 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_SIGNED) != 0 ? " signed" : "",
(param.flags & RTLIL::CONST_FLAG_REAL) != 0 ? " real" : "", (param.flags & RTLIL::CONST_FLAG_REAL) != 0 ? " real" : "",
(param.flags & RTLIL::CONST_FLAG_UNSIZED) != 0 ? " unsized" : "",
name); name);
dump_const(f, param); dump_const(f, param);
f << stringf("\n"); f << stringf("\n");

View file

@ -993,6 +993,8 @@ RTLIL::Const AstNode::asParaConst() const
RTLIL::Const val = asAttrConst(); RTLIL::Const val = asAttrConst();
if (is_signed) if (is_signed)
val.flags |= RTLIL::CONST_FLAG_SIGNED; val.flags |= RTLIL::CONST_FLAG_SIGNED;
if (is_unsized)
val.flags |= RTLIL::CONST_FLAG_UNSIZED;
return val; return val;
} }
@ -1766,7 +1768,10 @@ static std::string serialize_param_value(const RTLIL::Const &val) {
res.push_back('s'); res.push_back('s');
if (val.flags & RTLIL::ConstFlags::CONST_FLAG_REAL) if (val.flags & RTLIL::ConstFlags::CONST_FLAG_REAL)
res.push_back('r'); 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.push_back('\'');
res.append(val.as_string("?")); res.append(val.as_string("?"));
return res; return res;
@ -1860,7 +1865,7 @@ std::string AstModule::derive_common(RTLIL::Design *design, const dict<RTLIL::Id
} else if ((it->second.flags & RTLIL::CONST_FLAG_STRING) != 0) } else if ((it->second.flags & RTLIL::CONST_FLAG_STRING) != 0)
child->children[0] = AstNode::mkconst_str(loc, it->second.decode_string()); child->children[0] = AstNode::mkconst_str(loc, it->second.decode_string());
else 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); rewritten.insert(it->first);
} }

View file

@ -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 (children[0]->type == AST_CONSTANT) {
if (width != int(children[0]->bits.size())) { if (width != int(children[0]->bits.size())) {
RTLIL::SigSpec sig(children[0]->bits); RTLIL::Const val;
sig.extend_u0(width, children[0]->is_signed); if (children[0]->is_unsized) {
children[0] = mkconst_bits(location, sig.as_const().to_bits(), is_signed); val = children[0]->bitsAsUnsizedConst(width);
} else {
val = children[0]->bitsAsConst(width);
}
children[0] = mkconst_bits(location, val.to_bits(), is_signed);
fixup_hierarchy_flags(); fixup_hierarchy_flags();
} }
children[0]->is_signed = is_signed; children[0]->is_signed = is_signed;

View file

@ -567,10 +567,13 @@ struct RTLILFrontendWorker {
if (try_parse_keyword("parameter")) { if (try_parse_keyword("parameter")) {
bool is_signed = false; bool is_signed = false;
bool is_real = false; bool is_real = false;
bool is_unsized = false;
if (try_parse_keyword("signed")) { if (try_parse_keyword("signed")) {
is_signed = true; is_signed = true;
} else if (try_parse_keyword("real")) { } else if (try_parse_keyword("real")) {
is_real = true; is_real = true;
} else if (try_parse_keyword("unsized")) {
is_unsized = true;
} }
RTLIL::IdString param_name = parse_id(); RTLIL::IdString param_name = parse_id();
RTLIL::Const val = parse_const(); RTLIL::Const val = parse_const();
@ -578,6 +581,8 @@ struct RTLILFrontendWorker {
val.flags |= RTLIL::CONST_FLAG_SIGNED; val.flags |= RTLIL::CONST_FLAG_SIGNED;
if (is_real) if (is_real)
val.flags |= RTLIL::CONST_FLAG_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)}); cell->parameters.insert({std::move(param_name), std::move(val)});
expect_eol(); expect_eol();
} else if (try_parse_keyword("connect")) { } else if (try_parse_keyword("connect")) {

View file

@ -53,10 +53,11 @@ namespace RTLIL
// Semantic metadata - how can this constant be interpreted? // Semantic metadata - how can this constant be interpreted?
// Values may be generally non-exclusive // Values may be generally non-exclusive
enum ConstFlags : unsigned char { enum ConstFlags : unsigned char {
CONST_FLAG_NONE = 0, CONST_FLAG_NONE = 0,
CONST_FLAG_STRING = 1, CONST_FLAG_STRING = 1,
CONST_FLAG_SIGNED = 2, // only used for parameters CONST_FLAG_SIGNED = 2, // only used for parameters
CONST_FLAG_REAL = 4 // only used for parameters CONST_FLAG_REAL = 4, // only used for parameters
CONST_FLAG_UNSIZED = 8, // only used for parameters
}; };
enum SelectPartials : unsigned char { enum SelectPartials : unsigned char {

View file

@ -38,3 +38,20 @@ module foo(
assign b = bb; assign b = bb;
assign y = a + bb; assign y = a + bb;
endmodule 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

View file

@ -5,7 +5,20 @@ module pass_through(
assign out = inp; assign out = inp;
endmodule endmodule
module set_param #(
parameter logic [63:0] VALUE
) (
output logic [63:0] out
);
assign out = VALUE;
endmodule
module top; module top;
localparam logic [63:0]
l01 = '0,
l02 = '1,
l03 = 'x,
l04 = 'z;
logic [63:0] logic [63:0]
o01, o02, o03, o04, o01, o02, o03, o04,
o05, o06, o07, o08, o05, o06, o07, o08,
@ -23,6 +36,10 @@ module top;
pass_through pt10('1, o10); pass_through pt10('1, o10);
pass_through pt11('x, o11); pass_through pt11('x, o11);
pass_through pt12('z, o12); 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 always @* begin
assert (o01 === {64 {1'b0}}); assert (o01 === {64 {1'b0}});
assert (o02 === {64 {1'b1}}); assert (o02 === {64 {1'b1}});
@ -36,5 +53,13 @@ module top;
assert (o10 === {64 {1'b1}}); assert (o10 === {64 {1'b1}});
assert (o11 === {64 {1'bx}}); assert (o11 === {64 {1'bx}});
assert (o12 === {64 {1'bz}}); 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 end
endmodule endmodule

View file

@ -1,5 +1,5 @@
read_verilog -sv unbased_unsized.sv read_verilog -sv unbased_unsized.sv
hierarchy hierarchy -top top
proc proc
flatten flatten
opt -full opt -full