Merge pull request #985 from freechipsproject/flop-interrupts
Add Parameters to diplomatic edges
This commit is contained in:
		@@ -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
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user