3
0
Fork 0
mirror of https://github.com/YosysHQ/yosys synced 2026-07-14 19:25:40 +00:00

Fix wide shift count fold.

This commit is contained in:
nella 2026-07-07 15:04:57 +02:00
parent 8a2499b544
commit 5628dff0bd
3 changed files with 65 additions and 1 deletions

View file

@ -588,7 +588,7 @@ bool RTLIL::Const::convertible_to_int(bool is_signed) const
if (size == 32) {
if (is_signed)
return true;
return back() != State::S1;
return (*this)[size - 1] != State::S1;
}
return false;

View file

@ -114,6 +114,36 @@ select -assert-none t:$shiftx
design -reset
read_verilog <<EOT
module top (
input wire [3:0] in,
output wire [7:0] shl,
output wire [7:0] shr,
output wire [7:0] sshl,
output wire [7:0] sshr,
);
assign shl = in << 33'h0ffffffff;
assign shr = in >> 33'h0ffffffff;
assign sshl = in <<< 33'h0ffffffff;
assign sshr = in >>> 33'h0ffffffff;
endmodule
EOT
select -assert-count 1 t:$shl
select -assert-count 1 t:$shr
select -assert-count 1 t:$sshl
select -assert-count 1 t:$sshr
equiv_opt -assert 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
design -reset
read_verilog <<EOT
module top (
input wire [3:0] in,

View file

@ -1,4 +1,5 @@
#include <gtest/gtest.h>
#include <limits>
#include "kernel/rtlil.h"
YOSYS_NAMESPACE_BEGIN
@ -35,6 +36,39 @@ namespace RTLIL {
EXPECT_FALSE(c2 < c3);
}
TEST_F(KernelRtlilTest, ConstConvertibleToInt) {
// A Const whose minimal unsigned size is exactly 32 bits (bit 31 set)
// but whose full width is larger must not be reported as convertible
// to a (signed) int when treated as unsigned
{
// 33 bits: bits 0..31 = 1, bit 32 = 0 => value 0xffffffff
std::vector<State> v(33, S1);
v[32] = S0;
Const c(v);
EXPECT_FALSE(c.convertible_to_int(false));
EXPECT_EQ(c.as_int_saturating(false), std::numeric_limits<int>::max());
EXPECT_FALSE(c.convertible_to_int(true));
EXPECT_EQ(c.as_int_saturating(true), std::numeric_limits<int>::max());
}
{
// 32-bit unsigned 0x7fffffff fits in a signed int
std::vector<State> v(32, S1);
v[31] = S0;
Const c(v);
EXPECT_TRUE(c.convertible_to_int(false));
EXPECT_EQ(c.as_int(false), 0x7fffffff);
}
{
// 32-bit unsigned 0xffffffff does not fit in a signed int
std::vector<State> v(32, S1);
Const c(v);
EXPECT_FALSE(c.convertible_to_int(false));
EXPECT_EQ(c.as_int_saturating(false), std::numeric_limits<int>::max());
}
}
TEST_F(KernelRtlilTest, ConstStr) {
// We have multiple distinct sections since it's annoying
// to list multiple testcases as friends of Const in kernel/rtlil.h