Skip to content
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

Add width utility functions to avoid incorrect usage of bare log2Ceil(). #819

Merged
merged 11 commits into from
Jul 18, 2019

Conversation

ucbjrl
Copy link
Contributor

@ucbjrl ucbjrl commented Apr 27, 2018

Related issue: #818

Type of change: other enhancement

Impact: API addition (no impact on existing code)

Development Phase: proposal

Release Notes
Add helper functions UnsignedBitsRequired and UnsignedWidthRequired to provide an alternative to the potentially incorrect usage of log2Ceil to calculate wire widths.

@edwardcwang
Copy link
Contributor

Consensus from dev meeting: shorten names and general agreement to add something like this

@ucbjrl ucbjrl requested a review from a team as a code owner May 23, 2019 23:26
Copy link
Contributor

@chick chick left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM.
Nit Question:
Should your tests include the in: chisel3.Data signature?
E.g. UnsignedBitsRequired(8.U) or UnsignedBitsRequired(UInt(8.W))
Also: UnsignedBitsRequired(x) == UnsignedBitsRequired(x.W) for all x: Integer, right?

@ducky64 ducky64 added this to the 3.2.0 milestone May 24, 2019
@ucbjrl
Copy link
Contributor Author

ucbjrl commented May 24, 2019

Remove apply(Data) method
change name(s) to signedBitLength, unsignedBitLength

ucbjrl added 3 commits June 10, 2019 13:25
Remove apply(Data) method.
Change name(s) to signedBitLength, unsignedBitLength.
@ucbjrl ucbjrl requested a review from chick June 17, 2019 17:24
require(in >= 0)
if (in == 0) {
// 0.bitLength returns 0 - thank you Java.
1
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Was this the behavior we wanted? (I'm sure we brought this up, I don't remember the resolution and I don't think it was written down)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe so, but we can review at next dev meeting.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Return 0, not 1.


property ("unsignedBitLength is computed correctly") {
forAll(safeUIntWidth) { case (width: Int) =>
for ( offset <- List(-1, 0, 1)) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure this test is testing anything since it's basically the duplicating the code used to implement unsignedBitLength. Consider just dropping in a few values and hand-coding the result.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Corrected in ec3e030


property ("signedBitLength is computed correctly") {
forAll(safeUIntWidth) { case (width: Int) =>
for ( offset <- List(-1, 0, 1)) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Corrected in ec3e030

Independently calculate the bit length to verify correct operation.
@jackkoenig
Copy link
Contributor

@ducky64 thoughts on merging thisz?

@jackkoenig
Copy link
Contributor

Ping @ducky64

@ducky64
Copy link
Contributor

ducky64 commented Jul 8, 2019

Is the zero width fix implemented? It doesn't appear so?

@ucbjrl
Copy link
Contributor Author

ucbjrl commented Jul 8, 2019

Thanks @ducky64 for pointing out the zero width fix hadn't yet been implemented. Should we be doing this for signed 0 as well? (Currently signedBitLength(0) == 1.)

@ducky64
Copy link
Contributor

ducky64 commented Jul 10, 2019

The unsigned case looks fine. The signed zero case is a good question.

My thoughts for signed:
0 bits: 0
1 bit: 0, -1
2 bits: 1, 0, -1, -2
though more thoughts are welcome

I'm still not a fan of the test style since it's not simple enough to be obvious at a glance (eg, explicit testvectors) but also doesn't give you the better correctness guarantees from a more formal approach. In fact, the test code is much harder to reason about than the main code, because there's so much complexity going on. That being said, I don't care enough about this to block it. Once we resolve the signed zero, I'll give this a green.

@ucbjrl
Copy link
Contributor Author

ucbjrl commented Jul 11, 2019

I agree with @ducky64, but I think there's enough confusion over this, that we shouldn't incorporate it. (I don't see how you can represent 0 without requiring any bits. Perhaps my lack of hardware knowledge is showing.)

@jackkoenig
Copy link
Contributor

Zero-width wires are fine and we have rules for removing them.

The advantage of representing 0.U with zero bits is that you can perform operations on it without increasing the resulting width, eg.: wire +& 0.U(1.W) will have a resulting width 1 greater than that of wire, while wire +& 0.U(0.W) will have a width the same as that of wire. That being said, interval width inference could be an alternative mechanism for this feature and would work for literals of any width.

@ucbjrl
Copy link
Contributor Author

ucbjrl commented Jul 11, 2019

But why add the constant 0.U in the first place? I would argue that this should be dealt with in optimizations for specific operations, not as a side-effect of the width required to store a specific constant. Similarly, x - 0.U, x + 0.S, x - 0.S, x * 1.U, and x * 1.S should be optimized away, regardless of the width of the 0 or 1 constant.
(and ditto for shifts by 0.U)

@aswaterman
Copy link
Member

aswaterman commented Jul 11, 2019 via email

@ucbjrl
Copy link
Contributor Author

ucbjrl commented Jul 11, 2019

Right. I keep forgetting the assumption that a zero-width wire has the value 0. I won't let my confusion hinder the adoption of this PR.

@ducky64
Copy link
Contributor

ducky64 commented Jul 15, 2019

Resolution from today's meeting: signed 0 is 0 bits, signed -1 is 1 bit, signed 1 is 2 bits.

Copy link
Contributor

@ducky64 ducky64 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks fine.

@ucbjrl ucbjrl merged commit ae784b6 into master Jul 18, 2019
@ucbjrl ucbjrl deleted the bitsrequired branch July 18, 2019 20:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants