-
Notifications
You must be signed in to change notification settings - Fork 28
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
[minor] Bit-index support (subword assignment) #26
base: main
Are you sure you want to change the base?
Changes from all commits
51a68cf
86bcca2
b2dff2e
30c6c30
c6e26cd
2e26a19
65ebef3
267e1df
2872b62
eb59122
c72b34d
8e077c7
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -990,6 +990,9 @@ sub-element in the vector. | |
Invalidating a component with a bundle type recursively invalidates each | ||
sub-element in the bundle. | ||
|
||
Invalidating a particular subset of bits in an integer is possible by | ||
performing a bit-index with `is invalid`{.firrtl} (see [@sec:bit-indices]). | ||
|
||
## Attaches | ||
|
||
The `attach`{.firrtl} statement is used to attach two or more analog signals, | ||
|
@@ -1840,6 +1843,49 @@ module MyModule : | |
out[4] <= in | ||
``` | ||
|
||
## Bit-indices | ||
|
||
The bit-index expression statically refers, by index, to a particular bit, or | ||
slice of bits, of an expression with an integer type (`UInt`{.firrtl} or | ||
`SInt`{.firrtl}). The indices must be non-negative integers and cannot be equal | ||
to or exceed the width of the integer they index. The bit-index `x[hi:lo]` | ||
selects bits `hi` (most significant) through `lo` (least significant) of `x`. | ||
The bit-index `x[i]` selects the single bit `i`. | ||
|
||
The type of the bit-index expression `x[hi:lo]`.{firrtl} is `UInt<hi - lo + | ||
1>`.{firrtl} (even if `x` is an `SInt`) and the type of `x[i]`.{firrtl} is | ||
`UInt<1>`.{firrtl}. This means that when connecting to a bit-indexed value, the | ||
right-hand-side of the connection must be a `UInt`.{firrtl}, even if the value | ||
being indexed is an `SInt`.{firrtl}. | ||
|
||
The bit-index can be used as a sink or source. When used as a source, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Have you considered restricting your proposal to L-value bit slices? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's true that if it isn't restricted to L-value slices there is redundancy with the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I don't think that is necessary. As I said, firrtl is an IR, so it can be more explicit about some things than a user-facing language. I am very much opposed to introducing duplicate functionality since it will make the compiler more complicated for little to no gain. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
To clarify: the plan is to remove Is the concern about atomicity of updates to the spec? I was planning to just remove There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Why not keep
Yes. I believe that before merging into In addition to that, removing There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
It seems clean to have a single unified op for extraction. FIRRTL really screwed up here with not adding type information to each operation. Any sane parser is going to track the types of references and uses that to build up its internal FIRRTL IR (which necessarily must include type information). Hence, I'm not super concerned about this. I do admit that this means
I'm fine to just remove I don't know if backwards compatibility should be a goal here. We're attempting to make it easy for FIRRTL compilers to check if they support a given FIRRTL text via: #30. I guess my concern is that it seems weird to try to be backwards compatible for bits on the RHS of a connect when the fundamental change is to extend the spec in an entirely backwards incompatible way. Or: SFC will be "incompatible" with FIRRTL 2.0.0+ after this change even though it will work for Chisel designs where a user doesn't use bit index. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
My main point is that it will be harder to support older FIRRTL versions with the same compiler if we make this change. If we only add a new operation, then we trivially support older FIRRTL versions. However, if we replace |
||
`x[hi:lo]` is equivalent to `bits(x, hi, lo)` and `x[i]` is equivalent to | ||
`bits(x, i, i)`. See the `bits`{.firrtl} primitive operation | ||
([@sec:bit-extraction-operation]). When used as a sink, the bit-index assigns | ||
to only the sliced bits of the integer. If a value has multiple bit-index | ||
assignments, the assignments are accumulated in order according to last-connect | ||
semantics, in the same way as the behavior of last-connect semantics for | ||
aggregate types (see [@sec:last-connect-semantics]). | ||
zyedidia marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
A value that is bit-indexed must be fully initialized at the bit-level. There | ||
must be a valid assignment accounting for every bit in the value. Registers are | ||
implicitly initialized with their current contents. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is redundant with the section on registers. |
||
|
||
Bit-indexing does not participate in width inference (see | ||
[@sec:width-inference]), and if a bit-index is applied to a value with an | ||
unspecified width, that value must have another use that allows its width to be | ||
inferred. Otherwise this causes an error. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why not say that a bit-index forces the width to be at least sufficient to the slice bounds? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think that is definitely desirable, but I think the motivation for not participating in width inference was so that the the bit-index would be interchangeable with the If we want to add width inference support as part of this proposal, then perhaps this proposal should also add width inference for the bits primop. I think either approach is reasonable. |
||
|
||
The following example connects the `in`{.firrtl} port to the fifth bit | ||
of the `out`{.firrtl} port. | ||
|
||
``` firrtl | ||
module MyModule : | ||
input in: UInt<1> | ||
output out: UInt<10> | ||
out[4] <= in | ||
zyedidia marked this conversation as resolved.
Show resolved
Hide resolved
|
||
``` | ||
|
||
## Sub-accesses | ||
|
||
The sub-access expression dynamically refers to a sub-element of a vector-typed | ||
|
@@ -2382,6 +2428,8 @@ wire or register is duplex. | |
The flow of a sub-index or sub-access expression is the flow of the vector-typed | ||
expression it indexes or accesses. | ||
|
||
The flow of a bit-index is the flow of the integer-typed expression it indexes. | ||
|
||
The flow of a sub-field expression depends upon the orientation of the field. If | ||
the field is not flipped, its flow is the same flow as the bundle-typed | ||
expression it selects its field from. If the field is flipped, then its flow is | ||
|
@@ -2413,6 +2461,8 @@ expression. | |
|
||
The width of each primitive operation is detailed in [@sec:primitive-operations]. | ||
|
||
The width of a bit-index is detailed in [@sec:bit-indices]. | ||
|
||
The width of the integer literal expressions is detailed in their respective | ||
sections. | ||
|
||
|
@@ -2626,6 +2676,8 @@ following restrictions: | |
|
||
- The dynamic sub-access expression is not used. | ||
|
||
- The bit-index expression is not used as a sink. | ||
|
||
- All components are connected to exactly once. | ||
|
||
- All uninferred `Reset`{.firrtl} types have been inferred to `UInt<1>`{.firrtl} | ||
|
@@ -2896,6 +2948,7 @@ expr = | |
reference = id | ||
| reference , "." , id | ||
| reference , "[" , int , "]" | ||
| reference , "[" , int , ":" , int , "]" | ||
| reference , "[" , expr , "]" ; | ||
|
||
(* Memory *) | ||
|
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.
This is starting to sound like invalid is being used for don't care.
For normal wires/regs/outputs, how does invalidating a subset of bits get you anything that starting with an entire invalid value which is later partially written not get you?