diff --git a/src/main/scala/diplomacy/Nodes.scala b/src/main/scala/diplomacy/Nodes.scala index b1a46e69..db6b3513 100644 --- a/src/main/scala/diplomacy/Nodes.scala +++ b/src/main/scala/diplomacy/Nodes.scala @@ -14,20 +14,26 @@ trait InwardNodeImp[DI, UI, EI, BI <: Data] { def edgeI(pd: DI, pu: UI): EI def bundleI(ei: Seq[EI]): Vec[BI] - def mixI(pu: UI, node: InwardNode[DI, UI, BI]): UI = pu def colour: String def connect(bo: => BI, bi: => BI, e: => EI)(implicit sourceInfo: SourceInfo): (Option[LazyModule], () => Unit) + + // optional methods to track node graph + def mixI(pu: UI, node: InwardNode[DI, UI, BI]): UI = pu // insert node into parameters + def getO(pu: UI): Option[BaseNode] = None // most-outward common node } -// DO = Downwards flowing Parameters generated by the outner side of the node -// UO = Upwards flowing Parameters received on the outner side of the node +// DO = Downwards flowing Parameters generated by the outer side of the node +// UO = Upwards flowing Parameters received on the outer side of the node // EO = Edge Parameters describing a connection on the outer side of the node // BO = Bundle type used when connecting to the outer side of the node trait OutwardNodeImp[DO, UO, EO, BO <: Data] { def edgeO(pd: DO, pu: UO): EO def bundleO(eo: Seq[EO]): Vec[BO] - def mixO(pd: DO, node: OutwardNode[DO, UO, BO]): DO = pd + + // optional methods to track node graph + def mixO(pd: DO, node: OutwardNode[DO, UO, BO]): DO = pd // insert node into parameters + def getI(pd: DO): Option[BaseNode] = None // most-inward common node } abstract class NodeImp[D, U, EO, EI, B <: Data] @@ -46,6 +52,8 @@ abstract class BaseNode def name = lazyModule.name + "." + nodename def omitGraphML = outputs.isEmpty && inputs.isEmpty + protected[diplomacy] def gci: Option[BaseNode] // greatest common inner + protected[diplomacy] def gco: Option[BaseNode] // greatest common outer protected[diplomacy] def outputs: Seq[BaseNode] protected[diplomacy] def inputs: Seq[BaseNode] protected[diplomacy] def colour: String @@ -147,6 +155,9 @@ class MixedNode[DI, UI, EI, BI <: Data, DO, UO, EO, BO <: Data]( i.map(inner.mixI(_, this)) } + protected[diplomacy] def gco = if (iParams.size != 1) None else inner.getO(iParams(0)) + protected[diplomacy] def gci = if (oParams.size != 1) None else outer.getI(oParams(0)) + lazy val edgesOut = (oPorts zip oParams).map { case ((i, n), o) => outer.edgeO(o, n.iParams(i)) } lazy val edgesIn = (iPorts zip iParams).map { case ((o, n), i) => inner.edgeI(n.oParams(o), i) } diff --git a/src/main/scala/uncore/tilelink2/Nodes.scala b/src/main/scala/uncore/tilelink2/Nodes.scala index 56a8ec66..24668401 100644 --- a/src/main/scala/uncore/tilelink2/Nodes.scala +++ b/src/main/scala/uncore/tilelink2/Nodes.scala @@ -72,9 +72,21 @@ object TLImp extends NodeImp[TLClientPortParameters, TLManagerPortParameters, TL } override def mixO(pd: TLClientPortParameters, node: OutwardNode[TLClientPortParameters, TLManagerPortParameters, TLBundle]): TLClientPortParameters = - pd.copy(clients = pd.clients.map { c => c.copy (nodePath = node +: c.nodePath) }) + pd.copy(clients = pd.clients.map { c => c.copy (nodePath = node +: c.nodePath) }) override def mixI(pu: TLManagerPortParameters, node: InwardNode[TLClientPortParameters, TLManagerPortParameters, TLBundle]): TLManagerPortParameters = - pu.copy(managers = pu.managers.map { m => m.copy (nodePath = node +: m.nodePath) }) + pu.copy(managers = pu.managers.map { m => m.copy (nodePath = node +: m.nodePath) }) + override def getO(pu: TLManagerPortParameters): Option[BaseNode] = { + val head = pu.managers.map(_.nodePath.headOption) + if (head.exists(!_.isDefined) || head.map(_.get).distinct.size != 1) { + None + } else { + val subproblem = pu.copy(managers = pu.managers.map(m => m.copy(nodePath = m.nodePath.tail))) + getO(subproblem) match { + case Some(x) => Some(x) + case None => Some(head(0).get) + } + } + } } case class TLIdentityNode() extends IdentityNode(TLImp)