1
0

Merge pull request #536 from ucb-bar/diplomacy-star-nodes

diplomacy: add :*= and :=* to support flexible # of edges
This commit is contained in:
Henry Cook 2017-01-30 11:19:33 -08:00 committed by GitHub
commit b567a2a356
42 changed files with 1948 additions and 1895 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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 },

View File

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

View File

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

View File

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

View File

@ -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 },

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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 */

View File

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

View File

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

View File

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

View File

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

View File

@ -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 */

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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