-
Notifications
You must be signed in to change notification settings - Fork 603
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
The definitive binding refactor thread, request for comments #578
Comments
So there may be one issue with the direction refactor: the new semantics require explicit direction somewhere in the chain for ports, while Chisel (compatibility) assumed that nodes without direction were Outputs and nodes with just flip are Inputs. This becomes a problem when using Chisel._ bundles with the old semantics in a chisel3._ Module. Possible solutions:
This case came up in class ChiselBundle extends Bundle {
val a = UInt(width = 32)
val b = UInt(width = 32).flip
} used in this chisel3._ Module: class Chisel3ModuleChiselBundleA extends Chisel3DriverModule(new ChiselBundle) |
If Chisel._ assumed everything is an output, how is the chisel bundle with Chisel._ different from this as a chisel3._? class ChiselBundle extends Bundle {
val a = Output(UInt(width = 32))
val a = Flipped(Output(UInt(width = 32)))
} |
"Nodes can have these directions: Input, Output, Bidirectional (for Aggregates, below), or Unspecified (default)." What about Analog (InOut) type? |
@sdtwigg I'm not quite sure I understand. The Chisel._ ChiselBundle in my example should be equivalent to your ChiselBundle. However, the newly proposed semantics requires absolute direction somewhere, so nothing but a chain of flips (or even unspecified) would be an error in chisel3._. @mwachs5 Analog is counted as Bidirectional. |
The reason why I ask is because then it seems you can just assume any fields in a Chisel.Bundle default to Output. Analog counting as Bidirectional somewhat contradicts the parenthetical statement in "Bidirectional (for Aggregates, below)" implying that Bidirectional only shows up in Aggregates. |
Yes, though the difficulty is in the implementation, since Chisel.Bundle is equivalent to chisel3.Bundle, so there would need to be some way to differentiate them while maintaining interoperability (threading through compile options? having Chisel.Bundle be a sub-class of chisel3.Bundle?). It would also require compatibility code support in chisel3, which would be ugly, but there's already precedent in the auto IO wrap. Analog was one of the things that I didn't really consider in the proposal and was caught by test cases. I've updated the spec above. |
I think VecWire is confusing because it is supposed to take a hardware input but both Vec and Wire take type inputs, I don't really have a better name VecHW? Is the bundle assuming output problem intended to be the new solution to #495 ? Again I don't have a solution just a confirmation that it certainly an issue but has existed in some form for a while. |
I think the error out approach makes it very difficult to incrementally upgrade from Chisel._ to chisel3._ Is @jackkoenig's solution from the other issue as messy as your second solution? Giving up doesn't seem like the right solution... :/ |
@colinschmidt The Bundle Output problem is a new issue created by stricter checks. I guess #495 / #595 provides part of the implementation for solution #2, I'll try that. However, that still requires compatibility code in core, which is undesirable but not a dealbreaker. Vec/VecWire: I see what you mean, and in that light, they're really not good names. VecHW seems very different than anything else we have so also seems undesirable. |
I think VecInit makes sense to me. You end up with a Vec that has the same initial value as your hardware input. |
If we're renaming them anyway, we should rethink the names... init currently means something very different for Wire and Reg.
and |
Does that mean |
I don't know, that's not great either, but it is certainly more consistent. |
I strongly agree with @colinschmidt that we should prioritize allowing standard Chisel._ Bundles with implied output direction. Perhaps using compile options we can autowrap the elements upon construction? As we discussed in person, it's not clear how these implicits work when you construct a Chisel._ Bundle inside of chisel3._ code, need to investigate. |
Perhaps the problem is that |
Hmmm, but for RegNext I guess as a user I never even considered overriding the returned value. I assumed the "Next" meant that I was sure I always wanted it to take the Next value. Otherwise what is the point of RegNext. WireDefault and WireInit both make sense to me, but maybe that's just cuz I'm used to passing in |
WireDefault makes more sense to me |
I made a little example of implicits on a common supertype that takes an implicit and is then extended by subtypes that materialize this implicit and it seems to work just fine. By making Bundle (and record) accept an implicit CompileOptions, we then know if the subclass was defined in |
(probable bikeshedding!) |
I find both With that said, I actually like Also, I agree with @mwachs5 regarding |
Ok, so here's what we currently have:
There's also a few things in chisel3.utils:
In the larger picture, I'm not sure there's a clear consistent philosophy to how we order arguments, though we can certainly try to change the APIs and fix existing use cases. Suggestions for what things should look like are also welcome. |
This looks reasonable to me, it seems logical and fairly consistent. |
Part 1 of mega-change in #578 Major notes: - Input(...) and Output(...) now (effectively) recursively override their elements' directions - Nodes given userDirection (Input, Output, Flip - what the user assigned to _that_ node) and actualDirection (Input, Output, None, but also Bidirectional and BidirectionalFlip for mostly Aggregates), because of the above (since a higher-level Input(...) can override the locally specified user direction). - DataMirror (node reflection APIs) added to chisel3.experimental. This provides ways to query the user given direction of a node as well as the actual direction. - checkSynthesizable replaced with requireIsHardware and requireIsChiselType and made available in chisel3.experimental. Internal changes notes: - toType moved into Emitter, this makes the implementation cleaner especially considering that Vec types can't be flipped in FIRRTL. This also more clearly separates Chisel frontend from FIRRTL emission. - Direction separated from Bindings, both are now fields in Data, and all nodes are given hierarchical directions (Aggregates may be Bidirectional). The actualDirection at the Element (leaf) level should be the same as binding directions previously. - Bindings are hierarchical, children (of a, for example, Bundle) have a ChildBinding that points to their parent. This is different than the previous scheme where Bindings only applied at the Element (leaf) level. - Lots of small misc clean up. Future PRs will address other parts of #578, including stricter direction checks that aren't a side-effect of this internal refactor, stricter checks and splitting of binding operations (Wire vs. WireInit), and node operations not introduced here (getType and deprecation of chiselCloneType). Since those shouldn't mess with internals, those should be much smaller.
This is a summary of all the issues related to the bindings refactor (issues #440, #445, #419, #399, #368, #282, parts of #535, #543), and the proposed path forward. Work on this should begin soon.
Terminology & Conventions
These will primarily be documentation clarifications.
Directionality
Output(...)
andInput(...)
will (effectively) clear direction of internal nodes, so the top-level node can be set to an input/output._onModuleClose
Binding operations
Wire(t)
must havet
of chisel typeReg(t), Mem(t), Vec(t)
must havet
of chisel type that is not Bidirectional (either Input, Output, or Unspecified)Vec(t)
additionally is defined to create a chisel type.IO(t)
: must havet
of chisel type with direction.Vec(args*)
,Vec(elts)
deprecated, replace withVecWire(elts)
(or similar, someone suggest good names).elts
must be a hardware node, and this returns a hardware node.Node operations
.chiselCloneType
and.cloneType
are to be deprecated..getType
operator introduced, legal on hardware nodes..wipeDir
operator? The main use case would be for specifying Mem type, but the same could be done by wrapping it inInput(...)
..requireIsHardware
,requireIsChiselType
,.requireDirectioned
, and.requireUndirectioned
APIs.myNode.getType
) or as a global method (getType(myNode)
)? The first is consistent withcloneType
, but the second is consistent with the binding wrappers andInput(...)
/Output(...)
Style recommendations
gen
) should take a chisel type only, and shouldrequireIsChiselType
(orrequireDirectioned
/requireUndirectioned
to sanity-check their inputs. Use ofcloneType
/getType
in these occasions is discouraged and should be the responsibility of the caller.The text was updated successfully, but these errors were encountered: