diplomacy: support := composition
This makes it possible to treat chained composition associatively. x := y :=? z :=* a ... It also makes it easy to chain multiple optional adapters: node :=? (Seq(a, b) ++ c ++ d)
This commit is contained in:
		| @@ -119,23 +119,51 @@ object BaseNode | |||||||
|   protected[diplomacy] var serial = 0 |   protected[diplomacy] var serial = 0 | ||||||
| } | } | ||||||
|  |  | ||||||
| // !!! rename the nodes we bind? | trait NoHandle | ||||||
| case class NodeHandle[DI, UI, BI <: Data, DO, UO, BO <: Data] | case object NoHandleObject extends NoHandle | ||||||
|  |  | ||||||
|  | trait NodeHandle[DI, UI, BI <: Data, DO, UO, BO <: Data] | ||||||
|  |   extends InwardNodeHandle[DI, UI, BI] with OutwardNodeHandle[DO, UO, BO] | ||||||
|  | { | ||||||
|  |   // connecting two full nodes => full node | ||||||
|  |   override def :=  [DX, UX, BX <: Data](h: NodeHandle[DX, UX, BX, DI, UI, BI])(implicit p: Parameters, sourceInfo: SourceInfo): NodeHandle[DX, UX, BX, DO, UO, BO] = { inward.bind(h, BIND_ONCE);  NodeHandle(h, this) } | ||||||
|  |   override def :*= [DX, UX, BX <: Data](h: NodeHandle[DX, UX, BX, DI, UI, BI])(implicit p: Parameters, sourceInfo: SourceInfo): NodeHandle[DX, UX, BX, DO, UO, BO] = { inward.bind(h, BIND_STAR);  NodeHandle(h, this) } | ||||||
|  |   override def :=* [DX, UX, BX <: Data](h: NodeHandle[DX, UX, BX, DI, UI, BI])(implicit p: Parameters, sourceInfo: SourceInfo): NodeHandle[DX, UX, BX, DO, UO, BO] = { inward.bind(h, BIND_QUERY); NodeHandle(h, this) } | ||||||
|  |   override def :=? [DX, UX, BX <: Data](h: NodeHandle[DX, UX, BX, DI, UI, BI])(implicit p: Parameters, sourceInfo: SourceInfo): NodeHandle[DX, UX, BX, DO, UO, BO] = { inward.bind(h, p(CardinalityInferenceDirectionKey)); NodeHandle(h, this) } | ||||||
|  |   // connecting a full node with an output => an output | ||||||
|  |   override def :=  (h: OutwardNodeHandle[DI, UI, BI])(implicit p: Parameters, sourceInfo: SourceInfo): OutwardNodeHandle[DO, UO, BO] = { inward.bind(h, BIND_ONCE);  this } | ||||||
|  |   override def :*= (h: OutwardNodeHandle[DI, UI, BI])(implicit p: Parameters, sourceInfo: SourceInfo): OutwardNodeHandle[DO, UO, BO] = { inward.bind(h, BIND_STAR);  this } | ||||||
|  |   override def :=* (h: OutwardNodeHandle[DI, UI, BI])(implicit p: Parameters, sourceInfo: SourceInfo): OutwardNodeHandle[DO, UO, BO] = { inward.bind(h, BIND_QUERY); this } | ||||||
|  |   override def :=? (h: OutwardNodeHandle[DI, UI, BI])(implicit p: Parameters, sourceInfo: SourceInfo): OutwardNodeHandle[DO, UO, BO] = { inward.bind(h, p(CardinalityInferenceDirectionKey)); this } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | object NodeHandle | ||||||
|  | { | ||||||
|  |   def apply[DI, UI, BI <: Data, DO, UO, BO <: Data](i: InwardNodeHandle[DI, UI, BI], o: OutwardNodeHandle[DO, UO, BO]) = NodeHandlePair(i, o) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | case class NodeHandlePair[DI, UI, BI <: Data, DO, UO, BO <: Data] | ||||||
|   (inwardHandle: InwardNodeHandle[DI, UI, BI], outwardHandle: OutwardNodeHandle[DO, UO, BO]) |   (inwardHandle: InwardNodeHandle[DI, UI, BI], outwardHandle: OutwardNodeHandle[DO, UO, BO]) | ||||||
|   extends Object with InwardNodeHandle[DI, UI, BI] with OutwardNodeHandle[DO, UO, BO] |   extends NodeHandle[DI, UI, BI, DO, UO, BO] | ||||||
| { | { | ||||||
|   val inward = inwardHandle.inward |   val inward = inwardHandle.inward | ||||||
|   val outward = outwardHandle.outward |   val outward = outwardHandle.outward | ||||||
| } | } | ||||||
|  |  | ||||||
| trait InwardNodeHandle[DI, UI, BI <: Data] | trait InwardNodeHandle[DI, UI, BI <: Data] extends NoHandle | ||||||
| { | { | ||||||
|   protected[diplomacy] val inward: InwardNode[DI, UI, BI] |   protected[diplomacy] val inward: InwardNode[DI, UI, BI] | ||||||
|   def parentsIn: Seq[LazyModule] = inward.parents |   def parentsIn: Seq[LazyModule] = inward.parents | ||||||
|   def := (h: OutwardNodeHandle[DI, UI, BI])(implicit p: Parameters, sourceInfo: SourceInfo) { inward.:=(h)(p, sourceInfo) } |   // connecting an input node with a full nodes => an input node | ||||||
|   def :*= (h: OutwardNodeHandle[DI, UI, BI])(implicit p: Parameters, sourceInfo: SourceInfo) { inward.:*=(h)(p, sourceInfo) } |   def :=  [DX, UX, BX <: Data](h: NodeHandle[DX, UX, BX, DI, UI, BI])(implicit p: Parameters, sourceInfo: SourceInfo): InwardNodeHandle[DX, UX, BX] = { inward.bind(h, BIND_ONCE);  h } | ||||||
|   def :=* (h: OutwardNodeHandle[DI, UI, BI])(implicit p: Parameters, sourceInfo: SourceInfo) { inward.:=*(h)(p, sourceInfo) } |   def :*= [DX, UX, BX <: Data](h: NodeHandle[DX, UX, BX, DI, UI, BI])(implicit p: Parameters, sourceInfo: SourceInfo): InwardNodeHandle[DX, UX, BX] = { inward.bind(h, BIND_STAR);  h } | ||||||
|   def :=? (h: OutwardNodeHandle[DI, UI, BI])(implicit p: Parameters, sourceInfo: SourceInfo) { inward.:=?(h)(p, sourceInfo) } |   def :=* [DX, UX, BX <: Data](h: NodeHandle[DX, UX, BX, DI, UI, BI])(implicit p: Parameters, sourceInfo: SourceInfo): InwardNodeHandle[DX, UX, BX] = { inward.bind(h, BIND_QUERY); h } | ||||||
|  |   def :=? [DX, UX, BX <: Data](h: NodeHandle[DX, UX, BX, DI, UI, BI])(implicit p: Parameters, sourceInfo: SourceInfo): InwardNodeHandle[DX, UX, BX] = { inward.bind(h, p(CardinalityInferenceDirectionKey)); h } | ||||||
|  |   // connecting input node with output node => no node | ||||||
|  |   def :=  (h: OutwardNodeHandle[DI, UI, BI])(implicit p: Parameters, sourceInfo: SourceInfo): NoHandle = { inward.bind(h, BIND_ONCE);  NoHandleObject } | ||||||
|  |   def :*= (h: OutwardNodeHandle[DI, UI, BI])(implicit p: Parameters, sourceInfo: SourceInfo): NoHandle = { inward.bind(h, BIND_STAR);  NoHandleObject } | ||||||
|  |   def :=* (h: OutwardNodeHandle[DI, UI, BI])(implicit p: Parameters, sourceInfo: SourceInfo): NoHandle = { inward.bind(h, BIND_QUERY); NoHandleObject } | ||||||
|  |   def :=? (h: OutwardNodeHandle[DI, UI, BI])(implicit p: Parameters, sourceInfo: SourceInfo): NoHandle = { inward.bind(h, p(CardinalityInferenceDirectionKey)); NoHandleObject } | ||||||
| } | } | ||||||
|  |  | ||||||
| sealed trait NodeBinding | sealed trait NodeBinding | ||||||
| @@ -143,6 +171,15 @@ case object BIND_ONCE  extends NodeBinding | |||||||
| case object BIND_QUERY extends NodeBinding | case object BIND_QUERY extends NodeBinding | ||||||
| case object BIND_STAR  extends NodeBinding | case object BIND_STAR  extends NodeBinding | ||||||
|  |  | ||||||
|  | object NodeBinding | ||||||
|  | { | ||||||
|  |   implicit def apply(card: CardinalityInferenceDirection.T): NodeBinding = card match { | ||||||
|  |     case CardinalityInferenceDirection.SOURCE_TO_SINK => BIND_QUERY | ||||||
|  |     case CardinalityInferenceDirection.SINK_TO_SOURCE => BIND_STAR | ||||||
|  |     case CardinalityInferenceDirection.NO_INFERENCE   => BIND_ONCE | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
| trait InwardNode[DI, UI, BI <: Data] extends BaseNode with InwardNodeHandle[DI, UI, BI] | trait InwardNode[DI, UI, BI <: Data] extends BaseNode with InwardNodeHandle[DI, UI, BI] | ||||||
| { | { | ||||||
|   protected[diplomacy] val inward = this |   protected[diplomacy] val inward = this | ||||||
| @@ -168,9 +205,11 @@ trait InwardNode[DI, UI, BI <: Data] extends BaseNode with InwardNodeHandle[DI, | |||||||
|   protected[diplomacy] val iStar: Int |   protected[diplomacy] val iStar: Int | ||||||
|   protected[diplomacy] val iPortMapping: Seq[(Int, Int)] |   protected[diplomacy] val iPortMapping: Seq[(Int, Int)] | ||||||
|   protected[diplomacy] val iParams: Seq[UI] |   protected[diplomacy] val iParams: Seq[UI] | ||||||
|  |  | ||||||
|  |   protected[diplomacy] def bind(h: OutwardNodeHandle[DI, UI, BI], binding: NodeBinding)(implicit p: Parameters, sourceInfo: SourceInfo): Unit | ||||||
| } | } | ||||||
|  |  | ||||||
| trait OutwardNodeHandle[DO, UO, BO <: Data] | trait OutwardNodeHandle[DO, UO, BO <: Data] extends NoHandle | ||||||
| { | { | ||||||
|   protected[diplomacy] val outward: OutwardNode[DO, UO, BO] |   protected[diplomacy] val outward: OutwardNode[DO, UO, BO] | ||||||
|   def parentsOut: Seq[LazyModule] = outward.parents |   def parentsOut: Seq[LazyModule] = outward.parents | ||||||
| @@ -215,7 +254,7 @@ sealed abstract class MixedNode[DI, UI, EI, BI <: Data, DO, UO, EO, BO <: Data]( | |||||||
|   protected[diplomacy] val numPO: Range.Inclusive, |   protected[diplomacy] val numPO: Range.Inclusive, | ||||||
|   protected[diplomacy] val numPI: Range.Inclusive)( |   protected[diplomacy] val numPI: Range.Inclusive)( | ||||||
|   implicit valName: ValName) |   implicit valName: ValName) | ||||||
|   extends BaseNode with InwardNode[DI, UI, BI] with OutwardNode[DO, UO, BO] |   extends BaseNode with NodeHandle[DI, UI, BI, DO, UO, BO] with InwardNode[DI, UI, BI] with OutwardNode[DO, UO, BO] | ||||||
| { | { | ||||||
|   protected[diplomacy] def resolveStar(iKnown: Int, oKnown: Int, iStar: Int, oStar: Int): (Int, Int) |   protected[diplomacy] def resolveStar(iKnown: Int, oKnown: Int, iStar: Int, oStar: Int): (Int, Int) | ||||||
|   protected[diplomacy] def mapParamsD(n: Int, p: Seq[DI]): Seq[DO] |   protected[diplomacy] def mapParamsD(n: Int, p: Seq[DI]): Seq[DO] | ||||||
| @@ -341,7 +380,7 @@ sealed abstract class MixedNode[DI, UI, EI, BI <: Data, DO, UO, EO, BO <: Data]( | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   // connects the outward part of a node with the inward part of this node |   // connects the outward part of a node with the inward part of this node | ||||||
|   private def bind(h: OutwardNodeHandle[DI, UI, BI], binding: NodeBinding)(implicit p: Parameters, sourceInfo: SourceInfo) { |   protected[diplomacy] def bind(h: OutwardNodeHandle[DI, UI, BI], binding: NodeBinding)(implicit p: Parameters, sourceInfo: SourceInfo) { | ||||||
|     val x = this // x := y |     val x = this // x := y | ||||||
|     val y = h.outward |     val y = h.outward | ||||||
|     val info = sourceLine(sourceInfo, " at ", "") |     val info = sourceLine(sourceInfo, " at ", "") | ||||||
| @@ -354,17 +393,6 @@ sealed abstract class MixedNode[DI, UI, EI, BI <: Data, DO, UO, EO, BO <: Data]( | |||||||
|     x.iPush(o, y, binding) |     x.iPush(o, y, binding) | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   override def :=  (h: OutwardNodeHandle[DI, UI, BI])(implicit p: Parameters, sourceInfo: SourceInfo) = bind(h, BIND_ONCE) |  | ||||||
|   override def :*= (h: OutwardNodeHandle[DI, UI, BI])(implicit p: Parameters, sourceInfo: SourceInfo) = bind(h, BIND_STAR) |  | ||||||
|   override def :=* (h: OutwardNodeHandle[DI, UI, BI])(implicit p: Parameters, sourceInfo: SourceInfo) = bind(h, BIND_QUERY) |  | ||||||
|   override def :=? (h: OutwardNodeHandle[DI, UI, BI])(implicit p: Parameters, sourceInfo: SourceInfo) = { |  | ||||||
|     p(CardinalityInferenceDirectionKey) match { |  | ||||||
|       case CardinalityInferenceDirection.SOURCE_TO_SINK => this :=* h |  | ||||||
|       case CardinalityInferenceDirection.SINK_TO_SOURCE => this :*= h |  | ||||||
|       case CardinalityInferenceDirection.NO_INFERENCE   => this :=  h |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   // meta-data for printing the node graph |   // meta-data for printing the node graph | ||||||
|   protected[diplomacy] def inputs = (iPorts zip edgesIn) map { case ((_, n, p, _), e) => |   protected[diplomacy] def inputs = (iPorts zip edgesIn) map { case ((_, n, p, _), e) => | ||||||
|     val re = inner.render(e) |     val re = inner.render(e) | ||||||
|   | |||||||
| @@ -71,6 +71,12 @@ object TLBuffer | |||||||
|     buffer.node :=? x |     buffer.node :=? x | ||||||
|     buffer.node |     buffer.node | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   def chain(depth: Int, name: Option[String] = None)(implicit p: Parameters): Seq[TLNode] = { | ||||||
|  |     val buffers = Seq.fill(depth) { LazyModule(new TLBuffer()) } | ||||||
|  |     name.foreach { n => buffers.zipWithIndex.foreach { case (b, i) => b.suggestName(s"${n}_${i}") } } | ||||||
|  |     buffers.map(_.node) | ||||||
|  |   } | ||||||
| } | } | ||||||
|  |  | ||||||
| object TLNodeChain { | object TLNodeChain { | ||||||
|   | |||||||
| @@ -9,7 +9,7 @@ package object tilelink | |||||||
| { | { | ||||||
|   type TLInwardNode = InwardNodeHandle[TLClientPortParameters, TLManagerPortParameters, TLBundle] |   type TLInwardNode = InwardNodeHandle[TLClientPortParameters, TLManagerPortParameters, TLBundle] | ||||||
|   type TLOutwardNode = OutwardNodeHandle[TLClientPortParameters, TLManagerPortParameters, TLBundle] |   type TLOutwardNode = OutwardNodeHandle[TLClientPortParameters, TLManagerPortParameters, TLBundle] | ||||||
|   type TLNode = TLInwardNode with TLOutwardNode |   type TLNode = NodeHandle[TLClientPortParameters, TLManagerPortParameters, TLBundle, TLClientPortParameters, TLManagerPortParameters, TLBundle] | ||||||
|   type TLAsyncInwardNode = InwardNodeHandle[TLAsyncClientPortParameters, TLAsyncManagerPortParameters, TLAsyncBundle] |   type TLAsyncInwardNode = InwardNodeHandle[TLAsyncClientPortParameters, TLAsyncManagerPortParameters, TLAsyncBundle] | ||||||
|   type TLAsyncOutwardNode = OutwardNodeHandle[TLAsyncClientPortParameters, TLAsyncManagerPortParameters, TLAsyncBundle] |   type TLAsyncOutwardNode = OutwardNodeHandle[TLAsyncClientPortParameters, TLAsyncManagerPortParameters, TLAsyncBundle] | ||||||
|   type TLRationalInwardNode = InwardNodeHandle[TLRationalClientPortParameters, TLRationalManagerPortParameters, TLRationalBundle] |   type TLRationalInwardNode = InwardNodeHandle[TLRationalClientPortParameters, TLRationalManagerPortParameters, TLRationalBundle] | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user