From aaee58d374dc3f3a088856da13a6a59ecffb2cac Mon Sep 17 00:00:00 2001 From: Richard Lin Date: Mon, 26 Jun 2017 18:35:46 -0700 Subject: Directions internals mega-refactor (#617) 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.--- .../src/main/scala/chisel3/core/Binder.scala | 64 ---------------------- 1 file changed, 64 deletions(-) delete mode 100644 chiselFrontend/src/main/scala/chisel3/core/Binder.scala (limited to 'chiselFrontend/src/main/scala/chisel3/core/Binder.scala') diff --git a/chiselFrontend/src/main/scala/chisel3/core/Binder.scala b/chiselFrontend/src/main/scala/chisel3/core/Binder.scala deleted file mode 100644 index d872d7c6..00000000 --- a/chiselFrontend/src/main/scala/chisel3/core/Binder.scala +++ /dev/null @@ -1,64 +0,0 @@ -package chisel3.core - -/** -* A Binder is a function from UnboundBinding to some Binding. -* -* These are used exclusively by Binding.bind and sealed in order to keep -* all of them in one place. There are two flavors of Binders: -* Non-terminal (returns another UnboundBinding): These are used to reformat an -* UnboundBinding (like setting direction) before it is terminally bound. -* Terminal (returns any other Binding): Due to the nature of Bindings, once a -* Data is bound to anything but an UnboundBinding, it is forever locked to -* being that type (as it now represents something in the hardware graph). -* -* Note that some Binders require extra arguments to be constructed, like the -* enclosing Module. -*/ - -sealed trait Binder[Out <: Binding] extends Function1[UnboundBinding, Out]{ - def apply(in: UnboundBinding): Out -} - -// THE NON-TERMINAL BINDERS -// These 'rebind' to another unbound node of different direction! -case object InputBinder extends Binder[UnboundBinding] { - def apply(in: UnboundBinding) = UnboundBinding(Some(Direction.Input)) -} -case object OutputBinder extends Binder[UnboundBinding] { - def apply(in: UnboundBinding) = UnboundBinding(Some(Direction.Output)) -} -case object FlippedBinder extends Binder[UnboundBinding] { - def apply(in: UnboundBinding) = UnboundBinding(in.direction.map(_.flip)) - // TODO(twigg): flipping a None should probably be a warning/error -} -// The need for this should be transient. -case object NoDirectionBinder extends Binder[UnboundBinding] { - def apply(in: UnboundBinding) = UnboundBinding(None) -} - -// THE TERMINAL BINDERS -case object LitBinder extends Binder[LitBinding] { - def apply(in: UnboundBinding) = LitBinding() -} - -case class MemoryPortBinder(enclosure: UserModule) extends Binder[MemoryPortBinding] { - def apply(in: UnboundBinding) = MemoryPortBinding(enclosure) -} - -case class OpBinder(enclosure: UserModule) extends Binder[OpBinding] { - def apply(in: UnboundBinding) = OpBinding(enclosure) -} - -// Notice how PortBinder uses the direction of the UnboundNode -case class PortBinder(enclosure: BaseModule) extends Binder[PortBinding] { - def apply(in: UnboundBinding) = PortBinding(enclosure, in.direction) -} - -case class RegBinder(enclosure: UserModule) extends Binder[RegBinding] { - def apply(in: UnboundBinding) = RegBinding(enclosure) -} - -case class WireBinder(enclosure: UserModule) extends Binder[WireBinding] { - def apply(in: UnboundBinding) = WireBinding(enclosure) -} - -- cgit v1.2.3