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