1
0

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:
Wesley W. Terpstra 2017-10-24 23:34:16 -07:00
parent b48ab985d0
commit e894d64bca
3 changed files with 57 additions and 23 deletions

View File

@ -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)

View File

@ -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 {

View File

@ -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]