-
Notifications
You must be signed in to change notification settings - Fork 614
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
Change the width of static shift right #3824
Conversation
6517cd0
to
bb1abcd
Compare
@@ -124,38 +126,50 @@ trait ChiselRunners extends Assertions { | |||
assert(!runTester(t, additionalVResources, annotations)) | |||
} | |||
|
|||
def assertKnownWidth(expected: Int)(gen: => Data): Unit = { | |||
def assertKnownWidth(expected: Int, args: Iterable[String] = Nil)(gen: => Data)(implicit pos: Position): Unit = { |
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.
Huh, so this is for scalatest to properly pass the source locator to the assert? Interesting.
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.
Indeed, I added this because a test was failing and I wasn't sure which one.
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!
binop(sourceInfo, UInt(this.width.shiftRight(that)), ShiftRightOp, validateShiftAmount(that)) | ||
|
||
// Implement legacy [buggy] UInt shr behavior for both Chisel and FIRRTL | ||
@nowarn("msg=method shiftRight in class Width is deprecated") |
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.
What does nowarn mean again?
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.
I deprecated Width.shiftRight
and it would trigger a warning here (and warnings are errors), so this @nowarn
suppresses it. Obviously we are allowed to use our own deprecated APIs, but the API is public so I couldn't/shouldn't just delete it.
* A UInt shifted right by a static amount >= its width will now result in a 0-bit UInt * An SInt shifted right by a static amount >= its width will now result in a 1-bit SInt (the sign bit) This is a change for SInts which Chisel would treat the output as a 0-bit SInt. However, FIRRTL implemented different behavior where both UInts and SInts would result in 1-bit values (which shifted right by an amount >= the width of the input). This makes the width behavior consistent with the FIRRTL 4.0.0 spec.
New ChiselOption UseLegacyShiftRightWidthBehavior with CLI --legacy-shift-right-width will configure Chisel to emulate the old Chisel and FIRRTL behavior for the width of static shift right. This option is only intended for migrating old code and will eventually be removed.
bb1abcd
to
cdb3793
Compare
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
Nits and suggestions for compacting some code and tests.
def unsignedShiftRight(that: Int): Width = this.op(this, (a, b) => 0.max(a - that)) | ||
def signedShiftRight(that: Int): Width = this.op(this, (a, b) => 1.max(a - that)) | ||
def dynamicShiftLeft(that: Width): Width = |
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.
Mega-nit: the three new methods could all be made final. This would make them inconsistent with other methods here, though. There's also very limited risk here because this thing is sealed.
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.
I think the sealing is more than sufficient. I probably don't actually want them to be final because I have the ulterior motive of possibly introducing a "WidthChanged" private subclass of KnownWidth
that could capture information about semantic changes in widths and warn when they are observable. I don't intend to implement it any time soon but there may be future changes were we would want to.
assertKnownWidth(4, args) { | ||
val in = IO(Input(SInt(8.W))) | ||
in >> 4 | ||
} | ||
assertKnownWidth(0, args) { | ||
val in = IO(Input(SInt(8.W))) | ||
in >> 8 | ||
} | ||
assertKnownWidth(0, args) { | ||
val in = IO(Input(SInt(8.W))) | ||
in >> 16 | ||
} | ||
assertKnownWidth(0, args) { | ||
val in = IO(Input(SInt(0.W))) | ||
in >> 8 | ||
} | ||
assertKnownWidth(0, args) { | ||
val in = IO(Input(SInt(0.W))) | ||
in >> 0 | ||
} | ||
assertInferredWidth(4, args) { | ||
val in = IO(Input(SInt(8.W))) | ||
val w = WireInit(SInt(), in) | ||
w >> 4 | ||
} | ||
assertInferredWidth(1, args) { | ||
val in = IO(Input(SInt(8.W))) | ||
val w = WireInit(SInt(), in) | ||
w >> 8 | ||
} | ||
assertInferredWidth(1, args) { | ||
val in = IO(Input(SInt(8.W))) | ||
val w = WireInit(SInt(), in) | ||
w >> 16 | ||
} | ||
assertInferredWidth(1, args) { | ||
val in = IO(Input(SInt(0.W))) | ||
val w = WireInit(SInt(), in) | ||
w >> 8 | ||
} | ||
assertInferredWidth(1, args) { | ||
val in = IO(Input(SInt(0.W))) | ||
val w = WireInit(SInt(), in) | ||
w >> 0 | ||
} |
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.
There's a lot of duplication between this and the previous test. Consider if the patch could combine them in some way.
There is related commonality between these and the UInt tests.
val chiselCircuit: Option[Circuit] = None, | ||
val sourceRoots: Vector[File] = Vector.empty, | ||
val warningFilters: Vector[WarningFilter] = Vector.empty, | ||
val legacyShiftRightWidth: Boolean = false) { |
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.
Nit: the naming of this may be better as useLegacyShiftRightWidth
, i.e., something which is more obviously true/false.
This requires a recent change to CIRCT (llvm/circt#6698).
Note: The release notes were updated after merging #3841
Once firtool is released with the linked change, bumped in this repository, and this PR is merged, I think we should crack 7.0.0-M1 as it will serve as a useful milestone for dealing with this semantic change.
I also added a CLI option to emulate the old behavior:
--legacy-shift-right-width
. I'm not wedded to the name so if anyone has a better name for it, please suggest it.Instructions on using this option will be in the release notes but we should probably also add a page to the website about migrating from Chisel 6 to Chisel 7 that calls this out.
Contributor Checklist
docs/src
?Type of Improvement
Desired Merge Strategy
Release Notes
in a 0-bit UInt
in a 1-bit SInt (the sign bit)
This is a change for SInts which Chisel would treat the output as a 0-bit SInt. However, FIRRTL implemented different behavior where both UInts and SInts would result in 1-bit values (which shifted right by an amount >= the width of the input).
Users can emulate the old behavior by providing CLI option
--use-legacy-shift-right-width
. Users are encouraged to generate Verilog with and without this option and diff it to ensure the width change does not affect the correctness of their design. Note that this option is purely for code migration and should not be used long term--it will eventually be removed.Reviewer Checklist (only modified by reviewer)
3.6.x
,5.x
, or6.x
depending on impact, API modification or big change:7.0
)?Enable auto-merge (squash)
, clean up the commit message, and label withPlease Merge
.Create a merge commit
.