1
0

Merge pull request #985 from freechipsproject/flop-interrupts

Add Parameters to diplomatic edges
This commit is contained in:
Wesley W. Terpstra 2017-09-08 13:16:11 -07:00 committed by GitHub
commit e7de7f3e82
42 changed files with 271 additions and 127 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

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

View File

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

View File

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