From 33a22b5cd135b55b9e4d0f195832282be542e4b2 Mon Sep 17 00:00:00 2001 From: George Rennie Date: Mon, 26 May 2025 15:28:14 +0100 Subject: [PATCH 1/3] kernel: fix convertible_to_int for overflowing unsigned values --- kernel/rtlil.cc | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index c08e78dce..021aff73b 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -383,7 +383,23 @@ int RTLIL::Const::as_int(bool is_signed) const bool RTLIL::Const::convertible_to_int(bool is_signed) const { auto size = get_min_size(is_signed); - return (size > 0 && size <= 32); + + if (size <= 0) + return false; + + // If it fits in 31 bits it is definitely convertible + if (size <= 31) + return true; + + // If it fits in 32 bits, it is convertible if signed or if unsigned and the + // leading bit is not 1 + if (size == 32) { + if (is_signed) + return true; + return get_bits().at(31) != State::S1; + } + + return false; } std::optional RTLIL::Const::try_as_int(bool is_signed) const From 353fd0f7f424f5a7ae303b14285f108fc648468e Mon Sep 17 00:00:00 2001 From: George Rennie Date: Mon, 26 May 2025 15:28:44 +0100 Subject: [PATCH 2/3] tests: test opt_expr for 32 bit unsigned shifts --- tests/opt/opt_expr_shift.ys | 47 +++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/tests/opt/opt_expr_shift.ys b/tests/opt/opt_expr_shift.ys index 943d370dc..5a27562f6 100644 --- a/tests/opt/opt_expr_shift.ys +++ b/tests/opt/opt_expr_shift.ys @@ -111,3 +111,50 @@ select -assert-none t:$shr select -assert-none t:$sshl select -assert-none t:$sshr select -assert-none t:$shiftx + +design -reset + +read_verilog <> 32'hffffffff; + assign sshl = in <<< 32'hffffffff; + assign sshr = in >>> 32'hffffffff; + assign shiftx = in[32'hffffffff +: 8]; + + wire signed [31:0] shamt = 32'hffffffff; + assign shl_s = in << shamt; + assign shr_s = in >> shamt; + assign sshl_s = in <<< shamt; + assign sshr_s = in >>> shamt; + assign shiftx_s = in[shamt +: 8]; +endmodule +EOT + +select -assert-count 2 t:$shl +select -assert-count 2 t:$shr +select -assert-count 2 t:$sshl +select -assert-count 2 t:$sshr +select -assert-count 1 t:$shiftx + +equiv_opt opt_expr + +design -load postopt +select -assert-none t:$shl +select -assert-none t:$shr +select -assert-none t:$sshl +select -assert-none t:$sshr +select -assert-none t:$shiftx From e0c1e88f19a34aa91d53246e86810a8467de7ae4 Mon Sep 17 00:00:00 2001 From: George Rennie Date: Mon, 26 May 2025 15:34:13 +0100 Subject: [PATCH 3/3] kernel: use try_as_int to implement as_int_compress --- kernel/rtlil.cc | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index 021aff73b..1cdc15bb5 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -455,18 +455,7 @@ void RTLIL::Const::compress(bool is_signed) std::optional RTLIL::Const::as_int_compress(bool is_signed) const { - auto size = get_min_size(is_signed); - if(size == 0 || size > 32) - return std::nullopt; - - int32_t ret = 0; - for (auto i = 0; i < size && i < 32; i++) - if ((*this)[i] == State::S1) - ret |= 1 << i; - if (is_signed && (*this)[size-1] == State::S1) - for (auto i = size; i < 32; i++) - ret |= 1 << i; - return ret; + return try_as_int(is_signed); } std::string RTLIL::Const::as_string(const char* any) const