From 7d3e56523bf93fb3c63fc19de843278f38e43012 Mon Sep 17 00:00:00 2001 From: nella Date: Wed, 13 May 2026 16:25:15 +0200 Subject: [PATCH] Preserve param signedness across overrides. --- kernel/rtlil.cc | 9 +++++++++ kernel/rtlil.h | 2 ++ passes/cmds/setattr.cc | 1 + passes/hierarchy/hierarchy.cc | 8 ++++++-- tests/verilog/issue5745.ys | 18 ++++++++++++++++++ 5 files changed, 36 insertions(+), 2 deletions(-) create mode 100644 tests/verilog/issue5745.ys diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index a99f0803e..1a7dc6b41 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -615,6 +615,15 @@ int RTLIL::Const::as_int_saturating(bool is_signed) const return as_int(is_signed); } +void RTLIL::Const::tag_bare_integer_const(const std::string &value) +{ + if (value.empty() || value.find('\'') != std::string::npos) + return; + size_t start = (value[0] == '-' || value[0] == '+') ? 1 : 0; + if (start < value.size() && std::all_of(value.begin() + start, value.end(), ::isdigit)) + flags |= RTLIL::CONST_FLAG_SIGNED; +} + int RTLIL::Const::get_min_size(bool is_signed) const { if (empty()) return 0; diff --git a/kernel/rtlil.h b/kernel/rtlil.h index b32f9ea76..e55caf35a 100644 --- a/kernel/rtlil.h +++ b/kernel/rtlil.h @@ -1091,6 +1091,8 @@ public: // over/underflow, otherwise the max/min value for int depending on the sign. int as_int_saturating(bool is_signed = false) const; + void tag_bare_integer_const(const std::string &value); + std::string as_string(const char* any = "-") const; static Const from_string(const std::string &str); std::vector to_bits() const; diff --git a/passes/cmds/setattr.cc b/passes/cmds/setattr.cc index 25d8fd34c..ef9bd0d34 100644 --- a/passes/cmds/setattr.cc +++ b/passes/cmds/setattr.cc @@ -41,6 +41,7 @@ struct setunset_t if (!RTLIL::SigSpec::parse(sig_value, nullptr, set_value)) log_cmd_error("Can't decode value '%s'!\n", set_value); value = sig_value.as_const(); + value.tag_bare_integer_const(set_value); } } }; diff --git a/passes/hierarchy/hierarchy.cc b/passes/hierarchy/hierarchy.cc index 416997bee..34cedfd34 100644 --- a/passes/hierarchy/hierarchy.cc +++ b/passes/hierarchy/hierarchy.cc @@ -985,7 +985,9 @@ struct HierarchyPass : public Pass { SigSpec sig_value; if (!RTLIL::SigSpec::parse(sig_value, NULL, para.second)) log_cmd_error("Can't decode value '%s'!\n", para.second); - top_parameters[RTLIL::escape_id(para.first)] = sig_value.as_const(); + RTLIL::Const c = sig_value.as_const(); + c.tag_bare_integer_const(para.second); + top_parameters[RTLIL::escape_id(para.first)] = c; } } @@ -1073,7 +1075,9 @@ struct HierarchyPass : public Pass { SigSpec sig_value; if (!RTLIL::SigSpec::parse(sig_value, NULL, para.second)) log_cmd_error("Can't decode value '%s'!\n", para.second); - top_parameters[RTLIL::escape_id(para.first)] = sig_value.as_const(); + RTLIL::Const c = sig_value.as_const(); + c.tag_bare_integer_const(para.second); + top_parameters[RTLIL::escape_id(para.first)] = c; } top_mod = design->module(top_mod->derive(design, top_parameters)); diff --git a/tests/verilog/issue5745.ys b/tests/verilog/issue5745.ys new file mode 100644 index 000000000..938ead63a --- /dev/null +++ b/tests/verilog/issue5745.ys @@ -0,0 +1,18 @@ +# Issue #5745: chparam values are unsigned when using read_verilog frontend +# +# When chparam overrides a parameter value, the signed attribute is lost, +# causing signed comparisons to silently use unsigned logic. +# +# m = -32 (signed 9-bit), p2 = 11. Correct signed semantics: -32 < 11, so k = 1. +# Bug: chparam strips the signed attribute from p2. The $lt cell gets A_SIGNED=0, +# B_SIGNED=0, so the comparison treats m as unsigned (480 > 11), giving k = 0. + +read_verilog <