Merge pull request #536 from ucb-bar/diplomacy-star-nodes
diplomacy: add :*= and :=* to support flexible # of edges
This commit is contained in:
commit
b567a2a356
@ -11,17 +11,14 @@ import util._
|
||||
|
||||
class DefaultCoreplex(implicit p: Parameters) extends BaseCoreplex
|
||||
with CoreplexRISCVPlatform
|
||||
with HasL2MasterPort
|
||||
with HasRocketTiles {
|
||||
override lazy val module = new DefaultCoreplexModule(this, () => new DefaultCoreplexBundle(this))
|
||||
}
|
||||
|
||||
class DefaultCoreplexBundle[+L <: DefaultCoreplex](_outer: L) extends BaseCoreplexBundle(_outer)
|
||||
with CoreplexRISCVPlatformBundle
|
||||
with HasL2MasterPortBundle
|
||||
with HasRocketTilesBundle
|
||||
|
||||
class DefaultCoreplexModule[+L <: DefaultCoreplex, +B <: DefaultCoreplexBundle[L]](_outer: L, _io: () => B) extends BaseCoreplexModule(_outer, _io)
|
||||
with CoreplexRISCVPlatformModule
|
||||
with HasL2MasterPortModule
|
||||
with HasRocketTilesModule
|
||||
|
@ -24,9 +24,13 @@ trait CoreplexNetwork extends HasCoreplexParameters {
|
||||
|
||||
val mmio = TLOutputNode()
|
||||
val mmioInt = IntInputNode()
|
||||
val l2in = TLInputNode()
|
||||
|
||||
intBar.intnode := mmioInt
|
||||
|
||||
// Allows a variable number of inputs from outside to the Xbar
|
||||
l1tol2.node :=* l2in
|
||||
|
||||
cbus.node :=
|
||||
TLBuffer()(
|
||||
TLAtomicAutomata(arithmetic = true)( // disable once TLB uses TL2 metadata
|
||||
@ -43,6 +47,7 @@ trait CoreplexNetworkBundle extends HasCoreplexParameters {
|
||||
|
||||
val mmio = outer.mmio.bundleOut
|
||||
val interrupts = outer.mmioInt.bundleIn
|
||||
val l2in = outer.l2in.bundleIn
|
||||
}
|
||||
|
||||
trait CoreplexNetworkModule extends HasCoreplexParameters {
|
||||
@ -93,21 +98,3 @@ trait BankedL2CoherenceManagersModule extends CoreplexNetworkModule {
|
||||
val outer: BankedL2CoherenceManagers
|
||||
val io: BankedL2CoherenceManagersBundle
|
||||
}
|
||||
|
||||
/////
|
||||
|
||||
trait HasL2MasterPort extends CoreplexNetwork {
|
||||
val module: HasL2MasterPortModule
|
||||
val l2in = TLInputNode()
|
||||
l1tol2.node := TLBuffer()(l2in)
|
||||
}
|
||||
|
||||
trait HasL2MasterPortBundle extends CoreplexNetworkBundle {
|
||||
val outer: HasL2MasterPort
|
||||
val l2in = outer.l2in.bundleIn
|
||||
}
|
||||
|
||||
trait HasL2MasterPortModule extends CoreplexNetworkModule {
|
||||
val outer: HasL2MasterPort
|
||||
val io: HasL2MasterPortBundle
|
||||
}
|
||||
|
@ -16,7 +16,9 @@ trait InwardNodeImp[DI, UI, EI, BI <: Data]
|
||||
def edgeI(pd: DI, pu: UI): EI
|
||||
def bundleI(ei: Seq[EI]): Vec[BI]
|
||||
def colour: String
|
||||
def connect(bo: => BI, bi: => BI, e: => EI)(implicit p: Parameters, sourceInfo: SourceInfo): (Option[LazyModule], () => Unit)
|
||||
def connect(bindings: () => Seq[(EI, BI, BI)])(implicit p: Parameters, sourceInfo: SourceInfo): (Option[LazyModule], () => Unit) = {
|
||||
(None, () => bindings().foreach { case (_, i, o) => i <> o })
|
||||
}
|
||||
|
||||
// optional methods to track node graph
|
||||
def mixI(pu: UI, node: InwardNode[DI, UI, BI]): UI = pu // insert node into parameters
|
||||
@ -71,8 +73,17 @@ trait InwardNodeHandle[DI, UI, BI <: Data]
|
||||
val inward: InwardNode[DI, UI, BI]
|
||||
def := (h: OutwardNodeHandle[DI, UI, BI])(implicit p: Parameters, sourceInfo: SourceInfo): Option[LazyModule] =
|
||||
inward.:=(h)(p, sourceInfo)
|
||||
def :*= (h: OutwardNodeHandle[DI, UI, BI])(implicit p: Parameters, sourceInfo: SourceInfo): Option[LazyModule] =
|
||||
inward.:*=(h)(p, sourceInfo)
|
||||
def :=* (h: OutwardNodeHandle[DI, UI, BI])(implicit p: Parameters, sourceInfo: SourceInfo): Option[LazyModule] =
|
||||
inward.:=*(h)(p, sourceInfo)
|
||||
}
|
||||
|
||||
sealed trait NodeBinding
|
||||
case object BIND_ONCE extends NodeBinding
|
||||
case object BIND_QUERY extends NodeBinding
|
||||
case object BIND_STAR extends NodeBinding
|
||||
|
||||
trait InwardNode[DI, UI, BI <: Data] extends BaseNode with InwardNodeHandle[DI, UI, BI]
|
||||
{
|
||||
val inward = this
|
||||
@ -81,21 +92,22 @@ trait InwardNode[DI, UI, BI <: Data] extends BaseNode with InwardNodeHandle[DI,
|
||||
require (!numPI.isEmpty, s"No number of inputs would be acceptable to ${name}${lazyModule.line}")
|
||||
require (numPI.start >= 0, s"${name} accepts a negative number of inputs${lazyModule.line}")
|
||||
|
||||
private val accPI = ListBuffer[(Int, OutwardNode[DI, UI, BI])]()
|
||||
private val accPI = ListBuffer[(Int, OutwardNode[DI, UI, BI], NodeBinding)]()
|
||||
private var iRealized = false
|
||||
|
||||
protected[diplomacy] def iPushed = accPI.size
|
||||
protected[diplomacy] def iPush(index: Int, node: OutwardNode[DI, UI, BI])(implicit sourceInfo: SourceInfo) {
|
||||
protected[diplomacy] def iPush(index: Int, node: OutwardNode[DI, UI, BI], binding: NodeBinding)(implicit sourceInfo: SourceInfo) {
|
||||
val info = sourceLine(sourceInfo, " at ", "")
|
||||
val noIs = numPI.size == 1 && numPI.contains(0)
|
||||
require (!noIs, s"${name}${lazyModule.line} was incorrectly connected as a sink" + info)
|
||||
require (!iRealized, s"${name}${lazyModule.line} was incorrectly connected as a sink after it's .module was used" + info)
|
||||
accPI += ((index, node))
|
||||
accPI += ((index, node, binding))
|
||||
}
|
||||
|
||||
private def reqI() = require(numPI.contains(accPI.size), s"${name} has ${accPI.size} inputs, expected ${numPI}${lazyModule.line}")
|
||||
protected[diplomacy] lazy val iPorts = { iRealized = true; reqI(); accPI.result() }
|
||||
protected[diplomacy] lazy val iBindings = { iRealized = true; accPI.result() }
|
||||
|
||||
protected[diplomacy] val iStar: Int
|
||||
protected[diplomacy] val iPortMapping: Seq[(Int, Int)]
|
||||
protected[diplomacy] val iParams: Seq[UI]
|
||||
val bundleIn: Vec[BI]
|
||||
}
|
||||
@ -113,48 +125,84 @@ trait OutwardNode[DO, UO, BO <: Data] extends BaseNode with OutwardNodeHandle[DO
|
||||
require (!numPO.isEmpty, s"No number of outputs would be acceptable to ${name}${lazyModule.line}")
|
||||
require (numPO.start >= 0, s"${name} accepts a negative number of outputs${lazyModule.line}")
|
||||
|
||||
private val accPO = ListBuffer[(Int, InwardNode [DO, UO, BO])]()
|
||||
private val accPO = ListBuffer[(Int, InwardNode [DO, UO, BO], NodeBinding)]()
|
||||
private var oRealized = false
|
||||
|
||||
protected[diplomacy] def oPushed = accPO.size
|
||||
protected[diplomacy] def oPush(index: Int, node: InwardNode [DO, UO, BO])(implicit sourceInfo: SourceInfo) {
|
||||
protected[diplomacy] def oPush(index: Int, node: InwardNode [DO, UO, BO], binding: NodeBinding)(implicit sourceInfo: SourceInfo) {
|
||||
val info = sourceLine(sourceInfo, " at ", "")
|
||||
val noOs = numPO.size == 1 && numPO.contains(0)
|
||||
require (!noOs, s"${name}${lazyModule.line} was incorrectly connected as a source" + info)
|
||||
require (!oRealized, s"${name}${lazyModule.line} was incorrectly connected as a source after it's .module was used" + info)
|
||||
accPO += ((index, node))
|
||||
accPO += ((index, node, binding))
|
||||
}
|
||||
|
||||
private def reqO() = require(numPO.contains(accPO.size), s"${name} has ${accPO.size} outputs, expected ${numPO}${lazyModule.line}")
|
||||
protected[diplomacy] lazy val oPorts = { oRealized = true; reqO(); accPO.result() }
|
||||
protected[diplomacy] lazy val oBindings = { oRealized = true; accPO.result() }
|
||||
|
||||
protected[diplomacy] val oStar: Int
|
||||
protected[diplomacy] val oPortMapping: Seq[(Int, Int)]
|
||||
protected[diplomacy] val oParams: Seq[DO]
|
||||
val bundleOut: Vec[BO]
|
||||
}
|
||||
|
||||
class MixedNode[DI, UI, EI, BI <: Data, DO, UO, EO, BO <: Data](
|
||||
abstract class MixedNode[DI, UI, EI, BI <: Data, DO, UO, EO, BO <: Data](
|
||||
inner: InwardNodeImp [DI, UI, EI, BI],
|
||||
outer: OutwardNodeImp[DO, UO, EO, BO])(
|
||||
private val dFn: (Int, Seq[DI]) => Seq[DO],
|
||||
private val uFn: (Int, Seq[UO]) => Seq[UI],
|
||||
protected[diplomacy] val numPO: Range.Inclusive,
|
||||
protected[diplomacy] val numPI: Range.Inclusive)
|
||||
extends BaseNode with InwardNode[DI, UI, BI] with OutwardNode[DO, UO, BO]
|
||||
{
|
||||
// meta-data for printing the node graph
|
||||
protected[diplomacy] def colour = inner.colour
|
||||
protected[diplomacy] def outputs = oPorts.map(_._2) zip edgesOut.map(e => outer.labelO(e))
|
||||
protected[diplomacy] def inputs = iPorts.map(_._2) zip edgesIn .map(e => inner.labelI(e))
|
||||
protected[diplomacy] def resolveStarO(i: Int, o: Int): Int
|
||||
protected[diplomacy] def resolveStarI(i: Int, o: Int): Int
|
||||
protected[diplomacy] def mapParamsD(n: Int, p: Seq[DI]): Seq[DO]
|
||||
protected[diplomacy] def mapParamsU(n: Int, p: Seq[UO]): Seq[UI]
|
||||
|
||||
protected[diplomacy] lazy val (oPortMapping, iPortMapping, oStar, iStar) = {
|
||||
val oStars = oBindings.filter { case (_,_,b) => b == BIND_STAR }.size
|
||||
val iStars = iBindings.filter { case (_,_,b) => b == BIND_STAR }.size
|
||||
require (oStars + iStars <= 1, s"${name} appears beside a :*= ${iStars} times and a :=* ${oStars} times; at most once is allowed${lazyModule.line}")
|
||||
val oKnown = oBindings.map { case (_, n, b) => b match {
|
||||
case BIND_ONCE => 1
|
||||
case BIND_QUERY => n.iStar
|
||||
case BIND_STAR => 0 }}.foldLeft(0)(_+_)
|
||||
val iKnown = iBindings.map { case (_, n, b) => b match {
|
||||
case BIND_ONCE => 1
|
||||
case BIND_QUERY => n.oStar
|
||||
case BIND_STAR => 0 }}.foldLeft(0)(_+_)
|
||||
val oStar = if (oStars > 0) resolveStarO(iKnown, oKnown) else 0
|
||||
val iStar = if (iStars > 0) resolveStarI(iKnown, oKnown) else 0
|
||||
val oSum = oBindings.map { case (_, n, b) => b match {
|
||||
case BIND_ONCE => 1
|
||||
case BIND_QUERY => n.iStar
|
||||
case BIND_STAR => oStar }}.scanLeft(0)(_+_)
|
||||
val iSum = iBindings.map { case (_, n, b) => b match {
|
||||
case BIND_ONCE => 1
|
||||
case BIND_QUERY => n.oStar
|
||||
case BIND_STAR => iStar }}.scanLeft(0)(_+_)
|
||||
val oTotal = oSum.lastOption.getOrElse(0)
|
||||
val iTotal = iSum.lastOption.getOrElse(0)
|
||||
require(numPO.contains(oTotal), s"${name} has ${oTotal} outputs, expected ${numPO}${lazyModule.line}")
|
||||
require(numPI.contains(iTotal), s"${name} has ${iTotal} inputs, expected ${numPI}${lazyModule.line}")
|
||||
(oSum.init zip oSum.tail, iSum.init zip iSum.tail, oStar, iStar)
|
||||
}
|
||||
|
||||
lazy val oPorts = oBindings.flatMap { case (i, n, _) =>
|
||||
val (start, end) = n.iPortMapping(i)
|
||||
(start until end) map { j => (j, n) }
|
||||
}
|
||||
lazy val iPorts = iBindings.flatMap { case (i, n, _) =>
|
||||
val (start, end) = n.oPortMapping(i)
|
||||
(start until end) map { j => (j, n) }
|
||||
}
|
||||
|
||||
private def reqE(o: Int, i: Int) = require(i == o, s"${name} has ${i} inputs and ${o} outputs; they must match${lazyModule.line}")
|
||||
protected[diplomacy] lazy val oParams: Seq[DO] = {
|
||||
val o = dFn(oPorts.size, iPorts.map { case (i, n) => n.oParams(i) })
|
||||
reqE(oPorts.size, o.size)
|
||||
val o = mapParamsD(oPorts.size, iPorts.map { case (i, n) => n.oParams(i) })
|
||||
require (o.size == oPorts.size, s"Bug in diplomacy; ${name} has ${o.size} != ${oPorts.size} down/up outer parameters${lazyModule.line}")
|
||||
o.map(outer.mixO(_, this))
|
||||
}
|
||||
protected[diplomacy] lazy val iParams: Seq[UI] = {
|
||||
val i = uFn(iPorts.size, oPorts.map { case (o, n) => n.iParams(o) })
|
||||
reqE(i.size, iPorts.size)
|
||||
val i = mapParamsU(iPorts.size, oPorts.map { case (o, n) => n.iParams(o) })
|
||||
require (i.size == iPorts.size, s"Bug in diplomacy; ${name} has ${i.size} != ${iPorts.size} up/down inner parameters${lazyModule.line}")
|
||||
i.map(inner.mixI(_, this))
|
||||
}
|
||||
|
||||
@ -175,87 +223,174 @@ class MixedNode[DI, UI, EI, BI <: Data, DO, UO, EO, BO <: Data](
|
||||
lazy val bundleIn = wireI(flipI(inner.bundleI(edgesIn)))
|
||||
|
||||
// connects the outward part of a node with the inward part of this node
|
||||
override def := (h: OutwardNodeHandle[DI, UI, BI])(implicit p: Parameters, sourceInfo: SourceInfo): Option[LazyModule] = {
|
||||
private def bind(h: OutwardNodeHandle[DI, UI, BI], binding: NodeBinding)(implicit p: Parameters, sourceInfo: SourceInfo): Option[LazyModule] = {
|
||||
val x = this // x := y
|
||||
val y = h.outward
|
||||
val info = sourceLine(sourceInfo, " at ", "")
|
||||
require (!LazyModule.stack.isEmpty, s"${y.name} cannot be connected to ${x.name} outside of LazyModule scope" + info)
|
||||
val i = x.iPushed
|
||||
val o = y.oPushed
|
||||
y.oPush(i, x)
|
||||
x.iPush(o, y)
|
||||
val (out, binding) = inner.connect(y.bundleOut(o), x.bundleIn(i), x.edgesIn(i))
|
||||
LazyModule.stack.head.bindings = binding :: LazyModule.stack.head.bindings
|
||||
y.oPush(i, x, binding match {
|
||||
case BIND_ONCE => BIND_ONCE
|
||||
case BIND_STAR => BIND_QUERY
|
||||
case BIND_QUERY => BIND_STAR })
|
||||
x.iPush(o, y, binding)
|
||||
def bindings() = {
|
||||
val (iStart, iEnd) = x.iPortMapping(i)
|
||||
val (oStart, oEnd) = y.oPortMapping(o)
|
||||
require (iEnd - iStart == oEnd - oStart, s"Bug in diplomacy; ${iEnd-iStart} != ${oEnd-oStart} means port resolution failed")
|
||||
Seq.tabulate(iEnd - iStart) { j =>
|
||||
(x.edgesIn(iStart+j), x.bundleIn(iStart+j), y.bundleOut(oStart+j))
|
||||
}
|
||||
}
|
||||
val (out, newbinding) = inner.connect(bindings _)
|
||||
LazyModule.stack.head.bindings = newbinding :: LazyModule.stack.head.bindings
|
||||
out
|
||||
}
|
||||
|
||||
override def := (h: OutwardNodeHandle[DI, UI, BI])(implicit p: Parameters, sourceInfo: SourceInfo): Option[LazyModule] = bind(h, BIND_ONCE)
|
||||
override def :*= (h: OutwardNodeHandle[DI, UI, BI])(implicit p: Parameters, sourceInfo: SourceInfo): Option[LazyModule] = bind(h, BIND_STAR)
|
||||
override def :=* (h: OutwardNodeHandle[DI, UI, BI])(implicit p: Parameters, sourceInfo: SourceInfo): Option[LazyModule] = bind(h, BIND_QUERY)
|
||||
|
||||
// meta-data for printing the node graph
|
||||
protected[diplomacy] def colour = inner.colour
|
||||
protected[diplomacy] def outputs = oPorts.map(_._2) zip edgesOut.map(e => outer.labelO(e))
|
||||
protected[diplomacy] def inputs = iPorts.map(_._2) zip edgesIn .map(e => inner.labelI(e))
|
||||
}
|
||||
|
||||
class MixedAdapterNode[DI, UI, EI, BI <: Data, DO, UO, EO, BO <: Data](
|
||||
inner: InwardNodeImp [DI, UI, EI, BI],
|
||||
outer: OutwardNodeImp[DO, UO, EO, BO])(
|
||||
dFn: DI => DO,
|
||||
uFn: UO => UI,
|
||||
num: Range.Inclusive = 0 to 999)
|
||||
extends MixedNode(inner, outer)(num, num)
|
||||
{
|
||||
protected[diplomacy] def resolveStarO(i: Int, o: Int): Int = {
|
||||
require (i >= o, s"${name} has ${o} outputs and ${i} inputs; cannot assign ${i-o} edges to resolve :=*${lazyModule.line}")
|
||||
i - o
|
||||
}
|
||||
protected[diplomacy] def resolveStarI(i: Int, o: Int): Int = {
|
||||
require (o >= i, s"${name} has ${o} outputs and ${i} inputs; cannot assign ${o-i} edges to resolve :*=${lazyModule.line}")
|
||||
o - i
|
||||
}
|
||||
protected[diplomacy] def mapParamsD(n: Int, p: Seq[DI]): Seq[DO] = {
|
||||
require(n == p.size, s"${name} has ${p.size} inputs and ${n} outputs; they must match${lazyModule.line}")
|
||||
p.map(dFn)
|
||||
}
|
||||
protected[diplomacy] def mapParamsU(n: Int, p: Seq[UO]): Seq[UI] = {
|
||||
require(n == p.size, s"${name} has ${n} inputs and ${p.size} outputs; they must match${lazyModule.line}")
|
||||
p.map(uFn)
|
||||
}
|
||||
}
|
||||
|
||||
class SimpleNode[D, U, EO, EI, B <: Data](imp: NodeImp[D, U, EO, EI, B])(
|
||||
oFn: (Int, Seq[D]) => Seq[D],
|
||||
iFn: (Int, Seq[U]) => Seq[U],
|
||||
numPO: Range.Inclusive,
|
||||
numPI: Range.Inclusive)
|
||||
extends MixedNode[D, U, EI, B, D, U, EO, B](imp, imp)(oFn, iFn, numPO, numPI)
|
||||
class MixedNexusNode[DI, UI, EI, BI <: Data, DO, UO, EO, BO <: Data](
|
||||
inner: InwardNodeImp [DI, UI, EI, BI],
|
||||
outer: OutwardNodeImp[DO, UO, EO, BO])(
|
||||
dFn: Seq[DI] => DO,
|
||||
uFn: Seq[UO] => UI,
|
||||
numPO: Range.Inclusive = 1 to 999,
|
||||
numPI: Range.Inclusive = 1 to 999)
|
||||
extends MixedNode(inner, outer)(numPO, numPI)
|
||||
{
|
||||
require (numPO.end >= 1, s"${name} does not accept outputs${lazyModule.line}")
|
||||
require (numPI.end >= 1, s"${name} does not accept inputs${lazyModule.line}")
|
||||
protected[diplomacy] def resolveStarO(i: Int, o: Int): Int = {
|
||||
require (false, "${name} cannot resolve :=*${lazyModule.line}")
|
||||
0
|
||||
}
|
||||
protected[diplomacy] def resolveStarI(i: Int, o: Int): Int = {
|
||||
require (false, s"${name} cannot resolve :*=${lazyModule.line}")
|
||||
0
|
||||
}
|
||||
protected[diplomacy] def mapParamsD(n: Int, p: Seq[DI]): Seq[DO] = Seq.fill(n) { dFn(p) }
|
||||
protected[diplomacy] def mapParamsU(n: Int, p: Seq[UO]): Seq[UI] = Seq.fill(n) { uFn(p) }
|
||||
}
|
||||
|
||||
class IdentityNode[PO, PI, EO, EI, B <: Data](imp: NodeImp[PO, PI, EO, EI, B])
|
||||
extends SimpleNode(imp)({case (_, s) => s}, {case (_, s) => s}, 0 to 999, 0 to 999)
|
||||
class AdapterNode[D, U, EO, EI, B <: Data](imp: NodeImp[D, U, EO, EI, B])(
|
||||
dFn: D => D,
|
||||
uFn: U => U,
|
||||
num: Range.Inclusive = 0 to 999)
|
||||
extends MixedAdapterNode[D, U, EI, B, D, U, EO, B](imp, imp)(dFn, uFn, num)
|
||||
|
||||
class OutputNode[PO, PI, EO, EI, B <: Data](imp: NodeImp[PO, PI, EO, EI, B]) extends IdentityNode(imp)
|
||||
class NexusNode[D, U, EO, EI, B <: Data](imp: NodeImp[D, U, EO, EI, B])(
|
||||
dFn: Seq[D] => D,
|
||||
uFn: Seq[U] => U,
|
||||
numPO: Range.Inclusive = 1 to 999,
|
||||
numPI: Range.Inclusive = 1 to 999)
|
||||
extends MixedNexusNode[D, U, EI, B, D, U, EO, B](imp, imp)(dFn, uFn, numPO, numPI)
|
||||
|
||||
class IdentityNode[D, U, EO, EI, B <: Data](imp: NodeImp[D, U, EO, EI, B])
|
||||
extends AdapterNode(imp)({s => s}, {s => s})
|
||||
|
||||
class OutputNode[D, U, EO, EI, B <: Data](imp: NodeImp[D, U, EO, EI, B]) extends IdentityNode(imp)
|
||||
{
|
||||
override lazy val bundleIn = bundleOut
|
||||
}
|
||||
|
||||
class InputNode[PO, PI, EO, EI, B <: Data](imp: NodeImp[PO, PI, EO, EI, B]) extends IdentityNode(imp)
|
||||
class InputNode[D, U, EO, EI, B <: Data](imp: NodeImp[D, U, EO, EI, B]) extends IdentityNode(imp)
|
||||
{
|
||||
override lazy val bundleOut = bundleIn
|
||||
}
|
||||
|
||||
class SourceNode[PO, PI, EO, EI, B <: Data](imp: NodeImp[PO, PI, EO, EI, B])(po: PO, num: Range.Inclusive = 1 to 1)
|
||||
extends SimpleNode(imp)({case (n, Seq()) => Seq.fill(n)(po)}, {case (0, _) => Seq()}, num, 0 to 0)
|
||||
class SourceNode[D, U, EO, EI, B <: Data](imp: NodeImp[D, U, EO, EI, B])(po: Seq[D])
|
||||
extends MixedNode(imp, imp)(po.size to po.size, 0 to 0)
|
||||
{
|
||||
require (num.end >= 1, s"${name} is a source which does not accept outputs${lazyModule.line}")
|
||||
protected[diplomacy] def resolveStarO(i: Int, o: Int): Int = {
|
||||
require (po.size >= o, s"${name} has ${o} outputs out of ${po.size}; cannot assign ${po.size - o} edges to resolve :=*${lazyModule.line}")
|
||||
po.size - o
|
||||
}
|
||||
protected[diplomacy] def resolveStarI(i: Int, o: Int): Int = {
|
||||
require (false, s"${name} cannot resolve :*=${lazyModule.line}")
|
||||
0
|
||||
}
|
||||
protected[diplomacy] def mapParamsD(n: Int, p: Seq[D]): Seq[D] = po
|
||||
protected[diplomacy] def mapParamsU(n: Int, p: Seq[U]): Seq[U] = Seq()
|
||||
|
||||
override lazy val bundleIn = { require(false, s"${name} has no bundleIn; try bundleOut?"); bundleOut }
|
||||
}
|
||||
|
||||
class SinkNode[PO, PI, EO, EI, B <: Data](imp: NodeImp[PO, PI, EO, EI, B])(pi: PI, num: Range.Inclusive = 1 to 1)
|
||||
extends SimpleNode(imp)({case (0, _) => Seq()}, {case (n, Seq()) => Seq.fill(n)(pi)}, 0 to 0, num)
|
||||
class SinkNode[D, U, EO, EI, B <: Data](imp: NodeImp[D, U, EO, EI, B])(pi: Seq[U])
|
||||
extends MixedNode(imp, imp)(0 to 0, pi.size to pi.size)
|
||||
{
|
||||
require (num.end >= 1, s"${name} is a sink which does not accept inputs${lazyModule.line}")
|
||||
protected[diplomacy] def resolveStarO(i: Int, o: Int): Int = {
|
||||
require (false, s"${name} cannot resolve :=*${lazyModule.line}")
|
||||
0
|
||||
}
|
||||
protected[diplomacy] def resolveStarI(i: Int, o: Int): Int = {
|
||||
require (pi.size >= i, s"${name} has ${i} inputs out of ${pi.size}; cannot assign ${pi.size - i} edges to resolve :*=${lazyModule.line}")
|
||||
pi.size - i
|
||||
}
|
||||
protected[diplomacy] def mapParamsD(n: Int, p: Seq[D]): Seq[D] = Seq()
|
||||
protected[diplomacy] def mapParamsU(n: Int, p: Seq[U]): Seq[U] = pi
|
||||
|
||||
override lazy val bundleOut = { require(false, s"${name} has no bundleOut; try bundleIn?"); bundleIn }
|
||||
}
|
||||
|
||||
class BlindOutputNode[PO, PI, EO, EI, B <: Data](imp: NodeImp[PO, PI, EO, EI, B])(pi: Seq[PI])
|
||||
extends SimpleNode(imp)({case (0, _) => Seq()}, {case (_, Seq()) => pi}, 0 to 0, pi.size to pi.size)
|
||||
class BlindOutputNode[D, U, EO, EI, B <: Data](imp: NodeImp[D, U, EO, EI, B])(pi: Seq[U])
|
||||
extends SinkNode(imp)(pi)
|
||||
{
|
||||
override val flip = true
|
||||
override lazy val bundleOut = bundleIn
|
||||
}
|
||||
|
||||
class BlindInputNode[PO, PI, EO, EI, B <: Data](imp: NodeImp[PO, PI, EO, EI, B])(po: Seq[PO])
|
||||
extends SimpleNode(imp)({case (_, Seq()) => po}, {case (0, _) => Seq()}, po.size to po.size, 0 to 0)
|
||||
class BlindInputNode[D, U, EO, EI, B <: Data](imp: NodeImp[D, U, EO, EI, B])(po: Seq[D])
|
||||
extends SourceNode(imp)(po)
|
||||
{
|
||||
override val flip = true
|
||||
override lazy val bundleIn = bundleOut
|
||||
}
|
||||
|
||||
class InternalOutputNode[PO, PI, EO, EI, B <: Data](imp: NodeImp[PO, PI, EO, EI, B])(pi: Seq[PI])
|
||||
extends SimpleNode(imp)({case (0, _) => Seq()}, {case (_, Seq()) => pi}, 0 to 0, pi.size to pi.size)
|
||||
class InternalOutputNode[D, U, EO, EI, B <: Data](imp: NodeImp[D, U, EO, EI, B])(pi: Seq[U])
|
||||
extends SinkNode(imp)(pi)
|
||||
{
|
||||
override val wire = true
|
||||
override lazy val bundleOut = bundleIn
|
||||
}
|
||||
|
||||
class InternalInputNode[PO, PI, EO, EI, B <: Data](imp: NodeImp[PO, PI, EO, EI, B])(po: Seq[PO])
|
||||
extends SimpleNode(imp)({case (_, Seq()) => po}, {case (0, _) => Seq()}, po.size to po.size, 0 to 0)
|
||||
class InternalInputNode[D, U, EO, EI, B <: Data](imp: NodeImp[D, U, EO, EI, B])(po: Seq[D])
|
||||
extends SourceNode(imp)(po)
|
||||
{
|
||||
override val wire = true
|
||||
override lazy val bundleIn = bundleOut
|
||||
}
|
||||
|
||||
class InteriorNode[PO, PI, EO, EI, B <: Data](imp: NodeImp[PO, PI, EO, EI, B])
|
||||
(oFn: Seq[PO] => PO, iFn: Seq[PI] => PI, numPO: Range.Inclusive, numPI: Range.Inclusive)
|
||||
extends SimpleNode(imp)({case (n,s) => Seq.fill(n)(oFn(s))}, {case (n,s) => Seq.fill(n)(iFn(s))}, numPO, numPI)
|
||||
{
|
||||
require (numPO.end >= 1, s"${name} is an adapter which does not accept outputs${lazyModule.line}")
|
||||
require (numPI.end >= 1, s"${name} is an adapter which does not accept inputs${lazyModule.line}")
|
||||
}
|
||||
|
@ -13,7 +13,7 @@ import uncore.util._
|
||||
|
||||
class ScratchpadSlavePort(implicit p: Parameters) extends LazyModule {
|
||||
val coreDataBytes = p(XLen)/8
|
||||
val node = TLManagerNode(TLManagerPortParameters(
|
||||
val node = TLManagerNode(Seq(TLManagerPortParameters(
|
||||
Seq(TLManagerParameters(
|
||||
address = List(AddressSet(0x80000000L, BigInt(p(DataScratchpadSize)-1))),
|
||||
regionType = RegionType.UNCACHED,
|
||||
@ -25,7 +25,7 @@ class ScratchpadSlavePort(implicit p: Parameters) extends LazyModule {
|
||||
supportsGet = TransferSizes(1, coreDataBytes),
|
||||
fifoId = Some(0))), // requests handled in FIFO order
|
||||
beatBytes = coreDataBytes,
|
||||
minLatency = 1))
|
||||
minLatency = 1)))
|
||||
|
||||
lazy val module = new LazyModuleImp(this) {
|
||||
val io = new Bundle {
|
||||
|
@ -34,6 +34,7 @@ trait TopNetwork extends HasPeripheryParameters {
|
||||
val socBus = LazyModule(new TLXbar)
|
||||
val peripheryBus = LazyModule(new TLXbar)
|
||||
val intBus = LazyModule(new IntXbar)
|
||||
val l2 = LazyModule(new TLBuffer)
|
||||
|
||||
peripheryBus.node :=
|
||||
TLBuffer()(
|
||||
@ -62,13 +63,3 @@ class BaseTopBundle[+L <: BaseTop](_outer: L) extends BareTopBundle(_outer)
|
||||
|
||||
class BaseTopModule[+L <: BaseTop, +B <: BaseTopBundle[L]](_outer: L, _io: () => B) extends BareTopModule(_outer, _io)
|
||||
with TopNetworkModule
|
||||
|
||||
trait L2Crossbar extends TopNetwork {
|
||||
val l2 = LazyModule(new TLXbar)
|
||||
}
|
||||
|
||||
trait L2CrossbarBundle extends TopNetworkBundle {
|
||||
}
|
||||
|
||||
trait L2CrossbarModule extends TopNetworkModule {
|
||||
}
|
||||
|
@ -165,7 +165,7 @@ trait PeripheryMasterAXI4MMIOModule {
|
||||
/////
|
||||
|
||||
// PeripherySlaveAXI4 is an example, make your own cake pattern like this one.
|
||||
trait PeripherySlaveAXI4 extends L2Crossbar {
|
||||
trait PeripherySlaveAXI4 extends TopNetwork {
|
||||
private val config = p(ExtIn)
|
||||
val l2_axi4 = AXI4BlindInputNode(Seq(AXI4MasterPortParameters(
|
||||
masters = Seq(AXI4MasterParameters(
|
||||
@ -179,12 +179,12 @@ trait PeripherySlaveAXI4 extends L2Crossbar {
|
||||
l2_axi4))))
|
||||
}
|
||||
|
||||
trait PeripherySlaveAXI4Bundle extends L2CrossbarBundle {
|
||||
trait PeripherySlaveAXI4Bundle extends TopNetworkBundle {
|
||||
val outer: PeripherySlaveAXI4
|
||||
val l2_axi4 = outer.l2_axi4.bundleIn
|
||||
}
|
||||
|
||||
trait PeripherySlaveAXI4Module extends L2CrossbarModule {
|
||||
trait PeripherySlaveAXI4Module extends TopNetworkModule {
|
||||
val outer: PeripherySlaveAXI4
|
||||
val io: PeripherySlaveAXI4Bundle
|
||||
// nothing to do
|
||||
@ -231,7 +231,7 @@ trait PeripheryMasterTLMMIOModule {
|
||||
/////
|
||||
|
||||
// NOTE: this port is NOT allowed to issue Acquires
|
||||
trait PeripherySlaveTL extends L2Crossbar {
|
||||
trait PeripherySlaveTL extends TopNetwork {
|
||||
private val config = p(ExtIn)
|
||||
val l2_tl = TLBlindInputNode(Seq(TLClientPortParameters(
|
||||
clients = Seq(TLClientParameters(
|
||||
@ -243,12 +243,12 @@ trait PeripherySlaveTL extends L2Crossbar {
|
||||
l2_tl))
|
||||
}
|
||||
|
||||
trait PeripherySlaveTLBundle extends L2CrossbarBundle {
|
||||
trait PeripherySlaveTLBundle extends TopNetworkBundle {
|
||||
val outer: PeripherySlaveTL
|
||||
val l2_tl = outer.l2_tl.bundleIn
|
||||
}
|
||||
|
||||
trait PeripherySlaveTLModule extends L2CrossbarModule {
|
||||
trait PeripherySlaveTLModule extends TopNetworkModule {
|
||||
val outer: PeripherySlaveTL
|
||||
val io: PeripherySlaveTLBundle
|
||||
// nothing to do
|
||||
|
@ -10,23 +10,23 @@ import uncore.devices._
|
||||
import util._
|
||||
import coreplex._
|
||||
|
||||
trait RocketPlexMaster extends L2Crossbar {
|
||||
trait RocketPlexMaster extends TopNetwork {
|
||||
val module: RocketPlexMasterModule
|
||||
val mem: Seq[TLInwardNode]
|
||||
|
||||
val coreplex = LazyModule(new DefaultCoreplex)
|
||||
|
||||
coreplex.l2in := l2.node
|
||||
coreplex.l2in :=* l2.node
|
||||
socBus.node := coreplex.mmio
|
||||
coreplex.mmioInt := intBus.intnode
|
||||
mem.foreach { _ := coreplex.mem }
|
||||
}
|
||||
|
||||
trait RocketPlexMasterBundle extends L2CrossbarBundle {
|
||||
trait RocketPlexMasterBundle extends TopNetworkBundle {
|
||||
val outer: RocketPlexMaster
|
||||
}
|
||||
|
||||
trait RocketPlexMasterModule extends L2CrossbarModule {
|
||||
trait RocketPlexMasterModule extends TopNetworkModule {
|
||||
val outer: RocketPlexMaster
|
||||
val io: RocketPlexMasterBundle
|
||||
val clock: Clock
|
||||
|
@ -19,10 +19,6 @@ object AHBImp extends NodeImp[AHBMasterPortParameters, AHBSlavePortParameters, A
|
||||
override def labelI(ei: AHBEdgeParameters) = (ei.slave.beatBytes * 8).toString
|
||||
override def labelO(eo: AHBEdgeParameters) = (eo.slave.beatBytes * 8).toString
|
||||
|
||||
def connect(bo: => AHBBundle, bi: => AHBBundle, ei: => AHBEdgeParameters)(implicit p: Parameters, sourceInfo: SourceInfo): (Option[LazyModule], () => Unit) = {
|
||||
(None, () => { bi <> bo })
|
||||
}
|
||||
|
||||
override def mixO(pd: AHBMasterPortParameters, node: OutwardNode[AHBMasterPortParameters, AHBSlavePortParameters, AHBBundle]): AHBMasterPortParameters =
|
||||
pd.copy(masters = pd.masters.map { c => c.copy (nodePath = node +: c.nodePath) })
|
||||
override def mixI(pu: AHBSlavePortParameters, node: InwardNode[AHBMasterPortParameters, AHBSlavePortParameters, AHBBundle]): AHBSlavePortParameters =
|
||||
@ -31,16 +27,14 @@ object AHBImp extends NodeImp[AHBMasterPortParameters, AHBSlavePortParameters, A
|
||||
|
||||
// Nodes implemented inside modules
|
||||
case class AHBIdentityNode() extends IdentityNode(AHBImp)
|
||||
case class AHBMasterNode(portParams: AHBMasterPortParameters, numPorts: Range.Inclusive = 1 to 1)
|
||||
extends SourceNode(AHBImp)(portParams, numPorts)
|
||||
case class AHBSlaveNode(portParams: AHBSlavePortParameters, numPorts: Range.Inclusive = 1 to 1)
|
||||
extends SinkNode(AHBImp)(portParams, numPorts)
|
||||
case class AHBAdapterNode(
|
||||
case class AHBMasterNode(portParams: Seq[AHBMasterPortParameters]) extends SourceNode(AHBImp)(portParams)
|
||||
case class AHBSlaveNode(portParams: Seq[AHBSlavePortParameters]) extends SinkNode(AHBImp)(portParams)
|
||||
case class AHBNexusNode(
|
||||
masterFn: Seq[AHBMasterPortParameters] => AHBMasterPortParameters,
|
||||
slaveFn: Seq[AHBSlavePortParameters] => AHBSlavePortParameters,
|
||||
numMasterPorts: Range.Inclusive = 1 to 1,
|
||||
numSlavePorts: Range.Inclusive = 1 to 1)
|
||||
extends InteriorNode(AHBImp)(masterFn, slaveFn, numMasterPorts, numSlavePorts)
|
||||
numMasterPorts: Range.Inclusive = 1 to 999,
|
||||
numSlavePorts: Range.Inclusive = 1 to 999)
|
||||
extends NexusNode(AHBImp)(masterFn, slaveFn, numMasterPorts, numSlavePorts)
|
||||
|
||||
// Nodes passed from an inner module
|
||||
case class AHBOutputNode() extends OutputNode(AHBImp)
|
||||
|
@ -9,13 +9,13 @@ import regmapper._
|
||||
import scala.math.{min,max}
|
||||
|
||||
class AHBRegisterNode(address: AddressSet, concurrency: Int = 0, beatBytes: Int = 4, undefZero: Boolean = true, executable: Boolean = false)
|
||||
extends AHBSlaveNode(AHBSlavePortParameters(
|
||||
extends AHBSlaveNode(Seq(AHBSlavePortParameters(
|
||||
Seq(AHBSlaveParameters(
|
||||
address = Seq(address),
|
||||
executable = executable,
|
||||
supportsWrite = TransferSizes(1, min(address.alignment.toInt, beatBytes * AHBParameters.maxTransfer)),
|
||||
supportsRead = TransferSizes(1, min(address.alignment.toInt, beatBytes * AHBParameters.maxTransfer)))),
|
||||
beatBytes = beatBytes))
|
||||
beatBytes = beatBytes)))
|
||||
{
|
||||
require (address.contiguous)
|
||||
|
||||
|
@ -8,14 +8,14 @@ import diplomacy._
|
||||
|
||||
class AHBRAM(address: AddressSet, executable: Boolean = true, beatBytes: Int = 4)(implicit p: Parameters) extends LazyModule
|
||||
{
|
||||
val node = AHBSlaveNode(AHBSlavePortParameters(
|
||||
val node = AHBSlaveNode(Seq(AHBSlavePortParameters(
|
||||
Seq(AHBSlaveParameters(
|
||||
address = List(address),
|
||||
regionType = RegionType.UNCACHED,
|
||||
executable = executable,
|
||||
supportsRead = TransferSizes(1, beatBytes * AHBParameters.maxTransfer),
|
||||
supportsWrite = TransferSizes(1, beatBytes * AHBParameters.maxTransfer))),
|
||||
beatBytes = beatBytes))
|
||||
beatBytes = beatBytes)))
|
||||
|
||||
// We require the address range to include an entire beat (for the write mask)
|
||||
require ((address.mask & (beatBytes-1)) == beatBytes-1)
|
||||
|
@ -9,7 +9,7 @@ import regmapper._
|
||||
import scala.math.{min,max}
|
||||
|
||||
class AHBFanout()(implicit p: Parameters) extends LazyModule {
|
||||
val node = AHBAdapterNode(
|
||||
val node = AHBNexusNode(
|
||||
numSlavePorts = 1 to 1,
|
||||
numMasterPorts = 1 to 32,
|
||||
masterFn = { case Seq(m) => m },
|
||||
|
@ -19,10 +19,6 @@ object APBImp extends NodeImp[APBMasterPortParameters, APBSlavePortParameters, A
|
||||
override def labelI(ei: APBEdgeParameters) = (ei.slave.beatBytes * 8).toString
|
||||
override def labelO(eo: APBEdgeParameters) = (eo.slave.beatBytes * 8).toString
|
||||
|
||||
def connect(bo: => APBBundle, bi: => APBBundle, ei: => APBEdgeParameters)(implicit p: Parameters, sourceInfo: SourceInfo): (Option[LazyModule], () => Unit) = {
|
||||
(None, () => { bi <> bo })
|
||||
}
|
||||
|
||||
override def mixO(pd: APBMasterPortParameters, node: OutwardNode[APBMasterPortParameters, APBSlavePortParameters, APBBundle]): APBMasterPortParameters =
|
||||
pd.copy(masters = pd.masters.map { c => c.copy (nodePath = node +: c.nodePath) })
|
||||
override def mixI(pu: APBSlavePortParameters, node: InwardNode[APBMasterPortParameters, APBSlavePortParameters, APBBundle]): APBSlavePortParameters =
|
||||
@ -31,16 +27,14 @@ object APBImp extends NodeImp[APBMasterPortParameters, APBSlavePortParameters, A
|
||||
|
||||
// Nodes implemented inside modules
|
||||
case class APBIdentityNode() extends IdentityNode(APBImp)
|
||||
case class APBMasterNode(portParams: APBMasterPortParameters, numPorts: Range.Inclusive = 1 to 1)
|
||||
extends SourceNode(APBImp)(portParams, numPorts)
|
||||
case class APBSlaveNode(portParams: APBSlavePortParameters, numPorts: Range.Inclusive = 1 to 1)
|
||||
extends SinkNode(APBImp)(portParams, numPorts)
|
||||
case class APBAdapterNode(
|
||||
case class APBMasterNode(portParams: Seq[APBMasterPortParameters]) extends SourceNode(APBImp)(portParams)
|
||||
case class APBSlaveNode(portParams: Seq[APBSlavePortParameters]) extends SinkNode(APBImp)(portParams)
|
||||
case class APBNexusNode(
|
||||
masterFn: Seq[APBMasterPortParameters] => APBMasterPortParameters,
|
||||
slaveFn: Seq[APBSlavePortParameters] => APBSlavePortParameters,
|
||||
numMasterPorts: Range.Inclusive = 1 to 1,
|
||||
numSlavePorts: Range.Inclusive = 1 to 1)
|
||||
extends InteriorNode(APBImp)(masterFn, slaveFn, numMasterPorts, numSlavePorts)
|
||||
extends NexusNode(APBImp)(masterFn, slaveFn, numMasterPorts, numSlavePorts)
|
||||
|
||||
// Nodes passed from an inner module
|
||||
case class APBOutputNode() extends OutputNode(APBImp)
|
||||
|
@ -9,13 +9,13 @@ import regmapper._
|
||||
import scala.math.{min,max}
|
||||
|
||||
class APBRegisterNode(address: AddressSet, concurrency: Int = 0, beatBytes: Int = 4, undefZero: Boolean = true, executable: Boolean = false)
|
||||
extends APBSlaveNode(APBSlavePortParameters(
|
||||
extends APBSlaveNode(Seq(APBSlavePortParameters(
|
||||
Seq(APBSlaveParameters(
|
||||
address = Seq(address),
|
||||
executable = executable,
|
||||
supportsWrite = true,
|
||||
supportsRead = true)),
|
||||
beatBytes = beatBytes))
|
||||
beatBytes = beatBytes)))
|
||||
{
|
||||
require (address.contiguous)
|
||||
|
||||
|
@ -8,14 +8,14 @@ import diplomacy._
|
||||
|
||||
class APBRAM(address: AddressSet, executable: Boolean = true, beatBytes: Int = 4)(implicit p: Parameters) extends LazyModule
|
||||
{
|
||||
val node = APBSlaveNode(APBSlavePortParameters(
|
||||
val node = APBSlaveNode(Seq(APBSlavePortParameters(
|
||||
Seq(APBSlaveParameters(
|
||||
address = List(address),
|
||||
regionType = RegionType.UNCACHED,
|
||||
executable = executable,
|
||||
supportsRead = true,
|
||||
supportsWrite = true)),
|
||||
beatBytes = beatBytes))
|
||||
beatBytes = beatBytes)))
|
||||
|
||||
// We require the address range to include an entire beat (for the write mask)
|
||||
require ((address.mask & (beatBytes-1)) == beatBytes-1)
|
||||
|
@ -9,7 +9,7 @@ import regmapper._
|
||||
import scala.math.{min,max}
|
||||
|
||||
class APBFanout()(implicit p: Parameters) extends LazyModule {
|
||||
val node = APBAdapterNode(
|
||||
val node = APBNexusNode(
|
||||
numSlavePorts = 1 to 1,
|
||||
numMasterPorts = 1 to 32,
|
||||
masterFn = { case Seq(m) => m },
|
||||
|
@ -18,8 +18,8 @@ class AXI4Buffer(aw: Int = 2, w: Int = 2, b: Int = 2, ar: Int = 2, r: Int = 2, p
|
||||
require (r >= 0)
|
||||
|
||||
val node = AXI4AdapterNode(
|
||||
masterFn = { case Seq(p) => p },
|
||||
slaveFn = { case Seq(p) => p.copy(minLatency = p.minLatency + min(1,min(aw,ar)) + min(1,min(r,b))) })
|
||||
masterFn = { p => p },
|
||||
slaveFn = { p => p.copy(minLatency = p.minLatency + min(1,min(aw,ar)) + min(1,min(r,b))) })
|
||||
|
||||
lazy val module = new LazyModuleImp(this) {
|
||||
val io = new Bundle {
|
||||
|
@ -23,8 +23,8 @@ class AXI4Fragmenter(lite: Boolean = false, maxInFlight: => Int = 32, combinatio
|
||||
def mapMaster(m: AXI4MasterParameters) = m.copy(aligned = true)
|
||||
|
||||
val node = AXI4AdapterNode(
|
||||
masterFn = { case Seq(mp) => mp.copy(masters = mp.masters.map(m => mapMaster(m))) },
|
||||
slaveFn = { case Seq(sp) => sp.copy(slaves = sp.slaves .map(s => mapSlave(s, sp.beatBytes))) })
|
||||
masterFn = { mp => mp.copy(masters = mp.masters.map(m => mapMaster(m))) },
|
||||
slaveFn = { sp => sp.copy(slaves = sp.slaves .map(s => mapSlave(s, sp.beatBytes))) })
|
||||
|
||||
lazy val module = new LazyModuleImp(this) {
|
||||
val io = new Bundle {
|
||||
@ -32,8 +32,7 @@ class AXI4Fragmenter(lite: Boolean = false, maxInFlight: => Int = 32, combinatio
|
||||
val out = node.bundleOut
|
||||
}
|
||||
|
||||
val edgeOut = node.edgesOut(0)
|
||||
val edgeIn = node.edgesIn(0)
|
||||
((io.in zip io.out) zip (node.edgesIn zip node.edgesOut)) foreach { case ((in, out), (edgeIn, edgeOut)) =>
|
||||
val slave = edgeOut.slave
|
||||
val slaves = slave.slaves
|
||||
val beatBytes = slave.beatBytes
|
||||
@ -136,9 +135,6 @@ class AXI4Fragmenter(lite: Boolean = false, maxInFlight: => Int = 32, combinatio
|
||||
(out, last, beats)
|
||||
}
|
||||
|
||||
val in = io.in(0)
|
||||
val out = io.out(0)
|
||||
|
||||
// The size to which we will fragment the access
|
||||
val readSizes1 = slaves.map(s => s.supportsRead .max/beatBytes-1)
|
||||
val writeSizes1 = slaves.map(s => s.supportsWrite.max/beatBytes-1)
|
||||
@ -237,9 +233,9 @@ class AXI4Fragmenter(lite: Boolean = false, maxInFlight: => Int = 32, combinatio
|
||||
when (out_b.fire()) { r_resp := Mux(b_last, UInt(0), resp) }
|
||||
in_b.bits.resp := resp
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* We want to put barriers between the fragments of a fragmented transfer and all other transfers.
|
||||
/* We want to put barriers between the fragments of a fragmented transfer and all other transfers.
|
||||
* This lets us use very little state to reassemble the fragments (else we need one FIFO per ID).
|
||||
* Furthermore, because all the fragments share the same AXI ID, they come back contiguously.
|
||||
* This guarantees that no other R responses might get mixed between fragments, ensuring that the
|
||||
@ -247,8 +243,8 @@ class AXI4Fragmenter(lite: Boolean = false, maxInFlight: => Int = 32, combinatio
|
||||
* Of course, if you need to fragment, this means there is a potentially hefty serialization cost.
|
||||
* However, this design allows full concurrency in the common no-fragmentation-needed scenario.
|
||||
*/
|
||||
class AXI4FragmenterSideband(maxInFlight: Int, flow: Boolean = false) extends Module
|
||||
{
|
||||
class AXI4FragmenterSideband(maxInFlight: Int, flow: Boolean = false) extends Module
|
||||
{
|
||||
val io = new QueueIO(Bool(), maxInFlight)
|
||||
io.count := UInt(0)
|
||||
|
||||
@ -283,6 +279,7 @@ class AXI4FragmenterSideband(maxInFlight: Int, flow: Boolean = false) extends Mo
|
||||
is(FIND) { when (io.enq.valid && io.enq.bits && !full) { state := Mux(empty, PASS, WAIT) } }
|
||||
is(WAIT) { when (last && io.deq.ready) { state := PASS } }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
object AXI4Fragmenter
|
||||
|
@ -19,10 +19,6 @@ object AXI4Imp extends NodeImp[AXI4MasterPortParameters, AXI4SlavePortParameters
|
||||
override def labelI(ei: AXI4EdgeParameters) = (ei.slave.beatBytes * 8).toString
|
||||
override def labelO(eo: AXI4EdgeParameters) = (eo.slave.beatBytes * 8).toString
|
||||
|
||||
def connect(bo: => AXI4Bundle, bi: => AXI4Bundle, ei: => AXI4EdgeParameters)(implicit p: Parameters, sourceInfo: SourceInfo): (Option[LazyModule], () => Unit) = {
|
||||
(None, () => { bi <> bo })
|
||||
}
|
||||
|
||||
override def mixO(pd: AXI4MasterPortParameters, node: OutwardNode[AXI4MasterPortParameters, AXI4SlavePortParameters, AXI4Bundle]): AXI4MasterPortParameters =
|
||||
pd.copy(masters = pd.masters.map { c => c.copy (nodePath = node +: c.nodePath) })
|
||||
override def mixI(pu: AXI4SlavePortParameters, node: InwardNode[AXI4MasterPortParameters, AXI4SlavePortParameters, AXI4Bundle]): AXI4SlavePortParameters =
|
||||
@ -31,16 +27,13 @@ object AXI4Imp extends NodeImp[AXI4MasterPortParameters, AXI4SlavePortParameters
|
||||
|
||||
// Nodes implemented inside modules
|
||||
case class AXI4IdentityNode() extends IdentityNode(AXI4Imp)
|
||||
case class AXI4MasterNode(portParams: AXI4MasterPortParameters, numPorts: Range.Inclusive = 1 to 1)
|
||||
extends SourceNode(AXI4Imp)(portParams, numPorts)
|
||||
case class AXI4SlaveNode(portParams: AXI4SlavePortParameters, numPorts: Range.Inclusive = 1 to 1)
|
||||
extends SinkNode(AXI4Imp)(portParams, numPorts)
|
||||
case class AXI4MasterNode(portParams: Seq[AXI4MasterPortParameters]) extends SourceNode(AXI4Imp)(portParams)
|
||||
case class AXI4SlaveNode(portParams: Seq[AXI4SlavePortParameters]) extends SinkNode(AXI4Imp)(portParams)
|
||||
case class AXI4AdapterNode(
|
||||
masterFn: Seq[AXI4MasterPortParameters] => AXI4MasterPortParameters,
|
||||
slaveFn: Seq[AXI4SlavePortParameters] => AXI4SlavePortParameters,
|
||||
numMasterPorts: Range.Inclusive = 1 to 1,
|
||||
numSlavePorts: Range.Inclusive = 1 to 1)
|
||||
extends InteriorNode(AXI4Imp)(masterFn, slaveFn, numMasterPorts, numSlavePorts)
|
||||
masterFn: AXI4MasterPortParameters => AXI4MasterPortParameters,
|
||||
slaveFn: AXI4SlavePortParameters => AXI4SlavePortParameters,
|
||||
numPorts: Range.Inclusive = 0 to 999)
|
||||
extends AdapterNode(AXI4Imp)(masterFn, slaveFn, numPorts)
|
||||
|
||||
// Nodes passed from an inner module
|
||||
case class AXI4OutputNode() extends OutputNode(AXI4Imp)
|
||||
|
@ -9,7 +9,7 @@ import regmapper._
|
||||
import scala.math.{min,max}
|
||||
|
||||
class AXI4RegisterNode(address: AddressSet, concurrency: Int = 0, beatBytes: Int = 4, undefZero: Boolean = true, executable: Boolean = false)
|
||||
extends AXI4SlaveNode(AXI4SlavePortParameters(
|
||||
extends AXI4SlaveNode(Seq(AXI4SlavePortParameters(
|
||||
Seq(AXI4SlaveParameters(
|
||||
address = Seq(address),
|
||||
executable = executable,
|
||||
@ -17,7 +17,7 @@ class AXI4RegisterNode(address: AddressSet, concurrency: Int = 0, beatBytes: Int
|
||||
supportsRead = TransferSizes(1, beatBytes),
|
||||
interleavedId = Some(0))),
|
||||
beatBytes = beatBytes,
|
||||
minLatency = min(concurrency, 1))) // the Queue adds at most one cycle
|
||||
minLatency = min(concurrency, 1)))) // the Queue adds at most one cycle
|
||||
{
|
||||
require (address.contiguous)
|
||||
|
||||
|
@ -8,7 +8,7 @@ import diplomacy._
|
||||
|
||||
class AXI4RAM(address: AddressSet, executable: Boolean = true, beatBytes: Int = 4)(implicit p: Parameters) extends LazyModule
|
||||
{
|
||||
val node = AXI4SlaveNode(AXI4SlavePortParameters(
|
||||
val node = AXI4SlaveNode(Seq(AXI4SlavePortParameters(
|
||||
Seq(AXI4SlaveParameters(
|
||||
address = List(address),
|
||||
regionType = RegionType.UNCACHED,
|
||||
@ -17,7 +17,7 @@ class AXI4RAM(address: AddressSet, executable: Boolean = true, beatBytes: Int =
|
||||
supportsWrite = TransferSizes(1, beatBytes),
|
||||
interleavedId = Some(0))),
|
||||
beatBytes = beatBytes,
|
||||
minLatency = 0)) // B responds on same cycle
|
||||
minLatency = 0))) // B responds on same cycle
|
||||
|
||||
// We require the address range to include an entire beat (for the write mask)
|
||||
require ((address.mask & (beatBytes-1)) == beatBytes-1)
|
||||
|
@ -8,15 +8,15 @@ import config._
|
||||
import diplomacy._
|
||||
import uncore.tilelink2._
|
||||
|
||||
case class AXI4ToTLNode() extends MixedNode(AXI4Imp, TLImp)(
|
||||
dFn = { case (1, Seq(AXI4MasterPortParameters(masters))) =>
|
||||
Seq(TLClientPortParameters(clients = masters.map { m =>
|
||||
case class AXI4ToTLNode() extends MixedAdapterNode(AXI4Imp, TLImp)(
|
||||
dFn = { case AXI4MasterPortParameters(masters) =>
|
||||
TLClientPortParameters(clients = masters.map { m =>
|
||||
TLClientParameters(
|
||||
sourceId = IdRange(m.id.start << 1, m.id.end << 1), // R+W ids are distinct
|
||||
nodePath = m.nodePath)
|
||||
}))
|
||||
})
|
||||
},
|
||||
uFn = { case (1, Seq(mp)) => Seq(AXI4SlavePortParameters(
|
||||
uFn = { mp => AXI4SlavePortParameters(
|
||||
slaves = mp.managers.map { m =>
|
||||
AXI4SlaveParameters(
|
||||
address = m.address,
|
||||
@ -27,10 +27,8 @@ case class AXI4ToTLNode() extends MixedNode(AXI4Imp, TLImp)(
|
||||
supportsRead = m.supportsGet,
|
||||
interleavedId = Some(0))}, // TL2 never interleaves D beats
|
||||
beatBytes = mp.beatBytes,
|
||||
minLatency = mp.minLatency))
|
||||
},
|
||||
numPO = 1 to 1,
|
||||
numPI = 1 to 1)
|
||||
minLatency = mp.minLatency)
|
||||
})
|
||||
|
||||
class AXI4ToTL()(implicit p: Parameters) extends LazyModule
|
||||
{
|
||||
@ -42,10 +40,7 @@ class AXI4ToTL()(implicit p: Parameters) extends LazyModule
|
||||
val out = node.bundleOut
|
||||
}
|
||||
|
||||
val in = io.in(0)
|
||||
val out = io.out(0)
|
||||
val edgeIn = node.edgesIn(0)
|
||||
val edgeOut = node.edgesOut(0)
|
||||
((io.in zip io.out) zip (node.edgesIn zip node.edgesOut)) foreach { case ((in, out), (edgeIn, edgeOut)) =>
|
||||
val numIds = edgeIn.master.endId
|
||||
val beatBytes = edgeOut.manager.beatBytes
|
||||
val countBits = AXI4Parameters.lenBits + (1 << AXI4Parameters.sizeBits) - 1
|
||||
@ -168,6 +163,7 @@ class AXI4ToTL()(implicit p: Parameters) extends LazyModule
|
||||
out.c.valid := Bool(false)
|
||||
out.e.valid := Bool(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class AXI4BundleRError(params: AXI4BundleParameters) extends AXI4BundleBase(params)
|
||||
|
@ -62,7 +62,7 @@ class TLPLIC(supervisor: Boolean, maxPriorities: Int, address: BigInt = 0xC00000
|
||||
beatBytes = p(rocket.XLen)/8,
|
||||
undefZero = false)
|
||||
|
||||
val intnode = IntAdapterNode(
|
||||
val intnode = IntNexusNode(
|
||||
numSourcePorts = 0 to 1024,
|
||||
numSinkPorts = 0 to 1024,
|
||||
sourceFn = { _ => IntSourcePortParameters(Seq(IntSourceParameters(contextsPerHart))) },
|
||||
|
@ -6,6 +6,7 @@ import Chisel._
|
||||
import chisel3.internal.sourceinfo.SourceInfo
|
||||
import config._
|
||||
import diplomacy._
|
||||
import util.GenericParameterizedBundle
|
||||
import scala.math.{min,max}
|
||||
|
||||
// Ensures that all downstream RW managers support Atomic operationss.
|
||||
@ -15,8 +16,8 @@ class TLAtomicAutomata(logical: Boolean = true, arithmetic: Boolean = true, conc
|
||||
require (concurrency >= 1)
|
||||
|
||||
val node = TLAdapterNode(
|
||||
clientFn = { case Seq(cp) => require (!cp.unsafeAtomics); cp.copy(unsafeAtomics = true) },
|
||||
managerFn = { case Seq(mp) => mp.copy(managers = mp.managers.map { m =>
|
||||
clientFn = { case cp => require (!cp.unsafeAtomics); cp.copy(unsafeAtomics = true) },
|
||||
managerFn = { case mp => mp.copy(managers = mp.managers.map { m =>
|
||||
val ourSupport = TransferSizes(1, mp.beatBytes)
|
||||
def widen(x: TransferSizes) = if (passthrough && x.min <= 2*mp.beatBytes) TransferSizes(1, max(mp.beatBytes, x.max)) else ourSupport
|
||||
val canDoit = m.supportsPutFull.contains(ourSupport) && m.supportsGet.contains(ourSupport)
|
||||
@ -33,10 +34,7 @@ class TLAtomicAutomata(logical: Boolean = true, arithmetic: Boolean = true, conc
|
||||
val out = node.bundleOut
|
||||
}
|
||||
|
||||
val in = io.in(0)
|
||||
val out = io.out(0)
|
||||
val edgeIn = node.edgesIn(0)
|
||||
val edgeOut = node.edgesOut(0)
|
||||
((io.in zip io.out) zip (node.edgesIn zip node.edgesOut)) foreach { case ((in, out), (edgeIn, edgeOut)) =>
|
||||
val managers = edgeOut.manager.managers
|
||||
val beatBytes = edgeOut.manager.beatBytes
|
||||
|
||||
@ -72,25 +70,14 @@ class TLAtomicAutomata(logical: Boolean = true, arithmetic: Boolean = true, conc
|
||||
if (x.map(_ == x(0)).reduce(_ && _)) x(0).containsLg(lgSize) else
|
||||
Mux1H(select, x.map(_.containsLg(lgSize)))
|
||||
|
||||
val params = TLAtomicAutomata.CAMParams(out.a.bits.params, domainsNeedingHelp.size)
|
||||
// Do we need to do anything at all?
|
||||
if (camSize > 0) {
|
||||
class CAM_S extends Bundle {
|
||||
val state = UInt(width = 2)
|
||||
}
|
||||
class CAM_A extends Bundle {
|
||||
val bits = new TLBundleA(out.a.bits.params)
|
||||
val fifoId = UInt(width = log2Up(domainsNeedingHelp.size))
|
||||
val lut = UInt(width = 4)
|
||||
}
|
||||
class CAM_D extends Bundle {
|
||||
val data = UInt(width = out.a.bits.params.dataBits)
|
||||
}
|
||||
|
||||
val initval = Wire(new CAM_S)
|
||||
val initval = Wire(new TLAtomicAutomata.CAM_S(params))
|
||||
initval.state := FREE
|
||||
val cam_s = RegInit(Vec.fill(camSize)(initval))
|
||||
val cam_a = Reg(Vec(camSize, new CAM_A))
|
||||
val cam_d = Reg(Vec(camSize, new CAM_D))
|
||||
val cam_a = Reg(Vec(camSize, new TLAtomicAutomata.CAM_A(params)))
|
||||
val cam_d = Reg(Vec(camSize, new TLAtomicAutomata.CAM_D(params)))
|
||||
|
||||
val cam_free = cam_s.map(_.state === FREE)
|
||||
val cam_amo = cam_s.map(_.state === AMO)
|
||||
@ -274,6 +261,7 @@ class TLAtomicAutomata(logical: Boolean = true, arithmetic: Boolean = true, conc
|
||||
out.e.valid := Bool(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
object TLAtomicAutomata
|
||||
@ -284,6 +272,20 @@ object TLAtomicAutomata
|
||||
atomics.node := x
|
||||
atomics.node
|
||||
}
|
||||
|
||||
case class CAMParams(a: TLBundleParameters, domainsNeedingHelp: Int)
|
||||
|
||||
class CAM_S(params: CAMParams) extends GenericParameterizedBundle(params) {
|
||||
val state = UInt(width = 2)
|
||||
}
|
||||
class CAM_A(params: CAMParams) extends GenericParameterizedBundle(params) {
|
||||
val bits = new TLBundleA(params.a)
|
||||
val fifoId = UInt(width = log2Up(params.domainsNeedingHelp))
|
||||
val lut = UInt(width = 4)
|
||||
}
|
||||
class CAM_D(params: CAMParams) extends GenericParameterizedBundle(params) {
|
||||
val data = UInt(width = params.a.dataBits)
|
||||
}
|
||||
}
|
||||
|
||||
/** Synthesizeable unit tests */
|
||||
|
@ -13,11 +13,11 @@ class TLBroadcast(lineBytes: Int, numTrackers: Int = 4, bufferless: Boolean = fa
|
||||
require (numTrackers > 0)
|
||||
|
||||
val node = TLAdapterNode(
|
||||
clientFn = { case Seq(cp) =>
|
||||
clientFn = { cp =>
|
||||
cp.copy(clients = Seq(TLClientParameters(
|
||||
sourceId = IdRange(0, 1 << log2Ceil(cp.endSourceId*4)))))
|
||||
},
|
||||
managerFn = { case Seq(mp) =>
|
||||
managerFn = { mp =>
|
||||
mp.copy(
|
||||
endSinkId = numTrackers,
|
||||
managers = mp.managers.map { m =>
|
||||
@ -56,10 +56,7 @@ class TLBroadcast(lineBytes: Int, numTrackers: Int = 4, bufferless: Boolean = fa
|
||||
val out = node.bundleOut
|
||||
}
|
||||
|
||||
val in = io.in(0)
|
||||
val out = io.out(0)
|
||||
val edgeIn = node.edgesIn(0)
|
||||
val edgeOut = node.edgesOut(0)
|
||||
((io.in zip io.out) zip (node.edgesIn zip node.edgesOut)) foreach { case ((in, out), (edgeIn, edgeOut)) =>
|
||||
val clients = edgeIn.client.clients
|
||||
val managers = edgeOut.manager.managers
|
||||
val lineShift = log2Ceil(lineBytes)
|
||||
@ -205,6 +202,7 @@ class TLBroadcast(lineBytes: Int, numTrackers: Int = 4, bufferless: Boolean = fa
|
||||
out.c.valid := Bool(false)
|
||||
out.e.valid := Bool(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class TLBroadcastTracker(id: Int, lineBytes: Int, probeCountBits: Int, bufferless: Boolean, edgeIn: TLEdgeIn, edgeOut: TLEdgeOut) extends Module
|
||||
|
@ -18,8 +18,8 @@ class TLBuffer(a: Int = 2, b: Int = 2, c: Int = 2, d: Int = 2, e: Int = 2, pipe:
|
||||
require (e >= 0)
|
||||
|
||||
val node = TLAdapterNode(
|
||||
clientFn = { case Seq(p) => p.copy(minLatency = p.minLatency + min(1,b) + min(1,c)) },
|
||||
managerFn = { case Seq(p) => p.copy(minLatency = p.minLatency + min(1,a) + min(1,d)) })
|
||||
clientFn = { p => p.copy(minLatency = p.minLatency + min(1,b) + min(1,c)) },
|
||||
managerFn = { p => p.copy(minLatency = p.minLatency + min(1,a) + min(1,d)) })
|
||||
|
||||
lazy val module = new LazyModuleImp(this) {
|
||||
val io = new Bundle {
|
||||
|
@ -210,11 +210,11 @@ final class DecoupledSnoop[+T <: Data](gen: T) extends Bundle
|
||||
|
||||
object DecoupledSnoop
|
||||
{
|
||||
def apply[T <: Data](i: DecoupledIO[T]) = {
|
||||
val out = Wire(new DecoupledSnoop(i.bits))
|
||||
out.ready := i.ready
|
||||
out.valid := i.valid
|
||||
out.bits := i.bits
|
||||
def apply[T <: Data](source: DecoupledIO[T], sink: DecoupledIO[T]) = {
|
||||
val out = Wire(new DecoupledSnoop(sink.bits))
|
||||
out.ready := sink.ready
|
||||
out.valid := source.valid
|
||||
out.bits := source.bits
|
||||
out
|
||||
}
|
||||
}
|
||||
@ -230,13 +230,13 @@ class TLBundleSnoop(params: TLBundleParameters) extends TLBundleBase(params)
|
||||
|
||||
object TLBundleSnoop
|
||||
{
|
||||
def apply(x: TLBundle) = {
|
||||
val out = Wire(new TLBundleSnoop(x.params))
|
||||
out.a <> DecoupledSnoop(x.a)
|
||||
out.b <> DecoupledSnoop(x.b)
|
||||
out.c <> DecoupledSnoop(x.c)
|
||||
out.d <> DecoupledSnoop(x.d)
|
||||
out.e <> DecoupledSnoop(x.e)
|
||||
def apply(source: TLBundle, sink: TLBundle) = {
|
||||
val out = Wire(new TLBundleSnoop(sink.params))
|
||||
out.a := DecoupledSnoop(source.a, sink.a)
|
||||
out.b := DecoupledSnoop(sink.b, source.b)
|
||||
out.c := DecoupledSnoop(source.c, sink.c)
|
||||
out.d := DecoupledSnoop(sink.d, source.d)
|
||||
out.e := DecoupledSnoop(source.e, sink.e)
|
||||
out
|
||||
}
|
||||
}
|
||||
|
@ -12,10 +12,10 @@ import TLMessages._
|
||||
class TLCacheCork(unsafe: Boolean = false)(implicit p: Parameters) extends LazyModule
|
||||
{
|
||||
val node = TLAdapterNode(
|
||||
clientFn = { case Seq(cp) =>
|
||||
clientFn = { case cp =>
|
||||
cp.copy(clients = cp.clients.map { c => c.copy(
|
||||
sourceId = IdRange(c.sourceId.start*2, c.sourceId.end*2))})},
|
||||
managerFn = { case Seq(mp) =>
|
||||
managerFn = { case mp =>
|
||||
mp.copy(managers = mp.managers.map { m => m.copy(
|
||||
regionType = if (m.regionType == RegionType.UNCACHED) RegionType.TRACKED else m.regionType,
|
||||
supportsAcquireB = m.supportsGet,
|
||||
@ -27,18 +27,13 @@ class TLCacheCork(unsafe: Boolean = false)(implicit p: Parameters) extends LazyM
|
||||
val out = node.bundleOut
|
||||
}
|
||||
|
||||
val edgeIn = node.edgesIn(0)
|
||||
val edgeOut = node.edgesOut(0)
|
||||
|
||||
((io.in zip io.out) zip (node.edgesIn zip node.edgesOut)) foreach { case ((in, out), (edgeIn, edgeOut)) =>
|
||||
require (edgeIn.client.clients.size == 1 || unsafe, "Only one client can safely use a TLCacheCork")
|
||||
require (edgeIn.client.clients.filter(_.supportsProbe).size == 1, "Only one caching client allowed")
|
||||
edgeOut.manager.managers.foreach { case m =>
|
||||
require (!m.supportsAcquireB, "Cannot support caches beyond the Cork")
|
||||
}
|
||||
|
||||
val out = io.out(0)
|
||||
val in = io.in(0)
|
||||
|
||||
// The Cork turns [Acquire=>Get] => [AccessAckData=>GrantData]
|
||||
// and [ReleaseData=>PutFullData] => [AccessAck=>ReleaseAck]
|
||||
// We need to encode information sufficient to reverse the transformation in output.
|
||||
@ -115,6 +110,7 @@ class TLCacheCork(unsafe: Boolean = false)(implicit p: Parameters) extends LazyM
|
||||
out.c.valid := Bool(false)
|
||||
out.e.valid := Bool(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
object TLCacheCork
|
||||
|
@ -11,8 +11,8 @@ import scala.math.{min,max}
|
||||
class TLFilter(select: AddressSet)(implicit p: Parameters) extends LazyModule
|
||||
{
|
||||
val node = TLAdapterNode(
|
||||
clientFn = { case Seq(cp) => cp },
|
||||
managerFn = { case Seq(mp) =>
|
||||
clientFn = { cp => cp },
|
||||
managerFn = { mp =>
|
||||
mp.copy(managers = mp.managers.map { m =>
|
||||
val filtered = m.address.map(_.intersect(select)).flatten
|
||||
val alignment = select.alignment /* alignment 0 means 'select' selected everything */
|
||||
|
@ -41,8 +41,8 @@ class TLFragmenter(val minSize: Int, val maxSize: Int, val alwaysMin: Boolean =
|
||||
sourceId = IdRange(c.sourceId.start << fragmentBits, c.sourceId.end << fragmentBits))
|
||||
|
||||
val node = TLAdapterNode(
|
||||
clientFn = { case Seq(c) => c.copy(clients = c.clients.map(mapClient)) },
|
||||
managerFn = { case Seq(m) => m.copy(managers = m.managers.map(mapManager)) })
|
||||
clientFn = { c => c.copy(clients = c.clients.map(mapClient)) },
|
||||
managerFn = { m => m.copy(managers = m.managers.map(mapManager)) })
|
||||
|
||||
lazy val module = new LazyModuleImp(this) {
|
||||
val io = new Bundle {
|
||||
@ -50,9 +50,8 @@ class TLFragmenter(val minSize: Int, val maxSize: Int, val alwaysMin: Boolean =
|
||||
val out = node.bundleOut
|
||||
}
|
||||
|
||||
((io.in zip io.out) zip (node.edgesIn zip node.edgesOut)) foreach { case ((in, out), (edgeIn, edgeOut)) =>
|
||||
// All managers must share a common FIFO domain (responses might end up interleaved)
|
||||
val edgeOut = node.edgesOut(0)
|
||||
val edgeIn = node.edgesIn(0)
|
||||
val manager = edgeOut.manager
|
||||
val managers = manager.managers
|
||||
val beatBytes = manager.beatBytes
|
||||
@ -129,9 +128,6 @@ class TLFragmenter(val minSize: Int, val maxSize: Int, val alwaysMin: Boolean =
|
||||
* put1 put1 0 ack1 0 ack1 0 0
|
||||
*/
|
||||
|
||||
val in = io.in(0)
|
||||
val out = io.out(0)
|
||||
|
||||
val counterBits = log2Up(maxSize/beatBytes)
|
||||
val maxDownSize = if (alwaysMin) minSize else manager.maxTransfer
|
||||
|
||||
@ -249,6 +245,7 @@ class TLFragmenter(val minSize: Int, val maxSize: Int, val alwaysMin: Boolean =
|
||||
out.c.valid := Bool(false)
|
||||
out.e.valid := Bool(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
object TLFragmenter
|
||||
|
@ -12,8 +12,8 @@ import diplomacy._
|
||||
class TLHintHandler(supportManagers: Boolean = true, supportClients: Boolean = false, passthrough: Boolean = true)(implicit p: Parameters) extends LazyModule
|
||||
{
|
||||
val node = TLAdapterNode(
|
||||
clientFn = { case Seq(c) => if (!supportClients) c else c.copy(minLatency = min(1, c.minLatency), clients = c.clients .map(_.copy(supportsHint = TransferSizes(1, c.maxTransfer)))) },
|
||||
managerFn = { case Seq(m) => if (!supportManagers) m else m.copy(minLatency = min(1, m.minLatency), managers = m.managers.map(_.copy(supportsHint = TransferSizes(1, m.maxTransfer)))) })
|
||||
clientFn = { c => if (!supportClients) c else c.copy(minLatency = min(1, c.minLatency), clients = c.clients .map(_.copy(supportsHint = TransferSizes(1, c.maxTransfer)))) },
|
||||
managerFn = { m => if (!supportManagers) m else m.copy(minLatency = min(1, m.minLatency), managers = m.managers.map(_.copy(supportsHint = TransferSizes(1, m.maxTransfer)))) })
|
||||
|
||||
lazy val module = new LazyModuleImp(this) {
|
||||
val io = new Bundle {
|
||||
@ -21,11 +21,7 @@ class TLHintHandler(supportManagers: Boolean = true, supportClients: Boolean = f
|
||||
val out = node.bundleOut
|
||||
}
|
||||
|
||||
val in = io.in(0)
|
||||
val out = io.out(0)
|
||||
val edgeIn = node.edgesIn(0)
|
||||
val edgeOut = node.edgesOut(0)
|
||||
|
||||
((io.in zip io.out) zip (node.edgesIn zip node.edgesOut)) foreach { case ((in, out), (edgeIn, edgeOut)) =>
|
||||
// Don't add support for clients if there is no BCE channel
|
||||
val bce = edgeOut.manager.anySupportAcquireB && edgeIn.client.anySupportProbe
|
||||
require (!supportClients || bce)
|
||||
@ -96,6 +92,7 @@ class TLHintHandler(supportManagers: Boolean = true, supportClients: Boolean = f
|
||||
out.e.valid := Bool(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
object TLHintHandler
|
||||
|
@ -81,16 +81,16 @@ object IntImp extends NodeImp[IntSourcePortParameters, IntSinkPortParameters, In
|
||||
|
||||
case class IntIdentityNode() extends IdentityNode(IntImp)
|
||||
case class IntSourceNode(num: Int) extends SourceNode(IntImp)(
|
||||
IntSourcePortParameters(Seq(IntSourceParameters(num))), (if (num == 0) 0 else 1) to 1)
|
||||
if (num == 0) Seq() else Seq(IntSourcePortParameters(Seq(IntSourceParameters(num)))))
|
||||
case class IntSinkNode() extends SinkNode(IntImp)(
|
||||
IntSinkPortParameters(Seq(IntSinkParameters())))
|
||||
Seq(IntSinkPortParameters(Seq(IntSinkParameters()))))
|
||||
|
||||
case class IntAdapterNode(
|
||||
case class IntNexusNode(
|
||||
sourceFn: Seq[IntSourcePortParameters] => IntSourcePortParameters,
|
||||
sinkFn: Seq[IntSinkPortParameters] => IntSinkPortParameters,
|
||||
numSourcePorts: Range.Inclusive = 1 to 1,
|
||||
numSinkPorts: Range.Inclusive = 1 to 1)
|
||||
extends InteriorNode(IntImp)(sourceFn, sinkFn, numSourcePorts, numSinkPorts)
|
||||
numSourcePorts: Range.Inclusive = 0 to 128,
|
||||
numSinkPorts: Range.Inclusive = 0 to 128)
|
||||
extends NexusNode(IntImp)(sourceFn, sinkFn, numSourcePorts, numSinkPorts)
|
||||
|
||||
case class IntOutputNode() extends OutputNode(IntImp)
|
||||
case class IntInputNode() extends InputNode(IntImp)
|
||||
@ -103,9 +103,7 @@ case class IntInternalInputNode(num: Int) extends InternalInputNode(IntImp)(Seq(
|
||||
|
||||
class IntXbar()(implicit p: Parameters) extends LazyModule
|
||||
{
|
||||
val intnode = IntAdapterNode(
|
||||
numSourcePorts = 0 to 128,
|
||||
numSinkPorts = 0 to 128,
|
||||
val intnode = IntNexusNode(
|
||||
sinkFn = { _ => IntSinkPortParameters(Seq(IntSinkParameters())) },
|
||||
sourceFn = { seq =>
|
||||
IntSourcePortParameters((seq zip seq.map(_.num).scanLeft(0)(_+_).init).map {
|
||||
|
@ -7,7 +7,7 @@ import chisel3.internal.sourceinfo.{SourceInfo, SourceLine}
|
||||
import config._
|
||||
import diplomacy._
|
||||
|
||||
case class TLMonitorArgs(gen: () => TLBundleSnoop, edge: () => TLEdge, sourceInfo: SourceInfo, p: Parameters)
|
||||
case class TLMonitorArgs(edge: () => Seq[TLEdge], sourceInfo: SourceInfo, p: Parameters)
|
||||
|
||||
abstract class TLMonitorBase(args: TLMonitorArgs) extends LazyModule()(args.p)
|
||||
{
|
||||
@ -16,11 +16,12 @@ abstract class TLMonitorBase(args: TLMonitorArgs) extends LazyModule()(args.p)
|
||||
def legalize(bundle: TLBundleSnoop, edge: TLEdge, reset: Bool): Unit
|
||||
|
||||
lazy val module = new LazyModuleImp(this) {
|
||||
val edges = args.edge()
|
||||
val io = new Bundle {
|
||||
val in = args.gen().asInput
|
||||
val in = Vec(edges.size, new TLBundleSnoop(TLBundleParameters.union(edges.map(_.bundle)))).flip
|
||||
}
|
||||
|
||||
legalize(io.in, args.edge(), reset)
|
||||
(edges zip io.in).foreach { case (e, in) => legalize(in, e, reset) }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -24,11 +24,13 @@ object TLImp extends NodeImp[TLClientPortParameters, TLManagerPortParameters, TL
|
||||
override def labelI(ei: TLEdgeIn) = (ei.manager.beatBytes * 8).toString
|
||||
override def labelO(eo: TLEdgeOut) = (eo.manager.beatBytes * 8).toString
|
||||
|
||||
def connect(bo: => TLBundle, bi: => TLBundle, ei: => TLEdgeIn)(implicit p: Parameters, sourceInfo: SourceInfo): (Option[LazyModule], () => Unit) = {
|
||||
val monitor = p(TLMonitorBuilder)(TLMonitorArgs(() => new TLBundleSnoop(bo.params), () => ei, sourceInfo, p))
|
||||
override def connect(bindings: () => Seq[(TLEdgeIn, TLBundle, TLBundle)])(implicit p: Parameters, sourceInfo: SourceInfo): (Option[LazyModule], () => Unit) = {
|
||||
val monitor = p(TLMonitorBuilder)(TLMonitorArgs(() => bindings().map(_._1), sourceInfo, p))
|
||||
(monitor, () => {
|
||||
val eval = bindings ()
|
||||
monitor.foreach { m => (eval zip m.module.io.in) foreach { case ((_,i,o), m) => m := TLBundleSnoop(o,i) } }
|
||||
eval.foreach { case (_, bi, bo) =>
|
||||
bi <> bo
|
||||
monitor.foreach { _.module.io.in := TLBundleSnoop(bo) }
|
||||
if (p(TLCombinationalCheck)) {
|
||||
// It is forbidden for valid to depend on ready in TL2
|
||||
// If someone did that, then this will create a detectable combinational loop
|
||||
@ -63,6 +65,7 @@ object TLImp extends NodeImp[TLClientPortParameters, TLManagerPortParameters, TL
|
||||
when (!bo.d.valid) { bo.d.bits := bits_d }
|
||||
when (!bi.e.valid) { bi.e.bits := bits_e }
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@ -86,29 +89,33 @@ object TLImp extends NodeImp[TLClientPortParameters, TLManagerPortParameters, TL
|
||||
|
||||
// Nodes implemented inside modules
|
||||
case class TLIdentityNode() extends IdentityNode(TLImp)
|
||||
case class TLClientNode(portParams: TLClientPortParameters, numPorts: Range.Inclusive = 1 to 1)
|
||||
extends SourceNode(TLImp)(portParams, numPorts)
|
||||
case class TLManagerNode(portParams: TLManagerPortParameters, numPorts: Range.Inclusive = 1 to 1)
|
||||
extends SinkNode(TLImp)(portParams, numPorts)
|
||||
case class TLClientNode(portParams: Seq[TLClientPortParameters]) extends SourceNode(TLImp)(portParams)
|
||||
case class TLManagerNode(portParams: Seq[TLManagerPortParameters]) extends SinkNode(TLImp)(portParams)
|
||||
|
||||
object TLClientNode
|
||||
{
|
||||
def apply(params: TLClientParameters) =
|
||||
new TLClientNode(TLClientPortParameters(Seq(params)), 1 to 1)
|
||||
new TLClientNode(Seq(TLClientPortParameters(Seq(params))))
|
||||
}
|
||||
|
||||
object TLManagerNode
|
||||
{
|
||||
def apply(beatBytes: Int, params: TLManagerParameters) =
|
||||
new TLManagerNode(TLManagerPortParameters(Seq(params), beatBytes, minLatency = 0), 1 to 1)
|
||||
new TLManagerNode(Seq(TLManagerPortParameters(Seq(params), beatBytes, minLatency = 0)))
|
||||
}
|
||||
|
||||
case class TLAdapterNode(
|
||||
clientFn: TLClientPortParameters => TLClientPortParameters,
|
||||
managerFn: TLManagerPortParameters => TLManagerPortParameters,
|
||||
num: Range.Inclusive = 0 to 999)
|
||||
extends AdapterNode(TLImp)(clientFn, managerFn, num)
|
||||
|
||||
case class TLNexusNode(
|
||||
clientFn: Seq[TLClientPortParameters] => TLClientPortParameters,
|
||||
managerFn: Seq[TLManagerPortParameters] => TLManagerPortParameters,
|
||||
numClientPorts: Range.Inclusive = 1 to 1,
|
||||
numManagerPorts: Range.Inclusive = 1 to 1)
|
||||
extends InteriorNode(TLImp)(clientFn, managerFn, numClientPorts, numManagerPorts)
|
||||
numClientPorts: Range.Inclusive = 1 to 999,
|
||||
numManagerPorts: Range.Inclusive = 1 to 999)
|
||||
extends NexusNode(TLImp)(clientFn, managerFn, numClientPorts, numManagerPorts)
|
||||
|
||||
// Nodes passed from an inner module
|
||||
case class TLOutputNode() extends OutputNode(TLImp)
|
||||
@ -155,10 +162,6 @@ object TLAsyncImp extends NodeImp[TLAsyncClientPortParameters, TLAsyncManagerPor
|
||||
override def labelI(ei: TLAsyncEdgeParameters) = ei.manager.depth.toString
|
||||
override def labelO(eo: TLAsyncEdgeParameters) = eo.manager.depth.toString
|
||||
|
||||
def connect(bo: => TLAsyncBundle, bi: => TLAsyncBundle, ei: => TLAsyncEdgeParameters)(implicit p: Parameters, sourceInfo: SourceInfo): (Option[LazyModule], () => Unit) = {
|
||||
(None, () => { bi <> bo })
|
||||
}
|
||||
|
||||
override def mixO(pd: TLAsyncClientPortParameters, node: OutwardNode[TLAsyncClientPortParameters, TLAsyncManagerPortParameters, TLAsyncBundle]): TLAsyncClientPortParameters =
|
||||
pd.copy(base = pd.base.copy(clients = pd.base.clients.map { c => c.copy (nodePath = node +: c.nodePath) }))
|
||||
override def mixI(pu: TLAsyncManagerPortParameters, node: InwardNode[TLAsyncClientPortParameters, TLAsyncManagerPortParameters, TLAsyncBundle]): TLAsyncManagerPortParameters =
|
||||
@ -169,17 +172,15 @@ case class TLAsyncIdentityNode() extends IdentityNode(TLAsyncImp)
|
||||
case class TLAsyncOutputNode() extends OutputNode(TLAsyncImp)
|
||||
case class TLAsyncInputNode() extends InputNode(TLAsyncImp)
|
||||
|
||||
case class TLAsyncSourceNode(sync: Int) extends MixedNode(TLImp, TLAsyncImp)(
|
||||
dFn = { case (1, Seq(p)) => Seq(TLAsyncClientPortParameters(p)) },
|
||||
uFn = { case (1, Seq(p)) => Seq(p.base.copy(minLatency = sync+1)) }, // discard cycles in other clock domain
|
||||
numPO = 1 to 1,
|
||||
numPI = 1 to 1)
|
||||
case class TLAsyncSourceNode(sync: Int)
|
||||
extends MixedAdapterNode(TLImp, TLAsyncImp)(
|
||||
dFn = { p => TLAsyncClientPortParameters(p) },
|
||||
uFn = { p => p.base.copy(minLatency = sync+1) }) // discard cycles in other clock domain
|
||||
|
||||
case class TLAsyncSinkNode(depth: Int, sync: Int) extends MixedNode(TLAsyncImp, TLImp)(
|
||||
dFn = { case (1, Seq(p)) => Seq(p.base.copy(minLatency = sync+1)) },
|
||||
uFn = { case (1, Seq(p)) => Seq(TLAsyncManagerPortParameters(depth, p)) },
|
||||
numPO = 1 to 1,
|
||||
numPI = 1 to 1)
|
||||
case class TLAsyncSinkNode(depth: Int, sync: Int)
|
||||
extends MixedAdapterNode(TLAsyncImp, TLImp)(
|
||||
dFn = { p => p.base.copy(minLatency = sync+1) },
|
||||
uFn = { p => TLAsyncManagerPortParameters(depth, p) })
|
||||
|
||||
object TLRationalImp extends NodeImp[TLClientPortParameters, TLManagerPortParameters, TLEdgeParameters, TLEdgeParameters, TLRationalBundle]
|
||||
{
|
||||
@ -191,10 +192,6 @@ object TLRationalImp extends NodeImp[TLClientPortParameters, TLManagerPortParame
|
||||
|
||||
def colour = "#00ff00" // green
|
||||
|
||||
def connect(bo: => TLRationalBundle, bi: => TLRationalBundle, ei: => TLEdgeParameters)(implicit p: Parameters, sourceInfo: SourceInfo): (Option[LazyModule], () => Unit) = {
|
||||
(None, () => { bi <> bo })
|
||||
}
|
||||
|
||||
override def mixO(pd: TLClientPortParameters, node: OutwardNode[TLClientPortParameters, TLManagerPortParameters, TLRationalBundle]): TLClientPortParameters =
|
||||
pd.copy(clients = pd.clients.map { c => c.copy (nodePath = node +: c.nodePath) })
|
||||
override def mixI(pu: TLManagerPortParameters, node: InwardNode[TLClientPortParameters, TLManagerPortParameters, TLRationalBundle]): TLManagerPortParameters =
|
||||
@ -205,14 +202,12 @@ case class TLRationalIdentityNode() extends IdentityNode(TLRationalImp)
|
||||
case class TLRationalOutputNode() extends OutputNode(TLRationalImp)
|
||||
case class TLRationalInputNode() extends InputNode(TLRationalImp)
|
||||
|
||||
case class TLRationalSourceNode() extends MixedNode(TLImp, TLRationalImp)(
|
||||
dFn = { case (_, s) => s },
|
||||
uFn = { case (_, s) => s.map(p => p.copy(minLatency = 1)) }, // discard cycles from other clock domain
|
||||
numPO = 0 to 999,
|
||||
numPI = 0 to 999)
|
||||
case class TLRationalSourceNode()
|
||||
extends MixedAdapterNode(TLImp, TLRationalImp)(
|
||||
dFn = { p => p },
|
||||
uFn = { p => p.copy(minLatency = 1) }) // discard cycles from other clock domain
|
||||
|
||||
case class TLRationalSinkNode() extends MixedNode(TLRationalImp, TLImp)(
|
||||
dFn = { case (_, s) => s.map(p => p.copy(minLatency = 1)) },
|
||||
uFn = { case (_, s) => s },
|
||||
numPO = 0 to 999,
|
||||
numPI = 0 to 999)
|
||||
case class TLRationalSinkNode()
|
||||
extends MixedAdapterNode(TLRationalImp, TLImp)(
|
||||
dFn = { p => p.copy(minLatency = 1) },
|
||||
uFn = { p => p })
|
||||
|
@ -5,6 +5,7 @@ package uncore.tilelink2
|
||||
import Chisel._
|
||||
import config._
|
||||
import diplomacy._
|
||||
import util.GenericParameterizedBundle
|
||||
|
||||
// We detect concurrent puts that put memory into an undefined state.
|
||||
// put0, put0Ack, put1, put1Ack => ok: defined
|
||||
@ -31,13 +32,8 @@ class TLRAMModel(log: String = "")(implicit p: Parameters) extends LazyModule
|
||||
val out = node.bundleOut
|
||||
}
|
||||
|
||||
// !!! support multiple clients via clock division
|
||||
require (io.out.size == 1)
|
||||
|
||||
val in = io.in(0)
|
||||
val out = io.out(0)
|
||||
|
||||
val edge = node.edgesIn(0)
|
||||
((io.in zip io.out) zip (node.edgesIn zip node.edgesOut)) foreach { case ((in, out), (edgeIn, edgeOut)) =>
|
||||
val edge = edgeIn
|
||||
val endAddress = edge.manager.maxAddress + 1
|
||||
val endSourceId = edge.client.endSourceId
|
||||
val maxTransfer = edge.manager.maxTransfer
|
||||
@ -71,18 +67,10 @@ class TLRAMModel(log: String = "")(implicit p: Parameters) extends LazyModule
|
||||
in.c.ready := Bool(true)
|
||||
in.e.ready := Bool(true)
|
||||
|
||||
class ByteMonitor extends Bundle {
|
||||
val valid = Bool()
|
||||
val value = UInt(width = 8)
|
||||
}
|
||||
class FlightMonitor extends Bundle {
|
||||
val base = UInt(width = addressBits)
|
||||
val size = UInt(width = sizeBits)
|
||||
val opcode = UInt(width = 3)
|
||||
}
|
||||
val params = TLRAMModel.MonitorParameters(addressBits, sizeBits)
|
||||
|
||||
// Infer as simple dual port BRAM/M10k with write-first/new-data semantics (bypass needed)
|
||||
val shadow = Seq.fill(beatBytes) { Mem(endAddressHi, new ByteMonitor) }
|
||||
val shadow = Seq.fill(beatBytes) { Mem(endAddressHi, new TLRAMModel.ByteMonitor(params)) }
|
||||
val inc_bytes = Seq.fill(beatBytes) { Mem(endAddressHi, UInt(width = countBits)) }
|
||||
val dec_bytes = Seq.fill(beatBytes) { Mem(endAddressHi, UInt(width = countBits)) }
|
||||
val inc_trees = Seq.tabulate(decTrees) { i => Mem(endAddressHi >> (i+1), UInt(width = countBits)) }
|
||||
@ -95,11 +83,11 @@ class TLRAMModel(log: String = "")(implicit p: Parameters) extends LazyModule
|
||||
val dec_trees_wen = Wire(init = Fill(decTrees, wipe))
|
||||
|
||||
// This must be registers b/c we build a CAM from it
|
||||
val flight = Reg(Vec(endSourceId, new FlightMonitor))
|
||||
val flight = Reg(Vec(endSourceId, new TLRAMModel.FlightMonitor(params)))
|
||||
val valid = Reg(Vec(endSourceId, Bool()))
|
||||
|
||||
// We want to cross flight data from A to D in the same cycle (for combinational TL2 devices)
|
||||
val a_flight = Wire(new FlightMonitor)
|
||||
val a_flight = Wire(new TLRAMModel.FlightMonitor(params))
|
||||
a_flight.base := edge.address(in.a.bits)
|
||||
a_flight.size := edge.size(in.a.bits)
|
||||
a_flight.opcode := in.a.bits.opcode
|
||||
@ -169,7 +157,7 @@ class TLRAMModel(log: String = "")(implicit p: Parameters) extends LazyModule
|
||||
|
||||
val a_waddr = Mux(wipe, wipeIndex, a_addr_hi)
|
||||
for (i <- 0 until beatBytes) {
|
||||
val data = Wire(new ByteMonitor)
|
||||
val data = Wire(new TLRAMModel.ByteMonitor(params))
|
||||
val busy = a_inc(i) =/= a_dec(i) + (!a_first).asUInt
|
||||
val amo = a.opcode === TLMessages.ArithmeticData || a.opcode === TLMessages.LogicalData
|
||||
data.valid := Mux(wipe, Bool(false), (!busy || a_fifo) && !amo)
|
||||
@ -295,4 +283,20 @@ class TLRAMModel(log: String = "")(implicit p: Parameters) extends LazyModule
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
object TLRAMModel
|
||||
{
|
||||
case class MonitorParameters(addressBits: Int, sizeBits: Int)
|
||||
|
||||
class ByteMonitor(params: MonitorParameters) extends GenericParameterizedBundle(params) {
|
||||
val valid = Bool()
|
||||
val value = UInt(width = 8)
|
||||
}
|
||||
class FlightMonitor(params: MonitorParameters) extends GenericParameterizedBundle(params) {
|
||||
val base = UInt(width = params.addressBits)
|
||||
val size = UInt(width = params.sizeBits)
|
||||
val opcode = UInt(width = 3)
|
||||
}
|
||||
}
|
||||
|
@ -9,7 +9,7 @@ import regmapper._
|
||||
import scala.math.{min,max}
|
||||
|
||||
class TLRegisterNode(address: AddressSet, concurrency: Int = 0, beatBytes: Int = 4, undefZero: Boolean = true, executable: Boolean = false)
|
||||
extends TLManagerNode(TLManagerPortParameters(
|
||||
extends TLManagerNode(Seq(TLManagerPortParameters(
|
||||
Seq(TLManagerParameters(
|
||||
address = Seq(address),
|
||||
executable = executable,
|
||||
@ -18,7 +18,7 @@ class TLRegisterNode(address: AddressSet, concurrency: Int = 0, beatBytes: Int =
|
||||
supportsPutFull = TransferSizes(1, beatBytes),
|
||||
fifoId = Some(0))), // requests are handled in order
|
||||
beatBytes = beatBytes,
|
||||
minLatency = min(concurrency, 1))) // the Queue adds at most one cycle
|
||||
minLatency = min(concurrency, 1)))) // the Queue adds at most one cycle
|
||||
{
|
||||
require (address.contiguous)
|
||||
|
||||
|
@ -8,7 +8,7 @@ import diplomacy._
|
||||
|
||||
class TLRAM(address: AddressSet, executable: Boolean = true, beatBytes: Int = 4)(implicit p: Parameters) extends LazyModule
|
||||
{
|
||||
val node = TLManagerNode(TLManagerPortParameters(
|
||||
val node = TLManagerNode(Seq(TLManagerPortParameters(
|
||||
Seq(TLManagerParameters(
|
||||
address = List(address),
|
||||
regionType = RegionType.UNCACHED,
|
||||
@ -18,7 +18,7 @@ class TLRAM(address: AddressSet, executable: Boolean = true, beatBytes: Int = 4)
|
||||
supportsPutFull = TransferSizes(1, beatBytes),
|
||||
fifoId = Some(0))), // requests are handled in order
|
||||
beatBytes = beatBytes,
|
||||
minLatency = 1)) // no bypass needed for this device
|
||||
minLatency = 1))) // no bypass needed for this device
|
||||
|
||||
// We require the address range to include an entire beat (for the write mask)
|
||||
require ((address.mask & (beatBytes-1)) == beatBytes-1)
|
||||
|
@ -15,8 +15,8 @@ class TLSourceShrinker(maxInFlight: Int)(implicit p: Parameters) extends LazyMod
|
||||
private val client = TLClientParameters(sourceId = IdRange(0, maxInFlight))
|
||||
val node = TLAdapterNode(
|
||||
// We erase all client information since we crush the source Ids
|
||||
clientFn = { case _ => TLClientPortParameters(clients = Seq(client)) },
|
||||
managerFn = { case Seq(mp) => mp })
|
||||
clientFn = { _ => TLClientPortParameters(clients = Seq(client)) },
|
||||
managerFn = { mp => mp })
|
||||
|
||||
lazy val module = new LazyModuleImp(this) {
|
||||
val io = new Bundle {
|
||||
@ -24,11 +24,7 @@ class TLSourceShrinker(maxInFlight: Int)(implicit p: Parameters) extends LazyMod
|
||||
val out = node.bundleOut
|
||||
}
|
||||
|
||||
val edgeIn = node.edgesIn(0)
|
||||
val edgeOut = node.edgesOut(0)
|
||||
val in = io.in(0)
|
||||
val out = io.out(0)
|
||||
|
||||
((io.in zip io.out) zip (node.edgesIn zip node.edgesOut)) foreach { case ((in, out), (edgeIn, edgeOut)) =>
|
||||
// Acquires cannot pass this adapter; it makes Probes impossible
|
||||
require (!edgeIn.client.anySupportProbe ||
|
||||
!edgeOut.manager.anySupportAcquireB)
|
||||
@ -74,6 +70,7 @@ class TLSourceShrinker(maxInFlight: Int)(implicit p: Parameters) extends LazyMod
|
||||
allocated := (allocated | alloc_id) & ~free_id
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
object TLSourceShrinker
|
||||
|
@ -10,12 +10,12 @@ import uncore.ahb._
|
||||
import scala.math.{min, max}
|
||||
import AHBParameters._
|
||||
|
||||
case class TLToAHBNode() extends MixedNode(TLImp, AHBImp)(
|
||||
dFn = { case (1, Seq(TLClientPortParameters(clients, unsafeAtomics, minLatency))) =>
|
||||
case class TLToAHBNode() extends MixedAdapterNode(TLImp, AHBImp)(
|
||||
dFn = { case TLClientPortParameters(clients, unsafeAtomics, minLatency) =>
|
||||
val masters = clients.map { case c => AHBMasterParameters(nodePath = c.nodePath) }
|
||||
Seq(AHBMasterPortParameters(masters))
|
||||
AHBMasterPortParameters(masters)
|
||||
},
|
||||
uFn = { case (1, Seq(AHBSlavePortParameters(slaves, beatBytes))) =>
|
||||
uFn = { case AHBSlavePortParameters(slaves, beatBytes) =>
|
||||
val managers = slaves.map { case s =>
|
||||
TLManagerParameters(
|
||||
address = s.address,
|
||||
@ -26,10 +26,8 @@ case class TLToAHBNode() extends MixedNode(TLImp, AHBImp)(
|
||||
supportsPutFull = s.supportsWrite, // but not PutPartial
|
||||
fifoId = Some(0)) // a common FIFO domain
|
||||
}
|
||||
Seq(TLManagerPortParameters(managers, beatBytes, 1, 1))
|
||||
},
|
||||
numPO = 1 to 1,
|
||||
numPI = 1 to 1)
|
||||
TLManagerPortParameters(managers, beatBytes, 1, 1)
|
||||
})
|
||||
|
||||
class TLToAHB(combinational: Boolean = true)(implicit p: Parameters) extends LazyModule
|
||||
{
|
||||
@ -41,10 +39,7 @@ class TLToAHB(combinational: Boolean = true)(implicit p: Parameters) extends Laz
|
||||
val out = node.bundleOut
|
||||
}
|
||||
|
||||
val in = io.in(0)
|
||||
val out = io.out(0)
|
||||
val edgeIn = node.edgesIn(0)
|
||||
val edgeOut = node.edgesOut(0)
|
||||
((io.in zip io.out) zip (node.edgesIn zip node.edgesOut)) foreach { case ((in, out), (edgeIn, edgeOut)) =>
|
||||
val beatBytes = edgeOut.slave.beatBytes
|
||||
val maxTransfer = edgeOut.slave.maxTransfer
|
||||
val lgMax = log2Ceil(maxTransfer)
|
||||
@ -127,6 +122,7 @@ class TLToAHB(combinational: Boolean = true)(implicit p: Parameters) extends Laz
|
||||
out.hprot := PROT_DEFAULT
|
||||
out.hwdata := RegEnable(a.bits.data, a.fire())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
object TLToAHB
|
||||
|
@ -10,12 +10,12 @@ import uncore.apb._
|
||||
import scala.math.{min, max}
|
||||
import APBParameters._
|
||||
|
||||
case class TLToAPBNode() extends MixedNode(TLImp, APBImp)(
|
||||
dFn = { case (1, Seq(TLClientPortParameters(clients, unsafeAtomics, minLatency))) =>
|
||||
case class TLToAPBNode() extends MixedAdapterNode(TLImp, APBImp)(
|
||||
dFn = { case TLClientPortParameters(clients, unsafeAtomics, minLatency) =>
|
||||
val masters = clients.map { case c => APBMasterParameters(nodePath = c.nodePath) }
|
||||
Seq(APBMasterPortParameters(masters))
|
||||
APBMasterPortParameters(masters)
|
||||
},
|
||||
uFn = { case (1, Seq(APBSlavePortParameters(slaves, beatBytes))) =>
|
||||
uFn = { case APBSlavePortParameters(slaves, beatBytes) =>
|
||||
val managers = slaves.map { case s =>
|
||||
TLManagerParameters(
|
||||
address = s.address,
|
||||
@ -27,10 +27,8 @@ case class TLToAPBNode() extends MixedNode(TLImp, APBImp)(
|
||||
supportsPutFull = if (s.supportsWrite) TransferSizes(1, beatBytes) else TransferSizes.none,
|
||||
fifoId = Some(0)) // a common FIFO domain
|
||||
}
|
||||
Seq(TLManagerPortParameters(managers, beatBytes, 1, 0))
|
||||
},
|
||||
numPO = 1 to 1,
|
||||
numPI = 1 to 1)
|
||||
TLManagerPortParameters(managers, beatBytes, 1, 0)
|
||||
})
|
||||
|
||||
class TLToAPB(combinational: Boolean = true)(implicit p: Parameters) extends LazyModule
|
||||
{
|
||||
@ -42,10 +40,7 @@ class TLToAPB(combinational: Boolean = true)(implicit p: Parameters) extends Laz
|
||||
val out = node.bundleOut
|
||||
}
|
||||
|
||||
val in = io.in(0)
|
||||
val out = io.out(0)
|
||||
val edgeIn = node.edgesIn(0)
|
||||
val edgeOut = node.edgesOut(0)
|
||||
((io.in zip io.out) zip (node.edgesIn zip node.edgesOut)) foreach { case ((in, out), (edgeIn, edgeOut)) =>
|
||||
val beatBytes = edgeOut.slave.beatBytes
|
||||
val lgBytes = log2Ceil(beatBytes)
|
||||
|
||||
@ -88,6 +83,7 @@ class TLToAPB(combinational: Boolean = true)(implicit p: Parameters) extends Laz
|
||||
d.bits := edgeIn.AccessAck(a.bits, UInt(0), out.prdata, out.pslverr)
|
||||
d.bits.opcode := Mux(a_write, TLMessages.AccessAck, TLMessages.AccessAckData)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
object TLToAPB
|
||||
|
@ -10,16 +10,16 @@ import util.PositionalMultiQueue
|
||||
import uncore.axi4._
|
||||
import scala.math.{min, max}
|
||||
|
||||
case class TLToAXI4Node(idBits: Int) extends MixedNode(TLImp, AXI4Imp)(
|
||||
dFn = { case (1, _) =>
|
||||
case class TLToAXI4Node(idBits: Int) extends MixedAdapterNode(TLImp, AXI4Imp)(
|
||||
dFn = { _ =>
|
||||
// We must erase all client information, because we crush their source Ids
|
||||
val masters = Seq(
|
||||
AXI4MasterParameters(
|
||||
id = IdRange(0, 1 << idBits),
|
||||
aligned = true))
|
||||
Seq(AXI4MasterPortParameters(masters))
|
||||
AXI4MasterPortParameters(masters)
|
||||
},
|
||||
uFn = { case (1, Seq(p)) => Seq(TLManagerPortParameters(
|
||||
uFn = { p => TLManagerPortParameters(
|
||||
managers = p.slaves.map { case s =>
|
||||
TLManagerParameters(
|
||||
address = s.address,
|
||||
@ -31,10 +31,8 @@ case class TLToAXI4Node(idBits: Int) extends MixedNode(TLImp, AXI4Imp)(
|
||||
supportsPutPartial = s.supportsWrite)},
|
||||
// AXI4 is NEVER fifo in TL sense (R+W are independent)
|
||||
beatBytes = p.beatBytes,
|
||||
minLatency = p.minLatency))
|
||||
},
|
||||
numPO = 1 to 1,
|
||||
numPI = 1 to 1)
|
||||
minLatency = p.minLatency)
|
||||
})
|
||||
|
||||
class TLToAXI4(idBits: Int, combinational: Boolean = true)(implicit p: Parameters) extends LazyModule
|
||||
{
|
||||
@ -46,11 +44,7 @@ class TLToAXI4(idBits: Int, combinational: Boolean = true)(implicit p: Parameter
|
||||
val out = node.bundleOut
|
||||
}
|
||||
|
||||
val in = io.in(0)
|
||||
val out = io.out(0)
|
||||
|
||||
val edgeIn = node.edgesIn(0)
|
||||
val edgeOut = node.edgesOut(0)
|
||||
((io.in zip io.out) zip (node.edgesIn zip node.edgesOut)) foreach { case ((in, out), (edgeIn, edgeOut)) =>
|
||||
val slaves = edgeOut.slave.slaves
|
||||
|
||||
// All pairs of slaves must promise that they will never interleave data
|
||||
@ -226,6 +220,7 @@ class TLToAXI4(idBits: Int, combinational: Boolean = true)(implicit p: Parameter
|
||||
in.c.ready := Bool(true)
|
||||
in.e.ready := Bool(true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
object TLToAXI4
|
||||
|
@ -12,8 +12,8 @@ import scala.math.{min,max}
|
||||
class TLWidthWidget(innerBeatBytes: Int)(implicit p: Parameters) extends LazyModule
|
||||
{
|
||||
val node = TLAdapterNode(
|
||||
clientFn = { case Seq(c) => c },
|
||||
managerFn = { case Seq(m) => m.copy(beatBytes = innerBeatBytes) })
|
||||
clientFn = { case c => c },
|
||||
managerFn = { case m => m.copy(beatBytes = innerBeatBytes) })
|
||||
|
||||
lazy val module = new LazyModuleImp(this) {
|
||||
val io = new Bundle {
|
||||
@ -139,11 +139,7 @@ class TLWidthWidget(innerBeatBytes: Int)(implicit p: Parameters) extends LazyMod
|
||||
}
|
||||
}
|
||||
|
||||
val edgeOut = node.edgesOut(0)
|
||||
val edgeIn = node.edgesIn(0)
|
||||
val in = io.in(0)
|
||||
val out = io.out(0)
|
||||
|
||||
((io.in zip io.out) zip (node.edgesIn zip node.edgesOut)) foreach { case ((in, out), (edgeIn, edgeOut)) =>
|
||||
splice(edgeIn, in.a, edgeOut, out.a)
|
||||
splice(edgeOut, out.d, edgeIn, in.d)
|
||||
|
||||
@ -162,6 +158,7 @@ class TLWidthWidget(innerBeatBytes: Int)(implicit p: Parameters) extends LazyMod
|
||||
out.e.valid := Bool(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
object TLWidthWidget
|
||||
|
@ -34,7 +34,7 @@ class TLXbar(policy: TLArbiter.Policy = TLArbiter.lowestIndexFirst)(implicit p:
|
||||
}
|
||||
}
|
||||
|
||||
val node = TLAdapterNode(
|
||||
val node = TLNexusNode(
|
||||
numClientPorts = 1 to 32,
|
||||
numManagerPorts = 1 to 32,
|
||||
clientFn = { seq =>
|
||||
|
Loading…
Reference in New Issue
Block a user