Merge pull request #985 from freechipsproject/flop-interrupts
Add Parameters to diplomatic edges
This commit is contained in:
commit
e7de7f3e82
@ -139,7 +139,7 @@ object AHBToTL
|
||||
{
|
||||
def apply()(x: AHBOutwardNode)(implicit p: Parameters, sourceInfo: SourceInfo): TLOutwardNode = {
|
||||
val tl = LazyModule(new AHBToTL)
|
||||
tl.node := x
|
||||
tl.node :=? x
|
||||
tl.node
|
||||
}
|
||||
}
|
||||
|
@ -62,7 +62,7 @@ object AXI4Buffer
|
||||
ar: BufferParams,
|
||||
r: BufferParams)(x: AXI4OutwardNode)(implicit p: Parameters, sourceInfo: SourceInfo): AXI4OutwardNode = {
|
||||
val buffer = LazyModule(new AXI4Buffer(aw, w, b, ar, r))
|
||||
buffer.node := x
|
||||
buffer.node :=? x
|
||||
buffer.node
|
||||
}
|
||||
}
|
||||
|
@ -108,7 +108,7 @@ object AXI4Deinterleaver
|
||||
// applied to the AXI4 source node; y.node := AXI4Deinterleaver()(x.node)
|
||||
def apply(maxReadBytes: Int)(x: AXI4OutwardNode)(implicit p: Parameters, sourceInfo: SourceInfo): AXI4OutwardNode = {
|
||||
val deinterleaver = LazyModule(new AXI4Deinterleaver(maxReadBytes))
|
||||
deinterleaver.node := x
|
||||
deinterleaver.node :=? x
|
||||
deinterleaver.node
|
||||
}
|
||||
}
|
||||
|
@ -208,7 +208,7 @@ object AXI4Fragmenter
|
||||
// applied to the AXI4 source node; y.node := AXI4Fragmenter()(x.node)
|
||||
def apply()(x: AXI4OutwardNode)(implicit p: Parameters, sourceInfo: SourceInfo): AXI4OutwardNode = {
|
||||
val fragmenter = LazyModule(new AXI4Fragmenter)
|
||||
fragmenter.node := x
|
||||
fragmenter.node :=? x
|
||||
fragmenter.node
|
||||
}
|
||||
}
|
||||
|
@ -84,7 +84,7 @@ object AXI4IdIndexer
|
||||
// applied to the AXI4 source node; y.node := AXI4IdIndexer(idBits)(x.node)
|
||||
def apply(idBits: Int)(x: AXI4OutwardNode)(implicit p: Parameters, sourceInfo: SourceInfo): AXI4OutwardNode = {
|
||||
val indexer = LazyModule(new AXI4IdIndexer(idBits))
|
||||
indexer.node := x
|
||||
indexer.node :=? x
|
||||
indexer.node
|
||||
}
|
||||
}
|
||||
|
@ -168,7 +168,7 @@ object AXI4ToTL
|
||||
{
|
||||
def apply()(x: AXI4OutwardNode)(implicit p: Parameters, sourceInfo: SourceInfo): TLOutwardNode = {
|
||||
val tl = LazyModule(new AXI4ToTL)
|
||||
tl.node := x
|
||||
tl.node :=? x
|
||||
tl.node
|
||||
}
|
||||
}
|
||||
|
@ -100,7 +100,7 @@ object AXI4UserYanker
|
||||
// applied to the AXI4 source node; y.node := AXI4UserYanker(idBits, maxFlight)(x.node)
|
||||
def apply(capMaxFlight: Option[Int] = None)(x: AXI4OutwardNode)(implicit p: Parameters, sourceInfo: SourceInfo): AXI4OutwardNode = {
|
||||
val yanker = LazyModule(new AXI4UserYanker(capMaxFlight))
|
||||
yanker.node := x
|
||||
yanker.node :=? x
|
||||
yanker.node
|
||||
}
|
||||
}
|
||||
|
@ -2,13 +2,22 @@
|
||||
|
||||
package freechips.rocketchip.config
|
||||
|
||||
class Field[T]
|
||||
abstract class Field[T] private (val default: Option[T])
|
||||
{
|
||||
def this() = this(None)
|
||||
def this(x: T) = this(Some(x))
|
||||
}
|
||||
|
||||
abstract class View {
|
||||
final def apply[T](pname: Field[T]): T = apply(pname, this)
|
||||
final def apply[T](pname: Field[T], site: View): T = find(pname, site).asInstanceOf[T]
|
||||
final def apply[T](pname: Field[T], site: View): T = find(pname, site) match {
|
||||
case Some(x) => x.asInstanceOf[T]
|
||||
}
|
||||
|
||||
protected[config] def find(pname: Any, site: View): Any
|
||||
final def lift[T](pname: Field[T]): Option[T] = lift(pname, this)
|
||||
final def lift[T](pname: Field[T], site: View): Option[T] = find(pname, site).map(_.asInstanceOf[T])
|
||||
|
||||
protected[config] def find[T](pname: Field[T], site: View): Option[T]
|
||||
}
|
||||
|
||||
abstract class Parameters extends View {
|
||||
@ -16,8 +25,8 @@ abstract class Parameters extends View {
|
||||
final def alter(f: (View, View, View) => PartialFunction[Any,Any]): Parameters = Parameters(f) ++ this
|
||||
final def alterPartial(f: PartialFunction[Any,Any]): Parameters = Parameters((_,_,_) => f) ++ this
|
||||
|
||||
protected[config] def chain(site: View, tail: View, pname: Any): Any
|
||||
protected[config] def find(pname: Any, site: View) = chain(site, new TerminalView, pname)
|
||||
protected[config] def chain[T](site: View, tail: View, pname: Field[T]): Option[T]
|
||||
protected[config] def find[T](pname: Field[T], site: View) = chain(site, new TerminalView, pname)
|
||||
}
|
||||
|
||||
object Parameters {
|
||||
@ -29,7 +38,7 @@ object Parameters {
|
||||
class Config(p: Parameters) extends Parameters {
|
||||
def this(f: (View, View, View) => PartialFunction[Any,Any]) = this(Parameters(f))
|
||||
|
||||
protected[config] def chain(site: View, tail: View, pname: Any) = p.chain(site, tail, pname)
|
||||
protected[config] def chain[T](site: View, tail: View, pname: Field[T]) = p.chain(site, tail, pname)
|
||||
override def toString = this.getClass.getSimpleName
|
||||
def toInstance = this
|
||||
}
|
||||
@ -37,25 +46,24 @@ class Config(p: Parameters) extends Parameters {
|
||||
// Internal implementation:
|
||||
|
||||
private class TerminalView extends View {
|
||||
private class Unusable
|
||||
def find(pname: Any, site: View): Any = pname match { case x: Unusable => () }
|
||||
def find[T](pname: Field[T], site: View): Option[T] = pname.default
|
||||
}
|
||||
|
||||
private class ChainView(head: Parameters, tail: View) extends View {
|
||||
def find(pname: Any, site: View) = head.chain(site, tail, pname)
|
||||
def find[T](pname: Field[T], site: View) = head.chain(site, tail, pname)
|
||||
}
|
||||
|
||||
private class ChainParameters(x: Parameters, y: Parameters) extends Parameters {
|
||||
def chain(site: View, tail: View, pname: Any) = x.chain(site, new ChainView(y, tail), pname)
|
||||
def chain[T](site: View, tail: View, pname: Field[T]) = x.chain(site, new ChainView(y, tail), pname)
|
||||
}
|
||||
|
||||
private class EmptyParameters extends Parameters {
|
||||
def chain(site: View, tail: View, pname: Any) = tail.find(pname, site)
|
||||
def chain[T](site: View, tail: View, pname: Field[T]) = tail.find(pname, site)
|
||||
}
|
||||
|
||||
private class PartialParameters(f: (View, View, View) => PartialFunction[Any,Any]) extends Parameters {
|
||||
protected[config] def chain(site: View, tail: View, pname: Any) = {
|
||||
protected[config] def chain[T](site: View, tail: View, pname: Field[T]) = {
|
||||
val g = f(site, this, tail)
|
||||
if (g.isDefinedAt(pname)) g.apply(pname) else tail.find(pname, site)
|
||||
if (g.isDefinedAt(pname)) Some(g.apply(pname).asInstanceOf[T]) else tail.find(pname, site)
|
||||
}
|
||||
}
|
||||
|
@ -36,9 +36,6 @@ class BaseCoreplexConfig extends Config ((site, here, up) => {
|
||||
case PLICParams => PLICParams()
|
||||
case ClintParams => ClintParams()
|
||||
case DTSTimebase => BigInt(1000000) // 1 MHz
|
||||
// TileLink connection global parameters
|
||||
case TLMonitorBuilder => (args: TLMonitorArgs) => Some(LazyModule(new TLMonitor(args)))
|
||||
case TLCombinationalCheck => false
|
||||
case TLBusDelayProbability => 0.0
|
||||
})
|
||||
|
||||
|
@ -67,7 +67,7 @@ trait HasMemoryBus extends HasSystemBus with HasPeripheryBus with HasInterruptBu
|
||||
val mbus = new MemoryBus(mbusParams)
|
||||
for (bank <- 0 until nBanksPerChannel) {
|
||||
val offset = (bank * nMemoryChannels) + channel
|
||||
in := sbus.toMemoryBus
|
||||
ForceFanout(a = true) { implicit p => in := sbus.toMemoryBus }
|
||||
mbus.fromCoherenceManager := TLFilter(TLFilter.Mmask(AddressSet(offset * blockBytes, mask)))(out)
|
||||
}
|
||||
mbus
|
||||
|
@ -45,20 +45,20 @@ trait HasRocketTiles extends HasSystemBus
|
||||
val wrapper = crossing match {
|
||||
case SynchronousCrossing(params) => {
|
||||
val wrapper = LazyModule(new SyncRocketTile(tp, i)(pWithExtra))
|
||||
sbus.fromSyncTiles(params, tp.externalBuffers, tp.name) :=* wrapper.masterNode
|
||||
wrapper.slaveNode :*= pbus.bufferToSlaves
|
||||
sbus.fromSyncTiles(params, tp.externalMasterBuffers, tp.name) :=* wrapper.masterNode
|
||||
wrapper.slaveNode :*= pbus.toSyncSlaves(tp.name, tp.externalSlaveBuffers)
|
||||
wrapper
|
||||
}
|
||||
case AsynchronousCrossing(depth, sync) => {
|
||||
val wrapper = LazyModule(new AsyncRocketTile(tp, i)(pWithExtra))
|
||||
sbus.fromAsyncTiles(depth, sync, tp.externalBuffers, tp.name) :=* wrapper.masterNode
|
||||
wrapper.slaveNode :*= pbus.toAsyncSlaves(sync, tp.name)
|
||||
sbus.fromAsyncTiles(depth, sync, tp.externalMasterBuffers, tp.name) :=* wrapper.masterNode
|
||||
wrapper.slaveNode :*= pbus.toAsyncSlaves(sync, tp.name, tp.externalSlaveBuffers)
|
||||
wrapper
|
||||
}
|
||||
case RationalCrossing(direction) => {
|
||||
val wrapper = LazyModule(new RationalRocketTile(tp, i)(pWithExtra))
|
||||
sbus.fromRationalTiles(direction, tp.externalBuffers, tp.name) :=* wrapper.masterNode
|
||||
wrapper.slaveNode :*= pbus.toRationalSlaves(tp.name)
|
||||
sbus.fromRationalTiles(direction, tp.externalMasterBuffers, tp.name) :=* wrapper.masterNode
|
||||
wrapper.slaveNode :*= pbus.toRationalSlaves(tp.name, tp.externalSlaveBuffers)
|
||||
wrapper
|
||||
}
|
||||
}
|
||||
|
@ -25,7 +25,7 @@ object ClintConsts
|
||||
def ints = 2
|
||||
}
|
||||
|
||||
case class ClintParams(baseAddress: BigInt = 0x02000000)
|
||||
case class ClintParams(baseAddress: BigInt = 0x02000000, intStages: Int = 0)
|
||||
{
|
||||
def address = AddressSet(baseAddress, ClintConsts.size-1)
|
||||
}
|
||||
@ -71,8 +71,8 @@ class CoreplexLocalInterrupter(params: ClintParams)(implicit p: Parameters) exte
|
||||
val ipi = Seq.fill(nTiles) { RegInit(UInt(0, width = 1)) }
|
||||
|
||||
io.int.zipWithIndex.foreach { case (int, i) =>
|
||||
int(0) := ipi(i)(0) // msip
|
||||
int(1) := time.asUInt >= timecmp(i).asUInt // mtip
|
||||
int(0) := ShiftRegister(ipi(i)(0), params.intStages) // msip
|
||||
int(1) := ShiftRegister(time.asUInt >= timecmp(i).asUInt, params.intStages) // mtip
|
||||
}
|
||||
|
||||
/* 0000 msip hart 0
|
||||
|
@ -52,7 +52,7 @@ object PLICConsts
|
||||
require(hartBase >= enableBase(maxHarts))
|
||||
}
|
||||
|
||||
case class PLICParams(baseAddress: BigInt = 0xC000000, maxPriorities: Int = 7)
|
||||
case class PLICParams(baseAddress: BigInt = 0xC000000, maxPriorities: Int = 7, intStages: Int = 0)
|
||||
{
|
||||
require (maxPriorities >= 0)
|
||||
def address = AddressSet(baseAddress, PLICConsts.size-1)
|
||||
@ -166,7 +166,7 @@ class TLPLIC(params: PLICParams)(implicit p: Parameters) extends LazyModule
|
||||
val (maxPri, maxDev) = findMax(effectivePriority)
|
||||
|
||||
maxDevs(hart) := maxDev
|
||||
harts(hart) := Reg(next = maxPri) > Cat(UInt(1), threshold(hart))
|
||||
harts(hart) := ShiftRegister(Reg(next = maxPri) > Cat(UInt(1), threshold(hart)), params.intStages)
|
||||
}
|
||||
|
||||
def priorityRegField(x: UInt) = if (nPriorities > 0) RegField(32, x) else RegField.r(32, x)
|
||||
|
@ -4,10 +4,30 @@ package freechips.rocketchip.diplomacy
|
||||
|
||||
import Chisel._
|
||||
import chisel3.internal.sourceinfo.SourceInfo
|
||||
import freechips.rocketchip.config.Parameters
|
||||
import freechips.rocketchip.config.{Parameters,Field}
|
||||
import freechips.rocketchip.util.HeterogeneousBag
|
||||
import scala.collection.mutable.ListBuffer
|
||||
|
||||
object CardinalityInferenceDirection {
|
||||
val cases = Seq(SOURCE_TO_SINK, SINK_TO_SOURCE, NO_INFERENCE)
|
||||
sealed trait T {
|
||||
def flip = this match {
|
||||
case SOURCE_TO_SINK => SINK_TO_SOURCE
|
||||
case SINK_TO_SOURCE => SOURCE_TO_SINK
|
||||
case NO_INFERENCE => NO_INFERENCE
|
||||
}
|
||||
}
|
||||
|
||||
case object SOURCE_TO_SINK extends T
|
||||
case object SINK_TO_SOURCE extends T
|
||||
case object NO_INFERENCE extends T
|
||||
}
|
||||
|
||||
private case object CardinalityInferenceDirectionKey extends
|
||||
Field[CardinalityInferenceDirection.T](CardinalityInferenceDirection.NO_INFERENCE)
|
||||
|
||||
private case object MonitorsEnabled extends Field[Boolean](true)
|
||||
|
||||
// DI = Downwards flowing Parameters received on the inner side of the node
|
||||
// UI = Upwards flowing Parameters generated by the inner side of the node
|
||||
// EI = Edge Parameters describing a connection on the inner side of the node
|
||||
@ -77,13 +97,15 @@ case class NodeHandle[DI, UI, BI <: Data, DO, UO, BO <: Data]
|
||||
|
||||
trait InwardNodeHandle[DI, UI, BI <: Data]
|
||||
{
|
||||
val inward: InwardNode[DI, UI, BI]
|
||||
protected[diplomacy] val inward: InwardNode[DI, UI, BI]
|
||||
def := (h: OutwardNodeHandle[DI, UI, BI])(implicit p: Parameters, sourceInfo: SourceInfo): Option[MonitorBase] =
|
||||
inward.:=(h)(p, sourceInfo)
|
||||
def :*= (h: OutwardNodeHandle[DI, UI, BI])(implicit p: Parameters, sourceInfo: SourceInfo): Option[MonitorBase] =
|
||||
inward.:*=(h)(p, sourceInfo)
|
||||
def :=* (h: OutwardNodeHandle[DI, UI, BI])(implicit p: Parameters, sourceInfo: SourceInfo): Option[MonitorBase] =
|
||||
inward.:=*(h)(p, sourceInfo)
|
||||
def :=? (h: OutwardNodeHandle[DI, UI, BI])(implicit p: Parameters, sourceInfo: SourceInfo): Option[MonitorBase] =
|
||||
inward.:=?(h)(p, sourceInfo)
|
||||
}
|
||||
|
||||
sealed trait NodeBinding
|
||||
@ -93,22 +115,22 @@ case object BIND_STAR extends NodeBinding
|
||||
|
||||
trait InwardNode[DI, UI, BI <: Data] extends BaseNode with InwardNodeHandle[DI, UI, BI]
|
||||
{
|
||||
val inward = this
|
||||
protected[diplomacy] val inward = this
|
||||
|
||||
protected[diplomacy] val numPI: Range.Inclusive
|
||||
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], NodeBinding)]()
|
||||
private val accPI = ListBuffer[(Int, OutwardNode[DI, UI, BI], NodeBinding, Parameters)]()
|
||||
private var iRealized = false
|
||||
|
||||
protected[diplomacy] def iPushed = accPI.size
|
||||
protected[diplomacy] def iPush(index: Int, node: OutwardNode[DI, UI, BI], binding: NodeBinding)(implicit sourceInfo: SourceInfo) {
|
||||
protected[diplomacy] def iPush(index: Int, node: OutwardNode[DI, UI, BI], binding: NodeBinding)(implicit p: Parameters, 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, binding))
|
||||
accPI += ((index, node, binding, p))
|
||||
}
|
||||
|
||||
protected[diplomacy] lazy val iBindings = { iRealized = true; accPI.result() }
|
||||
@ -116,32 +138,32 @@ trait InwardNode[DI, UI, BI <: Data] extends BaseNode with InwardNodeHandle[DI,
|
||||
protected[diplomacy] val iStar: Int
|
||||
protected[diplomacy] val iPortMapping: Seq[(Int, Int)]
|
||||
protected[diplomacy] val iParams: Seq[UI]
|
||||
val bundleIn: HeterogeneousBag[BI]
|
||||
protected[diplomacy] val bundleIn: HeterogeneousBag[BI]
|
||||
}
|
||||
|
||||
trait OutwardNodeHandle[DO, UO, BO <: Data]
|
||||
{
|
||||
val outward: OutwardNode[DO, UO, BO]
|
||||
protected[diplomacy] val outward: OutwardNode[DO, UO, BO]
|
||||
}
|
||||
|
||||
trait OutwardNode[DO, UO, BO <: Data] extends BaseNode with OutwardNodeHandle[DO, UO, BO]
|
||||
{
|
||||
val outward = this
|
||||
protected[diplomacy] val outward = this
|
||||
|
||||
protected[diplomacy] val numPO: Range.Inclusive
|
||||
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], NodeBinding)]()
|
||||
private val accPO = ListBuffer[(Int, InwardNode [DO, UO, BO], NodeBinding, Parameters)]()
|
||||
private var oRealized = false
|
||||
|
||||
protected[diplomacy] def oPushed = accPO.size
|
||||
protected[diplomacy] def oPush(index: Int, node: InwardNode [DO, UO, BO], binding: NodeBinding)(implicit sourceInfo: SourceInfo) {
|
||||
protected[diplomacy] def oPush(index: Int, node: InwardNode [DO, UO, BO], binding: NodeBinding)(implicit p: Parameters, 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, binding))
|
||||
accPO += ((index, node, binding, p))
|
||||
}
|
||||
|
||||
protected[diplomacy] lazy val oBindings = { oRealized = true; accPO.result() }
|
||||
@ -149,7 +171,7 @@ trait OutwardNode[DO, UO, BO <: Data] extends BaseNode with OutwardNodeHandle[DO
|
||||
protected[diplomacy] val oStar: Int
|
||||
protected[diplomacy] val oPortMapping: Seq[(Int, Int)]
|
||||
protected[diplomacy] val oParams: Seq[DO]
|
||||
val bundleOut: HeterogeneousBag[BO]
|
||||
protected[diplomacy] val bundleOut: HeterogeneousBag[BO]
|
||||
}
|
||||
|
||||
abstract class MixedNode[DI, UI, EI, BI <: Data, DO, UO, EO, BO <: Data](
|
||||
@ -164,22 +186,22 @@ abstract class MixedNode[DI, UI, EI, BI <: Data, DO, UO, EO, BO <: Data](
|
||||
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
|
||||
val oKnown = oBindings.map { case (_, n, b) => b match {
|
||||
val oStars = oBindings.filter { case (_,_,b,_) => b == BIND_STAR }.size
|
||||
val iStars = iBindings.filter { case (_,_,b,_) => b == BIND_STAR }.size
|
||||
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 {
|
||||
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 (iStar, oStar) = resolveStar(iKnown, oKnown, iStars, oStars)
|
||||
val oSum = oBindings.map { case (_, n, b) => b match {
|
||||
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 {
|
||||
val iSum = iBindings.map { case (_, n, b, _) => b match {
|
||||
case BIND_ONCE => 1
|
||||
case BIND_QUERY => n.oStar
|
||||
case BIND_STAR => iStar }}.scanLeft(0)(_+_)
|
||||
@ -190,11 +212,11 @@ abstract class MixedNode[DI, UI, EI, BI <: Data, DO, UO, EO, BO <: Data](
|
||||
(oSum.init zip oSum.tail, iSum.init zip iSum.tail, oStar, iStar)
|
||||
}
|
||||
|
||||
lazy val oPorts = oBindings.flatMap { case (i, n, _) =>
|
||||
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, _) =>
|
||||
lazy val iPorts = iBindings.flatMap { case (i, n, _, _) =>
|
||||
val (start, end) = n.oPortMapping(i)
|
||||
(start until end) map { j => (j, n) }
|
||||
}
|
||||
@ -218,6 +240,9 @@ abstract class MixedNode[DI, UI, EI, BI <: Data, DO, UO, EO, BO <: Data](
|
||||
lazy val externalEdgesOut = if (externalOut) {edgesOut} else { Seq() }
|
||||
lazy val externalEdgesIn = if (externalIn) {edgesIn} else { Seq() }
|
||||
|
||||
lazy val paramsOut: Seq[Parameters] = (oPortMapping zip oBindings).flatMap { case ((s, e), b) => Seq.fill(e-s) { b._4 } }
|
||||
lazy val paramsIn: Seq[Parameters] = (iPortMapping zip iBindings).flatMap { case ((s, e), b) => Seq.fill(e-s) { b._4 } }
|
||||
|
||||
val flip = false // needed for blind nodes
|
||||
private def flipO(b: HeterogeneousBag[BO]) = if (flip) b.flip else b
|
||||
private def flipI(b: HeterogeneousBag[BI]) = if (flip) b else b.flip
|
||||
@ -229,7 +254,7 @@ abstract class MixedNode[DI, UI, EI, BI <: Data, DO, UO, EO, BO <: Data](
|
||||
lazy val bundleIn = wireI(flipI(HeterogeneousBag(edgesIn .map(inner.bundleI(_)))))
|
||||
|
||||
// connects the outward part of a node with the inward part of this node
|
||||
private def bind(h: OutwardNodeHandle[DI, UI, BI], binding: NodeBinding, enableMonitoring: Boolean)
|
||||
private def bind(h: OutwardNodeHandle[DI, UI, BI], binding: NodeBinding)
|
||||
(implicit p: Parameters, sourceInfo: SourceInfo): Option[MonitorBase] = {
|
||||
val x = this // x := y
|
||||
val y = h.outward
|
||||
@ -256,18 +281,21 @@ abstract class MixedNode[DI, UI, EI, BI <: Data, DO, UO, EO, BO <: Data](
|
||||
(x.bundleIn(iStart+j), y.bundleOut(oStart+j))
|
||||
}
|
||||
}
|
||||
val (out, newbinding) = inner.connect(edges _, bundles _, enableMonitoring)
|
||||
val (out, newbinding) = inner.connect(edges _, bundles _, p(MonitorsEnabled))
|
||||
LazyModule.stack.head.bindings = newbinding :: LazyModule.stack.head.bindings
|
||||
out
|
||||
}
|
||||
|
||||
override def := (h: OutwardNodeHandle[DI, UI, BI])(implicit p: Parameters, sourceInfo: SourceInfo): Option[MonitorBase] = bind(h, BIND_ONCE, true)
|
||||
override def :*= (h: OutwardNodeHandle[DI, UI, BI])(implicit p: Parameters, sourceInfo: SourceInfo): Option[MonitorBase] = bind(h, BIND_STAR, true)
|
||||
override def :=* (h: OutwardNodeHandle[DI, UI, BI])(implicit p: Parameters, sourceInfo: SourceInfo): Option[MonitorBase] = bind(h, BIND_QUERY, true)
|
||||
|
||||
def connectButDontMonitor(h: OutwardNodeHandle[DI, UI, BI])(implicit p: Parameters, sourceInfo: SourceInfo): Option[MonitorBase] = bind(h, BIND_ONCE, false)
|
||||
def connectButDontMonitorSlaves(h: OutwardNodeHandle[DI, UI, BI])(implicit p: Parameters, sourceInfo: SourceInfo): Option[MonitorBase] = bind(h, BIND_STAR, false)
|
||||
def connectButDontMonitorMasters(h: OutwardNodeHandle[DI, UI, BI])(implicit p: Parameters, sourceInfo: SourceInfo): Option[MonitorBase] = bind(h, BIND_QUERY, false)
|
||||
override def := (h: OutwardNodeHandle[DI, UI, BI])(implicit p: Parameters, sourceInfo: SourceInfo): Option[MonitorBase] = bind(h, BIND_ONCE)
|
||||
override def :*= (h: OutwardNodeHandle[DI, UI, BI])(implicit p: Parameters, sourceInfo: SourceInfo): Option[MonitorBase] = bind(h, BIND_STAR)
|
||||
override def :=* (h: OutwardNodeHandle[DI, UI, BI])(implicit p: Parameters, sourceInfo: SourceInfo): Option[MonitorBase] = bind(h, BIND_QUERY)
|
||||
override def :=? (h: OutwardNodeHandle[DI, UI, BI])(implicit p: Parameters, sourceInfo: SourceInfo): Option[MonitorBase] = {
|
||||
p(CardinalityInferenceDirectionKey) match {
|
||||
case CardinalityInferenceDirection.SOURCE_TO_SINK => this :=* h
|
||||
case CardinalityInferenceDirection.SINK_TO_SOURCE => this :*= h
|
||||
case CardinalityInferenceDirection.NO_INFERENCE => this := h
|
||||
}
|
||||
}
|
||||
|
||||
// meta-data for printing the node graph
|
||||
protected[diplomacy] def colour = inner.colour
|
||||
|
@ -293,3 +293,14 @@ object BufferParams
|
||||
val flow = BufferParams(1, true, false)
|
||||
val pipe = BufferParams(1, false, true)
|
||||
}
|
||||
|
||||
case class TriStateValue(value: Boolean, set: Boolean)
|
||||
{
|
||||
def update(orig: Boolean) = if (set) value else orig
|
||||
}
|
||||
|
||||
object TriStateValue
|
||||
{
|
||||
implicit def apply(value: Boolean): TriStateValue = TriStateValue(value, true)
|
||||
def unset = TriStateValue(false, false)
|
||||
}
|
||||
|
@ -3,6 +3,7 @@
|
||||
package freechips.rocketchip
|
||||
|
||||
import chisel3.internal.sourceinfo.{SourceInfo, SourceLine, UnlocatableSourceInfo}
|
||||
import freechips.rocketchip.config.Parameters
|
||||
|
||||
package object diplomacy
|
||||
{
|
||||
@ -20,4 +21,23 @@ package object diplomacy
|
||||
bitIndexes(x.clearBit(lowest), lowest +: tail)
|
||||
}
|
||||
}
|
||||
|
||||
def SinkCardinality[T](body: Parameters => T)(implicit p: Parameters) = body(p.alterPartial {
|
||||
case CardinalityInferenceDirectionKey => CardinalityInferenceDirection.SINK_TO_SOURCE
|
||||
})
|
||||
def SourceCardinality[T](body: Parameters => T)(implicit p: Parameters) = body(p.alterPartial {
|
||||
case CardinalityInferenceDirectionKey => CardinalityInferenceDirection.SOURCE_TO_SINK
|
||||
})
|
||||
def UnaryCardinality[T](body: Parameters => T)(implicit p: Parameters) = body(p.alterPartial {
|
||||
case CardinalityInferenceDirectionKey => CardinalityInferenceDirection.NO_INFERENCE
|
||||
})
|
||||
def FlipCardinality[T](body: Parameters => T)(implicit p: Parameters) = body(p.alterPartial {
|
||||
case CardinalityInferenceDirectionKey => p(CardinalityInferenceDirectionKey).flip
|
||||
})
|
||||
def EnableMonitors[T](body: Parameters => T)(implicit p: Parameters) = body(p.alterPartial {
|
||||
case MonitorsEnabled => true
|
||||
})
|
||||
def DisableMonitors[T](body: Parameters => T)(implicit p: Parameters) = body(p.alterPartial {
|
||||
case MonitorsEnabled => false
|
||||
})
|
||||
}
|
||||
|
@ -8,7 +8,7 @@ import Chisel.ImplicitConversions._
|
||||
import chisel3.core.withReset
|
||||
import freechips.rocketchip.config._
|
||||
import freechips.rocketchip.coreplex._
|
||||
import freechips.rocketchip.diplomacy.{LazyModule, LazyModuleImp}
|
||||
import freechips.rocketchip.diplomacy._
|
||||
import freechips.rocketchip.tilelink._
|
||||
import freechips.rocketchip.tile._
|
||||
import freechips.rocketchip.util._
|
||||
@ -61,7 +61,7 @@ class Frontend(val icacheParams: ICacheParams, hartid: Int)(implicit p: Paramete
|
||||
|
||||
masterNode := icache.masterNode
|
||||
// Avoid breaking tile dedup due to address constants in the monitor
|
||||
icache.slaveNode.map { _ connectButDontMonitor slaveNode }
|
||||
DisableMonitors { implicit p => icache.slaveNode.map { _ := slaveNode } }
|
||||
}
|
||||
|
||||
class FrontendBundle(outer: Frontend) extends CoreBundle()(outer.p) {
|
||||
|
@ -103,16 +103,18 @@ trait CanHaveScratchpad extends HasHellaCache with HasICacheFrontend with HasCor
|
||||
val slaveNode = TLInputNode() // Up to two uses for this input node:
|
||||
|
||||
// 1) Frontend always exists, but may or may not have a scratchpad node
|
||||
// 2) ScratchpadSlavePort always has a node, but only exists when the HellaCache has a scratchpad
|
||||
val fg = LazyModule(new TLFragmenter(fetchWidth*coreInstBytes, p(CacheBlockBytes), earlyAck=true))
|
||||
val ww = LazyModule(new TLWidthWidget(xLen/8))
|
||||
frontend.slaveNode connectButDontMonitorSlaves fg.node
|
||||
fg.node connectButDontMonitorSlaves ww.node
|
||||
ww.node connectButDontMonitorSlaves slaveNode
|
||||
|
||||
// 2) ScratchpadSlavePort always has a node, but only exists when the HellaCache has a scratchpad
|
||||
val scratch = tileParams.dcache.flatMap(d => d.scratch.map(s =>
|
||||
LazyModule(new ScratchpadSlavePort(AddressSet(s, d.dataScratchpadBytes-1)))))
|
||||
scratch foreach { lm => lm.node connectButDontMonitor TLFragmenter(xLen/8, p(CacheBlockBytes), earlyAck=true)(slaveNode) }
|
||||
|
||||
DisableMonitors { implicit p =>
|
||||
frontend.slaveNode :*= fg.node
|
||||
fg.node :*= ww.node
|
||||
ww.node :*= slaveNode
|
||||
scratch foreach { lm => lm.node := TLFragmenter(xLen/8, p(CacheBlockBytes), earlyAck=true)(slaveNode) }
|
||||
}
|
||||
|
||||
def findScratchpadFromICache: Option[AddressSet] = scratch.map { s =>
|
||||
val finalNode = frontend.masterNode.edgesOut.head.manager.managers.find(_.nodePath.last == s.node)
|
||||
|
@ -20,7 +20,8 @@ case class RocketTileParams(
|
||||
dataScratchpadBytes: Int = 0,
|
||||
boundaryBuffers: Boolean = false,
|
||||
name: Option[String] = Some("tile"),
|
||||
externalBuffers: Int = 0) extends TileParams {
|
||||
externalMasterBuffers: Int = 0,
|
||||
externalSlaveBuffers: Int = 0) extends TileParams {
|
||||
require(icache.isDefined)
|
||||
require(dcache.isDefined)
|
||||
}
|
||||
@ -190,7 +191,7 @@ abstract class RocketTileWrapper(rtp: RocketTileParams, hartid: Int)(implicit p:
|
||||
def optionalSlaveBuffer(in: TLOutwardNode): TLOutwardNode = {
|
||||
if (rtp.boundaryBuffers) {
|
||||
val sbuf = LazyModule(new TLBuffer(BufferParams.flow, BufferParams.none, BufferParams.none, BufferParams.none, BufferParams.none))
|
||||
sbuf.node connectButDontMonitorSlaves in
|
||||
DisableMonitors { implicit p => sbuf.node :*= in }
|
||||
sbuf.node
|
||||
} else {
|
||||
in
|
||||
@ -216,7 +217,7 @@ class SyncRocketTile(rtp: RocketTileParams, hartid: Int)(implicit p: Parameters)
|
||||
masterNode :=* optionalMasterBuffer(rocket.masterNode)
|
||||
|
||||
val slaveNode = new TLInputNode() { override def reverse = true }
|
||||
rocket.slaveNode connectButDontMonitorSlaves optionalSlaveBuffer(slaveNode)
|
||||
DisableMonitors { implicit p => rocket.slaveNode :*= optionalSlaveBuffer(slaveNode) }
|
||||
|
||||
// Fully async interrupts need synchronizers.
|
||||
// Others need no synchronization.
|
||||
@ -236,8 +237,11 @@ class AsyncRocketTile(rtp: RocketTileParams, hartid: Int)(implicit p: Parameters
|
||||
|
||||
val slaveNode = new TLAsyncInputNode() { override def reverse = true }
|
||||
val sink = LazyModule(new TLAsyncCrossingSink)
|
||||
rocket.slaveNode connectButDontMonitorSlaves sink.node
|
||||
sink.node connectButDontMonitorSlaves slaveNode
|
||||
|
||||
DisableMonitors { implicit p =>
|
||||
rocket.slaveNode :*= sink.node
|
||||
sink.node :*= slaveNode
|
||||
}
|
||||
|
||||
// Fully async interrupts need synchronizers,
|
||||
// as do those coming from the periphery clock.
|
||||
@ -260,8 +264,11 @@ class RationalRocketTile(rtp: RocketTileParams, hartid: Int)(implicit p: Paramet
|
||||
|
||||
val slaveNode = new TLRationalInputNode() { override def reverse = true }
|
||||
val sink = LazyModule(new TLRationalCrossingSink(SlowToFast))
|
||||
sink.node connectButDontMonitorSlaves slaveNode
|
||||
rocket.slaveNode connectButDontMonitorSlaves optionalSlaveBuffer(sink.node)
|
||||
|
||||
DisableMonitors { implicit p =>
|
||||
sink.node :*= slaveNode
|
||||
rocket.slaveNode :*= optionalSlaveBuffer(sink.node)
|
||||
}
|
||||
|
||||
// Fully async interrupts need synchronizers.
|
||||
// Those coming from periphery clock need a
|
||||
|
@ -80,7 +80,7 @@ object TLAsyncCrossingSource
|
||||
// applied to the TL source node; y.node := TLAsyncCrossingSource()(x.node)
|
||||
def apply(sync: Int = 3)(x: TLOutwardNode)(implicit p: Parameters, sourceInfo: SourceInfo): TLAsyncOutwardNode = {
|
||||
val source = LazyModule(new TLAsyncCrossingSource(sync))
|
||||
source.node := x
|
||||
source.node :=? x
|
||||
source.node
|
||||
}
|
||||
}
|
||||
@ -90,7 +90,7 @@ object TLAsyncCrossingSink
|
||||
// applied to the TL source node; y.node := TLAsyncCrossingSink()(x.node)
|
||||
def apply(depth: Int = 8, sync: Int = 3)(x: TLAsyncOutwardNode)(implicit p: Parameters, sourceInfo: SourceInfo): TLOutwardNode = {
|
||||
val sink = LazyModule(new TLAsyncCrossingSink(depth, sync))
|
||||
sink.node := x
|
||||
sink.node :=? x
|
||||
sink.node
|
||||
}
|
||||
}
|
||||
|
@ -265,7 +265,7 @@ object TLAtomicAutomata
|
||||
// applied to the TL source node; y.node := TLAtomicAutomata(x.node)
|
||||
def apply(logical: Boolean = true, arithmetic: Boolean = true, concurrency: Int = 1, passthrough: Boolean = true)(x: TLOutwardNode)(implicit p: Parameters, sourceInfo: SourceInfo): TLOutwardNode = {
|
||||
val atomics = LazyModule(new TLAtomicAutomata(logical, arithmetic, concurrency, passthrough))
|
||||
atomics.node := x
|
||||
atomics.node :=? x
|
||||
atomics.node
|
||||
}
|
||||
|
||||
|
@ -73,7 +73,7 @@ object TLBuffer
|
||||
d: BufferParams,
|
||||
e: BufferParams)(x: TLOutwardNode)(implicit p: Parameters, sourceInfo: SourceInfo): TLOutwardNode = {
|
||||
val buffer = LazyModule(new TLBuffer(a, b, c, d, e))
|
||||
buffer.node := x
|
||||
buffer.node :=? x
|
||||
buffer.node
|
||||
}
|
||||
}
|
||||
@ -82,18 +82,19 @@ class TLBufferChain(depth: Int)(implicit p: Parameters) extends LazyModule {
|
||||
|
||||
val nodeIn = TLInputNode()
|
||||
val nodeOut = TLOutputNode()
|
||||
val node = NodeHandle(nodeIn, nodeOut)
|
||||
|
||||
val buf_chain = if (depth > 0) {
|
||||
val chain = List.fill(depth)(LazyModule(new TLBuffer(BufferParams.default)))
|
||||
|
||||
(chain.init zip chain.tail) foreach { case(prev, next) => next.node :=* prev.node }
|
||||
(chain.init zip chain.tail) foreach { case(prev, next) => next.node :=? prev.node }
|
||||
chain
|
||||
} else {
|
||||
List(LazyModule(new TLBuffer(BufferParams.none)))
|
||||
}
|
||||
|
||||
buf_chain.head.node :=* nodeIn
|
||||
nodeOut :=* buf_chain.last.node
|
||||
buf_chain.head.node :=? nodeIn
|
||||
nodeOut :=? buf_chain.last.node
|
||||
|
||||
lazy val module = new LazyModuleImp(this) {
|
||||
val io = new Bundle {
|
||||
@ -102,3 +103,12 @@ class TLBufferChain(depth: Int)(implicit p: Parameters) extends LazyModule {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
object TLBufferChain
|
||||
{
|
||||
def apply(depth: Int)(x: TLOutwardNode)(implicit p: Parameters, sourceInfo: SourceInfo): TLOutwardNode = {
|
||||
val buffer = LazyModule(new TLBufferChain(depth))
|
||||
buffer.node :=? x
|
||||
buffer.node
|
||||
}
|
||||
}
|
||||
|
@ -68,26 +68,32 @@ abstract class TLBusWrapper(params: TLBusParams, val busName: String)(implicit p
|
||||
protected def inwardBufNode: TLInwardNode = master_buffer.node
|
||||
|
||||
protected def bufferChain(depth: Int, name: Option[String] = None): (TLInwardNode, TLOutwardNode) = {
|
||||
SourceCardinality { implicit p =>
|
||||
val chain = LazyModule(new TLBufferChain(depth))
|
||||
name.foreach { n => chain.suggestName(s"${busName}_${n}_TLBufferChain")}
|
||||
(chain.nodeIn, chain.nodeOut)
|
||||
}
|
||||
}
|
||||
|
||||
def bufferFromMasters: TLInwardNode = inwardBufNode
|
||||
|
||||
def bufferToSlaves: TLOutwardNode = outwardBufNode
|
||||
|
||||
def toAsyncSlaves(sync: Int = 3, name: Option[String] = None): TLAsyncOutwardNode = {
|
||||
def toSyncSlaves(name: Option[String] = None, addBuffers: Int = 0): TLOutwardNode = SinkCardinality { implicit p =>
|
||||
TLBufferChain(addBuffers)(outwardBufNode)
|
||||
}
|
||||
|
||||
def toAsyncSlaves(sync: Int = 3, name: Option[String] = None, addBuffers: Int = 0): TLAsyncOutwardNode = SinkCardinality { implicit p =>
|
||||
val source = LazyModule(new TLAsyncCrossingSource(sync))
|
||||
name.foreach{ n => source.suggestName(s"${busName}_${n}_TLAsyncCrossingSource")}
|
||||
source.node :*= outwardNode
|
||||
source.node :=? TLBufferChain(addBuffers)(outwardNode)
|
||||
source.node
|
||||
}
|
||||
|
||||
def toRationalSlaves(name: Option[String] = None): TLRationalOutwardNode = {
|
||||
def toRationalSlaves(name: Option[String] = None, addBuffers: Int = 0): TLRationalOutwardNode = SinkCardinality { implicit p =>
|
||||
val source = LazyModule(new TLRationalCrossingSource())
|
||||
name.foreach{ n => source.suggestName(s"${busName}_${n}_TLRationalCrossingSource")}
|
||||
source.node :*= outwardNode
|
||||
source.node :=? TLBufferChain(addBuffers)(outwardNode)
|
||||
source.node
|
||||
}
|
||||
|
||||
|
@ -131,7 +131,7 @@ object TLCacheCork
|
||||
// applied to the TL source node; y.node := TLCacheCork()(x.node)
|
||||
def apply(unsafe: Boolean = false)(x: TLOutwardNode)(implicit p: Parameters, sourceInfo: SourceInfo): TLOutwardNode = {
|
||||
val cork = LazyModule(new TLCacheCork(unsafe))
|
||||
cork.node := x
|
||||
cork.node :=? x
|
||||
cork.node
|
||||
}
|
||||
}
|
||||
|
@ -81,7 +81,7 @@ object TLDelayer
|
||||
// applied to the TL source node; y.node := TLDelayer(0.01)(x.node)
|
||||
def apply(q: Double)(x: TLOutwardNode)(implicit p: Parameters, sourceInfo: SourceInfo): TLOutwardNode = {
|
||||
val delayer = LazyModule(new TLDelayer(q))
|
||||
delayer.node := x
|
||||
delayer.node :=? x
|
||||
delayer.node
|
||||
}
|
||||
}
|
||||
|
@ -122,7 +122,7 @@ object TLFIFOFixer
|
||||
// applied to the TL source node; y.node := TLFIFOFixer()(x.node)
|
||||
def apply(policy: Policy = all)(x: TLOutwardNode)(implicit p: Parameters, sourceInfo: SourceInfo): TLOutwardNode = {
|
||||
val fixer = LazyModule(new TLFIFOFixer(policy))
|
||||
fixer.node := x
|
||||
fixer.node :=? x
|
||||
fixer.node
|
||||
}
|
||||
}
|
||||
|
@ -292,7 +292,7 @@ object TLFragmenter
|
||||
// applied to the TL source node; y.node := TLFragmenter(x.node, 256, 4)
|
||||
def apply(minSize: Int, maxSize: Int, alwaysMin: Boolean = false, earlyAck: Boolean = false)(x: TLOutwardNode)(implicit p: Parameters, sourceInfo: SourceInfo): TLOutwardNode = {
|
||||
val fragmenter = LazyModule(new TLFragmenter(minSize, maxSize, alwaysMin, earlyAck))
|
||||
fragmenter.node := x
|
||||
fragmenter.node :=? x
|
||||
fragmenter.node
|
||||
}
|
||||
}
|
||||
|
@ -100,7 +100,7 @@ object TLHintHandler
|
||||
// applied to the TL source node; y.node := TLHintHandler(x.node)
|
||||
def apply(supportManagers: Boolean = true, supportClients: Boolean = false, passthrough: Boolean = true)(x: TLOutwardNode)(implicit p: Parameters, sourceInfo: SourceInfo): TLOutwardNode = {
|
||||
val hints = LazyModule(new TLHintHandler(supportManagers, supportClients, passthrough))
|
||||
hints.node := x
|
||||
hints.node :=? x
|
||||
hints.node
|
||||
}
|
||||
}
|
||||
|
@ -79,7 +79,7 @@ object TLIsolation
|
||||
// **** WARNING: the isolation functions must bring the values to 0 ****
|
||||
def apply(fOut: (Bool, UInt) => UInt, fIn: (Bool, UInt) => UInt)(x: TLAsyncOutwardNode)(implicit p: Parameters, sourceInfo: SourceInfo): (TLAsyncOutwardNode, () => (Bool, Bool)) = {
|
||||
val iso = LazyModule(new TLIsolation(fOut, fIn))
|
||||
iso.node := x
|
||||
iso.node :=? x
|
||||
(iso.node, () => (iso.module.io.iso_out, iso.module.io.iso_in))
|
||||
}
|
||||
}
|
||||
|
@ -48,7 +48,7 @@ object TLMap
|
||||
// applied to the TL source node; y.node := TLMap(fn)(x.node)
|
||||
def apply(fn: AddressSet => BigInt)(x: TLOutwardNode)(implicit p: Parameters, sourceInfo: SourceInfo): TLOutwardNode = {
|
||||
val map = LazyModule(new TLMap(fn))
|
||||
map.node := x
|
||||
map.node :=? x
|
||||
map.node
|
||||
}
|
||||
}
|
||||
|
@ -67,7 +67,7 @@ object TLNodeNumberer
|
||||
// applied to the TL source node; y.node := TLBuffer(x.node)
|
||||
def apply(nodeAddressOffset: Option[Int] = None)(x: TLOutwardNode)(implicit p: Parameters, sourceInfo: SourceInfo): TLOutwardNode = {
|
||||
val numberer = LazyModule(new TLNodeNumberer(nodeAddressOffset))
|
||||
numberer.node := x
|
||||
numberer.node :=? x
|
||||
numberer.node
|
||||
}
|
||||
}
|
||||
|
@ -9,8 +9,8 @@ import freechips.rocketchip.diplomacy._
|
||||
import freechips.rocketchip.util.RationalDirection
|
||||
import scala.collection.mutable.ListBuffer
|
||||
|
||||
case object TLMonitorBuilder extends Field[TLMonitorArgs => Option[TLMonitorBase]]
|
||||
case object TLCombinationalCheck extends Field[Boolean]
|
||||
case object TLMonitorBuilder extends Field[TLMonitorArgs => TLMonitorBase](args => LazyModule(new TLMonitor(args)))
|
||||
case object TLCombinationalCheck extends Field[Boolean](false)
|
||||
|
||||
object TLImp extends NodeImp[TLClientPortParameters, TLManagerPortParameters, TLEdgeOut, TLEdgeIn, TLBundle]
|
||||
{
|
||||
@ -26,7 +26,7 @@ object TLImp extends NodeImp[TLClientPortParameters, TLManagerPortParameters, TL
|
||||
|
||||
override def connect(edges: () => Seq[TLEdgeIn], bundles: () => Seq[(TLBundle, TLBundle)], enableMonitoring: Boolean)
|
||||
(implicit p: Parameters, sourceInfo: SourceInfo): (Option[TLMonitorBase], () => Unit) = {
|
||||
val monitor = if (enableMonitoring) p(TLMonitorBuilder)(TLMonitorArgs(edges, sourceInfo, p)) else None
|
||||
val monitor = if (enableMonitoring) Some(p(TLMonitorBuilder)(TLMonitorArgs(edges, sourceInfo, p))) else None
|
||||
(monitor, () => {
|
||||
val eval = bundles ()
|
||||
monitor.foreach { m => (eval zip m.module.io.in) foreach { case ((i,o), m) => m := TLBundleSnoop(o,i) } }
|
||||
|
@ -92,7 +92,7 @@ object TLRationalCrossingSource
|
||||
// applied to the TL source node; y.node := TLRationalCrossingSource()(x.node)
|
||||
def apply()(x: TLOutwardNode)(implicit p: Parameters, sourceInfo: SourceInfo): TLRationalOutwardNode = {
|
||||
val source = LazyModule(new TLRationalCrossingSource)
|
||||
source.node := x
|
||||
source.node :=? x
|
||||
source.node
|
||||
}
|
||||
}
|
||||
@ -102,7 +102,7 @@ object TLRationalCrossingSink
|
||||
// applied to the TL source node; y.node := TLRationalCrossingSink()(x.node)
|
||||
def apply(direction: RationalDirection = Symmetric)(x: TLRationalOutwardNode)(implicit p: Parameters, sourceInfo: SourceInfo): TLOutwardNode = {
|
||||
val sink = LazyModule(new TLRationalCrossingSink(direction))
|
||||
sink.node := x
|
||||
sink.node :=? x
|
||||
sink.node
|
||||
}
|
||||
}
|
||||
|
@ -83,7 +83,7 @@ object TLSourceShrinker
|
||||
// applied to the TL source node; y.node := TLSourceShrinker(n)(x.node)
|
||||
def apply(maxInFlight: Int)(x: TLOutwardNode)(implicit p: Parameters, sourceInfo: SourceInfo): TLOutwardNode = {
|
||||
val shrinker = LazyModule(new TLSourceShrinker(maxInFlight))
|
||||
shrinker.node := x
|
||||
shrinker.node :=? x
|
||||
shrinker.node
|
||||
}
|
||||
}
|
||||
|
@ -195,7 +195,7 @@ object TLToAHB
|
||||
// applied to the TL source node; y.node := TLToAHB()(x.node)
|
||||
def apply(aFlow: Boolean = true)(x: TLOutwardNode)(implicit p: Parameters, sourceInfo: SourceInfo): AHBOutwardNode = {
|
||||
val ahb = LazyModule(new TLToAHB(aFlow))
|
||||
ahb.node := x
|
||||
ahb.node :=? x
|
||||
ahb.node
|
||||
}
|
||||
}
|
||||
|
@ -94,7 +94,7 @@ object TLToAPB
|
||||
// applied to the TL source node; y.node := TLToAPB()(x.node)
|
||||
def apply(aFlow: Boolean = true)(x: TLOutwardNode)(implicit p: Parameters, sourceInfo: SourceInfo): APBOutwardNode = {
|
||||
val apb = LazyModule(new TLToAPB(aFlow))
|
||||
apb.node := x
|
||||
apb.node :=? x
|
||||
apb.node
|
||||
}
|
||||
}
|
||||
|
@ -223,7 +223,7 @@ object TLToAXI4
|
||||
// applied to the TL source node; y.node := TLToAXI4(beatBytes)(x.node)
|
||||
def apply(beatBytes: Int, combinational: Boolean = true, adapterName: Option[String] = None, stripBits: Int = 0)(x: TLOutwardNode)(implicit p: Parameters, sourceInfo: SourceInfo): AXI4OutwardNode = {
|
||||
val axi4 = LazyModule(new TLToAXI4(beatBytes, combinational, adapterName, stripBits))
|
||||
axi4.node := x
|
||||
axi4.node :=? x
|
||||
axi4.node
|
||||
}
|
||||
|
||||
|
@ -200,7 +200,7 @@ object TLWidthWidget
|
||||
// applied to the TL source node; y.node := WidthWidget(x.node, 16)
|
||||
def apply(innerBeatBytes: Int)(x: TLOutwardNode)(implicit p: Parameters, sourceInfo: SourceInfo): TLOutwardNode = {
|
||||
val widget = LazyModule(new TLWidthWidget(innerBeatBytes))
|
||||
widget.node := x
|
||||
widget.node :=? x
|
||||
widget.node
|
||||
}
|
||||
}
|
||||
|
@ -3,9 +3,31 @@
|
||||
package freechips.rocketchip.tilelink
|
||||
|
||||
import Chisel._
|
||||
import freechips.rocketchip.config.Parameters
|
||||
import freechips.rocketchip.config._
|
||||
import freechips.rocketchip.diplomacy._
|
||||
|
||||
// Trades off slave port proximity against routing resource cost
|
||||
object ForceFanout
|
||||
{
|
||||
def apply[T](
|
||||
a: TriStateValue = TriStateValue.unset,
|
||||
b: TriStateValue = TriStateValue.unset,
|
||||
c: TriStateValue = TriStateValue.unset,
|
||||
d: TriStateValue = TriStateValue.unset,
|
||||
e: TriStateValue = TriStateValue.unset)(body: Parameters => T)(implicit p: Parameters) =
|
||||
{
|
||||
body(p.alterPartial {
|
||||
case ForceFanoutKey => p(ForceFanoutKey) match {
|
||||
case ForceFanoutParams(pa, pb, pc, pd, pe) =>
|
||||
ForceFanoutParams(a.update(pa), b.update(pb), c.update(pc), d.update(pd), e.update(pe))
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
private case class ForceFanoutParams(a: Boolean, b: Boolean, c: Boolean, d: Boolean, e: Boolean)
|
||||
private case object ForceFanoutKey extends Field(ForceFanoutParams(false, false, false, false, false))
|
||||
|
||||
class TLXbar(policy: TLArbiter.Policy = TLArbiter.roundRobin)(implicit p: Parameters) extends LazyModule
|
||||
{
|
||||
val node = TLNexusNode(
|
||||
@ -157,11 +179,11 @@ class TLXbar(policy: TLArbiter.Policy = TLArbiter.roundRobin)(implicit p: Parame
|
||||
def filter[T](data: Seq[T], mask: Seq[Boolean]) = (data zip mask).filter(_._2).map(_._1)
|
||||
|
||||
// Fanout the input sources to the output sinks
|
||||
val portsAOI = transpose((in zip requestAIO) map { case (i, r) => TLXbar.fanout(i.a, r) })
|
||||
val portsBIO = transpose((out zip requestBOI) map { case (o, r) => TLXbar.fanout(o.b, r) })
|
||||
val portsCOI = transpose((in zip requestCIO) map { case (i, r) => TLXbar.fanout(i.c, r) })
|
||||
val portsDIO = transpose((out zip requestDOI) map { case (o, r) => TLXbar.fanout(o.d, r) })
|
||||
val portsEOI = transpose((in zip requestEIO) map { case (i, r) => TLXbar.fanout(i.e, r) })
|
||||
val portsAOI = transpose((in zip requestAIO) map { case (i, r) => TLXbar.fanout(i.a, r, node.paramsOut.map(_(ForceFanoutKey).a)) })
|
||||
val portsBIO = transpose((out zip requestBOI) map { case (o, r) => TLXbar.fanout(o.b, r, node.paramsIn .map(_(ForceFanoutKey).b)) })
|
||||
val portsCOI = transpose((in zip requestCIO) map { case (i, r) => TLXbar.fanout(i.c, r, node.paramsOut.map(_(ForceFanoutKey).c)) })
|
||||
val portsDIO = transpose((out zip requestDOI) map { case (o, r) => TLXbar.fanout(o.d, r, node.paramsIn .map(_(ForceFanoutKey).d)) })
|
||||
val portsEOI = transpose((in zip requestEIO) map { case (i, r) => TLXbar.fanout(i.e, r, node.paramsOut.map(_(ForceFanoutKey).e)) })
|
||||
|
||||
// Arbitrate amongst the sources
|
||||
for (o <- 0 until out.size) {
|
||||
@ -216,10 +238,10 @@ object TLXbar
|
||||
}
|
||||
|
||||
// Replicate an input port to each output port
|
||||
def fanout[T <: TLChannel](input: DecoupledIO[T], select: Seq[Bool]) = {
|
||||
def fanout[T <: TLChannel](input: DecoupledIO[T], select: Seq[Bool], force: Seq[Boolean] = Nil) = {
|
||||
val filtered = Wire(Vec(select.size, input))
|
||||
for (i <- 0 until select.size) {
|
||||
filtered(i).bits := input.bits
|
||||
filtered(i).bits := (if (force.lift(i).getOrElse(false)) IdentityModule(input.bits) else input.bits)
|
||||
filtered(i).valid := input.valid && select(i)
|
||||
}
|
||||
input.ready := Mux1H(select, filtered.map(_.ready))
|
||||
|
24
src/main/scala/util/IdentityModule.scala
Normal file
24
src/main/scala/util/IdentityModule.scala
Normal file
@ -0,0 +1,24 @@
|
||||
// See LICENSE.SiFive for license details.
|
||||
|
||||
package freechips.rocketchip.tilelink
|
||||
|
||||
import Chisel._
|
||||
|
||||
class IdentityModule[T <: Data](gen: T) extends Module
|
||||
{
|
||||
val io = new Bundle {
|
||||
val in = gen.cloneType.flip
|
||||
val out = gen.cloneType
|
||||
}
|
||||
|
||||
io.out := io.in
|
||||
}
|
||||
|
||||
object IdentityModule
|
||||
{
|
||||
def apply[T <: Data](x: T): T = {
|
||||
val identity = Module(new IdentityModule(x))
|
||||
identity.io.in := x
|
||||
identity.io.out
|
||||
}
|
||||
}
|
@ -73,10 +73,10 @@ class RationalCrossingSource[T <: Data](gen: T, direction: RationalDirection = S
|
||||
|
||||
val deq = io.deq
|
||||
val enq = direction match {
|
||||
case Symmetric => Queue(io.enq, 1, flow=true)
|
||||
case Flexible => Queue(io.enq, 2)
|
||||
case Symmetric => ShiftQueue(io.enq, 1, flow=true)
|
||||
case Flexible => ShiftQueue(io.enq, 2)
|
||||
case FastToSlow => io.enq
|
||||
case SlowToFast => Queue(io.enq, 2)
|
||||
case SlowToFast => ShiftQueue(io.enq, 2)
|
||||
}
|
||||
|
||||
val count = RegInit(UInt(0, width = 2))
|
||||
@ -109,9 +109,9 @@ class RationalCrossingSink[T <: Data](gen: T, direction: RationalDirection = Sym
|
||||
val enq = io.enq
|
||||
val deq = Wire(io.deq)
|
||||
direction match {
|
||||
case Symmetric => io.deq <> Queue(deq, 1, pipe=true)
|
||||
case Flexible => io.deq <> Queue(deq, 2)
|
||||
case FastToSlow => io.deq <> Queue(deq, 2)
|
||||
case Symmetric => io.deq <> ShiftQueue(deq, 1, pipe=true)
|
||||
case Flexible => io.deq <> ShiftQueue(deq, 2)
|
||||
case FastToSlow => io.deq <> ShiftQueue(deq, 2)
|
||||
case SlowToFast => io.deq <> deq
|
||||
}
|
||||
|
||||
|
@ -26,7 +26,7 @@ class ShiftQueue[T <: Data](gen: T,
|
||||
val wdata = if (i == entries-1) io.enq.bits else Mux(valid(i+1), elts(i+1), io.enq.bits)
|
||||
val wen =
|
||||
Mux(io.deq.ready,
|
||||
paddedValid(i+1) || io.enq.fire() && valid(i),
|
||||
paddedValid(i+1) || io.enq.fire() && (Bool(i == 0 && !flow) || valid(i)),
|
||||
io.enq.fire() && paddedValid(i-1) && !valid(i))
|
||||
when (wen) { elts(i) := wdata }
|
||||
|
||||
@ -52,3 +52,12 @@ class ShiftQueue[T <: Data](gen: T,
|
||||
io.mask := valid.asUInt
|
||||
io.count := PopCount(io.mask)
|
||||
}
|
||||
|
||||
object ShiftQueue
|
||||
{
|
||||
def apply[T <: Data](enq: DecoupledIO[T], entries: Int = 2, pipe: Boolean = false, flow: Boolean = false): DecoupledIO[T] = {
|
||||
val q = Module(new ShiftQueue(enq.bits.cloneType, entries, pipe, flow))
|
||||
q.io.enq <> enq
|
||||
q.io.deq
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user