Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions kernel/rtlil.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
2 changes: 2 additions & 0 deletions kernel/rtlil.h
Original file line number Diff line number Diff line change
Expand Up @@ -1091,6 +1091,8 @@ struct RTLIL::Const
// 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<RTLIL::State> to_bits() const;
Expand Down
1 change: 1 addition & 0 deletions passes/cmds/setattr.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}
};
Expand Down
8 changes: 6 additions & 2 deletions passes/hierarchy/hierarchy.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
}

Expand Down Expand Up @@ -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));
Expand Down
18 changes: 18 additions & 0 deletions tests/verilog/issue5745.ys
Original file line number Diff line number Diff line change
@@ -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 <<EOT
module mod #(parameter p2=11) (output k);
wire signed [8:0] m = -32;
assign k = m < p2;
endmodule
EOT
chparam -set p2 11
hierarchy -top mod
sat -prove k 1 -verify
Loading