1
0
Fork 0
rocket-chip/uncore/src/main/scala/tilelink2/Nodes.scala

161 lines
5.1 KiB
Scala
Raw Normal View History

// See LICENSE for license details.
package uncore.tilelink2
import Chisel._
import scala.collection.mutable.ListBuffer
import chisel3.internal.sourceinfo.SourceInfo
// PI = PortInputParameters
// PO = PortOutputParameters
// EI = EdgeInput
// EO = EdgeOutput
abstract class NodeImp[PO, PI, EO, EI, B <: Bundle]
{
def edgeO(po: PO, pi: PI): EO
def edgeI(po: PO, pi: PI): EI
def bundleO(eo: Seq[EO]): Vec[B]
def bundleI(ei: Seq[EI]): Vec[B]
def connect(bo: B, eo: EO, bi: B, ei: EI)(implicit sourceInfo: SourceInfo): Unit
}
class BaseNode[PO, PI, EO, EI, B <: Bundle](imp: NodeImp[PO, PI, EO, EI, B])(
private val clientFn: Option[Seq[PO] => PO],
private val managerFn: Option[Seq[PI] => PI],
private val numClientPorts: Range.Inclusive,
private val numManagerPorts: Range.Inclusive)
{
// At least 0 ports must be supported
require (!numClientPorts.isEmpty)
require (!numManagerPorts.isEmpty)
require (numClientPorts.start >= 0)
require (numManagerPorts.start >= 0)
val noClients = numClientPorts.size == 1 && numClientPorts.contains(0)
val noManagers = numManagerPorts.size == 1 && numManagerPorts.contains(0)
require (noClients || clientFn.isDefined)
require (noManagers || managerFn.isDefined)
private val accClientPorts = ListBuffer[BaseNode[PO, PI, EO, EI, B]]()
private val accManagerPorts = ListBuffer[BaseNode[PO, PI, EO, EI, B]]()
private var clientRealized = false
private var managerRealized = false
private lazy val clientPorts = { clientRealized = true; require (numClientPorts.contains(accClientPorts.size)); accClientPorts.result() }
private lazy val managerPorts = { managerRealized = true; require (numManagerPorts.contains(accManagerPorts.size)); accManagerPorts.result() }
private lazy val clientParams : Option[PO] = clientFn.map(_(managerPorts.map(_.clientParams.get)))
private lazy val managerParams : Option[PI] = managerFn.map(_(clientPorts.map(_.managerParams.get)))
lazy val edgesOut = clientPorts.map { n => imp.edgeO(clientParams.get, n.managerParams.get) }
lazy val edgesIn = managerPorts.map { n => imp.edgeI(n.clientParams.get, managerParams.get) }
lazy val bundleOut = imp.bundleO(edgesOut)
lazy val bundleIn = imp.bundleI(edgesIn)
def connectOut = bundleOut
def connectIn = bundleIn
// source.edge(sink)
protected[tilelink2] def edge(x: BaseNode[PO, PI, EO, EI, B])(implicit sourceInfo: SourceInfo) = {
require (!noClients)
require (!clientRealized)
require (!x.noManagers)
require (!x.managerRealized)
val i = x.accManagerPorts.size
val o = accClientPorts.size
accClientPorts += x
x.accManagerPorts += this
() => {
imp.connect(connectOut(o), edgesOut(o), x.connectIn(i), x.edgesIn(i))
}
}
}
class TLClientNode(
params: TLClientParameters,
numPorts: Range.Inclusive = 1 to 1) extends BaseNode(TLImp)(
clientFn = Some {case Seq() => TLClientPortParameters(Seq(params))},
managerFn = None,
numClientPorts = numPorts,
numManagerPorts = 0 to 0)
{
require(numPorts.end >= 1)
}
object TLClientNode
{
def apply(
params: TLClientParameters,
numPorts: Range.Inclusive = 1 to 1) = new TLClientNode(params, numPorts)
}
class TLManagerNode(
beatBytes: Int,
params: TLManagerParameters,
numPorts: Range.Inclusive = 1 to 1) extends BaseNode(TLImp)(
clientFn = None,
managerFn = Some {case Seq() => TLManagerPortParameters(Seq(params), beatBytes)},
numClientPorts = 0 to 0,
numManagerPorts = numPorts)
{
require(numPorts.end >= 1)
}
object TLManagerNode
{
def apply(
beatBytes: Int,
params: TLManagerParameters,
numPorts: Range.Inclusive = 1 to 1) = new TLManagerNode(beatBytes, params, numPorts)
}
class TLAdapterNode(
clientFn: Seq[TLClientPortParameters] => TLClientPortParameters,
managerFn: Seq[TLManagerPortParameters] => TLManagerPortParameters,
numClientPorts: Range.Inclusive = 1 to 1,
numManagerPorts: Range.Inclusive = 1 to 1) extends BaseNode(TLImp)(
clientFn = Some(clientFn),
managerFn = Some(managerFn),
numClientPorts = numClientPorts,
numManagerPorts = numManagerPorts)
object TLAdapterNode
{
def apply(
clientFn: Seq[TLClientPortParameters] => TLClientPortParameters,
managerFn: Seq[TLManagerPortParameters] => TLManagerPortParameters,
numClientPorts: Range.Inclusive = 1 to 1,
numManagerPorts: Range.Inclusive = 1 to 1) = new TLAdapterNode(clientFn, managerFn, numClientPorts, numManagerPorts)
}
class TLOutputNode extends BaseNode(TLImp)(
clientFn = Some({case Seq(x) => x}),
managerFn = Some({case Seq(x) => x}),
numClientPorts = 1 to 1,
numManagerPorts = 1 to 1)
{
override def connectOut = bundleOut
override def connectIn = bundleOut
}
object TLOutputNode
{
def apply() = new TLOutputNode()
}
class TLInputNode extends BaseNode(TLImp)(
clientFn = Some({case Seq(x) => x}),
managerFn = Some({case Seq(x) => x}),
numClientPorts = 1 to 1,
numManagerPorts = 1 to 1)
{
override def connectOut = bundleIn
override def connectIn = bundleIn
}
object TLInputNode
{
def apply() = new TLInputNode()
}