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

Provide an implementation of litOption() for BundleLits #1280

Merged
merged 9 commits into from
Jul 13, 2020

Conversation

ucbjrl
Copy link
Contributor

@ucbjrl ucbjrl commented Dec 18, 2019

Related issue: #1277, ucb-bar/dsptools#184

Type of change: bug report

Impact: API addition (no impact on existing code)

Development Phase: implementation

Release Notes
Provide an implementation of litOption for Aggregates (Bundles).

This is just a band aid until an Aggregate `isLit()` method (for which work has begun) is implemented.
@ucbjrl ucbjrl requested a review from a team as a code owner December 18, 2019 00:20
# Conflicts:
#	chiselFrontend/src/main/scala/chisel3/Aggregate.scala
@jackkoenig
Copy link
Contributor

jackkoenig commented Dec 18, 2019

Probably want to rebase/cherry-pick on master since bandaid None was squashed-and-merged

@ucbjrl
Copy link
Contributor Author

ucbjrl commented Dec 18, 2019

We should add some tests to verify this works with Vec literals as well.

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.

Some style concerns, a question, and a possible overflow, but otherwise looks sane.
Also consider adding a test for a literal with a >64 bit element.

val value = shiftadd._2 & mask
(accumulator << width) + value
}
try {
Copy link
Contributor

Choose a reason for hiding this comment

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

The need for a try-catch seems like a red flag. What is this meant to catch that isn't handled by an Option? And can we fix that instead?

try {
topBindingOpt match {
case Some(BundleLitBinding(_)) =>
Some(getElements.reverse.map{ case e => (e.width.get, e.litOption().get)}.foldLeft(BigInt(0))(shiftAdd(_, _)))
Copy link
Contributor

Choose a reason for hiding this comment

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

I think the map and fold should be broken into multiple lines for readability. Took a while to parse this...

// Shift the accumulated value by our width and add in our component, masked by our width.
def shiftAdd(accumulator: BigInt, shiftadd: (Int, BigInt)): BigInt = {
val width = shiftadd._1
val mask = (1 << width) - 1
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this a Int or BigInt type? Will this work for >32 bits?

def shiftAdd(accumulator: BigInt, shiftadd: (Int, BigInt)): BigInt = {
val width = shiftadd._1
val mask = (1 << width) - 1
val value = shiftadd._2 & mask
Copy link
Contributor

Choose a reason for hiding this comment

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

Is the mask ever necessary? I'd be tempted to assert out of the mask actually did anything, since that means a literal is overflowing its allotted width?

@@ -28,7 +28,8 @@ class BundleLiteralSpec extends ChiselFlatSpec {
chisel3.assert(outsideBundleLit.a === 42.U)
chisel3.assert(outsideBundleLit.b === true.B)
chisel3.assert(outsideBundleLit.c === MyEnum.sB)

chisel3.assert(outsideBundleLit.isLit())
chisel3.assert(outsideBundleLit.litValue().U === outsideBundleLit.asUInt())
Copy link
Contributor

Choose a reason for hiding this comment

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

Is there a literal packing test anywhere? Do we want to test that too, by equivalence with a "magic number" in the test case, instead of solely equivalence with the .asUInt behavior?

Copy link
Member

Choose a reason for hiding this comment

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

I think LiteralExtractorSpec provides Lit test for Element type, and tests for Lit.
But in my understanding, Lit and LitOption are two different thing:
Lit will return a Option[BigInt], while LitOption will return T itself.
As for this case:
I think the result of outsideBundleLit.litValue().U === outsideBundleLit.asUInt() is only a necessary condition to this test.

If we wanna fully test this, I think the we should test the behavior of firrtl behavior of chisel3.internal.firrtl.PrimOp.AsUIntOp is equal to the (accumulator << width) + masked) behavior. At my first glance to firrtl.PrimOps.AsUInt, this behavior is correct. I think this is good enough here.

@ducky64
Copy link
Contributor

ducky64 commented Jun 29, 2020

Updated PR:

  • merged in latest
  • got rid of the try block, in favor of using Option throughout the foldLeft
  • added packing tests, including with signed and fixed-point types

It seems to work.

But one more general concerning point: in the LongBundle literal specifier, if I don't have explicit widths for the components (not in the most-significant position, at least), it seems .asUInt will return a different value in simulation. So it seems the structural width of the bundle is being ignored for the widths of literal elements in the simulation bundle packing, which seems wrong?

@ducky64 ducky64 dismissed their stale review June 29, 2020 18:17

PR ownership transfer

Copy link
Member

@sequencer sequencer left a comment

Choose a reason for hiding this comment

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

Generally, lgtm expect some small nitpicking.

core/src/main/scala/chisel3/Aggregate.scala Outdated Show resolved Hide resolved
src/test/scala/chiselTests/BundleLiteralSpec.scala Outdated Show resolved Hide resolved
@@ -28,7 +28,8 @@ class BundleLiteralSpec extends ChiselFlatSpec {
chisel3.assert(outsideBundleLit.a === 42.U)
chisel3.assert(outsideBundleLit.b === true.B)
chisel3.assert(outsideBundleLit.c === MyEnum.sB)

chisel3.assert(outsideBundleLit.isLit())
chisel3.assert(outsideBundleLit.litValue().U === outsideBundleLit.asUInt())
Copy link
Member

Choose a reason for hiding this comment

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

I think LiteralExtractorSpec provides Lit test for Element type, and tests for Lit.
But in my understanding, Lit and LitOption are two different thing:
Lit will return a Option[BigInt], while LitOption will return T itself.
As for this case:
I think the result of outsideBundleLit.litValue().U === outsideBundleLit.asUInt() is only a necessary condition to this test.

If we wanna fully test this, I think the we should test the behavior of firrtl behavior of chisel3.internal.firrtl.PrimOp.AsUIntOp is equal to the (accumulator << width) + masked) behavior. At my first glance to firrtl.PrimOps.AsUInt, this behavior is correct. I think this is good enough here.

@ducky64
Copy link
Contributor

ducky64 commented Jul 6, 2020

Fixed stylistic issues mentioned in review comments.

Not sure why GitHub isn't allowing a response to the last comment but:

  • I'm not sure I completely understand what you mean. LiteralExtractorSpec does test litValue and litOption, but doesn't have tests for bundles. I think an argument could be made for the bundle litOption tests to go in LiteralExtractorSpec, but I like centralizing all the bundle literal operations (including extraction) in a bundle literal test file.
  • I don't understand what you with Lit vs. LitOption. In the Data base class, litValue just delegates to litOption, so testing either makes sense?
  • For outsideBundleLit.litValue().U === outsideBundleLit.asUInt(), this should test FIRRTL behavior since it goes through to compilation and simulation. It's a blackbox test of FIRRTL since it only checks the overall simulation result, but I think that makes sense for this test.

Copy link
Member

@sequencer sequencer left a comment

Choose a reason for hiding this comment

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

As Jack mentioned in dev meeting, chisel3.assert will invoke FIRRTL to test, so generally lgtm. Thanks @ducky64

@ducky64 ducky64 merged commit 417fc2a into master Jul 13, 2020
@ducky64 ducky64 deleted the bundlelitoptionfix branch July 13, 2020 18:26
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.

5 participants