Skip to content
This repository has been archived by the owner on Aug 20, 2024. It is now read-only.

implement sub-word assignments #2545

Open
wants to merge 1 commit into
base: master-deprecated
Choose a base branch
from

Conversation

ekiwi
Copy link
Contributor

@ekiwi ekiwi commented Aug 24, 2022

Contributor Checklist

  • Did you add Scaladoc to every public function/method?
  • Did you update the FIRRTL spec to include every new feature/behavior?
  • Did you add at least one test demonstrating the PR?
  • Did you delete any extraneous printlns/debugging code?
  • Did you specify the type of improvement?
  • Did you state the API impact?
  • Did you specify the code generation impact?
  • Did you request a desired merge strategy?
  • Did you add text to be included in the Release Notes for this change?

Type of Improvement

API Impact

Backend Code Generation Impact

Desired Merge Strategy

Release Notes

Reviewer Checklist (only modified by reviewer)

  • Did you add the appropriate labels?
  • Did you mark the proper milestone (1.2.x, 1.3.0, 1.4.0) ?
  • Did you review?
  • Did you check whether all relevant Contributor checkboxes have been checked?
  • Did you mark as Please Merge?

@ekiwi ekiwi marked this pull request as ready for review August 26, 2022 14:47
@ekiwi ekiwi added this to the 1.6.0 milestone Aug 26, 2022
@ekiwi ekiwi requested a review from jackkoenig August 26, 2022 14:47
@schoeberl
Copy link

Great that this comes back to Chisel.

| x <= y
|""".stripMargin
check(src, expected)
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Might also want a test for subword-assigning an SInt:

circuit test :
  module test :
    input c : UInt<2>
    output x : SInt<2>

    x[0] <= c[0]
    x[1] <= c[1]

Note that since the type of x[...] is always UInt, it must be connected to a UInt even though x is an SInt.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes. Thanks, I need to add this test (and fix the implementation to support it)

/** performs special simplifications which are needed in the case of sub-word assignments to avoid false positives
* in the connection check
*/
private def simplifyBits(e: ir.Expression): ir.Expression = e match {
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 if this code already handles this, but I recently fixed a bug in the CIRCT implementation related to SInts so I thought I'd mention it here in case. First the connector must call asSInt if the bit-indexed value being assigned is an SInt.

Then the simplifications need to look through calls to asSInt (i.e., having a simplification that bits(asSInt(x), ..., ...) -> bits(x, ..., ...)).

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 subword-assignment for SInt is broken in this PR right now. Thanks for pointing out how I could fix it.

* CHIRRTL level type inference then converts this into either a `bits(..., ... , ...)`,
* or [[ir.SubIndex]] depending on the inferred type of the inner expression.
*/
case class WSliceNode(expr: ir.Expression, hi: Int, lo: Int) extends ir.Expression {
Copy link
Contributor

Choose a reason for hiding this comment

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

Would it be better to define this as a node in IR.scala so that it can be more easily accessed from the Chisel converter?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

No, this is an internal node used to hack around a short coming in the parser (that it does not do type inference). From Chisel you should know whether you want a bit-extract or a vector access since the types are available in the Chisel data structure.

Copy link
Member

@seldridge seldridge left a comment

Choose a reason for hiding this comment

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

I had one comment from a while back that I never actually filed. 🤦

It is bad if we are handling vec of bools differently from UInt. Users can annoyingly start to rely on this behavior and it then becomes the de facto way that Chisel works.

| x[0] <= UInt(1)
| x[1] is invalid
|""".stripMargin
// TODO: currently we actually do not perform this optimization since we replace invalid with 0 for sub-word assignments
Copy link
Member

Choose a reason for hiding this comment

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

See discussion around this here: llvm/circt#3658 (comment)

I think this is actually super critical that we do this, now that I think about it. My reasoning is that the behavior of a vector of bools needs to be the exact same as the behavior of a uint with bit selects. Otherwise this is defining a fifth invalid interpretation that is inconsistent with something that should be functionally the same.

I grok that just converting to zero is totally legal. However, if the SFC goes this route, it locks in this behavior for Chisel users, they may inadvertently write code which depends on it, and it effectively forces any other FIRRTL compiler to fall in line unless Chisel users are expected to change their code. We hit numerous issues around choices that the SFC made around invalid being or not being zero which would cause simulation failures. 😬 I'm trying to avoid that here.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants