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:
parent
b48ab985d0
commit
e894d64bca
@ -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]
|
||||||
|
Loading…
Reference in New Issue
Block a user