-
Notifications
You must be signed in to change notification settings - Fork 615
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Shift right produce at least 1 bit width result #3752
Conversation
Look good to the firrtl-spec, but I'm not sure if it would break some tests and large code, cc @jackkoenig and @seldridge |
Seems that none of the existing test cases are broken, I'm writing a new test case for it. |
6e232a4
to
47b8354
Compare
change base to |
@sequencer Done. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, feel free to revert or submit bug report if this PR affect some corner cases(I believe there won't be, due to firtool also fix it in the parser.)
This fix does break SiFive internal code, and may break other users' code. I am somewhat inclined to revert and then see if we can find a way to warn users so they can change their code before we then roll the fix out. On the other hand, this is a very real bug. If you write code that relies on Chisel's knowledge of the width, you can get the wrong result, consider the following: class Foo extends Module {
val a, b = IO(Input(UInt(1.W)))
val out1, out2, out3 = IO(Output(UInt()))
val m = Cat(a, b >> 1)
out1 := m
out2 := WireInit(UInt(m.getWidth.W), m)
out3 := WireInit(m)
} Chisel 6.0.0 gives: module Foo(
input clock,
reset,
a,
b,
x,
y,
output [1:0] out1,
output out2,
output [1:0] out3
);
wire [1:0] m = {a, 1'h0};
assign out1 = m;
assign out2 = 1'h0;
assign out3 = m;
endmodule
Note that So I'm of two minds. This fix does break currently functioning SiFive code which is not good, but it is also a real bug that can cause reasonable code written by the user to do the wrong thing. Let me see if there's a warning we can add that won't have too many false positives. |
Yes, this bug also infect the The reason not happening in current parsing-based firtool implementation is because it did some how hard coded fixing, see https://github.com/llvm/circt/blob/38b53252aec2c0a0f67acfe5ba5522154a755d32/lib/Dialect/FIRRTL/FIRRTLOps.cpp#L5101.
So the essential problem is: chisel width inference return a wrong result(v.s. spec). So basically we need to align the chisel width and firtool width. here is what I'm proposing to fix:
|
I don't see a good reason not to change the firrtl spec. tail is the only other op which might be expected to return 0-width values and it does. |
I need to work on more exhaustive checking, but a quick experiment using firtool modified to return 0-width for this case results in identical Verilog for the 2 designs I checked. This is still a change we need to be careful with and warn users of but, at least empirically, it seems less likely to cause quiet changes to the design. It's also much easier to get the old behavior in cases where it would cause a change in behavior as you can always OR the result of the right shift with a 1-bit 0 to get the old behavior (and have Chisel report the correct width as well!) |
I ran a much more extensive test of firtool modified to return 0-width for UInt. On over 100 configurations, I found that the vast majority had identical Verilog. For the handful that didn't, they all passed LEC. SiFive's experience here does not mean others won't see functional changes from this change so we need to roll this out carefully and help users check for silent behavior changes when bumping. This will be part of the Chisel 7.0.0 release. |
This reverts commit 1634320.
Revert changes to the width of static shift right. Originally, Chisel would return a 0-bit value. However, this violated the FIRRTL spec which mandated that this return a 1-bit value. FIRRTL compilers would then clean this up, however, if a user looks at the Chisel-determined width they would get the wrong answer. Commit 1634320 made Chisel align with FIRRTL. After additional discussion, it was decided that the best course of action was to make FIRRTL _align with Chisel_ for UInt, but not for SInt. Specifically, the following behaviors are what we want to move towards: 1. The smallest width of a UInt shifted right is 0-bit 2. The smallest width of an SInt shifted right is 1-bit This will then be handled with changes to the FIRRTL spec and by FIRRTL compilers. In the mean time, do not introduce incorrect behavior in Chisel and preserve things the way they were. This reverts commit 1634320. Signed-off-by: Schuyler Eldridge <schuyler.eldridge@sifive.com>
Revert changes to the width of static shift right. Originally, Chisel would return a 0-bit value. However, this violated the FIRRTL spec which mandated that this return a 1-bit value. FIRRTL compilers would then clean this up, however, if a user looks at the Chisel-determined width they would get the wrong answer. Commit 1634320 made Chisel align with FIRRTL. After additional discussion, it was decided that the best course of action was to make FIRRTL _align with Chisel_ for UInt, but not for SInt. Specifically, the following behaviors are what we want to move towards: 1. The smallest width of a UInt shifted right is 0-bit 2. The smallest width of an SInt shifted right is 1-bit This will then be handled with changes to the FIRRTL spec and by FIRRTL compilers. In the mean time, do not introduce incorrect behavior in Chisel and preserve things the way they were. This reverts commit 1634320. Signed-off-by: Schuyler Eldridge <schuyler.eldridge@sifive.com>
Fixes #3735.