diff --git a/src/main/scala/diplomacy/Nodes.scala b/src/main/scala/diplomacy/Nodes.scala index 7ed31673..868fffee 100644 --- a/src/main/scala/diplomacy/Nodes.scala +++ b/src/main/scala/diplomacy/Nodes.scala @@ -119,23 +119,51 @@ object BaseNode protected[diplomacy] var serial = 0 } -// !!! rename the nodes we bind? -case class NodeHandle[DI, UI, BI <: Data, DO, UO, BO <: Data] +trait NoHandle +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]) - 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 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] def parentsIn: Seq[LazyModule] = inward.parents - def := (h: OutwardNodeHandle[DI, UI, BI])(implicit p: Parameters, sourceInfo: SourceInfo) { inward.:=(h)(p, sourceInfo) } - def :*= (h: OutwardNodeHandle[DI, UI, BI])(implicit p: Parameters, sourceInfo: SourceInfo) { inward.:*=(h)(p, sourceInfo) } - def :=* (h: OutwardNodeHandle[DI, UI, BI])(implicit p: Parameters, sourceInfo: SourceInfo) { inward.:=*(h)(p, sourceInfo) } - 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 := [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 :*= [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 :=* [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 @@ -143,6 +171,15 @@ case object BIND_ONCE extends NodeBinding case object BIND_QUERY 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] { 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 iPortMapping: Seq[(Int, Int)] 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] 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 numPI: Range.Inclusive)( 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 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 - 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 y = h.outward 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) } - 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 protected[diplomacy] def inputs = (iPorts zip edgesIn) map { case ((_, n, p, _), e) => val re = inner.render(e) diff --git a/src/main/scala/tilelink/Buffer.scala b/src/main/scala/tilelink/Buffer.scala index dcf54d81..ba7006e2 100644 --- a/src/main/scala/tilelink/Buffer.scala +++ b/src/main/scala/tilelink/Buffer.scala @@ -71,6 +71,12 @@ object TLBuffer buffer.node :=? x 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 { diff --git a/src/main/scala/tilelink/package.scala b/src/main/scala/tilelink/package.scala index 140212d2..4dc8cc24 100644 --- a/src/main/scala/tilelink/package.scala +++ b/src/main/scala/tilelink/package.scala @@ -9,7 +9,7 @@ package object tilelink { type TLInwardNode = InwardNodeHandle[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 TLAsyncOutwardNode = OutwardNodeHandle[TLAsyncClientPortParameters, TLAsyncManagerPortParameters, TLAsyncBundle] type TLRationalInwardNode = InwardNodeHandle[TLRationalClientPortParameters, TLRationalManagerPortParameters, TLRationalBundle]