Merge pull request #993 from freechipsproject/auto-diplomacy-bundles
Auto diplomacy bundles
This commit is contained in:
		
							
								
								
									
										23
									
								
								macros/src/main/scala/ValName.scala
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								macros/src/main/scala/ValName.scala
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,23 @@ | ||||
| // See LICENSE.SiFive for license details. | ||||
|  | ||||
| package freechips.rocketchip.macros | ||||
|  | ||||
| import scala.language.experimental.macros | ||||
| import scala.reflect.macros.blackbox.Context | ||||
|  | ||||
| case class ValNameImpl(name: String) | ||||
|  | ||||
| object ValNameImpl | ||||
| { | ||||
|   implicit def materialize: ValNameImpl = macro detail | ||||
|   def detail(c: Context): c.Expr[ValNameImpl] = { | ||||
|     import c.universe._ | ||||
|     def allOwners(s: c.Symbol): Seq[c.Symbol] = | ||||
|       if (s == `NoSymbol`) Nil else s +: allOwners(s.owner) | ||||
|     val terms = allOwners(c.internal.enclosingOwner).filter(_.isTerm).map(_.asTerm) | ||||
|     terms.filter(_.isVal).map(_.name.toString).find(_(0) != '$').map { s => | ||||
|       val trim = s.replaceAll("\\s", "") | ||||
|       c.Expr[ValNameImpl] { q"_root_.freechips.rocketchip.macros.ValNameImpl(${trim})" } | ||||
|     }.getOrElse(c.abort(c.enclosingPosition, "Not a valid application.")) | ||||
|   } | ||||
| } | ||||
| @@ -21,7 +21,8 @@ object BuildSettings extends Build { | ||||
|  | ||||
|   lazy val chisel = project in file("chisel3") | ||||
|   lazy val hardfloat  = project.dependsOn(chisel) | ||||
|   lazy val rocketchip = (project in file(".")).settings(chipSettings).dependsOn(chisel, hardfloat) | ||||
|   lazy val macros = project in file("macros") | ||||
|   lazy val rocketchip = (project in file(".")).settings(chipSettings).dependsOn(chisel, hardfloat, macros) | ||||
|  | ||||
|   lazy val addons = settingKey[Seq[String]]("list of addons used for this build") | ||||
|   lazy val make = inputKey[Unit]("trigger backend-specific makefile command") | ||||
|   | ||||
| @@ -4,19 +4,14 @@ package freechips.rocketchip.amba.ahb | ||||
|  | ||||
| import Chisel._ | ||||
| import chisel3.internal.sourceinfo.SourceInfo | ||||
| import freechips.rocketchip.config.Parameters | ||||
| import freechips.rocketchip.diplomacy._ | ||||
|  | ||||
| object AHBImp extends NodeImp[AHBMasterPortParameters, AHBSlavePortParameters, AHBEdgeParameters, AHBEdgeParameters, AHBBundle] | ||||
| object AHBImp extends SimpleNodeImp[AHBMasterPortParameters, AHBSlavePortParameters, AHBEdgeParameters, AHBBundle] | ||||
| { | ||||
|   def edgeO(pd: AHBMasterPortParameters, pu: AHBSlavePortParameters): AHBEdgeParameters = AHBEdgeParameters(pd, pu) | ||||
|   def edgeI(pd: AHBMasterPortParameters, pu: AHBSlavePortParameters): AHBEdgeParameters = AHBEdgeParameters(pd, pu) | ||||
|  | ||||
|   def bundleO(eo: AHBEdgeParameters): AHBBundle = AHBBundle(eo.bundle) | ||||
|   def bundleI(ei: AHBEdgeParameters): AHBBundle = AHBBundle(ei.bundle) | ||||
|  | ||||
|   def colour = "#00ccff" // bluish | ||||
|   override def labelI(ei: AHBEdgeParameters) = (ei.slave.beatBytes * 8).toString | ||||
|   override def labelO(eo: AHBEdgeParameters) = (eo.slave.beatBytes * 8).toString | ||||
|   def edge(pd: AHBMasterPortParameters, pu: AHBSlavePortParameters, p: Parameters, sourceInfo: SourceInfo) = AHBEdgeParameters(pd, pu, p, sourceInfo) | ||||
|   def bundle(e: AHBEdgeParameters) = AHBBundle(e.bundle) | ||||
|   def render(e: AHBEdgeParameters) = RenderedEdge(colour = "#00ccff" /* bluish */, label = (e.slave.beatBytes * 8).toString) | ||||
|  | ||||
|   override def mixO(pd: AHBMasterPortParameters, node: OutwardNode[AHBMasterPortParameters, AHBSlavePortParameters, AHBBundle]): AHBMasterPortParameters  = | ||||
|    pd.copy(masters = pd.masters.map  { c => c.copy (nodePath = node +: c.nodePath) }) | ||||
| @@ -25,23 +20,14 @@ object AHBImp extends NodeImp[AHBMasterPortParameters, AHBSlavePortParameters, A | ||||
| } | ||||
|  | ||||
| // Nodes implemented inside modules | ||||
| case class AHBIdentityNode() extends IdentityNode(AHBImp) | ||||
| case class AHBMasterNode(portParams: Seq[AHBMasterPortParameters]) extends SourceNode(AHBImp)(portParams) | ||||
| case class AHBSlaveNode(portParams: Seq[AHBSlavePortParameters]) extends SinkNode(AHBImp)(portParams) | ||||
| case class AHBMasterNode(portParams: Seq[AHBMasterPortParameters])(implicit valName: ValName) extends SourceNode(AHBImp)(portParams) | ||||
| case class AHBSlaveNode(portParams: Seq[AHBSlavePortParameters])(implicit valName: ValName) extends SinkNode(AHBImp)(portParams) | ||||
| case class AHBNexusNode( | ||||
|   masterFn:       Seq[AHBMasterPortParameters] => AHBMasterPortParameters, | ||||
|   slaveFn:        Seq[AHBSlavePortParameters]  => AHBSlavePortParameters, | ||||
|   numMasterPorts: Range.Inclusive = 1 to 999, | ||||
|   numSlavePorts:  Range.Inclusive = 1 to 999) | ||||
|   numSlavePorts:  Range.Inclusive = 1 to 999)( | ||||
|   implicit valName: ValName) | ||||
|   extends NexusNode(AHBImp)(masterFn, slaveFn, numMasterPorts, numSlavePorts) | ||||
|  | ||||
| // Nodes passed from an inner module | ||||
| case class AHBOutputNode() extends OutputNode(AHBImp) | ||||
| case class AHBInputNode() extends InputNode(AHBImp) | ||||
|  | ||||
| // Nodes used for external ports | ||||
| case class AHBBlindOutputNode(portParams: Seq[AHBSlavePortParameters]) extends BlindOutputNode(AHBImp)(portParams) | ||||
| case class AHBBlindInputNode(portParams: Seq[AHBMasterPortParameters]) extends BlindInputNode(AHBImp)(portParams) | ||||
|  | ||||
| case class AHBInternalOutputNode(portParams: Seq[AHBSlavePortParameters]) extends InternalOutputNode(AHBImp)(portParams) | ||||
| case class AHBInternalInputNode(portParams: Seq[AHBMasterPortParameters]) extends InternalInputNode(AHBImp)(portParams) | ||||
| case class AHBIdentityNode()(implicit valName: ValName) extends IdentityNode(AHBImp)() | ||||
|   | ||||
| @@ -3,6 +3,8 @@ | ||||
| package freechips.rocketchip.amba.ahb | ||||
|  | ||||
| import Chisel._ | ||||
| import chisel3.internal.sourceinfo.SourceInfo | ||||
| import freechips.rocketchip.config.Parameters | ||||
| import freechips.rocketchip.diplomacy._ | ||||
| import scala.math.max | ||||
|  | ||||
| @@ -90,7 +92,9 @@ object AHBBundleParameters | ||||
|  | ||||
| case class AHBEdgeParameters( | ||||
|   master: AHBMasterPortParameters, | ||||
|   slave:  AHBSlavePortParameters) | ||||
|   slave:  AHBSlavePortParameters, | ||||
|   params: Parameters, | ||||
|   sourceInfo: SourceInfo) | ||||
| { | ||||
|   val bundle = AHBBundleParameters(master, slave) | ||||
| } | ||||
|   | ||||
| @@ -10,8 +10,8 @@ import freechips.rocketchip.tilelink.{IntSourceNode, IntSourcePortSimple} | ||||
| import freechips.rocketchip.util.{HeterogeneousBag, MaskGen} | ||||
| import scala.math.{min,max} | ||||
|  | ||||
| class AHBRegisterNode(address: AddressSet, concurrency: Int = 0, beatBytes: Int = 4, undefZero: Boolean = true, executable: Boolean = false) | ||||
|   extends AHBSlaveNode(Seq(AHBSlavePortParameters( | ||||
| case class AHBRegisterNode(address: AddressSet, concurrency: Int = 0, beatBytes: Int = 4, undefZero: Boolean = true, executable: Boolean = false)(implicit valName: ValName) | ||||
|   extends SinkNode(AHBImp)(Seq(AHBSlavePortParameters( | ||||
|     Seq(AHBSlaveParameters( | ||||
|       address       = Seq(address), | ||||
|       executable    = executable, | ||||
| @@ -24,7 +24,7 @@ class AHBRegisterNode(address: AddressSet, concurrency: Int = 0, beatBytes: Int | ||||
|   // Calling this method causes the matching AHB bundle to be | ||||
|   // configured to route all requests to the listed RegFields. | ||||
|   def regmap(mapping: RegField.Map*) = { | ||||
|     val ahb = bundleIn(0) | ||||
|     val (ahb, _) = this.in(0) | ||||
|  | ||||
|     val indexBits = log2Up((address.mask+1)/beatBytes) | ||||
|     val params = RegMapperParams(indexBits, beatBytes, 1) | ||||
| @@ -67,12 +67,6 @@ class AHBRegisterNode(address: AddressSet, concurrency: Int = 0, beatBytes: Int | ||||
|   } | ||||
| } | ||||
|  | ||||
| object AHBRegisterNode | ||||
| { | ||||
|   def apply(address: AddressSet, concurrency: Int = 0, beatBytes: Int = 4, undefZero: Boolean = true, executable: Boolean = false) = | ||||
|     new AHBRegisterNode(address, concurrency, beatBytes, undefZero, executable) | ||||
| } | ||||
|  | ||||
| // These convenience methods below combine to make it possible to create a AHB | ||||
| // register mapped device from a totally abstract register mapped device. | ||||
|  | ||||
| @@ -82,13 +76,11 @@ abstract class AHBRegisterRouterBase(address: AddressSet, interrupts: Int, concu | ||||
|   val intnode = IntSourceNode(IntSourcePortSimple(num = interrupts)) | ||||
| } | ||||
|  | ||||
| case class AHBRegBundleArg(interrupts: HeterogeneousBag[Vec[Bool]], in: HeterogeneousBag[AHBBundle])(implicit val p: Parameters) | ||||
| case class AHBRegBundleArg()(implicit val p: Parameters) | ||||
|  | ||||
| class AHBRegBundleBase(arg: AHBRegBundleArg) extends Bundle | ||||
| { | ||||
|   implicit val p = arg.p | ||||
|   val interrupts = arg.interrupts | ||||
|   val in = arg.in | ||||
| } | ||||
|  | ||||
| class AHBRegBundle[P](val params: P, arg: AHBRegBundleArg) extends AHBRegBundleBase(arg) | ||||
| @@ -96,8 +88,8 @@ class AHBRegBundle[P](val params: P, arg: AHBRegBundleArg) extends AHBRegBundleB | ||||
| class AHBRegModule[P, B <: AHBRegBundleBase](val params: P, bundleBuilder: => B, router: AHBRegisterRouterBase) | ||||
|   extends LazyModuleImp(router) with HasRegMap | ||||
| { | ||||
|   val io = bundleBuilder | ||||
|   val interrupts = if (io.interrupts.isEmpty) Vec(0, Bool()) else io.interrupts(0) | ||||
|   val io = IO(bundleBuilder) | ||||
|   val interrupts = if (router.intnode.out.isEmpty) Vec(0, Bool()) else router.intnode.out(0)._1 | ||||
|   def regmap(mapping: RegField.Map*) = router.node.regmap(mapping:_*) | ||||
| } | ||||
|  | ||||
| @@ -110,5 +102,5 @@ class AHBRegisterRouter[B <: AHBRegBundleBase, M <: LazyModuleImp] | ||||
|   require (isPow2(size)) | ||||
|   // require (size >= 4096) ... not absolutely required, but highly recommended | ||||
|  | ||||
|   lazy val module = moduleBuilder(bundleBuilder(AHBRegBundleArg(intnode.bundleOut, node.bundleIn)), this) | ||||
|   lazy val module = moduleBuilder(bundleBuilder(AHBRegBundleArg()), this) | ||||
| } | ||||
|   | ||||
| @@ -22,15 +22,11 @@ class AHBRAM(address: AddressSet, executable: Boolean = true, beatBytes: Int = 4 | ||||
|   require ((address.mask & (beatBytes-1)) == beatBytes-1) | ||||
|  | ||||
|   lazy val module = new LazyModuleImp(this) { | ||||
|     val io = new Bundle { | ||||
|       val in = node.bundleIn | ||||
|     } | ||||
|  | ||||
|     def bigBits(x: BigInt, tail: List[Boolean] = List.empty[Boolean]): List[Boolean] = | ||||
|       if (x == 0) tail.reverse else bigBits(x >> 1, ((x & 1) == 1) :: tail) | ||||
|     val mask = bigBits(address.mask >> log2Ceil(beatBytes)) | ||||
|  | ||||
|     val in = io.in(0) | ||||
|     val (in, _) = node.in(0) | ||||
|  | ||||
|     // The mask and address during the address phase | ||||
|     val a_access    = in.htrans === AHBParameters.TRANS_NONSEQ || in.htrans === AHBParameters.TRANS_SEQ | ||||
|   | ||||
| @@ -21,7 +21,7 @@ class AHBFuzzNative(aFlow: Boolean, txns: Int)(implicit p: Parameters) extends L | ||||
| { | ||||
|   val fuzz  = LazyModule(new TLFuzzer(txns)) | ||||
|   val model = LazyModule(new TLRAMModel("AHBFuzzNative")) | ||||
|   var xbar  = LazyModule(new AHBFanout) | ||||
|   val xbar  = LazyModule(new AHBFanout) | ||||
|   val ram   = LazyModule(new AHBRAM(AddressSet(0x0, 0xff))) | ||||
|   val gpio  = LazyModule(new RRTest0(0x100)) | ||||
|  | ||||
| @@ -30,7 +30,7 @@ class AHBFuzzNative(aFlow: Boolean, txns: Int)(implicit p: Parameters) extends L | ||||
|   ram.node  := xbar.node | ||||
|   gpio.node := xbar.node | ||||
|  | ||||
|   lazy val module = new LazyModuleImp(this) with HasUnitTestIO { | ||||
|   lazy val module = new LazyModuleImp(this) with UnitTestModule { | ||||
|     io.finished := fuzz.module.io.finished | ||||
|   } | ||||
| } | ||||
| @@ -42,7 +42,7 @@ class AHBNativeTest(aFlow: Boolean, txns: Int = 5000, timeout: Int = 500000)(imp | ||||
|  | ||||
| class AHBFuzzMaster(aFlow: Boolean, txns: Int)(implicit p: Parameters) extends LazyModule | ||||
| { | ||||
|   val node  = AHBOutputNode() | ||||
|   val node  = AHBIdentityNode() | ||||
|   val fuzz  = LazyModule(new TLFuzzer(txns)) | ||||
|   val model = LazyModule(new TLRAMModel("AHBFuzzMaster")) | ||||
|  | ||||
| @@ -55,10 +55,9 @@ class AHBFuzzMaster(aFlow: Boolean, txns: Int)(implicit p: Parameters) extends L | ||||
|     model.node)))) | ||||
|  | ||||
|   lazy val module = new LazyModuleImp(this) { | ||||
|     val io = new Bundle { | ||||
|       val out = node.bundleOut | ||||
|     val io = IO(new Bundle { | ||||
|       val finished = Bool(OUTPUT) | ||||
|     } | ||||
|     }) | ||||
|  | ||||
|     io.finished := fuzz.module.io.finished | ||||
|   } | ||||
| @@ -66,7 +65,7 @@ class AHBFuzzMaster(aFlow: Boolean, txns: Int)(implicit p: Parameters) extends L | ||||
|  | ||||
| class AHBFuzzSlave()(implicit p: Parameters) extends LazyModule | ||||
| { | ||||
|   val node = AHBInputNode() | ||||
|   val node = AHBIdentityNode() | ||||
|   val ram  = LazyModule(new TLTestRAM(AddressSet(0x0, 0xfff))) | ||||
|  | ||||
|   ram.node := | ||||
| @@ -77,11 +76,7 @@ class AHBFuzzSlave()(implicit p: Parameters) extends LazyModule | ||||
|     AHBToTL()( | ||||
|     node))))) | ||||
|  | ||||
|   lazy val module = new LazyModuleImp(this) { | ||||
|     val io = new Bundle { | ||||
|       val in = node.bundleIn | ||||
|     } | ||||
|   } | ||||
|   lazy val module = new LazyModuleImp(this) { } | ||||
| } | ||||
|  | ||||
| class AHBFuzzBridge(aFlow: Boolean, txns: Int)(implicit p: Parameters) extends LazyModule | ||||
| @@ -91,7 +86,7 @@ class AHBFuzzBridge(aFlow: Boolean, txns: Int)(implicit p: Parameters) extends L | ||||
|  | ||||
|   slave.node := master.node | ||||
|  | ||||
|   lazy val module = new LazyModuleImp(this) with HasUnitTestIO { | ||||
|   lazy val module = new LazyModuleImp(this) with UnitTestModule { | ||||
|     io.finished := master.module.io.finished | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -9,7 +9,7 @@ import freechips.rocketchip.diplomacy._ | ||||
| import freechips.rocketchip.tilelink._ | ||||
| import freechips.rocketchip.util.MaskGen | ||||
|  | ||||
| case class AHBToTLNode() extends MixedAdapterNode(AHBImp, TLImp)( | ||||
| case class AHBToTLNode()(implicit valName: ValName) extends MixedAdapterNode(AHBImp, TLImp)( | ||||
|   dFn = { case AHBMasterPortParameters(masters) => | ||||
|     TLClientPortParameters(clients = masters.map { m => | ||||
|       TLClientParameters(name = m.name, nodePath = m.nodePath) | ||||
| @@ -41,12 +41,7 @@ class AHBToTL()(implicit p: Parameters) extends LazyModule | ||||
|   val node = AHBToTLNode() | ||||
|  | ||||
|   lazy val module = new LazyModuleImp(this) { | ||||
|     val io = new Bundle { | ||||
|       val in = node.bundleIn | ||||
|       val out = node.bundleOut | ||||
|     } | ||||
|  | ||||
|     ((io.in zip io.out) zip (node.edgesIn zip node.edgesOut)) foreach { case ((in, out), (edgeIn, edgeOut)) => | ||||
|     (node.in zip node.out) foreach { case ((in, edgeIn), (out, edgeOut)) => | ||||
|       val beatBytes = edgeOut.manager.beatBytes | ||||
|  | ||||
|       val d_send  = RegInit(Bool(false)) | ||||
|   | ||||
| @@ -16,35 +16,31 @@ class AHBFanout()(implicit p: Parameters) extends LazyModule { | ||||
|     slaveFn  = { seq => seq(0).copy(slaves = seq.flatMap(_.slaves)) }) | ||||
|  | ||||
|   lazy val module = new LazyModuleImp(this) { | ||||
|     val io = new Bundle { | ||||
|       val in = node.bundleIn | ||||
|       val out = node.bundleOut | ||||
|     } | ||||
|  | ||||
|     // Require consistent bus widths | ||||
|     val port0 = node.edgesOut(0).slave | ||||
|     node.edgesOut.foreach { edge => | ||||
|     val (io_out, edgesOut) = node.out.unzip | ||||
|     val port0 = edgesOut(0).slave | ||||
|     edgesOut.foreach { edge => | ||||
|       val port = edge.slave | ||||
|       require (port.beatBytes == port0.beatBytes, | ||||
|         s"${port.slaves.map(_.name)} ${port.beatBytes} vs ${port0.slaves.map(_.name)} ${port0.beatBytes}") | ||||
|     } | ||||
|  | ||||
|     val port_addrs = node.edgesOut.map(_.slave.slaves.map(_.address).flatten) | ||||
|     val port_addrs = edgesOut.map(_.slave.slaves.map(_.address).flatten) | ||||
|     val routingMask = AddressDecoder(port_addrs) | ||||
|     val route_addrs = port_addrs.map(_.map(_.widen(~routingMask)).distinct) | ||||
|  | ||||
|     val in = io.in(0) | ||||
|     val (in, _) = node.in(0) | ||||
|     val a_sel = Vec(route_addrs.map(seq => seq.map(_.contains(in.haddr)).reduce(_ || _))) | ||||
|     val d_sel = Reg(a_sel) | ||||
|  | ||||
|     when (in.hready) { d_sel := a_sel } | ||||
|     (a_sel zip io.out) foreach { case (sel, out) => | ||||
|     (a_sel zip io_out) foreach { case (sel, out) => | ||||
|       out := in | ||||
|       out.hsel := in.hsel && sel | ||||
|     } | ||||
|  | ||||
|     in.hreadyout := !Mux1H(d_sel, io.out.map(!_.hreadyout)) | ||||
|     in.hresp     :=  Mux1H(d_sel, io.out.map(_.hresp)) | ||||
|     in.hrdata    :=  Mux1H(d_sel, io.out.map(_.hrdata)) | ||||
|     in.hreadyout := !Mux1H(d_sel, io_out.map(!_.hreadyout)) | ||||
|     in.hresp     :=  Mux1H(d_sel, io_out.map(_.hresp)) | ||||
|     in.hrdata    :=  Mux1H(d_sel, io_out.map(_.hrdata)) | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -7,17 +7,11 @@ import chisel3.internal.sourceinfo.SourceInfo | ||||
| import freechips.rocketchip.config.Parameters | ||||
| import freechips.rocketchip.diplomacy._ | ||||
|  | ||||
| object APBImp extends NodeImp[APBMasterPortParameters, APBSlavePortParameters, APBEdgeParameters, APBEdgeParameters, APBBundle] | ||||
| object APBImp extends SimpleNodeImp[APBMasterPortParameters, APBSlavePortParameters, APBEdgeParameters, APBBundle] | ||||
| { | ||||
|   def edgeO(pd: APBMasterPortParameters, pu: APBSlavePortParameters): APBEdgeParameters = APBEdgeParameters(pd, pu) | ||||
|   def edgeI(pd: APBMasterPortParameters, pu: APBSlavePortParameters): APBEdgeParameters = APBEdgeParameters(pd, pu) | ||||
|  | ||||
|   def bundleO(eo: APBEdgeParameters): APBBundle = APBBundle(eo.bundle) | ||||
|   def bundleI(ei: APBEdgeParameters): APBBundle = APBBundle(ei.bundle) | ||||
|  | ||||
|   def colour = "#00ccff" // bluish | ||||
|   override def labelI(ei: APBEdgeParameters) = (ei.slave.beatBytes * 8).toString | ||||
|   override def labelO(eo: APBEdgeParameters) = (eo.slave.beatBytes * 8).toString | ||||
|   def edge(pd: APBMasterPortParameters, pu: APBSlavePortParameters, p: Parameters, sourceInfo: SourceInfo) = APBEdgeParameters(pd, pu, p, sourceInfo) | ||||
|   def bundle(e: APBEdgeParameters) = APBBundle(e.bundle) | ||||
|   def render(e: APBEdgeParameters) = RenderedEdge(colour = "#00ccff" /* bluish */, (e.slave.beatBytes * 8).toString) | ||||
|  | ||||
|   override def mixO(pd: APBMasterPortParameters, node: OutwardNode[APBMasterPortParameters, APBSlavePortParameters, APBBundle]): APBMasterPortParameters  = | ||||
|    pd.copy(masters = pd.masters.map  { c => c.copy (nodePath = node +: c.nodePath) }) | ||||
| @@ -25,24 +19,14 @@ object APBImp extends NodeImp[APBMasterPortParameters, APBSlavePortParameters, A | ||||
|    pu.copy(slaves  = pu.slaves.map { m => m.copy (nodePath = node +: m.nodePath) }) | ||||
| } | ||||
|  | ||||
| // Nodes implemented inside modules | ||||
| case class APBIdentityNode() extends IdentityNode(APBImp) | ||||
| case class APBMasterNode(portParams: Seq[APBMasterPortParameters]) extends SourceNode(APBImp)(portParams) | ||||
| case class APBSlaveNode(portParams: Seq[APBSlavePortParameters]) extends SinkNode(APBImp)(portParams) | ||||
| case class APBMasterNode(portParams: Seq[APBMasterPortParameters])(implicit valName: ValName) extends SourceNode(APBImp)(portParams) | ||||
| case class APBSlaveNode(portParams: Seq[APBSlavePortParameters])(implicit valName: ValName) extends SinkNode(APBImp)(portParams) | ||||
| case class APBNexusNode( | ||||
|   masterFn:       Seq[APBMasterPortParameters] => APBMasterPortParameters, | ||||
|   slaveFn:        Seq[APBSlavePortParameters]  => APBSlavePortParameters, | ||||
|   numMasterPorts: Range.Inclusive = 1 to 1, | ||||
|   numSlavePorts:  Range.Inclusive = 1 to 1) | ||||
|   numSlavePorts:  Range.Inclusive = 1 to 1)( | ||||
|   implicit valName: ValName) | ||||
|   extends NexusNode(APBImp)(masterFn, slaveFn, numMasterPorts, numSlavePorts) | ||||
|  | ||||
| // Nodes passed from an inner module | ||||
| case class APBOutputNode() extends OutputNode(APBImp) | ||||
| case class APBInputNode() extends InputNode(APBImp) | ||||
|  | ||||
| // Nodes used for external ports | ||||
| case class APBBlindOutputNode(portParams: Seq[APBSlavePortParameters]) extends BlindOutputNode(APBImp)(portParams) | ||||
| case class APBBlindInputNode(portParams: Seq[APBMasterPortParameters]) extends BlindInputNode(APBImp)(portParams) | ||||
|  | ||||
| case class APBInternalOutputNode(portParams: Seq[APBSlavePortParameters]) extends InternalOutputNode(APBImp)(portParams) | ||||
| case class APBInternalInputNode(portParams: Seq[APBMasterPortParameters]) extends InternalInputNode(APBImp)(portParams) | ||||
| case class APBIdentityNode()(implicit valName: ValName) extends IdentityNode(APBImp)() | ||||
|   | ||||
| @@ -3,6 +3,7 @@ | ||||
| package freechips.rocketchip.amba.apb | ||||
|  | ||||
| import Chisel._ | ||||
| import chisel3.internal.sourceinfo.SourceInfo | ||||
| import freechips.rocketchip.config.Parameters | ||||
| import freechips.rocketchip.diplomacy._ | ||||
| import scala.math.max | ||||
| @@ -78,7 +79,9 @@ object APBBundleParameters | ||||
|  | ||||
| case class APBEdgeParameters( | ||||
|   master: APBMasterPortParameters, | ||||
|   slave:  APBSlavePortParameters) | ||||
|   slave:  APBSlavePortParameters, | ||||
|   params: Parameters, | ||||
|   sourceInfo: SourceInfo) | ||||
| { | ||||
|   val bundle = APBBundleParameters(master, slave) | ||||
| } | ||||
|   | ||||
| @@ -10,8 +10,8 @@ import freechips.rocketchip.tilelink.{IntSourceNode, IntSourcePortSimple} | ||||
| import freechips.rocketchip.util.HeterogeneousBag | ||||
| import scala.math.{min,max} | ||||
|  | ||||
| class APBRegisterNode(address: AddressSet, concurrency: Int = 0, beatBytes: Int = 4, undefZero: Boolean = true, executable: Boolean = false) | ||||
|   extends APBSlaveNode(Seq(APBSlavePortParameters( | ||||
| case class APBRegisterNode(address: AddressSet, concurrency: Int = 0, beatBytes: Int = 4, undefZero: Boolean = true, executable: Boolean = false)(implicit valName: ValName) | ||||
|   extends SinkNode(APBImp)(Seq(APBSlavePortParameters( | ||||
|     Seq(APBSlaveParameters( | ||||
|       address       = Seq(address), | ||||
|       executable    = executable, | ||||
| @@ -24,7 +24,7 @@ class APBRegisterNode(address: AddressSet, concurrency: Int = 0, beatBytes: Int | ||||
|   // Calling this method causes the matching APB bundle to be | ||||
|   // configured to route all requests to the listed RegFields. | ||||
|   def regmap(mapping: RegField.Map*) = { | ||||
|     val apb = bundleIn(0) | ||||
|     val (apb, _) = this.in(0) | ||||
|  | ||||
|     val indexBits = log2Up((address.mask+1)/beatBytes) | ||||
|     val params = RegMapperParams(indexBits, beatBytes, 1) | ||||
| @@ -51,12 +51,6 @@ class APBRegisterNode(address: AddressSet, concurrency: Int = 0, beatBytes: Int | ||||
|   } | ||||
| } | ||||
|  | ||||
| object APBRegisterNode | ||||
| { | ||||
|   def apply(address: AddressSet, concurrency: Int = 0, beatBytes: Int = 4, undefZero: Boolean = true, executable: Boolean = false) = | ||||
|     new APBRegisterNode(address, concurrency, beatBytes, undefZero, executable) | ||||
| } | ||||
|  | ||||
| // These convenience methods below combine to make it possible to create a APB | ||||
| // register mapped device from a totally abstract register mapped device. | ||||
|  | ||||
| @@ -66,13 +60,11 @@ abstract class APBRegisterRouterBase(address: AddressSet, interrupts: Int, concu | ||||
|   val intnode = IntSourceNode(IntSourcePortSimple(num = interrupts)) | ||||
| } | ||||
|  | ||||
| case class APBRegBundleArg(interrupts: HeterogeneousBag[Vec[Bool]], in: HeterogeneousBag[APBBundle])(implicit val p: Parameters) | ||||
| case class APBRegBundleArg()(implicit val p: Parameters) | ||||
|  | ||||
| class APBRegBundleBase(arg: APBRegBundleArg) extends Bundle | ||||
| { | ||||
|   implicit val p = arg.p | ||||
|   val interrupts = arg.interrupts | ||||
|   val in = arg.in | ||||
| } | ||||
|  | ||||
| class APBRegBundle[P](val params: P, arg: APBRegBundleArg) extends APBRegBundleBase(arg) | ||||
| @@ -80,8 +72,8 @@ class APBRegBundle[P](val params: P, arg: APBRegBundleArg) extends APBRegBundleB | ||||
| class APBRegModule[P, B <: APBRegBundleBase](val params: P, bundleBuilder: => B, router: APBRegisterRouterBase) | ||||
|   extends LazyModuleImp(router) with HasRegMap | ||||
| { | ||||
|   val io = bundleBuilder | ||||
|   val interrupts = if (io.interrupts.isEmpty) Vec(0, Bool()) else io.interrupts(0) | ||||
|   val io = IO(bundleBuilder) | ||||
|   val interrupts = if (router.intnode.out.isEmpty) Vec(0, Bool()) else router.intnode.out(0)._1 | ||||
|   def regmap(mapping: RegField.Map*) = router.node.regmap(mapping:_*) | ||||
| } | ||||
|  | ||||
| @@ -94,5 +86,5 @@ class APBRegisterRouter[B <: APBRegBundleBase, M <: LazyModuleImp] | ||||
|   require (isPow2(size)) | ||||
|   // require (size >= 4096) ... not absolutely required, but highly recommended | ||||
|  | ||||
|   lazy val module = moduleBuilder(bundleBuilder(APBRegBundleArg(intnode.bundleOut, node.bundleIn)), this) | ||||
|   lazy val module = moduleBuilder(bundleBuilder(APBRegBundleArg()), this) | ||||
| } | ||||
|   | ||||
| @@ -22,11 +22,7 @@ class APBRAM(address: AddressSet, executable: Boolean = true, beatBytes: Int = 4 | ||||
|   require ((address.mask & (beatBytes-1)) == beatBytes-1) | ||||
|  | ||||
|   lazy val module = new LazyModuleImp(this) { | ||||
|     val io = new Bundle { | ||||
|       val in = node.bundleIn | ||||
|     } | ||||
|  | ||||
|     val in = io.in(0) | ||||
|     val (in, _) = node.in(0) | ||||
|  | ||||
|     def bigBits(x: BigInt, tail: List[Boolean] = List.empty[Boolean]): List[Boolean] = | ||||
|       if (x == 0) tail.reverse else bigBits(x >> 1, ((x & 1) == 1) :: tail) | ||||
|   | ||||
| @@ -20,7 +20,7 @@ class APBFuzzBridge(aFlow: Boolean, txns: Int)(implicit p: Parameters) extends L | ||||
| { | ||||
|   val fuzz  = LazyModule(new TLFuzzer(txns)) | ||||
|   val model = LazyModule(new TLRAMModel("APBFuzzMaster")) | ||||
|   var xbar  = LazyModule(new APBFanout) | ||||
|   val xbar  = LazyModule(new APBFanout) | ||||
|   val ram   = LazyModule(new APBRAM(AddressSet(0x0, 0xff))) | ||||
|   val gpio  = LazyModule(new RRTest0(0x100)) | ||||
|  | ||||
| @@ -34,7 +34,7 @@ class APBFuzzBridge(aFlow: Boolean, txns: Int)(implicit p: Parameters) extends L | ||||
|     TLDelayer(0.2)( | ||||
|     model.node)))) | ||||
|  | ||||
|   lazy val module = new LazyModuleImp(this) with HasUnitTestIO { | ||||
|   lazy val module = new LazyModuleImp(this) with UnitTestModule { | ||||
|     io.finished := fuzz.module.io.finished | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -16,34 +16,30 @@ class APBFanout()(implicit p: Parameters) extends LazyModule { | ||||
|     slaveFn  = { seq => seq(0).copy(slaves = seq.flatMap(_.slaves)) }) | ||||
|  | ||||
|   lazy val module = new LazyModuleImp(this) { | ||||
|     val io = new Bundle { | ||||
|       val in = node.bundleIn | ||||
|       val out = node.bundleOut | ||||
|     } | ||||
|  | ||||
|     val in = io.in(0) | ||||
|     val (in, _) = node.in(0) | ||||
|  | ||||
|     // Require consistent bus widths | ||||
|     val port0 = node.edgesOut(0).slave | ||||
|     node.edgesOut.foreach { edge => | ||||
|     val (io_out, edgesOut) = node.out.unzip | ||||
|     val port0 = edgesOut(0).slave | ||||
|     edgesOut.foreach { edge => | ||||
|       val port = edge.slave | ||||
|       require (port.beatBytes == port0.beatBytes, | ||||
|         s"${port.slaves.map(_.name)} ${port.beatBytes} vs ${port0.slaves.map(_.name)} ${port0.beatBytes}") | ||||
|     } | ||||
|  | ||||
|     val port_addrs = node.edgesOut.map(_.slave.slaves.map(_.address).flatten) | ||||
|     val port_addrs = edgesOut.map(_.slave.slaves.map(_.address).flatten) | ||||
|     val routingMask = AddressDecoder(port_addrs) | ||||
|     val route_addrs = port_addrs.map(_.map(_.widen(~routingMask)).distinct) | ||||
|  | ||||
|     val sel = Vec(route_addrs.map(seq => seq.map(_.contains(in.paddr)).reduce(_ || _))) | ||||
|     (sel zip io.out) foreach { case (sel, out) => | ||||
|     (sel zip io_out) foreach { case (sel, out) => | ||||
|       out := in | ||||
|       out.psel    := sel && in.psel | ||||
|       out.penable := sel && in.penable | ||||
|     } | ||||
|  | ||||
|     in.pready  := !Mux1H(sel, io.out.map(!_.pready)) | ||||
|     in.pslverr :=  Mux1H(sel, io.out.map(_.pslverr)) | ||||
|     in.prdata  :=  Mux1H(sel, io.out.map(_.prdata)) | ||||
|     in.pready  := !Mux1H(sel, io_out.map(!_.pready)) | ||||
|     in.pslverr :=  Mux1H(sel, io_out.map(_.pslverr)) | ||||
|     in.prdata  :=  Mux1H(sel, io_out.map(_.prdata)) | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -26,11 +26,6 @@ class AXI4Buffer( | ||||
|     slaveFn  = { p => p.copy(minLatency = p.minLatency + min(aw.latency,ar.latency) + min(r.latency,b.latency)) }) | ||||
|  | ||||
|   lazy val module = new LazyModuleImp(this) { | ||||
|     val io = new Bundle { | ||||
|       val in  = node.bundleIn | ||||
|       val out = node.bundleOut | ||||
|     } | ||||
|  | ||||
|     def buffer[T <: Data](config: BufferParams, data: IrrevocableIO[T]): IrrevocableIO[T] = { | ||||
|       if (config.isDefined) { | ||||
|         Queue.irrevocable(data, config.depth, pipe=config.pipe, flow=config.flow) | ||||
| @@ -39,7 +34,7 @@ class AXI4Buffer( | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     ((io.in zip io.out) zip (node.edgesIn zip node.edgesOut)) foreach { case ((in, out), (edgeIn, edgeOut)) => | ||||
|     (node.in zip node.out) foreach { case ((in, edgeIn), (out, edgeOut)) => | ||||
|       out.aw <> buffer(aw, in .aw) | ||||
|       out.w  <> buffer(w,  in .w) | ||||
|       in .b  <> buffer(b,  out.b) | ||||
|   | ||||
| @@ -22,12 +22,7 @@ class AXI4Deinterleaver(maxReadBytes: Int)(implicit p: Parameters) extends LazyM | ||||
|   }) | ||||
|  | ||||
|   lazy val module = new LazyModuleImp(this) { | ||||
|     val io = new Bundle { | ||||
|       val in  = node.bundleIn | ||||
|       val out = node.bundleOut | ||||
|     } | ||||
|  | ||||
|     ((io.in zip io.out) zip (node.edgesIn zip node.edgesOut)) foreach { case ((in, out), (edgeIn, edgeOut)) => | ||||
|     (node.in zip node.out) foreach { case ((in, edgeIn), (out, edgeOut)) => | ||||
|       val endId = edgeOut.master.endId | ||||
|       val beatBytes = edgeOut.slave.beatBytes | ||||
|       val beats = (maxReadBytes+beatBytes-1) / beatBytes | ||||
|   | ||||
| @@ -26,12 +26,7 @@ class AXI4Fragmenter()(implicit p: Parameters) extends LazyModule | ||||
|     slaveFn  = { sp => sp.copy(slaves  = sp.slaves .map(s => mapSlave(s, sp.beatBytes))) }) | ||||
|  | ||||
|   lazy val module = new LazyModuleImp(this) { | ||||
|     val io = new Bundle { | ||||
|       val in  = node.bundleIn | ||||
|       val out = node.bundleOut | ||||
|     } | ||||
|  | ||||
|     ((io.in zip io.out) zip (node.edgesIn zip node.edgesOut)) foreach { case ((in, out), (edgeIn, edgeOut)) => | ||||
|     (node.in zip node.out) foreach { case ((in, edgeIn), (out, edgeOut)) => | ||||
|       val slave     = edgeOut.slave | ||||
|       val slaves    = slave.slaves | ||||
|       val beatBytes = slave.beatBytes | ||||
|   | ||||
| @@ -42,12 +42,7 @@ class AXI4IdIndexer(idBits: Int)(implicit p: Parameters) extends LazyModule | ||||
|     }) | ||||
|  | ||||
|   lazy val module = new LazyModuleImp(this) { | ||||
|     val io = new Bundle { | ||||
|       val in  = node.bundleIn | ||||
|       val out = node.bundleOut | ||||
|     } | ||||
|  | ||||
|     ((io.in zip io.out) zip (node.edgesIn zip node.edgesOut)) foreach { case ((in, out), (edgeIn, edgeOut)) => | ||||
|     (node.in zip node.out) foreach { case ((in, edgeIn), (out, edgeOut)) => | ||||
|  | ||||
|       // Leave everything mostly untouched | ||||
|       out.ar <> in.ar | ||||
|   | ||||
| @@ -7,17 +7,11 @@ import chisel3.internal.sourceinfo.SourceInfo | ||||
| import freechips.rocketchip.config.Parameters | ||||
| import freechips.rocketchip.diplomacy._ | ||||
|  | ||||
| object AXI4Imp extends NodeImp[AXI4MasterPortParameters, AXI4SlavePortParameters, AXI4EdgeParameters, AXI4EdgeParameters, AXI4Bundle] | ||||
| object AXI4Imp extends SimpleNodeImp[AXI4MasterPortParameters, AXI4SlavePortParameters, AXI4EdgeParameters, AXI4Bundle] | ||||
| { | ||||
|   def edgeO(pd: AXI4MasterPortParameters, pu: AXI4SlavePortParameters): AXI4EdgeParameters = AXI4EdgeParameters(pd, pu) | ||||
|   def edgeI(pd: AXI4MasterPortParameters, pu: AXI4SlavePortParameters): AXI4EdgeParameters = AXI4EdgeParameters(pd, pu) | ||||
|  | ||||
|   def bundleO(eo: AXI4EdgeParameters): AXI4Bundle = AXI4Bundle(eo.bundle) | ||||
|   def bundleI(ei: AXI4EdgeParameters): AXI4Bundle = AXI4Bundle(ei.bundle) | ||||
|  | ||||
|   def colour = "#00ccff" // bluish | ||||
|   override def labelI(ei: AXI4EdgeParameters) = (ei.slave.beatBytes * 8).toString | ||||
|   override def labelO(eo: AXI4EdgeParameters) = (eo.slave.beatBytes * 8).toString | ||||
|   def edge(pd: AXI4MasterPortParameters, pu: AXI4SlavePortParameters, p: Parameters, sourceInfo: SourceInfo) = AXI4EdgeParameters(pd, pu, p, sourceInfo) | ||||
|   def bundle(e: AXI4EdgeParameters) = AXI4Bundle(e.bundle) | ||||
|   def render(e: AXI4EdgeParameters) = RenderedEdge(colour = "#00ccff" /* bluish */, label  = (e.slave.beatBytes * 8).toString) | ||||
|  | ||||
|   override def mixO(pd: AXI4MasterPortParameters, node: OutwardNode[AXI4MasterPortParameters, AXI4SlavePortParameters, AXI4Bundle]): AXI4MasterPortParameters  = | ||||
|    pd.copy(masters = pd.masters.map  { c => c.copy (nodePath = node +: c.nodePath) }) | ||||
| @@ -25,23 +19,12 @@ object AXI4Imp extends NodeImp[AXI4MasterPortParameters, AXI4SlavePortParameters | ||||
|    pu.copy(slaves  = pu.slaves.map { m => m.copy (nodePath = node +: m.nodePath) }) | ||||
| } | ||||
|  | ||||
| // Nodes implemented inside modules | ||||
| case class AXI4IdentityNode() extends IdentityNode(AXI4Imp) | ||||
| case class AXI4MasterNode(portParams: Seq[AXI4MasterPortParameters]) extends SourceNode(AXI4Imp)(portParams) | ||||
| case class AXI4SlaveNode(portParams: Seq[AXI4SlavePortParameters]) extends SinkNode(AXI4Imp)(portParams) | ||||
| case class AXI4MasterNode(portParams: Seq[AXI4MasterPortParameters])(implicit valName: ValName) extends SourceNode(AXI4Imp)(portParams) | ||||
| case class AXI4SlaveNode(portParams: Seq[AXI4SlavePortParameters])(implicit valName: ValName) extends SinkNode(AXI4Imp)(portParams) | ||||
| case class AXI4AdapterNode( | ||||
|   masterFn:  AXI4MasterPortParameters => AXI4MasterPortParameters, | ||||
|   slaveFn:   AXI4SlavePortParameters  => AXI4SlavePortParameters, | ||||
|   numPorts:  Range.Inclusive = 0 to 999) | ||||
|   numPorts:  Range.Inclusive = 0 to 999)( | ||||
|   implicit valName: ValName) | ||||
|   extends AdapterNode(AXI4Imp)(masterFn, slaveFn, numPorts) | ||||
|  | ||||
| // Nodes passed from an inner module | ||||
| case class AXI4OutputNode() extends OutputNode(AXI4Imp) | ||||
| case class AXI4InputNode() extends InputNode(AXI4Imp) | ||||
|  | ||||
| // Nodes used for external ports | ||||
| case class AXI4BlindOutputNode(portParams: Seq[AXI4SlavePortParameters]) extends BlindOutputNode(AXI4Imp)(portParams) | ||||
| case class AXI4BlindInputNode(portParams: Seq[AXI4MasterPortParameters]) extends BlindInputNode(AXI4Imp)(portParams) | ||||
|  | ||||
| case class AXI4InternalOutputNode(portParams: Seq[AXI4SlavePortParameters]) extends InternalOutputNode(AXI4Imp)(portParams) | ||||
| case class AXI4InternalInputNode(portParams: Seq[AXI4MasterPortParameters]) extends InternalInputNode(AXI4Imp)(portParams) | ||||
| case class AXI4IdentityNode()(implicit valName: ValName) extends IdentityNode(AXI4Imp)() | ||||
|   | ||||
| @@ -3,6 +3,7 @@ | ||||
| package freechips.rocketchip.amba.axi4 | ||||
|  | ||||
| import Chisel._ | ||||
| import chisel3.internal.sourceinfo.SourceInfo | ||||
| import freechips.rocketchip.config.Parameters | ||||
| import freechips.rocketchip.diplomacy._ | ||||
| import scala.math.max | ||||
| @@ -124,7 +125,9 @@ object AXI4BundleParameters | ||||
|  | ||||
| case class AXI4EdgeParameters( | ||||
|   master: AXI4MasterPortParameters, | ||||
|   slave:  AXI4SlavePortParameters) | ||||
|   slave:  AXI4SlavePortParameters, | ||||
|   params: Parameters, | ||||
|   sourceInfo: SourceInfo) | ||||
| { | ||||
|   val bundle = AXI4BundleParameters(master, slave) | ||||
| } | ||||
|   | ||||
| @@ -10,8 +10,8 @@ import freechips.rocketchip.tilelink.{IntSourceNode, IntSourcePortSimple} | ||||
| import freechips.rocketchip.util.{HeterogeneousBag, MaskGen} | ||||
| import scala.math.{min,max} | ||||
|  | ||||
| class AXI4RegisterNode(address: AddressSet, concurrency: Int = 0, beatBytes: Int = 4, undefZero: Boolean = true, executable: Boolean = false) | ||||
|   extends AXI4SlaveNode(Seq(AXI4SlavePortParameters( | ||||
| case class AXI4RegisterNode(address: AddressSet, concurrency: Int = 0, beatBytes: Int = 4, undefZero: Boolean = true, executable: Boolean = false)(implicit valName: ValName) | ||||
|   extends SinkNode(AXI4Imp)(Seq(AXI4SlavePortParameters( | ||||
|     Seq(AXI4SlaveParameters( | ||||
|       address       = Seq(address), | ||||
|       executable    = executable, | ||||
| @@ -26,11 +26,12 @@ class AXI4RegisterNode(address: AddressSet, concurrency: Int = 0, beatBytes: Int | ||||
|   // Calling this method causes the matching AXI4 bundle to be | ||||
|   // configured to route all requests to the listed RegFields. | ||||
|   def regmap(mapping: RegField.Map*) = { | ||||
|     val ar = bundleIn(0).ar | ||||
|     val aw = bundleIn(0).aw | ||||
|     val w  = bundleIn(0).w | ||||
|     val r  = bundleIn(0).r | ||||
|     val b  = bundleIn(0).b | ||||
|     val (io, _) = this.in(0) | ||||
|     val ar = io.ar | ||||
|     val aw = io.aw | ||||
|     val w  = io.w | ||||
|     val r  = io.r | ||||
|     val b  = io.b | ||||
|  | ||||
|     val params = RegMapperParams(log2Up((address.mask+1)/beatBytes), beatBytes, ar.bits.params.idBits + ar.bits.params.userBits) | ||||
|     val in = Wire(Decoupled(new RegMapperInput(params))) | ||||
| @@ -77,12 +78,6 @@ class AXI4RegisterNode(address: AddressSet, concurrency: Int = 0, beatBytes: Int | ||||
|   } | ||||
| } | ||||
|  | ||||
| object AXI4RegisterNode | ||||
| { | ||||
|   def apply(address: AddressSet, concurrency: Int = 0, beatBytes: Int = 4, undefZero: Boolean = true, executable: Boolean = false) = | ||||
|     new AXI4RegisterNode(address, concurrency, beatBytes, undefZero, executable) | ||||
| } | ||||
|  | ||||
| // These convenience methods below combine to make it possible to create a AXI4 | ||||
| // register mapped device from a totally abstract register mapped device. | ||||
|  | ||||
| @@ -92,13 +87,11 @@ abstract class AXI4RegisterRouterBase(address: AddressSet, interrupts: Int, conc | ||||
|   val intnode = IntSourceNode(IntSourcePortSimple(num = interrupts)) | ||||
| } | ||||
|  | ||||
| case class AXI4RegBundleArg(interrupts: HeterogeneousBag[Vec[Bool]], in: HeterogeneousBag[AXI4Bundle])(implicit val p: Parameters) | ||||
| case class AXI4RegBundleArg()(implicit val p: Parameters) | ||||
|  | ||||
| class AXI4RegBundleBase(arg: AXI4RegBundleArg) extends Bundle | ||||
| { | ||||
|   implicit val p = arg.p | ||||
|   val interrupts = arg.interrupts | ||||
|   val in = arg.in | ||||
| } | ||||
|  | ||||
| class AXI4RegBundle[P](val params: P, arg: AXI4RegBundleArg) extends AXI4RegBundleBase(arg) | ||||
| @@ -106,8 +99,8 @@ class AXI4RegBundle[P](val params: P, arg: AXI4RegBundleArg) extends AXI4RegBund | ||||
| class AXI4RegModule[P, B <: AXI4RegBundleBase](val params: P, bundleBuilder: => B, router: AXI4RegisterRouterBase) | ||||
|   extends LazyModuleImp(router) with HasRegMap | ||||
| { | ||||
|   val io = bundleBuilder | ||||
|   val interrupts = if (io.interrupts.isEmpty) Vec(0, Bool()) else io.interrupts(0) | ||||
|   val io = IO(bundleBuilder) | ||||
|   val interrupts = if (router.intnode.out.isEmpty) Vec(0, Bool()) else router.intnode.out(0)._1 | ||||
|   def regmap(mapping: RegField.Map*) = router.node.regmap(mapping:_*) | ||||
| } | ||||
|  | ||||
| @@ -120,5 +113,5 @@ class AXI4RegisterRouter[B <: AXI4RegBundleBase, M <: LazyModuleImp] | ||||
|   require (isPow2(size)) | ||||
|   // require (size >= 4096) ... not absolutely required, but highly recommended | ||||
|  | ||||
|   lazy val module = moduleBuilder(bundleBuilder(AXI4RegBundleArg(intnode.bundleOut, node.bundleIn)), this) | ||||
|   lazy val module = moduleBuilder(bundleBuilder(AXI4RegBundleArg()), this) | ||||
| } | ||||
|   | ||||
| @@ -24,15 +24,11 @@ class AXI4RAM(address: AddressSet, executable: Boolean = true, beatBytes: Int = | ||||
|   require ((address.mask & (beatBytes-1)) == beatBytes-1) | ||||
|  | ||||
|   lazy val module = new LazyModuleImp(this) { | ||||
|     val io = new Bundle { | ||||
|       val in = node.bundleIn | ||||
|     } | ||||
|  | ||||
|     def bigBits(x: BigInt, tail: List[Boolean] = List.empty[Boolean]): List[Boolean] = | ||||
|       if (x == 0) tail.reverse else bigBits(x >> 1, ((x & 1) == 1) :: tail) | ||||
|     val mask = bigBits(address.mask >> log2Ceil(beatBytes)) | ||||
|  | ||||
|     val in = io.in(0) | ||||
|     val (in, _) = node.in(0) | ||||
|     val mem = SeqMem(1 << mask.filter(b=>b).size, Vec(beatBytes, Bits(width = 8))) | ||||
|  | ||||
|     val r_addr = Cat((mask zip (in.ar.bits.addr >> log2Ceil(beatBytes)).toBools).filter(_._1).map(_._2).reverse) | ||||
|   | ||||
| @@ -30,7 +30,7 @@ class AXI4LiteFuzzRAM(txns: Int)(implicit p: Parameters) extends LazyModule | ||||
|   ram.node   := AXI4UserYanker()(AXI4IdIndexer(0)(TLToAXI4(4, true )(TLFragmenter(4, 16)(xbar.node)))) | ||||
|   gpio.node  := AXI4UserYanker()(AXI4IdIndexer(0)(TLToAXI4(4, false)(TLFragmenter(4, 16)(xbar.node)))) | ||||
|  | ||||
|   lazy val module = new LazyModuleImp(this) with HasUnitTestIO { | ||||
|   lazy val module = new LazyModuleImp(this) with UnitTestModule { | ||||
|     io.finished := fuzz.module.io.finished | ||||
|   } | ||||
| } | ||||
| @@ -53,7 +53,7 @@ class AXI4FullFuzzRAM(txns: Int)(implicit p: Parameters) extends LazyModule | ||||
|   ram.node   := AXI4Fragmenter()(AXI4Deinterleaver(16)(TLToAXI4(4,false)(xbar.node))) | ||||
|   gpio.node  := AXI4Fragmenter()(AXI4Deinterleaver(16)(TLToAXI4(4,true )(xbar.node))) | ||||
|  | ||||
|   lazy val module = new LazyModuleImp(this) with HasUnitTestIO { | ||||
|   lazy val module = new LazyModuleImp(this) with UnitTestModule { | ||||
|     io.finished := fuzz.module.io.finished | ||||
|   } | ||||
| } | ||||
| @@ -69,7 +69,7 @@ trait HasFuzzTarget { | ||||
|  | ||||
| class AXI4FuzzMaster(txns: Int)(implicit p: Parameters) extends LazyModule with HasFuzzTarget | ||||
| { | ||||
|   val node  = AXI4OutputNode() | ||||
|   val node  = AXI4IdentityNode() | ||||
|   val fuzz  = LazyModule(new TLFuzzer(txns, overrideAddress = Some(fuzzAddr))) | ||||
|   val model = LazyModule(new TLRAMModel("AXI4FuzzMaster")) | ||||
|  | ||||
| @@ -84,10 +84,9 @@ class AXI4FuzzMaster(txns: Int)(implicit p: Parameters) extends LazyModule with | ||||
|     model.node)))))) | ||||
|  | ||||
|   lazy val module = new LazyModuleImp(this) { | ||||
|     val io = new Bundle { | ||||
|       val out = node.bundleOut | ||||
|     val io = IO(new Bundle { | ||||
|       val finished = Bool(OUTPUT) | ||||
|     } | ||||
|     }) | ||||
|  | ||||
|     io.finished := fuzz.module.io.finished | ||||
|   } | ||||
| @@ -95,7 +94,7 @@ class AXI4FuzzMaster(txns: Int)(implicit p: Parameters) extends LazyModule with | ||||
|  | ||||
| class AXI4FuzzSlave()(implicit p: Parameters) extends LazyModule with HasFuzzTarget | ||||
| { | ||||
|   val node = AXI4InputNode() | ||||
|   val node = AXI4IdentityNode() | ||||
|   val xbar = LazyModule(new TLXbar) | ||||
|   val ram  = LazyModule(new TLRAM(fuzzAddr)) | ||||
|   val error= LazyModule(new TLError(ErrorParams(Seq(AddressSet(0x1800, 0xff)), maxTransfer = 256))) | ||||
| @@ -114,11 +113,7 @@ class AXI4FuzzSlave()(implicit p: Parameters) extends LazyModule with HasFuzzTar | ||||
|     AXI4IdIndexer(2)( | ||||
|     node)))))))) | ||||
|  | ||||
|   lazy val module = new LazyModuleImp(this) { | ||||
|     val io = new Bundle { | ||||
|       val in = node.bundleIn | ||||
|     } | ||||
|   } | ||||
|   lazy val module = new LazyModuleImp(this) { } | ||||
| } | ||||
|  | ||||
| class AXI4FuzzBridge(txns: Int)(implicit p: Parameters) extends LazyModule | ||||
| @@ -128,7 +123,7 @@ class AXI4FuzzBridge(txns: Int)(implicit p: Parameters) extends LazyModule | ||||
|  | ||||
|   slave.node := master.node | ||||
|  | ||||
|   lazy val module = new LazyModuleImp(this) with HasUnitTestIO { | ||||
|   lazy val module = new LazyModuleImp(this) with UnitTestModule { | ||||
|     io.finished := master.module.io.finished | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -9,7 +9,7 @@ import freechips.rocketchip.diplomacy._ | ||||
| import freechips.rocketchip.tilelink._ | ||||
| import freechips.rocketchip.util._ | ||||
|  | ||||
| case class AXI4ToTLNode() extends MixedAdapterNode(AXI4Imp, TLImp)( | ||||
| case class AXI4ToTLNode()(implicit valName: ValName) extends MixedAdapterNode(AXI4Imp, TLImp)( | ||||
|   dFn = { case AXI4MasterPortParameters(masters, userBits) => | ||||
|     masters.foreach { m => require (m.maxFlight.isDefined, "AXI4 must include a transaction maximum per ID to convert to TL") } | ||||
|     val maxFlight = masters.map(_.maxFlight.get).max | ||||
| @@ -44,12 +44,7 @@ class AXI4ToTL()(implicit p: Parameters) extends LazyModule | ||||
|   val node = AXI4ToTLNode() | ||||
|  | ||||
|   lazy val module = new LazyModuleImp(this) { | ||||
|     val io = new Bundle { | ||||
|       val in = node.bundleIn | ||||
|       val out = node.bundleOut | ||||
|     } | ||||
|  | ||||
|     ((io.in zip io.out) zip (node.edgesIn zip node.edgesOut)) foreach { case ((in, out), (edgeIn, edgeOut)) => | ||||
|     (node.in zip node.out) foreach { case ((in, edgeIn), (out, edgeOut)) => | ||||
|       val numIds = edgeIn.master.endId | ||||
|       val beatBytes = edgeOut.manager.beatBytes | ||||
|       val beatCountBits = AXI4Parameters.lenBits + (1 << AXI4Parameters.sizeBits) - 1 | ||||
|   | ||||
| @@ -22,12 +22,7 @@ class AXI4UserYanker(capMaxFlight: Option[Int] = None)(implicit p: Parameters) e | ||||
|     slaveFn = { sp => sp }) | ||||
|  | ||||
|   lazy val module = new LazyModuleImp(this) { | ||||
|     val io = new Bundle { | ||||
|       val in  = node.bundleIn | ||||
|       val out = node.bundleOut | ||||
|     } | ||||
|  | ||||
|     ((io.in zip io.out) zip (node.edgesIn zip node.edgesOut)) foreach { case ((in, out), (edgeIn, edgeOut)) => | ||||
|     (node.in zip node.out) foreach { case ((in, edgeIn), (out, edgeOut)) => | ||||
|       val bits = edgeIn.bundle.userBits | ||||
|       val need_bypass = edgeOut.slave.minLatency < 1 | ||||
|       require (bits > 0) // useless UserYanker! | ||||
|   | ||||
| @@ -10,8 +10,10 @@ abstract class Field[T] private (val default: Option[T]) | ||||
|  | ||||
| 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) match { | ||||
|     case Some(x) => x.asInstanceOf[T] | ||||
|   final def apply[T](pname: Field[T], site: View): T = { | ||||
|     val out = find(pname, site) | ||||
|     require (out.isDefined, s"Key ${pname} is not defined in Parameters") | ||||
|     out.get | ||||
|   } | ||||
|  | ||||
|   final def lift[T](pname: Field[T]): Option[T] = lift(pname, this) | ||||
|   | ||||
| @@ -21,7 +21,7 @@ abstract class BareCoreplex(implicit p: Parameters) extends LazyModule with Bind | ||||
|   lazy val json = JSON(bindingTree) | ||||
| } | ||||
|  | ||||
| abstract class BareCoreplexModule[+L <: BareCoreplex](_outer: L) extends LazyMultiIOModuleImp(_outer) { | ||||
| abstract class BareCoreplexModule[+L <: BareCoreplex](_outer: L) extends LazyModuleImp(_outer) { | ||||
|   val outer = _outer | ||||
|   ElaborationArtefacts.add("graphml", outer.graphML) | ||||
|   ElaborationArtefacts.add("dts", outer.dts) | ||||
|   | ||||
| @@ -187,14 +187,21 @@ class WithRoccExample extends Config((site, here, up) => { | ||||
|       Seq( | ||||
|         RoCCParams( | ||||
|           opcodes = OpcodeSet.custom0, | ||||
|           generator = (p: Parameters) => LazyModule(new AccumulatorExample()(p))), | ||||
|           generator = (p: Parameters) => { | ||||
|             val accumulator = LazyModule(new AccumulatorExample()(p)) | ||||
|             accumulator}), | ||||
|         RoCCParams( | ||||
|           opcodes = OpcodeSet.custom1, | ||||
|           generator = (p: Parameters) => LazyModule(new TranslatorExample()(p)), | ||||
|           generator = (p: Parameters) => { | ||||
|             val translator = LazyModule(new TranslatorExample()(p)) | ||||
|             translator}, | ||||
|           nPTWPorts = 1), | ||||
|         RoCCParams( | ||||
|           opcodes = OpcodeSet.custom2, | ||||
|           generator = (p: Parameters) => LazyModule(new CharacterCountExample()(p))) | ||||
|           generator = (p: Parameters) => { | ||||
|             val counter = LazyModule(new CharacterCountExample()(p)) | ||||
|             counter | ||||
|           }) | ||||
|         )) | ||||
|     } | ||||
| }) | ||||
| @@ -265,7 +272,7 @@ class WithNBitPeripheryBus(nBits: Int) extends Config ((site, here, up) => { | ||||
| }) | ||||
|  | ||||
| class WithoutTLMonitors extends Config ((site, here, up) => { | ||||
|   case TLMonitorBuilder => (args: TLMonitorArgs) => None | ||||
|   case MonitorsEnabled => false | ||||
| }) | ||||
|  | ||||
| class WithNExtTopInterrupts(nExtInts: Int) extends Config((site, here, up) => { | ||||
|   | ||||
| @@ -53,8 +53,7 @@ trait HasFrontBus extends HasSystemBus { | ||||
|   private val frontbusParams = p(FrontBusKey) | ||||
|   val frontbusBeatBytes = frontbusParams.beatBytes | ||||
|  | ||||
|   val fbus = new FrontBus(frontbusParams) | ||||
|  | ||||
|   sbus.fromFrontBus := fbus.toSystemBus | ||||
|   val fbus = LazyModule(new FrontBus(frontbusParams)) | ||||
|  | ||||
|   FlipRendering { implicit p => sbus.fromFrontBus := fbus.toSystemBus } | ||||
| } | ||||
|   | ||||
| @@ -44,7 +44,7 @@ abstract trait HasExtInterrupts extends HasInterruptBus { | ||||
|   } | ||||
|  | ||||
|   val nExtInterrupts = p(NExtTopInterrupts) | ||||
|   val extInterrupts = IntInternalInputNode(IntSourcePortSimple(num = nExtInterrupts, resources = device.int)) | ||||
|   val extInterrupts = IntSourceNode(IntSourcePortSimple(num = nExtInterrupts, resources = device.int)) | ||||
| } | ||||
|  | ||||
| /** This trait should be used if the External Interrupts have NOT | ||||
| @@ -77,9 +77,9 @@ trait HasExtInterruptsBundle { | ||||
| /** This trait performs the translation from a UInt IO into Diplomatic Interrupts. | ||||
|   * The wiring must be done in the concrete LazyModuleImp.  | ||||
|   */ | ||||
| trait HasExtInterruptsModuleImp extends LazyMultiIOModuleImp with HasExtInterruptsBundle { | ||||
| trait HasExtInterruptsModuleImp extends LazyModuleImp with HasExtInterruptsBundle { | ||||
|   val outer: HasExtInterrupts | ||||
|   val interrupts = IO(UInt(INPUT, width = outer.nExtInterrupts)) | ||||
|  | ||||
|   outer.extInterrupts.bundleIn.flatten.zipWithIndex.foreach { case(o, i) => o := interrupts(i) } | ||||
|   outer.extInterrupts.in.map(_._1).flatten.zipWithIndex.foreach { case(o, i) => o := interrupts(i) } | ||||
| } | ||||
|   | ||||
| @@ -68,7 +68,7 @@ trait HasMemoryBus extends HasSystemBus with HasPeripheryBus with HasInterruptBu | ||||
|  | ||||
|   private val mask = ~BigInt((nBanks-1) * memBusBlockBytes) | ||||
|   val memBuses = Seq.tabulate(nMemoryChannels) { channel => | ||||
|     val mbus = new MemoryBus(mbusParams) | ||||
|     val mbus = LazyModule(new MemoryBus(mbusParams)) | ||||
|     for (bank <- 0 until nBanksPerChannel) { | ||||
|       val offset = (bank * nMemoryChannels) + channel | ||||
|       ForceFanout(a = true) { implicit p => in := sbus.toMemoryBus } | ||||
|   | ||||
| @@ -45,7 +45,7 @@ trait HasPeripheryBus extends HasSystemBus { | ||||
|   private val pbusParams = p(PeripheryBusKey) | ||||
|   val pbusBeatBytes = pbusParams.beatBytes | ||||
|  | ||||
|   val pbus = new PeripheryBus(pbusParams) | ||||
|   val pbus = LazyModule(new PeripheryBus(pbusParams)) | ||||
|  | ||||
|   // The peripheryBus hangs off of systemBus; here we convert TL-UH -> TL-UL | ||||
|   pbus.fromSystemBus := sbus.toPeripheryBus() | ||||
|   | ||||
| @@ -33,7 +33,7 @@ trait HasMasterAXI4MemPort extends HasMemoryBus { | ||||
|   private val params = p(ExtMem) | ||||
|   private val device = new MemoryDevice | ||||
|  | ||||
|   val mem_axi4 = AXI4BlindOutputNode(Seq.tabulate(nMemoryChannels) { channel => | ||||
|   val mem_axi4 = AXI4SlaveNode(Seq.tabulate(nMemoryChannels) { channel => | ||||
|     val base = AddressSet(params.base, params.size-1) | ||||
|     val filter = AddressSet(channel * cacheBlockBytes, ~((nMemoryChannels-1) * cacheBlockBytes)) | ||||
|  | ||||
| @@ -69,14 +69,18 @@ trait HasMasterAXI4MemPortBundle { | ||||
|   val mem_axi4: HeterogeneousBag[AXI4Bundle] | ||||
|   val nMemoryChannels: Int | ||||
|   def connectSimAXIMem(dummy: Int = 1) = { | ||||
|     if (nMemoryChannels > 0) Module(LazyModule(new SimAXIMem(nMemoryChannels)).module).io.axi4 <> mem_axi4 | ||||
|     if (nMemoryChannels > 0)  { | ||||
|       val mem = LazyModule(new SimAXIMem(nMemoryChannels)) | ||||
|       Module(mem.module).io.axi4 <> mem_axi4 | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  | ||||
| /** Actually generates the corresponding IO in the concrete Module */ | ||||
| trait HasMasterAXI4MemPortModuleImp extends LazyMultiIOModuleImp with HasMasterAXI4MemPortBundle { | ||||
| trait HasMasterAXI4MemPortModuleImp extends LazyModuleImp with HasMasterAXI4MemPortBundle { | ||||
|   val outer: HasMasterAXI4MemPort | ||||
|   val mem_axi4 = IO(outer.mem_axi4.bundleOut) | ||||
|   val mem_axi4 = IO(HeterogeneousBag.fromNode(outer.mem_axi4.in)) | ||||
|   (mem_axi4 zip outer.mem_axi4.in) foreach { case (i, (o, _)) => i <> o } | ||||
|   val nMemoryChannels = outer.nMemoryChannels | ||||
| } | ||||
|  | ||||
| @@ -84,7 +88,7 @@ trait HasMasterAXI4MemPortModuleImp extends LazyMultiIOModuleImp with HasMasterA | ||||
| trait HasMasterAXI4MMIOPort extends HasSystemBus { | ||||
|   private val params = p(ExtBus) | ||||
|   private val device = new SimpleBus("mmio", Nil) | ||||
|   val mmio_axi4 = AXI4BlindOutputNode(Seq(AXI4SlavePortParameters( | ||||
|   val mmio_axi4 = AXI4SlaveNode(Seq(AXI4SlavePortParameters( | ||||
|     slaves = Seq(AXI4SlaveParameters( | ||||
|       address       = List(AddressSet(params.base, params.size-1)), | ||||
|       resources     = device.ranges, | ||||
| @@ -107,20 +111,22 @@ trait HasMasterAXI4MMIOPortBundle { | ||||
|   implicit val p: Parameters | ||||
|   val mmio_axi4: HeterogeneousBag[AXI4Bundle] | ||||
|   def connectSimAXIMMIO(dummy: Int = 1) { | ||||
|     Module(LazyModule(new SimAXIMem(1, 4096)).module).io.axi4 <> mmio_axi4 | ||||
|     val mmio_mem = LazyModule(new SimAXIMem(1, 4096)) | ||||
|     Module(mmio_mem.module).io.axi4 <> mmio_axi4 | ||||
|   } | ||||
| } | ||||
|  | ||||
| /** Actually generates the corresponding IO in the concrete Module */ | ||||
| trait HasMasterAXI4MMIOPortModuleImp extends LazyMultiIOModuleImp with HasMasterAXI4MMIOPortBundle { | ||||
| trait HasMasterAXI4MMIOPortModuleImp extends LazyModuleImp with HasMasterAXI4MMIOPortBundle { | ||||
|   val outer: HasMasterAXI4MMIOPort | ||||
|   val mmio_axi4 = IO(outer.mmio_axi4.bundleOut) | ||||
|   val mmio_axi4 = IO(HeterogeneousBag.fromNode(outer.mmio_axi4.in)) | ||||
|   (mmio_axi4 zip outer.mmio_axi4.in) foreach { case (i, (o, _)) => i <> o } | ||||
| } | ||||
|  | ||||
| /** Adds an AXI4 port to the system intended to be a slave on an MMIO device bus */ | ||||
| trait HasSlaveAXI4Port extends HasSystemBus { | ||||
|   private val params = p(ExtIn) | ||||
|   val l2FrontendAXI4Node = AXI4BlindInputNode(Seq(AXI4MasterPortParameters( | ||||
|   val l2FrontendAXI4Node = AXI4MasterNode(Seq(AXI4MasterPortParameters( | ||||
|     masters = Seq(AXI4MasterParameters( | ||||
|       name = "AXI4 periphery", | ||||
|       id   = IdRange(0, 1 << params.idBits)))))) | ||||
| @@ -151,16 +157,17 @@ trait HasSlaveAXI4PortBundle { | ||||
| } | ||||
|  | ||||
| /** Actually generates the corresponding IO in the concrete Module */ | ||||
| trait HasSlaveAXI4PortModuleImp extends LazyMultiIOModuleImp with HasSlaveAXI4PortBundle { | ||||
| trait HasSlaveAXI4PortModuleImp extends LazyModuleImp with HasSlaveAXI4PortBundle { | ||||
|   val outer: HasSlaveAXI4Port | ||||
|   val l2_frontend_bus_axi4 = IO(outer.l2FrontendAXI4Node.bundleIn) | ||||
|   val l2_frontend_bus_axi4 = IO(HeterogeneousBag.fromNode(outer.l2FrontendAXI4Node.out).flip) | ||||
|   (outer.l2FrontendAXI4Node.out zip l2_frontend_bus_axi4) foreach { case ((i, _), o) => i <> o } | ||||
| } | ||||
|  | ||||
| /** Adds a TileLink port to the system intended to master an MMIO device bus */ | ||||
| trait HasMasterTLMMIOPort extends HasSystemBus { | ||||
|   private val params = p(ExtBus) | ||||
|   private val device = new SimpleBus("mmio", Nil) | ||||
|   val mmio_tl = TLBlindOutputNode(Seq(TLManagerPortParameters( | ||||
|   val mmio_tl = TLManagerNode(Seq(TLManagerPortParameters( | ||||
|     managers = Seq(TLManagerParameters( | ||||
|       address            = List(AddressSet(params.base, params.size-1)), | ||||
|       resources          = device.ranges, | ||||
| @@ -192,9 +199,10 @@ trait HasMasterTLMMIOPortBundle { | ||||
| } | ||||
|  | ||||
| /** Actually generates the corresponding IO in the concrete Module */ | ||||
| trait HasMasterTLMMIOPortModuleImp extends LazyMultiIOModuleImp with HasMasterTLMMIOPortBundle { | ||||
| trait HasMasterTLMMIOPortModuleImp extends LazyModuleImp with HasMasterTLMMIOPortBundle { | ||||
|   val outer: HasMasterTLMMIOPort | ||||
|   val mmio_tl = IO(outer.mmio_tl.bundleOut) | ||||
|   val mmio_tl = IO(HeterogeneousBag.fromNode(outer.mmio_tl.in)) | ||||
|   (mmio_tl zip outer.mmio_tl.out) foreach { case (i, (o, _)) => i <> o } | ||||
| } | ||||
|  | ||||
| /** Adds an TL port to the system intended to be a slave on an MMIO device bus. | ||||
| @@ -202,7 +210,7 @@ trait HasMasterTLMMIOPortModuleImp extends LazyMultiIOModuleImp with HasMasterTL | ||||
|   */ | ||||
| trait HasSlaveTLPort extends HasSystemBus { | ||||
|   private val params = p(ExtIn) | ||||
|   val l2FrontendTLNode = TLBlindInputNode(Seq(TLClientPortParameters( | ||||
|   val l2FrontendTLNode = TLClientNode(Seq(TLClientPortParameters( | ||||
|     clients = Seq(TLClientParameters( | ||||
|       name     = "Front Port (TL)", | ||||
|       sourceId = IdRange(0, 1 << params.idBits)))))) | ||||
| @@ -229,9 +237,10 @@ trait HasSlaveTLPortBundle { | ||||
| } | ||||
|  | ||||
| /** Actually generates the corresponding IO in the concrete Module */ | ||||
| trait HasSlaveTLPortModuleImp extends LazyMultiIOModuleImp with HasSlaveTLPortBundle { | ||||
| trait HasSlaveTLPortModuleImp extends LazyModuleImp with HasSlaveTLPortBundle { | ||||
|   val outer: HasSlaveTLPort | ||||
|   val l2_frontend_bus_tl = IO(outer.l2FrontendTLNode.bundleIn) | ||||
|   val l2_frontend_bus_tl = IO(HeterogeneousBag.fromNode(outer.l2FrontendTLNode.out).flip) | ||||
|   (outer.l2FrontendTLNode.in zip l2_frontend_bus_tl) foreach { case ((i, _), o) => i <> o } | ||||
| } | ||||
|  | ||||
| /** Memory with AXI port for use in elaboratable test harnesses. */ | ||||
| @@ -241,7 +250,7 @@ class SimAXIMem(channels: Int, forceSize: BigInt = 0)(implicit p: Parameters) ex | ||||
|   val size = totalSize / channels | ||||
|   require(totalSize % channels == 0) | ||||
|  | ||||
|   val node = AXI4BlindInputNode(Seq.fill(channels) { | ||||
|   val node = AXI4MasterNode(Seq.fill(channels) { | ||||
|     AXI4MasterPortParameters(Seq(AXI4MasterParameters( | ||||
|       name = "dut", | ||||
|       id   = IdRange(0, 1 << config.idBits) | ||||
| @@ -254,8 +263,9 @@ class SimAXIMem(channels: Int, forceSize: BigInt = 0)(implicit p: Parameters) ex | ||||
|   } | ||||
|  | ||||
|   lazy val module = new LazyModuleImp(this) { | ||||
|     val io = new Bundle { | ||||
|       val axi4 = node.bundleIn | ||||
|     } | ||||
|     val io = IO(new Bundle { | ||||
|       val axi4 = HeterogeneousBag.fromNode(node.out).flip | ||||
|     }) | ||||
|     (node.out zip io.axi4) foreach { case ((i, _), o) => i <> o } | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -3,10 +3,10 @@ | ||||
| package freechips.rocketchip.coreplex | ||||
|  | ||||
| import Chisel._ | ||||
| import freechips.rocketchip.diplomacy.{LazyMultiIOModuleImp, DTSTimebase} | ||||
| import freechips.rocketchip.diplomacy.{LazyModuleImp, DTSTimebase} | ||||
| import freechips.rocketchip.devices.tilelink.HasPeripheryClint | ||||
|  | ||||
| trait HasRTCModuleImp extends LazyMultiIOModuleImp { | ||||
| trait HasRTCModuleImp extends LazyModuleImp { | ||||
|   val outer: HasPeripheryClint | ||||
|   private val pbusFreq = outer.p(PeripheryBusKey).frequency | ||||
|   private val rtcFreq = outer.p(DTSTimebase) | ||||
|   | ||||
| @@ -46,19 +46,19 @@ trait HasRocketTiles extends HasSystemBus | ||||
|       case SynchronousCrossing(params) => { | ||||
|         val wrapper = LazyModule(new SyncRocketTile(tp, i)(pWithExtra)) | ||||
|         sbus.fromSyncTiles(params, tp.externalMasterBuffers, tp.name) :=* wrapper.masterNode | ||||
|         wrapper.slaveNode :*= pbus.toSyncSlaves(tp.name, tp.externalSlaveBuffers) | ||||
|         FlipRendering { implicit p => 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.externalMasterBuffers, tp.name) :=* wrapper.masterNode | ||||
|         wrapper.slaveNode :*= pbus.toAsyncSlaves(sync, tp.name, tp.externalSlaveBuffers) | ||||
|         FlipRendering { implicit p => 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.externalMasterBuffers, tp.name) :=* wrapper.masterNode | ||||
|         wrapper.slaveNode :*= pbus.toRationalSlaves(tp.name, tp.externalSlaveBuffers) | ||||
|         FlipRendering { implicit p => wrapper.slaveNode :*= pbus.toRationalSlaves(tp.name, tp.externalSlaveBuffers) } | ||||
|         wrapper | ||||
|       } | ||||
|     } | ||||
| @@ -86,7 +86,7 @@ trait HasRocketTiles extends HasSystemBus | ||||
|  | ||||
|     wrapper.intOutputNode.foreach { case int => | ||||
|       val rocketIntXing = LazyModule(new IntXing(wrapper.outputInterruptXingLatency)) | ||||
|       rocketIntXing.intnode := int | ||||
|       FlipRendering { implicit p => rocketIntXing.intnode := int } | ||||
|       plic.intnode := rocketIntXing.intnode | ||||
|     } | ||||
|  | ||||
| @@ -102,7 +102,7 @@ trait HasRocketTilesBundle { | ||||
|   val rocket_tile_inputs: Vec[ClockedRocketTileInputs] | ||||
| } | ||||
|  | ||||
| trait HasRocketTilesModuleImp extends LazyMultiIOModuleImp | ||||
| trait HasRocketTilesModuleImp extends LazyModuleImp | ||||
|     with HasRocketTilesBundle | ||||
|     with HasResetVectorWire | ||||
|     with HasPeripheryDebugModuleImp { | ||||
|   | ||||
| @@ -22,7 +22,7 @@ class SystemBus(params: SystemBusParams)(implicit p: Parameters) extends TLBusWr | ||||
|   private val master_splitter = LazyModule(new TLSplitter)  // Allows cycle-free connection to external networks | ||||
|   master_splitter.suggestName(s"${busName}_master_TLSplitter") | ||||
|   inwardNode :=* master_splitter.node | ||||
|   def busView = master_splitter.node.edgesIn.head | ||||
|   def busView = master_splitter.node.edges.in.head | ||||
|  | ||||
|   protected def inwardSplitNode: TLInwardNode = master_splitter.node | ||||
|   protected def outwardSplitNode: TLOutwardNode = master_splitter.node | ||||
| @@ -122,7 +122,7 @@ trait HasSystemBus extends HasInterruptBus { | ||||
|   private val sbusParams = p(SystemBusKey) | ||||
|   val sbusBeatBytes = sbusParams.beatBytes | ||||
|  | ||||
|   val sbus = new SystemBus(sbusParams) | ||||
|   val sbus = LazyModule(new SystemBus(sbusParams)) | ||||
|  | ||||
|   def sharedMemoryTLEdge: TLEdge = sbus.busView | ||||
|   def paddrBits: Int = sbus.busView.bundle.addressBits | ||||
|   | ||||
| @@ -288,14 +288,12 @@ class TLDebugModuleOuter(device: Device)(implicit p: Parameters) extends LazyMod | ||||
|  | ||||
|   lazy val module = new LazyModuleImp(this) { | ||||
|  | ||||
|     val nComponents = intnode.bundleOut.size | ||||
|     val nComponents = intnode.out.size | ||||
|  | ||||
|     val io = new Bundle { | ||||
|     val io = IO(new Bundle { | ||||
|       val ctrl = (new DebugCtrlBundle(nComponents)) | ||||
|       val tlIn = dmiNode.bundleIn | ||||
|       val debugInterrupts = intnode.bundleOut | ||||
|       val innerCtrl = new DecoupledIO(new DebugInternalBundle()) | ||||
|     } | ||||
|     }) | ||||
|  | ||||
|     //----DMCONTROL (The whole point of 'Outer' is to maintain this register on dmiClock (e.g. TCK) domain, so that it | ||||
|     //               can be written even if 'Inner' is not being clocked or is in reset. This allows halting | ||||
| @@ -355,8 +353,9 @@ class TLDebugModuleOuter(device: Device)(implicit p: Parameters) extends LazyMod | ||||
|  | ||||
|     debugIntNxt := debugIntRegs | ||||
|  | ||||
|     val (intnode_out, _) = intnode.out.unzip | ||||
|     for (component <- 0 until nComponents) { | ||||
|       io.debugInterrupts(component)(0) := debugIntRegs(component) | ||||
|       intnode_out(component)(0) := debugIntRegs(component) | ||||
|     } | ||||
|  | ||||
|     // Halt request registers are set & cleared by writes to DMCONTROL.haltreq | ||||
| @@ -393,27 +392,22 @@ class TLDebugModuleOuterAsync(device: Device)(implicit p: Parameters) extends La | ||||
|   val dmiXbar = LazyModule (new TLXbar()) | ||||
|  | ||||
|   val dmOuter = LazyModule( new TLDebugModuleOuter(device)) | ||||
|   val intnode = IntOutputNode() | ||||
|   val intnode = dmOuter.intnode | ||||
|  | ||||
|   val dmiInnerNode = TLAsyncOutputNode() | ||||
|  | ||||
|   intnode :*= dmOuter.intnode | ||||
|   val dmiInnerNode = TLAsyncCrossingSource()(dmiXbar.node) | ||||
|  | ||||
|   dmiXbar.node := dmi2tl.node | ||||
|   dmOuter.dmiNode := dmiXbar.node | ||||
|   dmiInnerNode := TLAsyncCrossingSource()(dmiXbar.node) | ||||
|    | ||||
|   lazy val module = new LazyModuleImp(this) { | ||||
|  | ||||
|     val nComponents = intnode.bundleOut.size | ||||
|     val nComponents = intnode.out.size | ||||
|  | ||||
|     val io = new Bundle { | ||||
|     val io = IO(new Bundle { | ||||
|       val dmi   = new DMIIO()(p).flip() | ||||
|       val dmiInner = dmiInnerNode.bundleOut | ||||
|       val ctrl = new DebugCtrlBundle(nComponents) | ||||
|       val debugInterrupts = intnode.bundleOut | ||||
|       val innerCtrl = new AsyncBundle(depth=1, new DebugInternalBundle()) | ||||
|     } | ||||
|     }) | ||||
|  | ||||
|     dmi2tl.module.io.dmi <> io.dmi | ||||
|  | ||||
| @@ -447,13 +441,11 @@ class TLDebugModuleInner(device: Device, getNComponents: () => Int)(implicit p: | ||||
|  | ||||
|     val nComponents = getNComponents() | ||||
|  | ||||
|     val io = new Bundle { | ||||
|       val hart_in = tlNode.bundleIn | ||||
|       val dmi_in = dmiNode.bundleIn | ||||
|     val io = IO(new Bundle { | ||||
|       val dmactive = Bool(INPUT) | ||||
|       val innerCtrl = (new DecoupledIO(new DebugInternalBundle())).flip | ||||
|       val debugUnavail = Vec(nComponents, Bool()).asInput | ||||
|     } | ||||
|     }) | ||||
|  | ||||
|     //-------------------------------------------------------------- | ||||
|     // Import constants for shorter variable names | ||||
| @@ -1011,26 +1003,23 @@ class TLDebugModuleInner(device: Device, getNComponents: () => Int)(implicit p: | ||||
| // Also is the Sink side of hartsel & resumereq fields of DMCONTROL. | ||||
| class TLDebugModuleInnerAsync(device: Device, getNComponents: () => Int)(implicit p: Parameters) extends LazyModule{ | ||||
|  | ||||
|   val dmInner = LazyModule(new TLDebugModuleInner(device, getNComponents)(p)) | ||||
|   val dmiNode = TLAsyncInputNode() | ||||
|   val tlNode = TLInputNode() | ||||
|   val dmInner = LazyModule(new TLDebugModuleInner(device, getNComponents)) | ||||
|   val dmiXing = LazyModule(new TLAsyncCrossingSink(depth=1)) | ||||
|   val dmiNode: TLAsyncInwardNode = dmiXing.node | ||||
|   val tlNode = dmInner.tlNode | ||||
|  | ||||
|   dmInner.dmiNode := TLAsyncCrossingSink(depth=1)(dmiNode) | ||||
|   dmInner.tlNode  := tlNode | ||||
|   dmInner.dmiNode := dmiXing.node | ||||
|  | ||||
|   lazy val module = new LazyModuleImp(this) { | ||||
|  | ||||
|     val io = new Bundle { | ||||
|       // this comes from tlClk domain. | ||||
|       val tl_in = tlNode.bundleIn | ||||
|     val io = IO(new Bundle { | ||||
|       // These are all asynchronous and come from Outer | ||||
|       val dmi_in = dmiNode.bundleIn | ||||
|       val dmactive = Bool(INPUT) | ||||
|       val innerCtrl = new AsyncBundle(1, new DebugInternalBundle()).flip | ||||
|       // This comes from tlClk domain. | ||||
|       val debugUnavail    = Vec(getNComponents(), Bool()).asInput | ||||
|       val psd = new PSDTestMode().asInput | ||||
|     } | ||||
|     }) | ||||
|  | ||||
|     dmInner.module.io.innerCtrl := FromAsyncBundle(io.innerCtrl) | ||||
|     dmInner.module.io.dmactive := ~ResetCatchAndSync(clock, ~io.dmactive, "dmactiveSync", io.psd) | ||||
| @@ -1049,26 +1038,22 @@ class TLDebugModule(implicit p: Parameters) extends LazyModule { | ||||
|     override val alwaysExtended = true | ||||
|   } | ||||
|  | ||||
|   val node = TLInputNode() | ||||
|   val intnode = IntOutputNode() | ||||
|  | ||||
|   val dmOuter = LazyModule(new TLDebugModuleOuterAsync(device)(p)) | ||||
|   val dmInner = LazyModule(new TLDebugModuleInnerAsync(device, () => {intnode.bundleOut.size})(p)) | ||||
|   val dmInner = LazyModule(new TLDebugModuleInnerAsync(device, () => {intnode.edges.out.size})(p)) | ||||
|  | ||||
|   val node = dmInner.tlNode | ||||
|   val intnode = dmOuter.intnode | ||||
|  | ||||
|   dmInner.dmiNode := dmOuter.dmiInnerNode | ||||
|   dmInner.tlNode := node | ||||
|   intnode :*= dmOuter.intnode | ||||
|  | ||||
|   lazy val module = new LazyModuleImp(this) { | ||||
|     val nComponents = intnode.bundleOut.size | ||||
|     val nComponents = intnode.out.size | ||||
|  | ||||
|     val io = new Bundle { | ||||
|     val io = IO(new Bundle { | ||||
|       val ctrl = new DebugCtrlBundle(nComponents) | ||||
|       val dmi = new ClockedDMIIO().flip | ||||
|       val in = node.bundleIn | ||||
|       val debugInterrupts = intnode.bundleOut | ||||
|       val psd = new PSDTestMode().asInput | ||||
|     } | ||||
|     }) | ||||
|  | ||||
|     dmOuter.module.io.dmi <> io.dmi.dmi | ||||
|     dmOuter.module.reset := io.dmi.dmiReset | ||||
| @@ -1102,16 +1087,14 @@ class ClockedDMIIO(implicit val p: Parameters) extends ParameterizedBundle()(p){ | ||||
|  | ||||
| class DMIToTL(implicit p: Parameters) extends LazyModule { | ||||
|  | ||||
|   val node = TLClientNode(TLClientParameters("debug")) | ||||
|   val node = TLClientNode(Seq(TLClientPortParameters(Seq(TLClientParameters("debug"))))) | ||||
|  | ||||
|   lazy val module = new LazyModuleImp(this) { | ||||
|     val io = new Bundle { | ||||
|     val io = IO(new Bundle { | ||||
|       val dmi = new DMIIO()(p).flip() | ||||
|       val out = node.bundleOut | ||||
|     } | ||||
|     }) | ||||
|  | ||||
|     val tl = io.out(0) | ||||
|     val edge = node.edgesOut(0) | ||||
|     val (tl, edge) = node.out(0) | ||||
|  | ||||
|     val src  = Wire(init = 0.U) | ||||
|     val addr = Wire(init = (io.dmi.req.bits.addr << 2)) | ||||
|   | ||||
| @@ -54,9 +54,9 @@ trait HasPeripheryDebugBundle { | ||||
|     } | ||||
|     debug.psd.foreach { _ <> psd } | ||||
|   } | ||||
|  | ||||
| } | ||||
| trait HasPeripheryDebugModuleImp extends LazyMultiIOModuleImp with HasPeripheryDebugBundle { | ||||
|  | ||||
| trait HasPeripheryDebugModuleImp extends LazyModuleImp with HasPeripheryDebugBundle { | ||||
|   val outer: HasPeripheryDebug | ||||
|  | ||||
|   val debug = IO(new DebugIO) | ||||
|   | ||||
| @@ -23,25 +23,22 @@ case object BootROMParams extends Field[BootROMParams] | ||||
| class TLROM(val base: BigInt, val size: Int, contentsDelayed: => Seq[Byte], executable: Boolean = true, beatBytes: Int = 4, | ||||
|   resources: Seq[Resource] = new SimpleDevice("rom", Seq("sifive,rom0")).reg("mem"))(implicit p: Parameters) extends LazyModule | ||||
| { | ||||
|   val node = TLManagerNode(beatBytes, TLManagerParameters ( | ||||
|   val node = TLManagerNode(Seq(TLManagerPortParameters( | ||||
|     Seq(TLManagerParameters( | ||||
|       address     = List(AddressSet(base, size-1)), | ||||
|       resources   = resources, | ||||
|       regionType  = RegionType.UNCACHED, | ||||
|       executable  = executable, | ||||
|       supportsGet = TransferSizes(1, beatBytes), | ||||
|     fifoId      = Some(0))) | ||||
|       fifoId      = Some(0))), | ||||
|     beatBytes = beatBytes))) | ||||
|  | ||||
|   lazy val module = new LazyModuleImp(this) { | ||||
|     val io = new Bundle { | ||||
|       val in = node.bundleIn | ||||
|     } | ||||
|  | ||||
|     val contents = contentsDelayed | ||||
|     val wrapSize = 1 << log2Ceil(contents.size) | ||||
|     require (wrapSize <= size) | ||||
|  | ||||
|     val in = io.in(0) | ||||
|     val edge = node.edgesIn(0) | ||||
|     val (in, edge) = node.in(0) | ||||
|  | ||||
|     val words = (contents ++ Seq.fill(wrapSize-contents.size)(0.toByte)).grouped(beatBytes).toSeq | ||||
|     val bigs = words.map(_.foldRight(BigInt(0)){ case (x,y) => (x.toInt & 0xff) | y << 8}) | ||||
| @@ -78,7 +75,7 @@ trait HasPeripheryBootROM extends HasPeripheryBus { | ||||
| } | ||||
|  | ||||
| /** Coreplex will power-on running at 0x10040 (BootROM) */ | ||||
| trait HasPeripheryBootROMModuleImp extends LazyMultiIOModuleImp | ||||
| trait HasPeripheryBootROMModuleImp extends LazyModuleImp | ||||
|     with HasResetVectorWire { | ||||
|   val outer: HasPeripheryBootROM | ||||
|   global_reset_vector := outer.resetVector.U | ||||
|   | ||||
| @@ -81,20 +81,13 @@ class BusBlocker(params: BusBlockerParams)(implicit p: Parameters) extends TLBus | ||||
|     beatBytes = params.controlBeatBytes) | ||||
|  | ||||
|   lazy val module = new LazyModuleImp(this) { | ||||
|     val io = new Bundle { | ||||
|       val ctl = controlNode.bundleIn | ||||
|       val in = nodeIn.bundleIn | ||||
|       val out = nodeOut.bundleOut | ||||
|     } | ||||
|  | ||||
|     // We need to be able to represent +1 larger than the largest populated address | ||||
|     val addressBits = log2Ceil(nodeOut.edgesOut(0).manager.maxAddress+1+1) | ||||
|     val addressBits = log2Ceil(nodeOut.edges.out(0).manager.maxAddress+1+1) | ||||
|     val pmps = RegInit(Vec.fill(params.pmpRegisters) { DevicePMP(addressBits, params.pageBits) }) | ||||
|     val blocks = pmps.tail.map(_.blockPriorAddress) :+ Bool(false) | ||||
|     controlNode.regmap(0 -> (pmps zip blocks).map { case (p, b) => p.fields(b) }.toList.flatten) | ||||
|  | ||||
|     val in = io.in(0) | ||||
|     val edge = nodeIn.edgesIn(0) | ||||
|     val (in, edge) = nodeIn.in(0) | ||||
|  | ||||
|     // Determine if a request is allowed | ||||
|     val needW = in.a.bits.opcode =/= TLMessages.Get | ||||
|   | ||||
| @@ -12,14 +12,15 @@ import scala.math.min | ||||
|  | ||||
| abstract class TLBusBypassBase(beatBytes: Int)(implicit p: Parameters) extends LazyModule | ||||
| { | ||||
|   protected val nodeIn = TLInputNode() | ||||
|   protected val nodeOut = TLOutputNode() | ||||
|   protected val nodeIn = TLIdentityNode() | ||||
|   protected val nodeOut = TLIdentityNode() | ||||
|   val node = NodeHandle(nodeIn, nodeOut) | ||||
|  | ||||
|   protected val bar = LazyModule(new TLBusBypassBar) | ||||
|   protected val everything = Seq(AddressSet(0, BigInt("ffffffffffffffffffffffffffffffff", 16))) // 128-bit | ||||
|   protected val error = LazyModule(new TLError(ErrorParams(everything), beatBytes)) | ||||
|  | ||||
|   // order matters | ||||
|   bar.node := nodeIn | ||||
|   error.node := bar.node | ||||
|   nodeOut := bar.node | ||||
| @@ -28,11 +29,9 @@ abstract class TLBusBypassBase(beatBytes: Int)(implicit p: Parameters) extends L | ||||
| class TLBusBypass(beatBytes: Int)(implicit p: Parameters) extends TLBusBypassBase(beatBytes) | ||||
| { | ||||
|   lazy val module = new LazyModuleImp(this) { | ||||
|     val io = new Bundle { | ||||
|       val in = nodeIn.bundleIn | ||||
|       val out = nodeOut.bundleOut | ||||
|     val io = IO(new Bundle { | ||||
|       val bypass = Bool(INPUT) | ||||
|     } | ||||
|     }) | ||||
|     bar.module.io.bypass := io.bypass | ||||
|   } | ||||
| } | ||||
| @@ -47,17 +46,13 @@ class TLBusBypassBar(implicit p: Parameters) extends LazyModule | ||||
|     managerFn = { seq => seq(1) }) | ||||
|  | ||||
|   lazy val module = new LazyModuleImp(this) { | ||||
|     val io = new Bundle { | ||||
|       val in  = node.bundleIn | ||||
|       val out = node.bundleOut | ||||
|     val io = IO(new Bundle { | ||||
|       val bypass = Bool(INPUT) | ||||
|     } | ||||
|     }) | ||||
|  | ||||
|     val in   = io.in(0) | ||||
|     val out0 = io.out(0) | ||||
|     val out1 = io.out(1) | ||||
|     val (in, edge) = node.in(0) | ||||
|     val Seq((out0,_), (out1,_)) = node.out | ||||
|  | ||||
|     val edge = node.edgesIn(0) | ||||
|     val bce = edge.manager.anySupportAcquireB && edge.client.anySupportProbe | ||||
|  | ||||
|     // We need to be locked to the given bypass direction until all transactions stop | ||||
|   | ||||
| @@ -53,11 +53,9 @@ class CoreplexLocalInterrupter(params: ClintParams)(implicit p: Parameters) exte | ||||
|     sinkFn         = { _ => IntSinkPortParameters(Seq(IntSinkParameters())) }) | ||||
|  | ||||
|   lazy val module = new LazyModuleImp(this) { | ||||
|     val io = new Bundle { | ||||
|     val io = IO(new Bundle { | ||||
|       val rtcTick = Bool(INPUT) | ||||
|       val int = intnode.bundleOut | ||||
|       val in = node.bundleIn | ||||
|     } | ||||
|     }) | ||||
|  | ||||
|     val time = Seq.fill(timeWidth/regWidth)(Reg(init=UInt(0, width = regWidth))) | ||||
|     when (io.rtcTick) { | ||||
| @@ -66,11 +64,12 @@ class CoreplexLocalInterrupter(params: ClintParams)(implicit p: Parameters) exte | ||||
|         reg := newTime >> i | ||||
|     } | ||||
|  | ||||
|     val nTiles = intnode.edgesOut.size | ||||
|     val nTiles = intnode.out.size | ||||
|     val timecmp = Seq.fill(nTiles) { Seq.fill(timeWidth/regWidth)(Reg(UInt(width = regWidth))) } | ||||
|     val ipi = Seq.fill(nTiles) { RegInit(UInt(0, width = 1)) } | ||||
|  | ||||
|     io.int.zipWithIndex.foreach { case (int, i) => | ||||
|     val (intnode_out, _) = intnode.out.unzip | ||||
|     intnode_out.zipWithIndex.foreach { case (int, i) => | ||||
|       int(0) := ShiftRegister(ipi(i)(0), params.intStages) // msip | ||||
|       int(1) := ShiftRegister(time.asUInt >= timecmp(i).asUInt, params.intStages) // mtip | ||||
|     } | ||||
|   | ||||
| @@ -40,15 +40,10 @@ class TLError(params: ErrorParams, beatBytes: Int = 4)(implicit p: Parameters) e | ||||
|     minLatency = 1))) // no bypass needed for this device | ||||
|  | ||||
|   lazy val module = new LazyModuleImp(this) { | ||||
|     val io = new Bundle { | ||||
|       val in = node.bundleIn | ||||
|     } | ||||
|  | ||||
|     import TLMessages._ | ||||
|     import TLPermissions._ | ||||
|  | ||||
|     val edge = node.edgesIn(0) | ||||
|     val in = io.in(0) | ||||
|     val (in, edge) = node.in(0) | ||||
|     val a = Queue(in.a, 1) | ||||
|     val c = Queue(in.c, 1) | ||||
|     val da = Wire(in.d) | ||||
|   | ||||
| @@ -24,21 +24,18 @@ trait HasPeripheryMaskROMSlave extends HasPeripheryBus { | ||||
|  | ||||
| class TLMaskROM(c: MaskROMParams)(implicit p: Parameters) extends LazyModule { | ||||
|   val beatBytes = c.width/8 | ||||
|   val node = TLManagerNode(beatBytes, TLManagerParameters( | ||||
|   val node = TLManagerNode(Seq(TLManagerPortParameters( | ||||
|     Seq(TLManagerParameters( | ||||
|       address            = AddressSet.misaligned(c.address, c.depth*beatBytes), | ||||
|       resources          = new SimpleDevice("rom", Seq("sifive,maskrom0")).reg("mem"), | ||||
|       regionType         = RegionType.UNCACHED, | ||||
|       executable         = true, | ||||
|       supportsGet        = TransferSizes(1, beatBytes), | ||||
|     fifoId             = Some(0))) // requests are handled in order | ||||
|       fifoId             = Some(0))), // requests are handled in order | ||||
|     beatBytes = beatBytes))) | ||||
|  | ||||
|   lazy val module = new LazyModuleImp(this) { | ||||
|     val io = new Bundle { | ||||
|       val in = node.bundleIn | ||||
|     } | ||||
|  | ||||
|     val in = io.in(0) | ||||
|     val edge = node.edgesIn(0) | ||||
|     val (in, edge)= node.in(0) | ||||
|  | ||||
|     val rom = ROMGenerator(ROMConfig(c.name, c.depth, c.width)) | ||||
|     rom.io.clock := clock | ||||
|   | ||||
| @@ -91,12 +91,12 @@ class TLPLIC(params: PLICParams)(implicit p: Parameters) extends LazyModule | ||||
|     sinkFn         = { _ => IntSinkPortParameters(Seq(IntSinkParameters())) }) | ||||
|  | ||||
|   /* Negotiated sizes */ | ||||
|   def nDevices: Int = intnode.edgesIn.map(_.source.num).sum | ||||
|   def nDevices: Int = intnode.edges.in.map(_.source.num).sum | ||||
|   def nPriorities = min(params.maxPriorities, nDevices) | ||||
|   def nHarts = intnode.edgesOut.map(_.source.num).sum | ||||
|   def nHarts = intnode.edges.out.map(_.source.num).sum | ||||
|  | ||||
|   // Assign all the devices unique ranges | ||||
|   lazy val sources = intnode.edgesIn.map(_.source) | ||||
|   lazy val sources = intnode.edges.in.map(_.source) | ||||
|   lazy val flatSources = (sources zip sources.map(_.num).scanLeft(0)(_+_).init).map { | ||||
|     case (s, o) => s.sources.map(z => z.copy(range = z.range.offset(o))) | ||||
|   }.flatten | ||||
| @@ -109,16 +109,13 @@ class TLPLIC(params: PLICParams)(implicit p: Parameters) extends LazyModule | ||||
|   } | ||||
|  | ||||
|   lazy val module = new LazyModuleImp(this) { | ||||
|     val io = new Bundle { | ||||
|       val tl_in = node.bundleIn | ||||
|       val devices = intnode.bundleIn | ||||
|       val harts = intnode.bundleOut | ||||
|     } | ||||
|     val (io_devices, edgesIn) = intnode.in.unzip | ||||
|     val (io_harts, _) = intnode.out.unzip | ||||
|  | ||||
|     // Compact the interrupt vector the same way | ||||
|     val interrupts = (intnode.edgesIn zip io.devices).map { case (e, i) => i.take(e.source.num) }.flatten | ||||
|     val interrupts = intnode.in.map { case (i, e) => i.take(e.source.num) }.flatten | ||||
|     // This flattens the harts into an MSMSMSMSMS... or MMMMM.... sequence | ||||
|     val harts = io.harts.flatten | ||||
|     val harts = io_harts.flatten | ||||
|  | ||||
|     println(s"Interrupt map (${nHarts} harts ${nDevices} interrupts):") | ||||
|     flatSources.foreach { s => | ||||
|   | ||||
| @@ -29,16 +29,11 @@ class TLTestRAM(address: AddressSet, executable: Boolean = true, beatBytes: Int | ||||
|   require ((address.mask & (beatBytes-1)) == beatBytes-1) | ||||
|  | ||||
|   lazy val module = new LazyModuleImp(this) { | ||||
|     val io = new Bundle { | ||||
|       val in = node.bundleIn | ||||
|     } | ||||
|  | ||||
|     def bigBits(x: BigInt, tail: List[Boolean] = List.empty[Boolean]): List[Boolean] = | ||||
|       if (x == 0) tail.reverse else bigBits(x >> 1, ((x & 1) == 1) :: tail) | ||||
|     val mask = bigBits(address.mask >> log2Ceil(beatBytes)) | ||||
|  | ||||
|     val in = io.in(0) | ||||
|     val edge = node.edgesIn(0) | ||||
|     val (in, edge) = node.in(0) | ||||
|  | ||||
|     val addrBits = (mask zip edge.addr_hi(in.a.bits).toBools).filter(_._1).map(_._2) | ||||
|     val memAddress = Cat(addrBits.reverse) | ||||
| @@ -75,7 +70,7 @@ class TLRAMZeroDelay(ramBeatBytes: Int, txns: Int)(implicit p: Parameters) exten | ||||
|   model.node := fuzz.node | ||||
|   ram.node := TLDelayer(0.25)(model.node) | ||||
|  | ||||
|   lazy val module = new LazyModuleImp(this) with HasUnitTestIO { | ||||
|   lazy val module = new LazyModuleImp(this) with UnitTestModule { | ||||
|     io.finished := fuzz.module.io.finished | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -24,12 +24,7 @@ class TLZero(address: AddressSet, resources: Seq[Resource], executable: Boolean | ||||
|     minLatency = 1))) // no bypass needed for this device | ||||
|  | ||||
|   lazy val module = new LazyModuleImp(this) { | ||||
|     val io = new Bundle { | ||||
|       val in = node.bundleIn | ||||
|     } | ||||
|  | ||||
|     val in = io.in(0) | ||||
|     val edge = node.edgesIn(0) | ||||
|     val (in, edge) = node.in(0) | ||||
|  | ||||
|     val a = Queue(in.a, 2) | ||||
|     val hasData = edge.hasData(a.bits) | ||||
|   | ||||
| @@ -6,6 +6,8 @@ import Chisel._ | ||||
| import chisel3.experimental.{BaseModule, RawModule, MultiIOModule, withClockAndReset} | ||||
| import chisel3.internal.sourceinfo.{SourceInfo, SourceLine, UnlocatableSourceInfo} | ||||
| import freechips.rocketchip.config.Parameters | ||||
| import scala.collection.immutable.ListMap | ||||
| import scala.util.matching._ | ||||
|  | ||||
| abstract class LazyModule()(implicit val p: Parameters) | ||||
| { | ||||
| @@ -13,9 +15,9 @@ abstract class LazyModule()(implicit val p: Parameters) | ||||
|   protected[diplomacy] var children = List[LazyModule]() | ||||
|   protected[diplomacy] var nodes = List[BaseNode]() | ||||
|   protected[diplomacy] var info: SourceInfo = UnlocatableSourceInfo | ||||
|   protected[diplomacy] val parent = LazyModule.stack.headOption | ||||
|   protected[diplomacy] val parent = LazyModule.scope | ||||
|  | ||||
|   LazyModule.stack = this :: LazyModule.stack | ||||
|   LazyModule.scope = Some(this) | ||||
|   parent.foreach(p => p.children = this :: p.children) | ||||
|  | ||||
|   private var suggestedName: Option[String] = None | ||||
| @@ -54,15 +56,6 @@ abstract class LazyModule()(implicit val p: Parameters) | ||||
|  | ||||
|   def module: LazyModuleImpLike | ||||
|  | ||||
|   protected[diplomacy] def instantiate() = { | ||||
|     children.reverse.foreach { c => | ||||
|       // !!! fix chisel3 so we can pass the desired sourceInfo | ||||
|       // implicit val sourceInfo = c.module.outer.info | ||||
|       Module(c.module) | ||||
|     } | ||||
|     bindings.reverse.foreach { f => f () } | ||||
|   } | ||||
|  | ||||
|   def omitGraphML: Boolean = !nodes.exists(!_.omitGraphML) && !children.exists(!_.omitGraphML) | ||||
|   lazy val graphML: String = parent.map(_.graphML).getOrElse { | ||||
|     val buf = new StringBuilder | ||||
| @@ -95,10 +88,11 @@ abstract class LazyModule()(implicit val p: Parameters) | ||||
|     buf ++= s"""${pad}</node>\n""" | ||||
|   } | ||||
|   private def edgesGraphML(buf: StringBuilder, pad: String) { | ||||
|     nodes.filter(!_.omitGraphML) foreach { n => n.outputs.filter(!_._1.omitGraphML).foreach { case (o, l) => | ||||
|     nodes.filter(!_.omitGraphML) foreach { n => n.outputs.filter(!_._1.omitGraphML).foreach { case (o, edge) => | ||||
|       val RenderedEdge(colour, label, flipped) = edge | ||||
|       buf ++= pad | ||||
|       buf ++= "<edge" | ||||
|       if (o.reverse) { | ||||
|       if (flipped) { | ||||
|         buf ++= s""" target=\"${index}::${n.index}\"""" | ||||
|         buf ++= s""" source=\"${o.lazyModule.index}::${o.index}\">""" | ||||
|       } else { | ||||
| @@ -106,13 +100,13 @@ abstract class LazyModule()(implicit val p: Parameters) | ||||
|         buf ++= s""" target=\"${o.lazyModule.index}::${o.index}\">""" | ||||
|       } | ||||
|       buf ++= s"""<data key=\"e\"><y:PolyLineEdge>""" | ||||
|       if (o.reverse) { | ||||
|       if (flipped) { | ||||
|         buf ++= s"""<y:Arrows source=\"standard\" target=\"none\"/>""" | ||||
|       } else { | ||||
|         buf ++= s"""<y:Arrows source=\"none\" target=\"standard\"/>""" | ||||
|       } | ||||
|       buf ++= s"""<y:LineStyle color=\"${o.colour}\" type=\"line\" width=\"1.0\"/>""" | ||||
|       buf ++= s"""<y:EdgeLabel modelName=\"centered\" rotationAngle=\"270.0\">${l}</y:EdgeLabel>""" | ||||
|       buf ++= s"""<y:LineStyle color=\"${colour}\" type=\"line\" width=\"1.0\"/>""" | ||||
|       buf ++= s"""<y:EdgeLabel modelName=\"centered\" rotationAngle=\"270.0\">${label}</y:EdgeLabel>""" | ||||
|       buf ++= s"""</y:PolyLineEdge></data></edge>\n""" | ||||
|     } } | ||||
|     children.filter(!_.omitGraphML).foreach { c => c.edgesGraphML(buf, pad) } | ||||
| @@ -126,16 +120,16 @@ abstract class LazyModule()(implicit val p: Parameters) | ||||
|  | ||||
| object LazyModule | ||||
| { | ||||
|   protected[diplomacy] var stack = List[LazyModule]() | ||||
|   protected[diplomacy] var scope: Option[LazyModule] = None | ||||
|   private var index = 0 | ||||
|  | ||||
|   def apply[T <: LazyModule](bc: T)(implicit sourceInfo: SourceInfo): T = { | ||||
|     // Make sure the user put LazyModule around modules in the correct order | ||||
|     // If this require fails, probably some grandchild was missing a LazyModule | ||||
|     // ... or you applied LazyModule twice | ||||
|     require (!stack.isEmpty, s"LazyModule() applied to ${bc.name} twice ${sourceLine(sourceInfo)}") | ||||
|     require (stack.head eq bc, s"LazyModule() applied to ${bc.name} before ${stack.head.name} ${sourceLine(sourceInfo)}") | ||||
|     stack = stack.tail | ||||
|     require (scope.isDefined, s"LazyModule() applied to ${bc.name} twice ${sourceLine(sourceInfo)}") | ||||
|     require (scope.get eq bc, s"LazyModule() applied to ${bc.name} before ${scope.get.name} ${sourceLine(sourceInfo)}") | ||||
|     scope = bc.parent | ||||
|     bc.info = sourceInfo | ||||
|     bc | ||||
|   } | ||||
| @@ -144,26 +138,96 @@ object LazyModule | ||||
| sealed trait LazyModuleImpLike extends BaseModule | ||||
| { | ||||
|   val wrapper: LazyModule | ||||
|   val auto: AutoBundle | ||||
|   protected[diplomacy] val dangles: Seq[Dangle] | ||||
|  | ||||
|   // .module had better not be accessed while LazyModules are still being built! | ||||
|   require (LazyModule.stack.isEmpty, s"${wrapper.name}.module was constructed before LazyModule() was run on ${LazyModule.stack.head.name}") | ||||
|   require (!LazyModule.scope.isDefined, s"${wrapper.name}.module was constructed before LazyModule() was run on ${LazyModule.scope.get.name}") | ||||
|  | ||||
|   override def desiredName = wrapper.moduleName | ||||
|   suggestName(wrapper.instanceName) | ||||
|  | ||||
|   implicit val p = wrapper.p | ||||
|  | ||||
|   protected[diplomacy] def instantiate() = { | ||||
|     val childDangles = wrapper.children.reverse.flatMap { c => | ||||
|       implicit val sourceInfo = c.info | ||||
|       Module(c.module).dangles | ||||
|     } | ||||
|     val nodeDangles = wrapper.nodes.reverse.flatMap(_.instantiate()) | ||||
|     val allDangles = nodeDangles ++ childDangles | ||||
|     val done = Set() ++ allDangles.groupBy(_.source).values.filter(_.size == 2).map { case Seq(a, b) => | ||||
|       require (a.flipped != b.flipped) | ||||
|       if (a.flipped) { a.data <> b.data } else { b.data <> a.data } | ||||
|       a.source | ||||
|     } | ||||
|     val forward = allDangles.filter(d => !done(d.source)) | ||||
|     val auto = IO(new AutoBundle(forward.map { d => (d.name, d.data, d.flipped) }:_*)) | ||||
|     val dangles = (forward zip auto.elements) map { case (d, (_, io)) => | ||||
|       if (d.flipped) { d.data <> io } else { io <> d.data } | ||||
|       d.copy(data = io, name = wrapper.valName.getOrElse("anon") + "_" + d.name) | ||||
|     } | ||||
|     wrapper.bindings.reverse.foreach { f => f () } | ||||
|     (auto, dangles) | ||||
|   } | ||||
| } | ||||
|  | ||||
| abstract class LazyModuleImp(val wrapper: LazyModule) extends Module with LazyModuleImpLike { | ||||
|   wrapper.instantiate() | ||||
| class LazyModuleImp(val wrapper: LazyModule) extends MultiIOModule with LazyModuleImpLike { | ||||
|   val (auto, dangles) = instantiate() | ||||
| } | ||||
|  | ||||
| abstract class LazyMultiIOModuleImp(val wrapper: LazyModule) extends MultiIOModule with LazyModuleImpLike { | ||||
|   wrapper.instantiate() | ||||
| class LazyRawModuleImp(val wrapper: LazyModule) extends RawModule with LazyModuleImpLike { | ||||
|   val (auto, dangles) = withClockAndReset(Bool(false).asClock, Bool(true)) { | ||||
|     instantiate() | ||||
|   } | ||||
| } | ||||
|  | ||||
| abstract class LazyRawModuleImp(val wrapper: LazyModule) extends RawModule with LazyModuleImpLike { | ||||
|   withClockAndReset(Bool(false).asClock, Bool(true)) { | ||||
|     wrapper.instantiate() | ||||
| class SimpleLazyModule(implicit p: Parameters) extends LazyModule | ||||
| { | ||||
|   lazy val module = new LazyModuleImp(this) | ||||
| } | ||||
|  | ||||
| trait LazyScope | ||||
| { | ||||
|   this: LazyModule => | ||||
|   def apply[T](body: => T)(implicit p: Parameters) = { | ||||
|     val saved = LazyModule.scope | ||||
|     LazyModule.scope = Some(this) | ||||
|     val out = body | ||||
|     require (LazyModule.scope.isDefined, s"LazyScope ${name} tried to exit, but scope was empty!") | ||||
|     require (LazyModule.scope.get eq this, s"LazyScope ${name} exited before LazyModule ${LazyModule.scope.get.name} was closed") | ||||
|     LazyModule.scope = saved | ||||
|     out | ||||
|   } | ||||
| } | ||||
|  | ||||
| object LazyScope | ||||
| { | ||||
|   def apply[T](name: String)(body: => T)(implicit p: Parameters) = { | ||||
|     val scope = LazyModule(new SimpleLazyModule with LazyScope) | ||||
|     scope.suggestName(name) | ||||
|     scope { body } | ||||
|   } | ||||
| } | ||||
|  | ||||
| case class HalfEdge(serial: Int, index: Int) | ||||
| case class Dangle(source: HalfEdge, sink: HalfEdge, flipped: Boolean, name: String, data: Data) | ||||
|  | ||||
| final class AutoBundle(elts: (String, Data, Boolean)*) extends Record { | ||||
|   // We need to preserve the order of elts, despite grouping by name to disambiguate things | ||||
|   val elements = ListMap() ++ elts.zipWithIndex.map(makeElements).groupBy(_._1).values.flatMap { | ||||
|     case Seq((key, element, i)) => Seq(i -> (key -> element)) | ||||
|     case seq => seq.zipWithIndex.map { case ((key, element, i), j) => i -> (key + "_" + j -> element) } | ||||
|   }.toList.sortBy(_._1).map(_._2) | ||||
|   require (elements.size == elts.size) | ||||
|  | ||||
|   private def makeElements(tuple: ((String, Data, Boolean), Int)) = { | ||||
|     val ((key, data, flip), i) = tuple | ||||
|     // trim trailing _0_1_2 stuff so that when we append _# we don't create collisions | ||||
|     val regex = new Regex("(_[0-9]+)*$") | ||||
|     val element = if (flip) data.cloneType.flip else data.cloneType | ||||
|     (regex.replaceAllIn(key, ""), element, i) | ||||
|   } | ||||
|  | ||||
|   override def cloneType = (new AutoBundle(elts:_*)).asInstanceOf[this.type] | ||||
| } | ||||
|   | ||||
| @@ -1,10 +0,0 @@ | ||||
| // See LICENSE.SiFive for license details. | ||||
|  | ||||
| package freechips.rocketchip.diplomacy | ||||
|  | ||||
| import chisel3.internal.sourceinfo.{SourceInfo, SourceLine} | ||||
| import freechips.rocketchip.config.Parameters | ||||
|  | ||||
| abstract class MonitorBase(implicit val sourceInfo: SourceInfo, p: Parameters) extends LazyModule()(p) { | ||||
|   override val module: LazyModuleImp | ||||
| } | ||||
| @@ -7,6 +7,7 @@ import chisel3.internal.sourceinfo.SourceInfo | ||||
| import freechips.rocketchip.config.{Parameters,Field} | ||||
| import freechips.rocketchip.util.HeterogeneousBag | ||||
| import scala.collection.mutable.ListBuffer | ||||
| import scala.util.matching._ | ||||
|  | ||||
| object CardinalityInferenceDirection { | ||||
|   val cases = Seq(SOURCE_TO_SINK, SINK_TO_SOURCE, NO_INFERENCE) | ||||
| @@ -26,7 +27,13 @@ object CardinalityInferenceDirection { | ||||
| private case object CardinalityInferenceDirectionKey extends | ||||
|   Field[CardinalityInferenceDirection.T](CardinalityInferenceDirection.NO_INFERENCE) | ||||
|  | ||||
| private case object MonitorsEnabled extends Field[Boolean](true) | ||||
| case object MonitorsEnabled extends Field[Boolean](true) | ||||
| case object RenderFlipped extends Field[Boolean](false) | ||||
|  | ||||
| case class RenderedEdge( | ||||
|   colour:  String, | ||||
|   label:   String  = "", | ||||
|   flipped: Boolean = false) // prefer to draw the arrow pointing the opposite direction of other edges | ||||
|  | ||||
| // DI = Downwards flowing Parameters received on the inner side of the node | ||||
| // UI = Upwards   flowing Parameters generated by the inner side of the node | ||||
| @@ -34,19 +41,16 @@ private case object MonitorsEnabled extends Field[Boolean](true) | ||||
| // BI = Bundle type used when connecting to the inner side of the node | ||||
| trait InwardNodeImp[DI, UI, EI, BI <: Data] | ||||
| { | ||||
|   def edgeI(pd: DI, pu: UI): EI | ||||
|   def edgeI(pd: DI, pu: UI, p: Parameters, sourceInfo: SourceInfo): EI | ||||
|   def bundleI(ei: EI): BI | ||||
|   def colour: String | ||||
|   def reverse: Boolean = false | ||||
|   def connect(edges: () => Seq[EI], bundles: () => Seq[(BI, BI)], enableMonitoring: Boolean) | ||||
|               (implicit p: Parameters, sourceInfo: SourceInfo): (Option[MonitorBase], () => Unit) = { | ||||
|     (None, () => bundles().foreach { case (i, o) => i <> o }) | ||||
|   } | ||||
|  | ||||
|   // Edge functions | ||||
|   def monitor(bundle: BI, edge: EI) {} | ||||
|   def render(e: EI): RenderedEdge | ||||
|  | ||||
|   // optional methods to track node graph | ||||
|   def mixI(pu: UI, node: InwardNode[DI, UI, BI]): UI = pu // insert node into parameters | ||||
|   def getO(pu: UI): Option[BaseNode] = None // most-outward common node | ||||
|   def labelI(ei: EI) = "" | ||||
| } | ||||
|  | ||||
| // DO = Downwards flowing Parameters generated by the outer side of the node | ||||
| @@ -55,57 +59,80 @@ trait InwardNodeImp[DI, UI, EI, BI <: Data] | ||||
| // BO = Bundle type used when connecting to the outer side of the node | ||||
| trait OutwardNodeImp[DO, UO, EO, BO <: Data] | ||||
| { | ||||
|   def edgeO(pd: DO, pu: UO): EO | ||||
|   def edgeO(pd: DO, pu: UO, p: Parameters, sourceInfo: SourceInfo): EO | ||||
|   def bundleO(eo: EO): BO | ||||
|  | ||||
|   // optional methods to track node graph | ||||
|   def mixO(pd: DO, node: OutwardNode[DO, UO, BO]): DO = pd // insert node into parameters | ||||
|   def getI(pd: DO): Option[BaseNode] = None // most-inward common node | ||||
|   def labelO(eo: EO) = "" | ||||
| } | ||||
|  | ||||
| abstract class NodeImp[D, U, EO, EI, B <: Data] | ||||
|   extends Object with InwardNodeImp[D, U, EI, B] with OutwardNodeImp[D, U, EO, B] | ||||
|  | ||||
| abstract class BaseNode | ||||
| // If your edges have the same direction, using this saves you some typing | ||||
| abstract class SimpleNodeImp[D, U, E, B <: Data] | ||||
|   extends NodeImp[D, U, E, E, B] | ||||
| { | ||||
|   require (!LazyModule.stack.isEmpty, "You cannot create a node outside a LazyModule!") | ||||
|   def edge(pd: D, pu: U, p: Parameters, sourceInfo: SourceInfo): E | ||||
|   def edgeO(pd: D, pu: U, p: Parameters, sourceInfo: SourceInfo) = edge(pd, pu, p, sourceInfo) | ||||
|   def edgeI(pd: D, pu: U, p: Parameters, sourceInfo: SourceInfo) = edge(pd, pu, p, sourceInfo) | ||||
|   def bundle(e: E): B | ||||
|   def bundleO(e: E) = bundle(e) | ||||
|   def bundleI(e: E) = bundle(e) | ||||
| } | ||||
|  | ||||
|   val lazyModule = LazyModule.stack.head | ||||
| abstract class BaseNode(implicit val valName: ValName) | ||||
| { | ||||
|   require (LazyModule.scope.isDefined, "You cannot create a node outside a LazyModule!") | ||||
|  | ||||
|   val lazyModule = LazyModule.scope.get | ||||
|   val index = lazyModule.nodes.size | ||||
|   lazyModule.nodes = this :: lazyModule.nodes | ||||
|  | ||||
|   val externalIn: Boolean | ||||
|   val externalOut: Boolean | ||||
|   val serial = BaseNode.serial | ||||
|   BaseNode.serial = BaseNode.serial + 1 | ||||
|   protected[diplomacy] def instantiate(): Seq[Dangle] | ||||
|  | ||||
|   def nodename = getClass.getName.split('.').last | ||||
|   def name = lazyModule.name + "." + nodename | ||||
|   def name = lazyModule.name + "." + valName.name | ||||
|   def omitGraphML = outputs.isEmpty && inputs.isEmpty | ||||
|   lazy val nodedebugstring: String = "" | ||||
|  | ||||
|   protected[diplomacy] def gci: Option[BaseNode] // greatest common inner | ||||
|   protected[diplomacy] def gco: Option[BaseNode] // greatest common outer | ||||
|   protected[diplomacy] def outputs: Seq[(BaseNode, String)] | ||||
|   protected[diplomacy] def inputs:  Seq[(BaseNode, String)] | ||||
|   protected[diplomacy] def colour:  String | ||||
|   protected[diplomacy] def reverse: Boolean | ||||
|   def wirePrefix = { | ||||
|     val camelCase = "([a-z])([A-Z])".r | ||||
|     val decamel = camelCase.replaceAllIn(valName.name, _ match { case camelCase(l, h) => l + "_" + h }) | ||||
|     val trimNode = "_?node$".r | ||||
|     val name = trimNode.replaceFirstIn(decamel.toLowerCase, "") | ||||
|     if (name.isEmpty) "" else name + "_" | ||||
|   } | ||||
|  | ||||
|   protected[diplomacy] def gci: Option[BaseNode] // greatest common inner | ||||
|   protected[diplomacy] def gco: Option[BaseNode] // greatest common outer | ||||
|   protected[diplomacy] def inputs:  Seq[(BaseNode, RenderedEdge)] | ||||
|   protected[diplomacy] def outputs: Seq[(BaseNode, RenderedEdge)] | ||||
| } | ||||
|  | ||||
| object BaseNode | ||||
| { | ||||
|   protected[diplomacy] var serial = 0 | ||||
| } | ||||
|  | ||||
| // !!! rename the nodes we bind? | ||||
| case class NodeHandle[DI, UI, BI <: Data, DO, UO, BO <: Data] | ||||
|   (inward: InwardNode[DI, UI, BI], outward: OutwardNode[DO, UO, BO]) | ||||
|   (inwardHandle: InwardNodeHandle[DI, UI, BI], outwardHandle: OutwardNodeHandle[DO, UO, BO]) | ||||
|   extends Object with InwardNodeHandle[DI, UI, BI] with OutwardNodeHandle[DO, UO, BO] | ||||
| { | ||||
|   val inward = inwardHandle.inward | ||||
|   val outward = outwardHandle.outward | ||||
| } | ||||
|  | ||||
| trait InwardNodeHandle[DI, UI, BI <: Data] | ||||
| { | ||||
|   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) | ||||
|   def := (h: OutwardNodeHandle[DI, UI, BI])(implicit p: Parameters, sourceInfo: SourceInfo) { inward.:=(h)(p, sourceInfo) } | ||||
|   def :*= (h: OutwardNodeHandle[DI, UI, BI])(implicit p: Parameters, sourceInfo: SourceInfo) { inward.:*=(h)(p, sourceInfo) } | ||||
|   def :=* (h: OutwardNodeHandle[DI, UI, BI])(implicit p: Parameters, sourceInfo: SourceInfo) { inward.:=*(h)(p, sourceInfo) } | ||||
|   def :=? (h: OutwardNodeHandle[DI, UI, BI])(implicit p: Parameters, sourceInfo: SourceInfo) { inward.:=?(h)(p, sourceInfo) } | ||||
| } | ||||
|  | ||||
| sealed trait NodeBinding | ||||
| @@ -121,7 +148,7 @@ trait InwardNode[DI, UI, BI <: Data] extends BaseNode with InwardNodeHandle[DI, | ||||
|   require (!numPI.isEmpty, s"No number of inputs would be acceptable to ${name}${lazyModule.line}") | ||||
|   require (numPI.start >= 0, s"${name} accepts a negative number of inputs${lazyModule.line}") | ||||
|  | ||||
|   private val accPI = ListBuffer[(Int, OutwardNode[DI, UI, BI], NodeBinding, Parameters)]() | ||||
|   private val accPI = ListBuffer[(Int, OutwardNode[DI, UI, BI], NodeBinding, Parameters, SourceInfo)]() | ||||
|   private var iRealized = false | ||||
|  | ||||
|   protected[diplomacy] def iPushed = accPI.size | ||||
| @@ -129,8 +156,8 @@ trait InwardNode[DI, UI, BI <: Data] extends BaseNode with InwardNodeHandle[DI, | ||||
|     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, p)) | ||||
|     require (!iRealized, s"${name}${lazyModule.line} was incorrectly connected as a sink after its .module was used" + info) | ||||
|     accPI += ((index, node, binding, p, sourceInfo)) | ||||
|   } | ||||
|  | ||||
|   protected[diplomacy] lazy val iBindings = { iRealized = true; accPI.result() } | ||||
| @@ -138,7 +165,6 @@ 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] | ||||
|   protected[diplomacy] val bundleIn: HeterogeneousBag[BI] | ||||
| } | ||||
|  | ||||
| trait OutwardNodeHandle[DO, UO, BO <: Data] | ||||
| @@ -154,7 +180,7 @@ trait OutwardNode[DO, UO, BO <: Data] extends BaseNode with OutwardNodeHandle[DO | ||||
|   require (!numPO.isEmpty, s"No number of outputs would be acceptable to ${name}${lazyModule.line}") | ||||
|   require (numPO.start >= 0, s"${name} accepts a negative number of outputs${lazyModule.line}") | ||||
|  | ||||
|   private val accPO = ListBuffer[(Int, InwardNode [DO, UO, BO], NodeBinding, Parameters)]() | ||||
|   private val accPO = ListBuffer[(Int, InwardNode [DO, UO, BO], NodeBinding, Parameters, SourceInfo)]() | ||||
|   private var oRealized = false | ||||
|  | ||||
|   protected[diplomacy] def oPushed = accPO.size | ||||
| @@ -162,8 +188,8 @@ trait OutwardNode[DO, UO, BO <: Data] extends BaseNode with OutwardNodeHandle[DO | ||||
|     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, p)) | ||||
|     require (!oRealized, s"${name}${lazyModule.line} was incorrectly connected as a source after its .module was used" + info) | ||||
|     accPO += ((index, node, binding, p, sourceInfo)) | ||||
|   } | ||||
|  | ||||
|   protected[diplomacy] lazy val oBindings = { oRealized = true; accPO.result() } | ||||
| @@ -171,37 +197,46 @@ 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] | ||||
|   protected[diplomacy] val bundleOut: HeterogeneousBag[BO] | ||||
| } | ||||
|  | ||||
| abstract class MixedNode[DI, UI, EI, BI <: Data, DO, UO, EO, BO <: Data]( | ||||
| abstract class CycleException(kind: String, loop: Seq[String]) extends Exception(s"Diplomatic ${kind} cycle detected involving ${loop}") | ||||
| case class StarCycleException(loop: Seq[String] = Nil) extends CycleException("star", loop) | ||||
| case class DownwardCycleException(loop: Seq[String] = Nil) extends CycleException("downward", loop) | ||||
| case class UpwardCycleException(loop: Seq[String] = Nil) extends CycleException("upward", loop) | ||||
|  | ||||
| case class Edges[EI, EO](in: EI, out: EO) | ||||
| sealed abstract class MixedNode[DI, UI, EI, BI <: Data, DO, UO, EO, BO <: Data]( | ||||
|   inner: InwardNodeImp [DI, UI, EI, BI], | ||||
|   outer: OutwardNodeImp[DO, UO, EO, BO])( | ||||
|   protected[diplomacy] val numPO: Range.Inclusive, | ||||
|   protected[diplomacy] val numPI: Range.Inclusive) | ||||
|   protected[diplomacy] val numPI: Range.Inclusive)( | ||||
|   implicit valName: ValName) | ||||
|   extends BaseNode with InwardNode[DI, UI, BI] with OutwardNode[DO, UO, BO] | ||||
| { | ||||
|   protected[diplomacy] def resolveStar(iKnown: Int, oKnown: Int, iStar: Int, oStar: Int): (Int, Int) | ||||
|   protected[diplomacy] def mapParamsD(n: Int, p: Seq[DI]): Seq[DO] | ||||
|   protected[diplomacy] def mapParamsU(n: Int, p: Seq[UO]): Seq[UI] | ||||
|  | ||||
|   private var starCycleGuard = false | ||||
|   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 { | ||||
|     try { | ||||
|       if (starCycleGuard) throw StarCycleException() | ||||
|       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)(_+_) | ||||
| @@ -210,56 +245,102 @@ abstract class MixedNode[DI, UI, EI, BI <: Data, DO, UO, EO, BO <: Data]( | ||||
|       require(numPO.contains(oTotal), s"${name} has ${oTotal} outputs, expected ${numPO}${lazyModule.line}") | ||||
|       require(numPI.contains(iTotal), s"${name} has ${iTotal} inputs, expected ${numPI}${lazyModule.line}") | ||||
|       (oSum.init zip oSum.tail, iSum.init zip iSum.tail, oStar, iStar) | ||||
|     } catch { | ||||
|       case c: StarCycleException => throw c.copy(loop = s"${name}${lazyModule.line}" +: c.loop) | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   lazy val oPorts = oBindings.flatMap { case (i, n, _, _) => | ||||
|   lazy val oPorts = oBindings.flatMap { case (i, n, _, p, s) => | ||||
|     val (start, end) = n.iPortMapping(i) | ||||
|     (start until end) map { j => (j, n) } | ||||
|     (start until end) map { j => (j, n, p, s) } | ||||
|   } | ||||
|   lazy val iPorts = iBindings.flatMap { case (i, n, _, _) => | ||||
|   lazy val iPorts = iBindings.flatMap { case (i, n, _, p, s) => | ||||
|     val (start, end) = n.oPortMapping(i) | ||||
|     (start until end) map { j => (j, n) } | ||||
|     (start until end) map { j => (j, n, p, s) } | ||||
|   } | ||||
|  | ||||
|   private var oParamsCycleGuard = false | ||||
|   protected[diplomacy] lazy val oParams: Seq[DO] = { | ||||
|     val o = mapParamsD(oPorts.size, iPorts.map { case (i, n) => n.oParams(i) }) | ||||
|     try { | ||||
|       if (oParamsCycleGuard) throw DownwardCycleException() | ||||
|       oParamsCycleGuard = true | ||||
|       val o = mapParamsD(oPorts.size, iPorts.map { case (i, n, _, _) => n.oParams(i) }) | ||||
|       require (o.size == oPorts.size, s"Bug in diplomacy; ${name} has ${o.size} != ${oPorts.size} down/up outer parameters${lazyModule.line}") | ||||
|       o.map(outer.mixO(_, this)) | ||||
|     } catch { | ||||
|       case c: DownwardCycleException => throw c.copy(loop = s"${name}${lazyModule.line}" +: c.loop) | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   private var iParamsCycleGuard = false | ||||
|   protected[diplomacy] lazy val iParams: Seq[UI] = { | ||||
|     val i = mapParamsU(iPorts.size, oPorts.map { case (o, n) => n.iParams(o) }) | ||||
|     try { | ||||
|       if (iParamsCycleGuard) throw UpwardCycleException() | ||||
|       iParamsCycleGuard = true | ||||
|       val i = mapParamsU(iPorts.size, oPorts.map { case (o, n, _, _) => n.iParams(o) }) | ||||
|       require (i.size == iPorts.size, s"Bug in diplomacy; ${name} has ${i.size} != ${iPorts.size} up/down inner parameters${lazyModule.line}") | ||||
|       i.map(inner.mixI(_, this)) | ||||
|     } catch { | ||||
|       case c: UpwardCycleException => throw c.copy(loop = s"${name}${lazyModule.line}" +: c.loop) | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   protected[diplomacy] def gco = if (iParams.size != 1) None else inner.getO(iParams(0)) | ||||
|   protected[diplomacy] def gci = if (oParams.size != 1) None else outer.getI(oParams(0)) | ||||
|  | ||||
|   lazy val edgesOut = (oPorts zip oParams).map { case ((i, n), o) => outer.edgeO(o, n.iParams(i)) } | ||||
|   lazy val edgesIn  = (iPorts zip iParams).map { case ((o, n), i) => inner.edgeI(n.oParams(o), i) } | ||||
|   lazy val externalEdgesOut = if (externalOut) {edgesOut} else { Seq() } | ||||
|   lazy val externalEdgesIn = if (externalIn) {edgesIn} else { Seq() } | ||||
|   protected[diplomacy] lazy val edgesOut = (oPorts zip oParams).map { case ((i, n, p, s), o) => outer.edgeO(o, n.iParams(i), p, s) } | ||||
|   protected[diplomacy] lazy val edgesIn  = (iPorts zip iParams).map { case ((o, n, p, s), i) => inner.edgeI(n.oParams(o), i, p, s) } | ||||
|  | ||||
|   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 } } | ||||
|   // If you need access to the edges of a foreign Node, use this method (in/out create bundles) | ||||
|   lazy val edges = Edges(edgesIn, edgesOut) | ||||
|  | ||||
|   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 | ||||
|   val wire = false // needed if you want to grab access to from inside a module | ||||
|   private def wireO(b: HeterogeneousBag[BO]) = if (wire) Wire(b) else b | ||||
|   private def wireI(b: HeterogeneousBag[BI]) = if (wire) Wire(b) else b | ||||
|   protected[diplomacy] lazy val bundleOut: Seq[BO] = edgesOut.map(e => Wire(outer.bundleO(e))) | ||||
|   protected[diplomacy] lazy val bundleIn:  Seq[BI] = edgesIn .map(e => Wire(inner.bundleI(e))) | ||||
|  | ||||
|   lazy val bundleOut = wireO(flipO(HeterogeneousBag(edgesOut.map(outer.bundleO(_))))) | ||||
|   lazy val bundleIn  = wireI(flipI(HeterogeneousBag(edgesIn .map(inner.bundleI(_))))) | ||||
|   protected[diplomacy] def danglesOut: Seq[Dangle] = oPorts.zipWithIndex.map { case ((j, n, _, _), i) => | ||||
|     Dangle( | ||||
|       source = HalfEdge(serial, i), | ||||
|       sink   = HalfEdge(n.serial, j), | ||||
|       flipped= false, | ||||
|       name   = wirePrefix + "out", | ||||
|       data   = bundleOut(i)) | ||||
|   } | ||||
|   protected[diplomacy] def danglesIn: Seq[Dangle] = iPorts.zipWithIndex.map { case ((j, n, _, _), i) => | ||||
|     Dangle( | ||||
|       source = HalfEdge(n.serial, j), | ||||
|       sink   = HalfEdge(serial, i), | ||||
|       flipped= true, | ||||
|       name   = wirePrefix + "in", | ||||
|       data   = bundleIn(i)) | ||||
|   } | ||||
|  | ||||
|   private var bundlesSafeNow = false | ||||
|   // Accessors to the result of negotiation to be used in LazyModuleImp: | ||||
|   def out: Seq[(BO, EO)] = { | ||||
|     require(bundlesSafeNow, s"${name}.out should only be called from the context of its module implementation") | ||||
|     bundleOut zip edgesOut | ||||
|   } | ||||
|   def in: Seq[(BI, EI)] = { | ||||
|     require(bundlesSafeNow, s"${name}.in should only be called from the context of its module implementation") | ||||
|     bundleIn zip edgesIn | ||||
|   } | ||||
|  | ||||
|   // Used by LazyModules.module.instantiate | ||||
|   protected val identity = false | ||||
|   protected[diplomacy] def instantiate() = { | ||||
|     bundlesSafeNow = true | ||||
|     if (!identity) { | ||||
|       (iPorts zip in) foreach { | ||||
|         case ((_, _, p, _), (b, e)) => if (p(MonitorsEnabled)) inner.monitor(b, e) | ||||
|     } } | ||||
|     danglesOut ++ danglesIn | ||||
|   } | ||||
|  | ||||
|   // connects the outward part of a node with the inward part of this node | ||||
|   private def bind(h: OutwardNodeHandle[DI, UI, BI], binding: NodeBinding) | ||||
|                   (implicit p: Parameters, sourceInfo: SourceInfo): Option[MonitorBase] = { | ||||
|   private def bind(h: OutwardNodeHandle[DI, UI, BI], binding: NodeBinding)(implicit p: Parameters, sourceInfo: SourceInfo) { | ||||
|     val x = this // x := y | ||||
|     val y = h.outward | ||||
|     val info = sourceLine(sourceInfo, " at ", "") | ||||
|     require (!LazyModule.stack.isEmpty, s"${y.name} cannot be connected to ${x.name} outside of LazyModule scope" + info) | ||||
|     val i = x.iPushed | ||||
|     val o = y.oPushed | ||||
|     y.oPush(i, x, binding match { | ||||
| @@ -267,29 +348,12 @@ abstract class MixedNode[DI, UI, EI, BI <: Data, DO, UO, EO, BO <: Data]( | ||||
|       case BIND_STAR  => BIND_QUERY | ||||
|       case BIND_QUERY => BIND_STAR }) | ||||
|     x.iPush(o, y, binding) | ||||
|     def edges() = { | ||||
|       val (iStart, iEnd) = x.iPortMapping(i) | ||||
|       val (oStart, oEnd) = y.oPortMapping(o) | ||||
|       require (iEnd - iStart == oEnd - oStart, s"Bug in diplomacy; ${iEnd-iStart} != ${oEnd-oStart} means port resolution failed") | ||||
|       Seq.tabulate(iEnd - iStart) { j => x.edgesIn(iStart+j) } | ||||
|     } | ||||
|     def bundles() = { | ||||
|       val (iStart, iEnd) = x.iPortMapping(i) | ||||
|       val (oStart, oEnd) = y.oPortMapping(o) | ||||
|       require (iEnd - iStart == oEnd - oStart, s"Bug in diplomacy; ${iEnd-iStart} != ${oEnd-oStart} means port resolution failed") | ||||
|       Seq.tabulate(iEnd - iStart) { j => | ||||
|         (x.bundleIn(iStart+j), y.bundleOut(oStart+j)) | ||||
|       } | ||||
|     } | ||||
|     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) | ||||
|   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] = { | ||||
|   override def :=  (h: OutwardNodeHandle[DI, UI, BI])(implicit p: Parameters, sourceInfo: SourceInfo) = bind(h, BIND_ONCE) | ||||
|   override def :*= (h: OutwardNodeHandle[DI, UI, BI])(implicit p: Parameters, sourceInfo: SourceInfo) = bind(h, BIND_STAR) | ||||
|   override def :=* (h: OutwardNodeHandle[DI, UI, BI])(implicit p: Parameters, sourceInfo: SourceInfo) = bind(h, BIND_QUERY) | ||||
|   override def :=? (h: OutwardNodeHandle[DI, UI, BI])(implicit p: Parameters, sourceInfo: SourceInfo) = { | ||||
|     p(CardinalityInferenceDirectionKey) match { | ||||
|       case CardinalityInferenceDirection.SOURCE_TO_SINK => this :=* h | ||||
|       case CardinalityInferenceDirection.SINK_TO_SOURCE => this :*= h | ||||
| @@ -298,17 +362,19 @@ abstract class MixedNode[DI, UI, EI, BI <: Data, DO, UO, EO, BO <: Data]( | ||||
|   } | ||||
|  | ||||
|   // meta-data for printing the node graph | ||||
|   protected[diplomacy] def colour  = inner.colour | ||||
|   protected[diplomacy] def reverse = inner.reverse | ||||
|   protected[diplomacy] def outputs = oPorts.map(_._2) zip edgesOut.map(e => outer.labelO(e)) | ||||
|   protected[diplomacy] def inputs  = iPorts.map(_._2) zip edgesIn .map(e => inner.labelI(e)) | ||||
|   protected[diplomacy] def inputs = (iPorts zip edgesIn) map { case ((_, n, p, _), e) => | ||||
|     val re = inner.render(e) | ||||
|     (n, re.copy(flipped = re.flipped != p(RenderFlipped))) | ||||
|   } | ||||
|   protected[diplomacy] def outputs = oPorts map { case (i, n, _, _) => (n, n.inputs(i)._2) } | ||||
| } | ||||
|  | ||||
| abstract class MixedCustomNode[DI, UI, EI, BI <: Data, DO, UO, EO, BO <: Data]( | ||||
|   inner: InwardNodeImp [DI, UI, EI, BI], | ||||
|   outer: OutwardNodeImp[DO, UO, EO, BO])( | ||||
|   numPO: Range.Inclusive, | ||||
|   numPI: Range.Inclusive) | ||||
|   numPI: Range.Inclusive)( | ||||
|   implicit valName: ValName) | ||||
|   extends MixedNode(inner, outer)(numPO, numPI) | ||||
| { | ||||
|   def resolveStar(iKnown: Int, oKnown: Int, iStars: Int, oStars: Int): (Int, Int) | ||||
| @@ -318,7 +384,8 @@ abstract class MixedCustomNode[DI, UI, EI, BI <: Data, DO, UO, EO, BO <: Data]( | ||||
|  | ||||
| abstract class CustomNode[D, U, EO, EI, B <: Data](imp: NodeImp[D, U, EO, EI, B])( | ||||
|   numPO: Range.Inclusive, | ||||
|   numPI: Range.Inclusive) | ||||
|   numPI: Range.Inclusive)( | ||||
|   implicit valName: ValName) | ||||
|   extends MixedCustomNode(imp, imp)(numPO, numPI) | ||||
|  | ||||
| class MixedAdapterNode[DI, UI, EI, BI <: Data, DO, UO, EO, BO <: Data]( | ||||
| @@ -326,12 +393,10 @@ class MixedAdapterNode[DI, UI, EI, BI <: Data, DO, UO, EO, BO <: Data]( | ||||
|   outer: OutwardNodeImp[DO, UO, EO, BO])( | ||||
|   dFn: DI => DO, | ||||
|   uFn: UO => UI, | ||||
|   num: Range.Inclusive = 0 to 999) | ||||
|   num: Range.Inclusive = 0 to 999)( | ||||
|   implicit valName: ValName) | ||||
|   extends MixedNode(inner, outer)(num, num) | ||||
| { | ||||
|   val externalIn: Boolean = true | ||||
|   val externalOut: Boolean = true | ||||
|  | ||||
|   protected[diplomacy] def resolveStar(iKnown: Int, oKnown: Int, iStars: Int, oStars: Int): (Int, Int) = { | ||||
|     require (oStars + iStars <= 1, s"${name} (an adapter) appears left of a :*= ${iStars} times and right of a :=* ${oStars} times; at most once is allowed${lazyModule.line}") | ||||
|     if (oStars > 0) { | ||||
| @@ -352,21 +417,38 @@ class MixedAdapterNode[DI, UI, EI, BI <: Data, DO, UO, EO, BO <: Data]( | ||||
|   } | ||||
| } | ||||
|  | ||||
| class AdapterNode[D, U, EO, EI, B <: Data](imp: NodeImp[D, U, EO, EI, B])( | ||||
|   dFn: D => D, | ||||
|   uFn: U => U, | ||||
|   num: Range.Inclusive = 0 to 999)( | ||||
|   implicit valName: ValName) | ||||
|     extends MixedAdapterNode[D, U, EI, B, D, U, EO, B](imp, imp)(dFn, uFn, num) | ||||
|  | ||||
| // IdentityNodes automatically connect their inputs to outputs | ||||
| class IdentityNode[D, U, EO, EI, B <: Data](imp: NodeImp[D, U, EO, EI, B])()(implicit valName: ValName) | ||||
|   extends AdapterNode(imp)({ s => s }, { s => s }) | ||||
| { | ||||
|   protected override val identity = true | ||||
|   override protected[diplomacy] def instantiate() = { | ||||
|     val dangles = super.instantiate() | ||||
|     (out zip in) map { case ((o, _), (i, _)) => o <> i } | ||||
|     dangles | ||||
|   }  | ||||
| } | ||||
|  | ||||
| class MixedNexusNode[DI, UI, EI, BI <: Data, DO, UO, EO, BO <: Data]( | ||||
|   inner: InwardNodeImp [DI, UI, EI, BI], | ||||
|   outer: OutwardNodeImp[DO, UO, EO, BO])( | ||||
|   dFn: Seq[DI] => DO, | ||||
|   uFn: Seq[UO] => UI, | ||||
|   numPO: Range.Inclusive = 1 to 999, | ||||
|   numPI: Range.Inclusive = 1 to 999) | ||||
|   numPI: Range.Inclusive = 1 to 999)( | ||||
|   implicit valName: ValName) | ||||
|   extends MixedNode(inner, outer)(numPO, numPI) | ||||
| { | ||||
| //  require (numPO.end >= 1, s"${name} does not accept outputs${lazyModule.line}") | ||||
| //  require (numPI.end >= 1, s"${name} does not accept inputs${lazyModule.line}") | ||||
|  | ||||
|   val externalIn: Boolean = true | ||||
|   val externalOut: Boolean = true | ||||
|  | ||||
|   protected[diplomacy] def resolveStar(iKnown: Int, oKnown: Int, iStars: Int, oStars: Int): (Int, Int) = { | ||||
|     require (iStars == 0, s"${name} (a nexus) appears left of :*= (perhaps you should flip the '*' to :=*?)${lazyModule.line}") | ||||
|     require (oStars == 0, s"${name} (a nexus) appears right of a :=* (perhaps you should flip the '*' to :*=?)${lazyModule.line}") | ||||
| @@ -376,82 +458,18 @@ class MixedNexusNode[DI, UI, EI, BI <: Data, DO, UO, EO, BO <: Data]( | ||||
|   protected[diplomacy] def mapParamsU(n: Int, p: Seq[UO]): Seq[UI] = { val a = uFn(p); Seq.fill(n)(a) } | ||||
| } | ||||
|  | ||||
| class AdapterNode[D, U, EO, EI, B <: Data](imp: NodeImp[D, U, EO, EI, B])( | ||||
|   dFn: D => D, | ||||
|   uFn: U => U, | ||||
|   num: Range.Inclusive = 0 to 999) | ||||
|     extends MixedAdapterNode[D, U, EI, B, D, U, EO, B](imp, imp)(dFn, uFn, num) | ||||
|  | ||||
| class NexusNode[D, U, EO, EI, B <: Data](imp: NodeImp[D, U, EO, EI, B])( | ||||
|   dFn: Seq[D] => D, | ||||
|   uFn: Seq[U] => U, | ||||
|   numPO: Range.Inclusive = 1 to 999, | ||||
|   numPI: Range.Inclusive = 1 to 999) | ||||
|   numPI: Range.Inclusive = 1 to 999)( | ||||
|   implicit valName: ValName) | ||||
|     extends MixedNexusNode[D, U, EI, B, D, U, EO, B](imp, imp)(dFn, uFn, numPO, numPI) | ||||
|  | ||||
| case class SplitterArg[T](newSize: Int, ports: Seq[T]) | ||||
| class MixedSplitterNode[DI, UI, EI, BI <: Data, DO, UO, EO, BO <: Data]( | ||||
|   inner: InwardNodeImp [DI, UI, EI, BI], | ||||
|   outer: OutwardNodeImp[DO, UO, EO, BO])( | ||||
|   dFn: SplitterArg[DI] => Seq[DO], | ||||
|   uFn: SplitterArg[UO] => Seq[UI], | ||||
|   numPO: Range.Inclusive = 1 to 999, | ||||
|   numPI: Range.Inclusive = 1 to 999) | ||||
|   extends MixedNode(inner, outer)(numPO, numPI) | ||||
| { | ||||
|   override val externalIn: Boolean = true | ||||
|   override val externalOut: Boolean = true | ||||
|  | ||||
|   protected[diplomacy] def resolveStar(iKnown: Int, oKnown: Int, iStars: Int, oStars: Int): (Int, Int) = { | ||||
|     require (oKnown == 0, s"${name} (a splitter) appears right of a := or :*=; use a :=* instead${lazyModule.line}") | ||||
|     require (iStars == 0, s"${name} (a splitter) cannot appear left of a :*=; did you mean :=*?${lazyModule.line}") | ||||
|     (0, iKnown) | ||||
|   } | ||||
|   protected[diplomacy] def mapParamsD(n: Int, p: Seq[DI]): Seq[DO] = { | ||||
|     require (p.size == 0 || n % p.size == 0, s"Diplomacy bug; splitter inputs do not divide outputs") | ||||
|     val out = dFn(SplitterArg(n, p)) | ||||
|     require (out.size == n, s"${name} created the wrong number of outputs from inputs${lazyModule.line}") | ||||
|     out | ||||
|   } | ||||
|   protected[diplomacy] def mapParamsU(n: Int, p: Seq[UO]): Seq[UI] = { | ||||
|     require (n == 0 || p.size % n == 0, s"Diplomacy bug; splitter outputs indivisable by inputs") | ||||
|     val out = uFn(SplitterArg(n, p)) | ||||
|     require (out.size == n, s"${name} created the wrong number of inputs from outputs${lazyModule.line}") | ||||
|     out | ||||
|   } | ||||
| } | ||||
|  | ||||
| class SplitterNode[D, U, EO, EI, B <: Data](imp: NodeImp[D, U, EO, EI, B])( | ||||
|   dFn: SplitterArg[D] => Seq[D], | ||||
|   uFn: SplitterArg[U] => Seq[U], | ||||
|   numPO: Range.Inclusive = 1 to 999, | ||||
|   numPI: Range.Inclusive = 1 to 999) | ||||
|     extends MixedSplitterNode[D, U, EI, B, D, U, EO, B](imp, imp)(dFn, uFn, numPO, numPI) | ||||
|  | ||||
| class IdentityNode[D, U, EO, EI, B <: Data](imp: NodeImp[D, U, EO, EI, B]) | ||||
|   extends AdapterNode(imp)({s => s}, {s => s}) | ||||
|  | ||||
| class OutputNode[D, U, EO, EI, B <: Data](imp: NodeImp[D, U, EO, EI, B]) extends IdentityNode(imp) | ||||
| { | ||||
|   override val externalIn: Boolean = false | ||||
|   override val externalOut: Boolean = true | ||||
|   override lazy val bundleIn = bundleOut | ||||
| } | ||||
|  | ||||
| class InputNode[D, U, EO, EI, B <: Data](imp: NodeImp[D, U, EO, EI, B]) extends IdentityNode(imp) | ||||
| { | ||||
|   override val externalIn: Boolean = true | ||||
|   override val externalOut: Boolean = false | ||||
|  | ||||
|   override lazy val bundleOut = bundleIn | ||||
| } | ||||
|  | ||||
| class SourceNode[D, U, EO, EI, B <: Data](imp: NodeImp[D, U, EO, EI, B])(po: Seq[D]) | ||||
| // There are no Mixed SourceNodes | ||||
| class SourceNode[D, U, EO, EI, B <: Data](imp: NodeImp[D, U, EO, EI, B])(po: Seq[D])(implicit valName: ValName) | ||||
|   extends MixedNode(imp, imp)(po.size to po.size, 0 to 0) | ||||
| { | ||||
|   override val externalIn: Boolean = false | ||||
|   override val externalOut: Boolean = true | ||||
|  | ||||
|   protected[diplomacy] def resolveStar(iKnown: Int, oKnown: Int, iStars: Int, oStars: Int): (Int, Int) = { | ||||
|     require (oStars <= 1, s"${name} (a source) appears right of a :=* ${oStars} times; at most once is allowed${lazyModule.line}") | ||||
|     require (iStars == 0, s"${name} (a source) cannot appear left of a :*=${lazyModule.line}") | ||||
| @@ -461,16 +479,12 @@ class SourceNode[D, U, EO, EI, B <: Data](imp: NodeImp[D, U, EO, EI, B])(po: Seq | ||||
|   } | ||||
|   protected[diplomacy] def mapParamsD(n: Int, p: Seq[D]): Seq[D] = po | ||||
|   protected[diplomacy] def mapParamsU(n: Int, p: Seq[U]): Seq[U] = Seq() | ||||
|  | ||||
|   override lazy val bundleIn = { require(false, s"${name} has no bundleIn; try bundleOut?"); bundleOut } | ||||
| } | ||||
|  | ||||
| class SinkNode[D, U, EO, EI, B <: Data](imp: NodeImp[D, U, EO, EI, B])(pi: Seq[U]) | ||||
| // There are no Mixed SinkNodes | ||||
| class SinkNode[D, U, EO, EI, B <: Data](imp: NodeImp[D, U, EO, EI, B])(pi: Seq[U])(implicit valName: ValName) | ||||
|   extends MixedNode(imp, imp)(0 to 0, pi.size to pi.size) | ||||
| { | ||||
|   override val externalIn: Boolean = true | ||||
|   override val externalOut: Boolean = false | ||||
|  | ||||
|   protected[diplomacy] def resolveStar(iKnown: Int, oKnown: Int, iStars: Int, oStars: Int): (Int, Int) = { | ||||
|     require (iStars <= 1, s"${name} (a sink) appears left of a :*= ${iStars} times; at most once is allowed${lazyModule.line}") | ||||
|     require (oStars == 0, s"${name} (a sink) cannot appear right of a :=*${lazyModule.line}") | ||||
| @@ -480,40 +494,4 @@ class SinkNode[D, U, EO, EI, B <: Data](imp: NodeImp[D, U, EO, EI, B])(pi: Seq[U | ||||
|   } | ||||
|   protected[diplomacy] def mapParamsD(n: Int, p: Seq[D]): Seq[D] = Seq() | ||||
|   protected[diplomacy] def mapParamsU(n: Int, p: Seq[U]): Seq[U] = pi | ||||
|  | ||||
|   override lazy val bundleOut = { require(false, s"${name} has no bundleOut; try bundleIn?"); bundleIn } | ||||
| } | ||||
|  | ||||
| class BlindOutputNode[D, U, EO, EI, B <: Data](imp: NodeImp[D, U, EO, EI, B])(pi: Seq[U]) | ||||
|   extends SinkNode(imp)(pi) | ||||
| { | ||||
|   override val externalIn: Boolean = false | ||||
|   override val flip = true | ||||
|   override lazy val bundleOut = bundleIn | ||||
| } | ||||
|  | ||||
| class BlindInputNode[D, U, EO, EI, B <: Data](imp: NodeImp[D, U, EO, EI, B])(po: Seq[D]) | ||||
|   extends SourceNode(imp)(po) | ||||
| { | ||||
|   override val externalOut: Boolean = false | ||||
|   override val flip = true | ||||
|   override lazy val bundleIn = bundleOut | ||||
| } | ||||
|  | ||||
| class InternalOutputNode[D, U, EO, EI, B <: Data](imp: NodeImp[D, U, EO, EI, B])(pi: Seq[U]) | ||||
|   extends SinkNode(imp)(pi) | ||||
| { | ||||
|   override val externalIn: Boolean = false | ||||
|   override val externalOut: Boolean = false | ||||
|   override val wire = true | ||||
|   override lazy val bundleOut = bundleIn | ||||
| } | ||||
|  | ||||
| class InternalInputNode[D, U, EO, EI, B <: Data](imp: NodeImp[D, U, EO, EI, B])(po: Seq[D]) | ||||
|   extends SourceNode(imp)(po) | ||||
| { | ||||
|   override val externalIn: Boolean = false | ||||
|   override val externalOut: Boolean = false | ||||
|   override val wire = true | ||||
|   override lazy val bundleIn = bundleOut | ||||
| } | ||||
|   | ||||
| @@ -179,7 +179,7 @@ trait BindingScope | ||||
|  | ||||
|   private case class ExpandedValue(path: Seq[String], labels: Seq[String], value: Seq[ResourceValue]) | ||||
|   private lazy val eval: Unit = { | ||||
|     require (LazyModule.stack.isEmpty, "May not evaluate binding while still constructing LazyModules") | ||||
|     require (!LazyModule.scope.isDefined, "May not evaluate binding while still constructing LazyModules") | ||||
|     parentScope.foreach { _.eval } | ||||
|     resourceBindings = parentScope.map(_.resourceBindings).getOrElse(Nil) | ||||
|     BindingScope.active = Some(this) | ||||
| @@ -224,7 +224,7 @@ trait BindingScope | ||||
| object BindingScope | ||||
| { | ||||
|   protected[diplomacy] var active: Option[BindingScope] = None | ||||
|   protected[diplomacy] def find(m: Option[LazyModule] = LazyModule.stack.headOption): Option[BindingScope] = m.flatMap { | ||||
|   protected[diplomacy] def find(m: Option[LazyModule] = LazyModule.scope): Option[BindingScope] = m.flatMap { | ||||
|     case s: BindingScope => Some(s) | ||||
|     case x => find(x.parent) | ||||
|   } | ||||
|   | ||||
							
								
								
									
										13
									
								
								src/main/scala/diplomacy/ValName.scala
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								src/main/scala/diplomacy/ValName.scala
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,13 @@ | ||||
| // See LICENSE.SiFive for license details. | ||||
|  | ||||
| package freechips.rocketchip.diplomacy | ||||
|  | ||||
| import scala.language.experimental.macros | ||||
| import freechips.rocketchip.macros.ValNameImpl | ||||
|  | ||||
| case class ValName(name: String) | ||||
|  | ||||
| object ValName | ||||
| { | ||||
|   implicit def materialize(implicit x: ValNameImpl): ValName = ValName(x.name) | ||||
| } | ||||
| @@ -47,4 +47,7 @@ package object diplomacy | ||||
|   def DisableMonitors[T](body: Parameters => T)(implicit p: Parameters) = body(p.alterPartial { | ||||
|     case MonitorsEnabled => false | ||||
|   }) | ||||
|   def FlipRendering[T](body: Parameters => T)(implicit p: Parameters) = body(p.alterPartial { | ||||
|     case RenderFlipped => !p(RenderFlipped) | ||||
|   }) | ||||
| } | ||||
|   | ||||
| @@ -5,6 +5,7 @@ package freechips.rocketchip.groundtest | ||||
|  | ||||
| import Chisel._ | ||||
| import freechips.rocketchip.config._ | ||||
| import freechips.rocketchip.diplomacy._ | ||||
| import freechips.rocketchip.coreplex._ | ||||
| import freechips.rocketchip.rocket.{HellaCache, RocketCoreParams} | ||||
| import freechips.rocketchip.tile._ | ||||
| @@ -29,7 +30,7 @@ case object GroundTestTilesKey extends Field[Seq[GroundTestTileParams]] | ||||
|  | ||||
| abstract class GroundTestTile(params: GroundTestTileParams)(implicit p: Parameters) extends BaseTile(params)(p) { | ||||
|   val slave = None | ||||
|   val dcacheOpt = params.dcache.map { dc => HellaCache(0, dc.nMSHRs == 0) } | ||||
|   val dcacheOpt = params.dcache.map { dc => LazyModule(HellaCache(0, dc.nMSHRs == 0)) } | ||||
|   dcacheOpt.foreach { tileBus.node := _.node } | ||||
|  | ||||
|   override lazy val module = new GroundTestTileModule(this, () => new GroundTestTileBundle(this)) | ||||
|   | ||||
| @@ -37,11 +37,9 @@ class BusErrorUnit[T <: BusErrors](t: => T, params: BusErrorUnitParams)(implicit | ||||
|     beatBytes = p(XLen)/8) | ||||
|  | ||||
|   lazy val module = new LazyModuleImp(this) { | ||||
|     val io = new Bundle { | ||||
|       val tl = node.bundleIn | ||||
|       val interrupt = intNode.bundleOut | ||||
|     val io = IO(new Bundle { | ||||
|       val errors = t.flip | ||||
|     } | ||||
|     }) | ||||
|  | ||||
|     val sources = io.errors.toErrorList | ||||
|     val mask = sources.map(_.nonEmpty.B).asUInt | ||||
| @@ -61,7 +59,8 @@ class BusErrorUnit[T <: BusErrors](t: => T, params: BusErrorUnitParams)(implicit | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     io.interrupt.head(0) := (accrued & interrupt).orR | ||||
|     val (int_out, _) = intNode.out(0) | ||||
|     int_out(0) := (accrued & interrupt).orR | ||||
|  | ||||
|     def reg(r: UInt) = RegField(regWidth, r) | ||||
|     def maskedReg(r: UInt, m: UInt) = RegField(regWidth, r, RegWriteFn((v, d) => { when (v) { r := d & m }; true })) | ||||
|   | ||||
| @@ -56,28 +56,22 @@ class FrontendIO(implicit p: Parameters) extends CoreBundle()(p) { | ||||
| class Frontend(val icacheParams: ICacheParams, hartid: Int)(implicit p: Parameters) extends LazyModule { | ||||
|   lazy val module = new FrontendModule(this) | ||||
|   val icache = LazyModule(new ICache(icacheParams, hartid)) | ||||
|   val masterNode = TLOutputNode() | ||||
|   val slaveNode = TLInputNode() | ||||
|  | ||||
|   masterNode := icache.masterNode | ||||
|   // Avoid breaking tile dedup due to address constants in the monitor | ||||
|   DisableMonitors { implicit p => icache.slaveNode.map { _ := slaveNode } } | ||||
|   val masterNode = icache.masterNode | ||||
|   val slaveNode = icache.slaveNode | ||||
| } | ||||
|  | ||||
| class FrontendBundle(outer: Frontend) extends CoreBundle()(outer.p) | ||||
|     with HasExternallyDrivenTileConstants { | ||||
|   val cpu = new FrontendIO().flip | ||||
|   val ptw = new TLBPTWIO() | ||||
|   val tl_out = outer.masterNode.bundleOut | ||||
|   val tl_in = outer.slaveNode.bundleIn | ||||
|   val errors = new ICacheErrors | ||||
| } | ||||
|  | ||||
| class FrontendModule(outer: Frontend) extends LazyModuleImp(outer) | ||||
|     with HasCoreParameters | ||||
|     with HasL1ICacheParameters { | ||||
|   val io = new FrontendBundle(outer) | ||||
|   implicit val edge = outer.masterNode.edgesOut.head | ||||
|   val io = IO(new FrontendBundle(outer)) | ||||
|   implicit val edge = outer.masterNode.edges.out(0) | ||||
|   val icache = outer.icache.module | ||||
|   require(fetchWidth*coreInstBytes == outer.icacheParams.fetchBytes) | ||||
|  | ||||
|   | ||||
| @@ -176,15 +176,14 @@ class HellaCacheBundle(outer: HellaCache)(implicit p: Parameters) extends CoreBu | ||||
|   val hartid = UInt(INPUT, hartIdLen) | ||||
|   val cpu = (new HellaCacheIO).flip | ||||
|   val ptw = new TLBPTWIO() | ||||
|   val mem = outer.node.bundleOut | ||||
|   val errors = new DCacheErrors | ||||
| } | ||||
|  | ||||
| class HellaCacheModule(outer: HellaCache) extends LazyModuleImp(outer) | ||||
|     with HasL1HellaCacheParameters { | ||||
|   implicit val edge = outer.node.edgesOut(0) | ||||
|   val io = new HellaCacheBundle(outer) | ||||
|   val tl_out = io.mem(0) | ||||
|   implicit val edge = outer.node.edges.out(0) | ||||
|   val (tl_out, _) = outer.node.out(0) | ||||
|   val io = IO(new HellaCacheBundle(outer)) | ||||
|  | ||||
|   private val fifoManagers = edge.manager.managers.filter(TLFIFOFixer.allUncacheable) | ||||
|   fifoManagers.foreach { m => | ||||
| @@ -195,8 +194,7 @@ class HellaCacheModule(outer: HellaCache) extends LazyModuleImp(outer) | ||||
|  | ||||
| object HellaCache { | ||||
|   def apply(hartid: Int, blocking: Boolean, scratch: () => Option[AddressSet] = () => None)(implicit p: Parameters) = { | ||||
|     if (blocking) LazyModule(new DCache(hartid, scratch)) | ||||
|     else LazyModule(new NonBlockingDCache(hartid)) | ||||
|     if (blocking) new DCache(hartid, scratch) else new NonBlockingDCache(hartid) | ||||
|   } | ||||
| } | ||||
|  | ||||
| @@ -208,7 +206,7 @@ trait HasHellaCache extends HasTileLinkMasterPort with HasTileParameters { | ||||
|   def findScratchpadFromICache: Option[AddressSet] | ||||
|   val hartid: Int | ||||
|   var nDCachePorts = 0 | ||||
|   val dcache = HellaCache(hartid, tileParams.dcache.get.nMSHRs == 0, findScratchpadFromICache _) | ||||
|   val dcache = LazyModule(HellaCache(hartid, tileParams.dcache.get.nMSHRs == 0, findScratchpadFromICache _)) | ||||
|   tileBus.node := dcache.node | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -45,15 +45,15 @@ class ICacheErrors(implicit p: Parameters) extends CoreBundle()(p) | ||||
|  | ||||
| class ICache(val icacheParams: ICacheParams, val hartid: Int)(implicit p: Parameters) extends LazyModule { | ||||
|   lazy val module = new ICacheModule(this) | ||||
|   val masterNode = TLClientNode(TLClientParameters( | ||||
|   val masterNode = TLClientNode(Seq(TLClientPortParameters(Seq(TLClientParameters( | ||||
|     sourceId = IdRange(0, 1 + icacheParams.prefetch.toInt), // 0=refill, 1=hint | ||||
|     name = s"Core ${hartid} ICache")) | ||||
|     name = s"Core ${hartid} ICache"))))) | ||||
|  | ||||
|   val size = icacheParams.nSets * icacheParams.nWays * icacheParams.blockBytes | ||||
|   val device = new SimpleDevice("itim", Seq("sifive,itim0")) | ||||
|   val slaveNode = icacheParams.itimAddr.map { itimAddr => | ||||
|     val wordBytes = icacheParams.fetchBytes | ||||
|     TLManagerNode(Seq(TLManagerPortParameters( | ||||
|   private val wordBytes = icacheParams.fetchBytes | ||||
|   val slaveNode = | ||||
|     TLManagerNode(icacheParams.itimAddr.toSeq.map { itimAddr => TLManagerPortParameters( | ||||
|       Seq(TLManagerParameters( | ||||
|         address         = Seq(AddressSet(itimAddr, size-1)), | ||||
|         resources       = device.reg("mem"), | ||||
| @@ -64,8 +64,7 @@ class ICache(val icacheParams: ICacheParams, val hartid: Int)(implicit p: Parame | ||||
|         supportsGet     = TransferSizes(1, wordBytes), | ||||
|         fifoId          = Some(0))), // requests handled in FIFO order | ||||
|       beatBytes = wordBytes, | ||||
|       minLatency = 1))) | ||||
|   } | ||||
|       minLatency = 1)}) | ||||
| } | ||||
|  | ||||
| class ICacheResp(outer: ICache) extends Bundle { | ||||
| @@ -91,8 +90,6 @@ class ICacheBundle(outer: ICache) extends CoreBundle()(outer.p) { | ||||
|  | ||||
|   val resp = Valid(new ICacheResp(outer)) | ||||
|   val invalidate = Bool(INPUT) | ||||
|   val tl_out = outer.masterNode.bundleOut | ||||
|   val tl_in = outer.slaveNode.map(_.bundleIn) | ||||
|  | ||||
|   val errors = new ICacheErrors | ||||
|   val perf = new ICachePerfEvents().asOutput | ||||
| @@ -109,11 +106,10 @@ class ICacheModule(outer: ICache) extends LazyModuleImp(outer) | ||||
|     with HasL1ICacheParameters { | ||||
|   override val cacheParams = outer.icacheParams // Use the local parameters | ||||
|  | ||||
|   val io = new ICacheBundle(outer) | ||||
|   val edge_out = outer.masterNode.edgesOut.head | ||||
|   val tl_out = io.tl_out.head | ||||
|   val edge_in = outer.slaveNode.map(_.edgesIn.head) | ||||
|   val tl_in = io.tl_in.map(_.head) | ||||
|   val io = IO(new ICacheBundle(outer)) | ||||
|   val (tl_out, edge_out) = outer.masterNode.out(0) | ||||
|   // Option.unzip does not exist :-( | ||||
|   val (tl_in, edge_in) = outer.slaveNode.in.headOption.unzip | ||||
|  | ||||
|   val tECC = cacheParams.tagECC | ||||
|   val dECC = cacheParams.dataECC | ||||
|   | ||||
| @@ -283,7 +283,7 @@ trait CanHavePTW extends HasHellaCache { | ||||
| trait CanHavePTWModule extends HasHellaCacheModule { | ||||
|   val outer: CanHavePTW | ||||
|   val ptwPorts = ListBuffer(outer.dcache.module.io.ptw) | ||||
|   val ptw = Module(new PTW(outer.nPTWPorts)(outer.dcache.node.edgesOut(0), outer.p)) | ||||
|   val ptw = Module(new PTW(outer.nPTWPorts)(outer.dcache.node.edges.out(0), outer.p)) | ||||
|   if (outer.usingPTW) | ||||
|     dcachePorts += ptw.io.mem | ||||
| } | ||||
|   | ||||
| @@ -30,13 +30,11 @@ class ScratchpadSlavePort(address: AddressSet, coreDataBytes: Int, usingAtomics: | ||||
|     minLatency = 1))) | ||||
|  | ||||
|   lazy val module = new LazyModuleImp(this) { | ||||
|     val io = new Bundle { | ||||
|       val tl_in = node.bundleIn | ||||
|     val io = IO(new Bundle { | ||||
|       val dmem = new HellaCacheIO | ||||
|     } | ||||
|     }) | ||||
|  | ||||
|     val tl_in = io.tl_in(0) | ||||
|     val edge = node.edgesIn(0) | ||||
|     val (tl_in, edge) = node.in(0) | ||||
|  | ||||
|     val s_ready :: s_wait :: s_replay :: s_grant :: Nil = Enum(UInt(), 4) | ||||
|     val state = Reg(init = s_ready) | ||||
| @@ -104,7 +102,7 @@ trait CanHaveScratchpad extends HasHellaCache with HasICacheFrontend { | ||||
|     LazyModule(new ScratchpadSlavePort(AddressSet(s, d.dataScratchpadBytes-1), xBytes, tileParams.core.useAtomics))) | ||||
|   } | ||||
|  | ||||
|   val intOutputNode = tileParams.core.tileControlAddr.map(dummy => IntOutputNode()) | ||||
|   val intOutputNode = tileParams.core.tileControlAddr.map(dummy => IntIdentityNode()) | ||||
|   val busErrorUnit = tileParams.core.tileControlAddr map { a => | ||||
|     val beu = LazyModule(new BusErrorUnit(new L1BusErrors, BusErrorUnitParams(a))) | ||||
|     intOutputNode.get := beu.intNode | ||||
| @@ -112,7 +110,7 @@ trait CanHaveScratchpad extends HasHellaCache with HasICacheFrontend { | ||||
|   } | ||||
|  | ||||
|   // connect any combination of ITIM, DTIM, and BusErrorUnit | ||||
|   val slaveNode = TLInputNode() | ||||
|   val slaveNode = TLIdentityNode() | ||||
|   DisableMonitors { implicit p => | ||||
|     val xbarPorts = | ||||
|       scratch.map(lm => (lm.node, xBytes)) ++ | ||||
| @@ -129,7 +127,7 @@ trait CanHaveScratchpad extends HasHellaCache with HasICacheFrontend { | ||||
|   } | ||||
|  | ||||
|   def findScratchpadFromICache: Option[AddressSet] = scratch.map { s => | ||||
|     val finalNode = frontend.masterNode.edgesOut.head.manager.managers.find(_.nodePath.last == s.node) | ||||
|     val finalNode = frontend.masterNode.edges.out.head.manager.managers.find(_.nodePath.last == s.node) | ||||
|     require (finalNode.isDefined, "Could not find the scratch pad; not reachable via icache?") | ||||
|     require (finalNode.get.address.size == 1, "Scratchpad address space was fragmented!") | ||||
|     finalNode.get.address(0) | ||||
| @@ -140,8 +138,6 @@ trait CanHaveScratchpad extends HasHellaCache with HasICacheFrontend { | ||||
|  | ||||
| trait CanHaveScratchpadBundle extends HasHellaCacheBundle with HasICacheFrontendBundle { | ||||
|   val outer: CanHaveScratchpad | ||||
|   val slave = outer.slaveNode.bundleIn | ||||
|   val intOutput = outer.intOutputNode.map(_.bundleOut) | ||||
| } | ||||
|  | ||||
| trait CanHaveScratchpadModule extends HasHellaCacheModule with HasICacheFrontendModule { | ||||
|   | ||||
| @@ -66,21 +66,20 @@ abstract class BareTileBundle[+L <: BareTile](_outer: L) extends GenericParamete | ||||
|  | ||||
| abstract class BareTileModule[+L <: BareTile, +B <: BareTileBundle[L]](_outer: L, _io: () => B) extends LazyModuleImp(_outer) { | ||||
|   val outer = _outer | ||||
|   val io = _io () | ||||
|   val io = IO(_io ()) | ||||
| } | ||||
|  | ||||
| /** Uses TileLink master port to connect caches and accelerators to the coreplex */ | ||||
| trait HasTileLinkMasterPort { | ||||
|   implicit val p: Parameters | ||||
|   val module: HasTileLinkMasterPortModule | ||||
|   val masterNode = TLOutputNode() | ||||
|   val masterNode = TLIdentityNode() | ||||
|   val tileBus = LazyModule(new TLXbar) // TileBus xbar for cache backends to connect to | ||||
|   masterNode := tileBus.node | ||||
| } | ||||
|  | ||||
| trait HasTileLinkMasterPortBundle { | ||||
|   val outer: HasTileLinkMasterPort | ||||
|   val master = outer.masterNode.bundleOut | ||||
| } | ||||
|  | ||||
| trait HasTileLinkMasterPortModule { | ||||
|   | ||||
| @@ -38,7 +38,6 @@ trait HasExternalInterrupts extends HasTileParameters { | ||||
|  | ||||
| trait HasExternalInterruptsBundle { | ||||
|   val outer: HasExternalInterrupts | ||||
|   val interrupts = outer.intNode.bundleIn | ||||
| } | ||||
|  | ||||
| trait HasExternalInterruptsModule { | ||||
| @@ -57,6 +56,7 @@ trait HasExternalInterruptsModule { | ||||
|  | ||||
|     val core_ips = core.lip | ||||
|  | ||||
|     (async_ips ++ periph_ips ++ seip ++ core_ips).zip(io.interrupts(0)).foreach { case(c, i) => c := i } | ||||
|     val (interrupts, _) = outer.intNode.in(0) | ||||
|     (async_ips ++ periph_ips ++ seip ++ core_ips).zip(interrupts).foreach { case(c, i) => c := i } | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -60,13 +60,11 @@ class RoCCCoreIO(implicit p: Parameters) extends CoreBundle()(p) { | ||||
| abstract class LazyRoCC(implicit p: Parameters) extends LazyModule { | ||||
|   val module: LazyRoCCModule | ||||
|  | ||||
|   val atlNode: TLMixedNode = TLOutputNode() | ||||
|   val tlNode: TLMixedNode = TLOutputNode() | ||||
|   val atlNode: TLMixedNode = TLIdentityNode() | ||||
|   val tlNode: TLMixedNode = TLIdentityNode() | ||||
| } | ||||
|  | ||||
| class RoCCIO(outer: LazyRoCC)(implicit p: Parameters) extends RoCCCoreIO()(p) { | ||||
|   val atl = outer.atlNode.bundleOut | ||||
|   val tl = outer.tlNode.bundleOut | ||||
|   // Should be handled differently, eventually | ||||
|   val ptw = Vec(p(RoccNPTWPorts), new TLBPTWIO) | ||||
|   val fpu_req = Decoupled(new FPInput) | ||||
| @@ -74,7 +72,7 @@ class RoCCIO(outer: LazyRoCC)(implicit p: Parameters) extends RoCCCoreIO()(p) { | ||||
| } | ||||
|  | ||||
| class LazyRoCCModule(outer: LazyRoCC) extends LazyModuleImp(outer) { | ||||
|   val io = new RoCCIO(outer) | ||||
|   val io = IO(new RoCCIO(outer)) | ||||
| } | ||||
|  | ||||
| /** Mixins for including RoCC **/ | ||||
| @@ -263,7 +261,7 @@ class TranslatorExampleModule(outer: TranslatorExample)(implicit p: Parameters) | ||||
|  | ||||
| class  CharacterCountExample(implicit p: Parameters) extends LazyRoCC { | ||||
|   override lazy val module = new CharacterCountExampleModule(this) | ||||
|   override val atlNode = TLClientNode(TLClientParameters("CharacterCountRoCC")) | ||||
|   override val atlNode = TLClientNode(Seq(TLClientPortParameters(Seq(TLClientParameters("CharacterCountRoCC"))))) | ||||
| } | ||||
|  | ||||
| class CharacterCountExampleModule(outer: CharacterCountExample)(implicit p: Parameters) extends LazyRoCCModule(outer) | ||||
| @@ -286,7 +284,7 @@ class CharacterCountExampleModule(outer: CharacterCountExample)(implicit p: Para | ||||
|   val s_idle :: s_acq :: s_gnt :: s_check :: s_resp :: Nil = Enum(Bits(), 5) | ||||
|   val state = Reg(init = s_idle) | ||||
|  | ||||
|   val tl_out = io.atl.head | ||||
|   val (tl_out, edgesOut) = outer.atlNode.out(0) | ||||
|   val gnt = tl_out.d.bits | ||||
|   val recv_data = Reg(UInt(width = cacheDataBits)) | ||||
|   val recv_beat = Reg(UInt(width = log2Up(cacheDataBeats+1)), init = UInt(0)) | ||||
| @@ -309,7 +307,7 @@ class CharacterCountExampleModule(outer: CharacterCountExample)(implicit p: Para | ||||
|   io.resp.bits.rd := resp_rd | ||||
|   io.resp.bits.data := count | ||||
|   tl_out.a.valid := (state === s_acq) | ||||
|   tl_out.a.bits := outer.atlNode.edgesOut(0).Get( | ||||
|   tl_out.a.bits := edgesOut.Get( | ||||
|                        fromSource = UInt(0), | ||||
|                        toAddress = addr_block << blockOffset, | ||||
|                        lgSize = UInt(lgCacheBlockBytes))._2 | ||||
|   | ||||
| @@ -57,7 +57,7 @@ class RocketTile(val rocketParams: RocketTileParams, val hartid: Int)(implicit p | ||||
|       val dtim = scratch.map(d => Map( | ||||
|         "sifive,dtim"          -> ofRef(d.device))).getOrElse(Map()) | ||||
|  | ||||
|       val itim = if (!frontend.icache.slaveNode.isDefined) Map() else Map( | ||||
|       val itim = if (frontend.icache.slaveNode.edges.in.isEmpty) Map() else Map( | ||||
|         "sifive,itim"          -> ofRef(frontend.icache.device)) | ||||
|  | ||||
|       val icache = rocketParams.icache.map(i => Map( | ||||
| @@ -82,7 +82,7 @@ class RocketTile(val rocketParams: RocketTileParams, val hartid: Int)(implicit p | ||||
|       })) | ||||
|  | ||||
|       // Find all the caches | ||||
|       val outer = masterNode.edgesOut | ||||
|       val outer = masterNode.edges.out | ||||
|         .flatMap(_.manager.managers) | ||||
|         .filter(_.supportsAcquireB) | ||||
|         .flatMap(_.resources.headOption) | ||||
| @@ -115,7 +115,7 @@ class RocketTile(val rocketParams: RocketTileParams, val hartid: Int)(implicit p | ||||
|     Resource(cpuDevice, "reg").bind(ResourceInt(BigInt(hartid))) | ||||
|     Resource(intcDevice, "reg").bind(ResourceInt(BigInt(hartid))) | ||||
|  | ||||
|     intNode.edgesIn.flatMap(_.source.sources).map { case s => | ||||
|     intNode.edges.in.flatMap(_.source.sources).map { case s => | ||||
|       for (i <- s.range.start until s.range.end) { | ||||
|        csrIntMap.lift(i).foreach { j => | ||||
|           s.resources.foreach { r => | ||||
| @@ -181,12 +181,10 @@ class RocketTileModule(outer: RocketTile) extends BaseTileModule(outer, () => ne | ||||
|  | ||||
| abstract class RocketTileWrapper(rtp: RocketTileParams, hartid: Int)(implicit p: Parameters) extends LazyModule { | ||||
|   val rocket = LazyModule(new RocketTile(rtp, hartid)) | ||||
|   val masterNode: OutputNode[_,_,_,_,_] | ||||
|   val slaveNode: InputNode[_,_,_,_,_] | ||||
|   val intOutputNode = rocket.intOutputNode.map(dummy => IntOutputNode()) | ||||
|   val asyncIntNode   = IntInputNode() | ||||
|   val periphIntNode  = IntInputNode() | ||||
|   val coreIntNode    = IntInputNode() | ||||
|   val asyncIntNode   : IntInwardNode | ||||
|   val periphIntNode  : IntInwardNode | ||||
|   val coreIntNode    : IntInwardNode | ||||
|   val intOutputNode = rocket.intOutputNode | ||||
|   val intXbar = LazyModule(new IntXbar) | ||||
|  | ||||
|   rocket.intNode := intXbar.intnode | ||||
| @@ -201,33 +199,25 @@ abstract class RocketTileWrapper(rtp: RocketTileParams, hartid: Int)(implicit p: | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   def optionalSlaveBuffer(in: TLOutwardNode): TLOutwardNode = { | ||||
|   def optionalSlaveBuffer(out: TLInwardNode): TLInwardNode = { | ||||
|     if (rtp.boundaryBuffers) { | ||||
|       val sbuf = LazyModule(new TLBuffer(BufferParams.flow, BufferParams.none, BufferParams.none, BufferParams.none, BufferParams.none)) | ||||
|       DisableMonitors { implicit p => sbuf.node :*= in } | ||||
|       DisableMonitors { implicit p => out :*= sbuf.node } | ||||
|       sbuf.node | ||||
|     } else { | ||||
|       in | ||||
|       out | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   def outputInterruptXingLatency: Int | ||||
|  | ||||
|   intOutputNode.foreach { _ := rocket.intOutputNode.get } | ||||
|  | ||||
|   lazy val module = new LazyModuleImp(this) { | ||||
|     val io = new CoreBundle | ||||
|     val io = IO(new CoreBundle | ||||
|         with HasExternallyDrivenTileConstants | ||||
|         with CanHaveInstructionTracePort | ||||
|         with CanHaltAndCatchFire { | ||||
|       val master = masterNode.bundleOut | ||||
|       val slave = slaveNode.bundleIn | ||||
|       val outputInterrupts = intOutputNode.map(_.bundleOut) | ||||
|       val asyncInterrupts  = asyncIntNode.bundleIn | ||||
|       val periphInterrupts = periphIntNode.bundleIn | ||||
|       val coreInterrupts   = coreIntNode.bundleIn | ||||
|       val halt_and_catch_fire = rocket.module.io.halt_and_catch_fire.map(_.cloneType) | ||||
|     } | ||||
|     }) | ||||
|     // signals that do not change based on crossing type: | ||||
|     rocket.module.io.hartid := io.hartid | ||||
|     rocket.module.io.reset_vector := io.reset_vector | ||||
| @@ -237,17 +227,18 @@ abstract class RocketTileWrapper(rtp: RocketTileParams, hartid: Int)(implicit p: | ||||
| } | ||||
|  | ||||
| class SyncRocketTile(rtp: RocketTileParams, hartid: Int)(implicit p: Parameters) extends RocketTileWrapper(rtp, hartid) { | ||||
|   val masterNode = TLOutputNode() | ||||
|   masterNode :=* optionalMasterBuffer(rocket.masterNode) | ||||
|  | ||||
|   val slaveNode = new TLInputNode() { override def reverse = true } | ||||
|   DisableMonitors { implicit p => rocket.slaveNode :*= optionalSlaveBuffer(slaveNode) } | ||||
|   val masterNode = optionalMasterBuffer(rocket.masterNode) | ||||
|   val slaveNode = optionalSlaveBuffer(rocket.slaveNode) | ||||
|  | ||||
|   // Fully async interrupts need synchronizers. | ||||
|   // Others need no synchronization. | ||||
|   val xing = LazyModule(new IntXing(3)) | ||||
|   xing.intnode := asyncIntNode | ||||
|   val asyncIntNode = xing.intnode | ||||
|  | ||||
|   val periphIntNode = IntIdentityNode() | ||||
|   val coreIntNode = IntIdentityNode() | ||||
|  | ||||
|   // order here matters | ||||
|   intXbar.intnode := xing.intnode | ||||
|   intXbar.intnode := periphIntNode | ||||
|   intXbar.intnode := coreIntNode | ||||
| @@ -256,27 +247,24 @@ class SyncRocketTile(rtp: RocketTileParams, hartid: Int)(implicit p: Parameters) | ||||
| } | ||||
|  | ||||
| class AsyncRocketTile(rtp: RocketTileParams, hartid: Int)(implicit p: Parameters) extends RocketTileWrapper(rtp, hartid) { | ||||
|   val masterNode = TLAsyncOutputNode() | ||||
|   val source = LazyModule(new TLAsyncCrossingSource) | ||||
|   source.node :=* rocket.masterNode | ||||
|   masterNode :=* source.node | ||||
|   val masterNode = source.node | ||||
|  | ||||
|   val slaveNode = new TLAsyncInputNode() { override def reverse = true } | ||||
|   val sink = LazyModule(new TLAsyncCrossingSink) | ||||
|  | ||||
|   DisableMonitors { implicit p => | ||||
|     rocket.slaveNode :*= sink.node | ||||
|     sink.node :*= slaveNode | ||||
|   } | ||||
|   DisableMonitors { implicit p => rocket.slaveNode :*= sink.node } | ||||
|   val slaveNode = sink.node | ||||
|  | ||||
|   // Fully async interrupts need synchronizers, | ||||
|   // as do those coming from the periphery clock. | ||||
|   // Others need no synchronization. | ||||
|   val asyncXing = LazyModule(new IntXing(3)) | ||||
|   val periphXing = LazyModule(new IntXing(3)) | ||||
|   asyncXing.intnode := asyncIntNode | ||||
|   periphXing.intnode := periphIntNode | ||||
|   val asyncIntNode = asyncXing.intnode | ||||
|   val periphIntNode = periphXing.intnode | ||||
|   val coreIntNode = IntIdentityNode() | ||||
|  | ||||
|   // order here matters | ||||
|   intXbar.intnode := asyncXing.intnode | ||||
|   intXbar.intnode := periphXing.intnode | ||||
|   intXbar.intnode := coreIntNode | ||||
| @@ -285,18 +273,13 @@ class AsyncRocketTile(rtp: RocketTileParams, hartid: Int)(implicit p: Parameters | ||||
| } | ||||
|  | ||||
| class RationalRocketTile(rtp: RocketTileParams, hartid: Int)(implicit p: Parameters) extends RocketTileWrapper(rtp, hartid) { | ||||
|   val masterNode = TLRationalOutputNode() | ||||
|   val source = LazyModule(new TLRationalCrossingSource) | ||||
|   source.node :=* optionalMasterBuffer(rocket.masterNode) | ||||
|   masterNode :=* source.node | ||||
|   val masterNode = source.node | ||||
|  | ||||
|   val slaveNode = new TLRationalInputNode() { override def reverse = true } | ||||
|   val sink = LazyModule(new TLRationalCrossingSink(SlowToFast)) | ||||
|  | ||||
|   DisableMonitors { implicit p => | ||||
|     sink.node :*= slaveNode | ||||
|     rocket.slaveNode :*= optionalSlaveBuffer(sink.node) | ||||
|   } | ||||
|   DisableMonitors { implicit p => optionalSlaveBuffer(rocket.slaveNode) :*= sink.node } | ||||
|   val slaveNode = sink.node | ||||
|  | ||||
|   // Fully async interrupts need synchronizers. | ||||
|   // Those coming from periphery clock need a | ||||
| @@ -304,9 +287,11 @@ class RationalRocketTile(rtp: RocketTileParams, hartid: Int)(implicit p: Paramet | ||||
|   // Others need no synchronization. | ||||
|   val asyncXing    = LazyModule(new IntXing(3)) | ||||
|   val periphXing = LazyModule(new IntXing(1)) | ||||
|   asyncXing.intnode := asyncIntNode | ||||
|   periphXing.intnode := periphIntNode | ||||
|   val asyncIntNode = asyncXing.intnode | ||||
|   val periphIntNode = periphXing.intnode | ||||
|   val coreIntNode = IntIdentityNode() | ||||
|  | ||||
|   // order here matters | ||||
|   intXbar.intnode := asyncXing.intnode | ||||
|   intXbar.intnode := periphXing.intnode | ||||
|   intXbar.intnode := coreIntNode | ||||
|   | ||||
| @@ -13,12 +13,7 @@ class TLAsyncCrossingSource(sync: Int = 3)(implicit p: Parameters) extends LazyM | ||||
|   val node = TLAsyncSourceNode(sync) | ||||
|  | ||||
|   lazy val module = new LazyModuleImp(this) { | ||||
|     val io = new Bundle { | ||||
|       val in  = node.bundleIn | ||||
|       val out = node.bundleOut | ||||
|     } | ||||
|  | ||||
|     ((io.in zip io.out) zip (node.edgesIn zip node.edgesOut)) foreach { case ((in, out), (edgeIn, edgeOut)) => | ||||
|     (node.in zip node.out) foreach { case ((in, edgeIn), (out, edgeOut)) => | ||||
|       val sink_reset_n = out.a.sink_reset_n | ||||
|       val bce = edgeIn.manager.anySupportAcquireB && edgeIn.client.anySupportProbe | ||||
|       val depth = edgeOut.manager.depth | ||||
| @@ -47,12 +42,7 @@ class TLAsyncCrossingSink(depth: Int = 8, sync: Int = 3)(implicit p: Parameters) | ||||
|   val node = TLAsyncSinkNode(depth, sync) | ||||
|  | ||||
|   lazy val module = new LazyModuleImp(this) { | ||||
|     val io = new Bundle { | ||||
|       val in  = node.bundleIn | ||||
|       val out = node.bundleOut | ||||
|     } | ||||
|  | ||||
|     ((io.in zip io.out) zip (node.edgesIn zip node.edgesOut)) foreach { case ((in, out), (edgeIn, edgeOut)) => | ||||
|     (node.in zip node.out) foreach { case ((in, edgeIn), (out, edgeOut)) => | ||||
|       val source_reset_n = in.a.source_reset_n | ||||
|       val bce = edgeOut.manager.anySupportAcquireB && edgeOut.client.anySupportProbe | ||||
|  | ||||
| @@ -97,40 +87,24 @@ object TLAsyncCrossingSink | ||||
|  | ||||
| class TLAsyncCrossing(depth: Int = 8, sync: Int = 3)(implicit p: Parameters) extends LazyModule | ||||
| { | ||||
|   val nodeIn = TLInputNode() | ||||
|   val nodeOut = TLOutputNode() | ||||
|   val node = NodeHandle(nodeIn, nodeOut) | ||||
|  | ||||
|   val source = LazyModule(new TLAsyncCrossingSource(sync)) | ||||
|   val sink = LazyModule(new TLAsyncCrossingSink(depth, sync)) | ||||
|   val node = NodeHandle(source.node, sink.node) | ||||
|  | ||||
|   val _    = (sink.node := source.node) // no monitor | ||||
|   val in   = (source.node := nodeIn) | ||||
|   val out  = (nodeOut := sink.node) | ||||
|   sink.node := source.node | ||||
|  | ||||
|   lazy val module = new LazyModuleImp(this) { | ||||
|     val io = new Bundle { | ||||
|       val in        = nodeIn.bundleIn | ||||
|     val io = IO(new Bundle { | ||||
|       val in_clock  = Clock(INPUT) | ||||
|       val in_reset  = Bool(INPUT) | ||||
|       val out       = nodeOut.bundleOut | ||||
|       val out_clock = Clock(INPUT) | ||||
|       val out_reset = Bool(INPUT) | ||||
|     } | ||||
|     }) | ||||
|  | ||||
|     source.module.clock := io.in_clock | ||||
|     source.module.reset := io.in_reset | ||||
|     in.foreach { lm => | ||||
|       lm.module.clock := io.in_clock | ||||
|       lm.module.reset := io.in_reset | ||||
|     } | ||||
|  | ||||
|     sink.module.clock := io.out_clock | ||||
|     sink.module.reset := io.out_reset | ||||
|     out.foreach { lm => | ||||
|       lm.module.clock := io.out_clock | ||||
|       lm.module.reset := io.out_reset | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  | ||||
| @@ -145,9 +119,9 @@ class TLRAMAsyncCrossing(txns: Int)(implicit p: Parameters) extends LazyModule { | ||||
|  | ||||
|   model.node := fuzz.node | ||||
|   cross.node := TLFragmenter(4, 256)(TLDelayer(0.1)(model.node)) | ||||
|   val monitor = (ram.node := cross.node) | ||||
|   ram.node := cross.node | ||||
|  | ||||
|   lazy val module = new LazyModuleImp(this) with HasUnitTestIO { | ||||
|   lazy val module = new LazyModuleImp(this) with UnitTestModule { | ||||
|     io.finished := fuzz.module.io.finished | ||||
|  | ||||
|     // Shove the RAM into another clock domain | ||||
| @@ -159,12 +133,6 @@ class TLRAMAsyncCrossing(txns: Int)(implicit p: Parameters) extends LazyModule { | ||||
|     cross.module.io.in_reset := reset | ||||
|     cross.module.io.out_clock := clocks.io.clock_out | ||||
|     cross.module.io.out_reset := reset | ||||
|  | ||||
|     // Push the Monitor into the right clock domain | ||||
|     monitor.foreach { m => | ||||
|       m.module.clock := clocks.io.clock_out | ||||
|       m.module.reset := reset | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -29,12 +29,7 @@ class TLAtomicAutomata(logical: Boolean = true, arithmetic: Boolean = true, conc | ||||
|     })}) | ||||
|  | ||||
|   lazy val module = new LazyModuleImp(this) { | ||||
|     val io = new Bundle { | ||||
|       val in  = node.bundleIn | ||||
|       val out = node.bundleOut | ||||
|     } | ||||
|  | ||||
|     ((io.in zip io.out) zip (node.edgesIn zip node.edgesOut)) foreach { case ((in, out), (edgeIn, edgeOut)) => | ||||
|     (node.in zip node.out) foreach { case ((in, edgeIn), (out, edgeOut)) => | ||||
|       val managers = edgeOut.manager.managers | ||||
|       val beatBytes = edgeOut.manager.beatBytes | ||||
|  | ||||
| @@ -297,7 +292,7 @@ class TLRAMAtomicAutomata(txns: Int)(implicit p: Parameters) extends LazyModule | ||||
|   model.node := fuzz.node | ||||
|   ram.node := TLFragmenter(4, 256)(TLDelayer(0.1)(TLAtomicAutomata()(TLDelayer(0.1)(model.node)))) | ||||
|  | ||||
|   lazy val module = new LazyModuleImp(this) with HasUnitTestIO { | ||||
|   lazy val module = new LazyModuleImp(this) with UnitTestModule { | ||||
|     io.finished := fuzz.module.io.finished | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -53,12 +53,7 @@ class TLBroadcast(lineBytes: Int, numTrackers: Int = 4, bufferless: Boolean = fa | ||||
|   ) | ||||
|  | ||||
|   lazy val module = new LazyModuleImp(this) { | ||||
|     val io = new Bundle { | ||||
|       val in  = node.bundleIn | ||||
|       val out = node.bundleOut | ||||
|     } | ||||
|  | ||||
|     ((io.in zip io.out) zip (node.edgesIn zip node.edgesOut)) foreach { case ((in, out), (edgeIn, edgeOut)) => | ||||
|     (node.in zip node.out) foreach { case ((in, edgeIn), (out, edgeOut)) => | ||||
|       val clients = edgeIn.client.clients | ||||
|       val managers = edgeOut.manager.managers | ||||
|       val lineShift = log2Ceil(lineBytes) | ||||
|   | ||||
| @@ -13,7 +13,7 @@ class TLBufferNode ( | ||||
|   b: BufferParams, | ||||
|   c: BufferParams, | ||||
|   d: BufferParams, | ||||
|   e: BufferParams)(implicit p: Parameters) extends TLAdapterNode( | ||||
|   e: BufferParams)(implicit valName: ValName) extends TLAdapterNode( | ||||
|     clientFn  = { p => p.copy(minLatency = p.minLatency + b.latency + c.latency) }, | ||||
|     managerFn = { p => p.copy(minLatency = p.minLatency + a.latency + d.latency) } | ||||
| ) { | ||||
| @@ -35,12 +35,7 @@ class TLBuffer( | ||||
|   val node = new TLBufferNode(a, b, c, d, e) | ||||
|  | ||||
|   lazy val module = new LazyModuleImp(this) { | ||||
|     val io = new Bundle { | ||||
|       val in  = node.bundleIn | ||||
|       val out = node.bundleOut | ||||
|     } | ||||
|  | ||||
|     ((io.in zip io.out) zip (node.edgesIn zip node.edgesOut)) foreach { case ((in, out), (edgeIn, edgeOut)) => | ||||
|     (node.in zip node.out) foreach { case ((in, edgeIn), (out, edgeOut)) => | ||||
|       out.a <> a(in .a) | ||||
|       in .d <> d(out.d) | ||||
|  | ||||
| @@ -79,36 +74,25 @@ object TLBuffer | ||||
| } | ||||
|  | ||||
| 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 | ||||
|   val buf_chain = List.fill(depth)(LazyModule(new TLBuffer(BufferParams.default))) | ||||
|   val node = if (depth > 0) { | ||||
|     (buf_chain.init zip buf_chain.tail) foreach { case (prev, next) => next.node :=? prev.node } | ||||
|     NodeHandle(buf_chain.head.node, buf_chain.last.node) | ||||
|   } else { | ||||
|     List(LazyModule(new TLBuffer(BufferParams.none))) | ||||
|   } | ||||
|  | ||||
|   buf_chain.head.node :=? nodeIn | ||||
|   nodeOut :=? buf_chain.last.node | ||||
|  | ||||
|   lazy val module = new LazyModuleImp(this) { | ||||
|     val io = new Bundle { | ||||
|       val in  = nodeIn.bundleIn | ||||
|       val out = nodeOut.bundleOut | ||||
|     } | ||||
|     TLIdentityNode() | ||||
|   } | ||||
|   lazy val module = new LazyModuleImp(this) { } | ||||
| } | ||||
|  | ||||
| object TLBufferChain | ||||
| { | ||||
|   def apply(depth: Int)(x: TLOutwardNode)(implicit p: Parameters, sourceInfo: SourceInfo): TLOutwardNode = { | ||||
|     if (depth > 0) { | ||||
|       val buffer = LazyModule(new TLBufferChain(depth)) | ||||
|       buffer.node :=? x | ||||
|       buffer.node | ||||
|     } else { | ||||
|       x | ||||
|     } | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -21,7 +21,8 @@ trait TLBusParams { | ||||
|   def blockOffset: Int = log2Up(blockBytes) | ||||
| } | ||||
|  | ||||
| abstract class TLBusWrapper(params: TLBusParams, val busName: String)(implicit p: Parameters) extends TLBusParams { | ||||
| abstract class TLBusWrapper(params: TLBusParams, val busName: String)(implicit p: Parameters) | ||||
|     extends SimpleLazyModule with LazyScope with TLBusParams { | ||||
|  | ||||
|   val beatBytes = params.beatBytes | ||||
|   val blockBytes = params.blockBytes | ||||
| @@ -71,7 +72,7 @@ abstract class TLBusWrapper(params: TLBusParams, val busName: String)(implicit p | ||||
|     SourceCardinality { implicit p => | ||||
|       val chain = LazyModule(new TLBufferChain(depth)) | ||||
|       name.foreach { n => chain.suggestName(s"${busName}_${n}_TLBufferChain")} | ||||
|       (chain.nodeIn, chain.nodeOut) | ||||
|       (chain.node, chain.node) | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   | ||||
| @@ -24,12 +24,7 @@ class TLCacheCork(unsafe: Boolean = false)(implicit p: Parameters) extends LazyM | ||||
|           supportsAcquireT = if (m.regionType == RegionType.UNCACHED) m.supportsPutFull else m.supportsAcquireT)})}) | ||||
|  | ||||
|   lazy val module = new LazyModuleImp(this) { | ||||
|     val io = new Bundle { | ||||
|       val in  = node.bundleIn | ||||
|       val out = node.bundleOut | ||||
|     } | ||||
|  | ||||
|     ((io.in zip io.out) zip (node.edgesIn zip node.edgesOut)) foreach { case ((in, out), (edgeIn, edgeOut)) => | ||||
|     (node.in zip node.out) foreach { case ((in, edgeIn), (out, edgeOut)) => | ||||
|       val clients = edgeIn.client.clients | ||||
|       val caches = clients.filter(_.supportsProbe) | ||||
|       require (clients.size == 1 || caches.size == 0 || unsafe, "Only one client can safely use a TLCacheCork") | ||||
|   | ||||
| @@ -10,15 +10,10 @@ import freechips.rocketchip.diplomacy._ | ||||
| // q is the probability to delay a request | ||||
| class TLDelayer(q: Double)(implicit p: Parameters) extends LazyModule | ||||
| { | ||||
|   val node = TLIdentityNode() | ||||
|   val node = TLAdapterNode() | ||||
|   require (0.0 <= q && q < 1) | ||||
|  | ||||
|   lazy val module = new LazyModuleImp(this) { | ||||
|     val io = new Bundle { | ||||
|       val in  = node.bundleIn | ||||
|       val out = node.bundleOut | ||||
|     } | ||||
|  | ||||
|     def feed[T <: Data](sink: DecoupledIO[T], source: DecoupledIO[T], noise: T) { | ||||
|       val allow = UInt((q * 65535.0).toInt) <= LFSR16(source.valid) | ||||
|       sink.valid := source.valid && allow | ||||
| @@ -27,7 +22,7 @@ class TLDelayer(q: Double)(implicit p: Parameters) extends LazyModule | ||||
|       when (!sink.valid) { sink.bits := noise } | ||||
|     } | ||||
|  | ||||
|     (io.in zip io.out) foreach { case (in, out) => | ||||
|     (node.in zip node.out) foreach { case ((in, _), (out, _)) => | ||||
|       val anoise = Wire(in.a.bits) | ||||
|       anoise.opcode  := LFSRNoiseMaker(3) | ||||
|       anoise.param   := LFSRNoiseMaker(3) | ||||
|   | ||||
| @@ -4,13 +4,16 @@ package freechips.rocketchip.tilelink | ||||
|  | ||||
| import Chisel._ | ||||
| import chisel3.internal.sourceinfo.SourceInfo | ||||
| import freechips.rocketchip.config.Parameters | ||||
| import freechips.rocketchip.diplomacy._ | ||||
| import freechips.rocketchip.util._ | ||||
|  | ||||
| class TLEdge( | ||||
|   client:  TLClientPortParameters, | ||||
|   manager: TLManagerPortParameters) | ||||
|   extends TLEdgeParameters(client, manager) | ||||
|   manager: TLManagerPortParameters, | ||||
|   params:  Parameters, | ||||
|   sourceInfo: SourceInfo) | ||||
|   extends TLEdgeParameters(client, manager, params, sourceInfo) | ||||
| { | ||||
|   def isAligned(address: UInt, lgSize: UInt): Bool = { | ||||
|     if (maxLgSize == 0) Bool(true) else { | ||||
| @@ -262,8 +265,10 @@ class TLEdge( | ||||
|  | ||||
| class TLEdgeOut( | ||||
|   client:  TLClientPortParameters, | ||||
|   manager: TLManagerPortParameters) | ||||
|   extends TLEdge(client, manager) | ||||
|   manager: TLManagerPortParameters, | ||||
|   params:  Parameters, | ||||
|   sourceInfo: SourceInfo) | ||||
|   extends TLEdge(client, manager, params, sourceInfo) | ||||
| { | ||||
|   // Transfers | ||||
|   def Acquire(fromSource: UInt, toAddress: UInt, lgSize: UInt, growPermissions: UInt) = { | ||||
| @@ -476,8 +481,10 @@ class TLEdgeOut( | ||||
|  | ||||
| class TLEdgeIn( | ||||
|   client:  TLClientPortParameters, | ||||
|   manager: TLManagerPortParameters) | ||||
|   extends TLEdge(client, manager) | ||||
|   manager: TLManagerPortParameters, | ||||
|   params:  Parameters, | ||||
|   sourceInfo: SourceInfo) | ||||
|   extends TLEdge(client, manager, params, sourceInfo) | ||||
| { | ||||
|   // Transfers | ||||
|   def Probe(fromAddress: UInt, toSource: UInt, lgSize: UInt, capPermissions: UInt) = { | ||||
|   | ||||
| @@ -41,12 +41,7 @@ class TLFIFOFixer(policy: TLFIFOFixer.Policy = TLFIFOFixer.all)(implicit p: Para | ||||
|     }) | ||||
|  | ||||
|   lazy val module = new LazyModuleImp(this) { | ||||
|     val io = new Bundle { | ||||
|       val in  = node.bundleIn | ||||
|       val out = node.bundleOut | ||||
|     } | ||||
|  | ||||
|     ((io.in zip io.out) zip (node.edgesIn zip node.edgesOut)) foreach { case ((in, out), (edgeIn, edgeOut)) => | ||||
|     (node.in zip node.out) foreach { case ((in, edgeIn), (out, edgeOut)) => | ||||
|       val (fixMap, splatMap) = fifoMap(edgeOut.manager.managers) | ||||
|  | ||||
|       // Do we need to serialize the request to this manager? | ||||
|   | ||||
| @@ -49,11 +49,9 @@ class TLFilter( | ||||
|     })}) | ||||
|  | ||||
|   lazy val module = new LazyModuleImp(this) { | ||||
|     val io = new Bundle { | ||||
|       val in  = node.bundleIn | ||||
|       val out = node.bundleOut | ||||
|     (node.in zip node.out) foreach { case ((in, edgeIn), (out, edgeOut)) => | ||||
|       out <> in | ||||
|     } | ||||
|     io.out <> io.in | ||||
|   } | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -52,12 +52,7 @@ class TLFragmenter(val minSize: Int, val maxSize: Int, val alwaysMin: Boolean = | ||||
|     managerFn = { m => m.copy(managers = m.managers.map(mapManager)) }) | ||||
|  | ||||
|   lazy val module = new LazyModuleImp(this) { | ||||
|     val io = new Bundle { | ||||
|       val in  = node.bundleIn | ||||
|       val out = node.bundleOut | ||||
|     } | ||||
|  | ||||
|     ((io.in zip io.out) zip (node.edgesIn zip node.edgesOut)) foreach { case ((in, out), (edgeIn, edgeOut)) => | ||||
|     (node.in zip node.out) foreach { case ((in, edgeIn), (out, edgeOut)) => | ||||
|       // All managers must share a common FIFO domain (responses might end up interleaved) | ||||
|       val manager   = edgeOut.manager | ||||
|       val managers  = manager.managers | ||||
| @@ -249,7 +244,7 @@ class TLFragmenter(val minSize: Int, val maxSize: Int, val alwaysMin: Boolean = | ||||
|       val aFrag = Mux(aOrig > limit, limit, aOrig) | ||||
|       val aOrigOH1 = UIntToOH1(aOrig, log2Ceil(maxSize)) | ||||
|       val aFragOH1 = UIntToOH1(aFrag, log2Up(maxDownSize)) | ||||
|       val aHasData = node.edgesIn(0).hasData(in_a.bits) | ||||
|       val aHasData = edgeIn.hasData(in_a.bits) | ||||
|       val aMask = Mux(aHasData, UInt(0), aFragOH1) | ||||
|  | ||||
|       val gennum = RegInit(UInt(0, width = counterBits)) | ||||
| @@ -317,7 +312,7 @@ class TLRAMFragmenter(ramBeatBytes: Int, maxSize: Int, txns: Int)(implicit p: Pa | ||||
|     TLBuffer(BufferParams.flow)( | ||||
|     model.node))))))))) | ||||
|  | ||||
|   lazy val module = new LazyModuleImp(this) with HasUnitTestIO { | ||||
|   lazy val module = new LazyModuleImp(this) with UnitTestModule { | ||||
|     io.finished := fuzz.module.io.finished | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -107,13 +107,11 @@ class TLFuzzer( | ||||
|   val node = TLClientNode(Seq(TLClientPortParameters(clientParams))) | ||||
|  | ||||
|   lazy val module = new LazyModuleImp(this) { | ||||
|     val io = new Bundle { | ||||
|       val out = node.bundleOut | ||||
|     val io = IO(new Bundle { | ||||
|       val finished = Bool(OUTPUT) | ||||
|     } | ||||
|     }) | ||||
|  | ||||
|     val out = io.out(0) | ||||
|     val edge = node.edgesOut(0) | ||||
|     val (out, edge) = node.out(0) | ||||
|  | ||||
|     // Extract useful parameters from the TL edge | ||||
|     val maxTransfer  = edge.manager.maxTransfer | ||||
| @@ -242,10 +240,10 @@ class TLFuzzRAM(txns: Int)(implicit p: Parameters) extends LazyModule | ||||
|   ram2.node := TLFragmenter(16, 256)(xbar2.node) | ||||
|   xbar.node := TLWidthWidget(16)(TLHintHandler()(xbar2.node)) | ||||
|   cross.node := TLFragmenter(4, 256)(TLBuffer()(xbar.node)) | ||||
|   val monitor = (ram.node := cross.node) | ||||
|   ram.node := cross.node | ||||
|   gpio.node := TLFragmenter(4, 32)(TLBuffer()(xbar.node)) | ||||
|  | ||||
|   lazy val module = new LazyModuleImp(this) with HasUnitTestIO { | ||||
|   lazy val module = new LazyModuleImp(this) with UnitTestModule { | ||||
|     io.finished := fuzz.module.io.finished | ||||
|  | ||||
|     // Shove the RAM into another clock domain | ||||
| @@ -257,12 +255,6 @@ class TLFuzzRAM(txns: Int)(implicit p: Parameters) extends LazyModule | ||||
|     cross.module.io.in_reset := reset | ||||
|     cross.module.io.out_clock := clocks.io.clock_out | ||||
|     cross.module.io.out_reset := reset | ||||
|  | ||||
|     // Push the Monitor into the right clock domain | ||||
|     monitor.foreach { m => | ||||
|       m.module.clock := clocks.io.clock_out | ||||
|       m.module.reset := reset | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -16,12 +16,7 @@ class TLHintHandler(supportManagers: Boolean = true, supportClients: Boolean = f | ||||
|     managerFn = { m => if (!supportManagers) m else m.copy(minLatency = min(1, m.minLatency), managers = m.managers.map(_.copy(supportsHint = TransferSizes(1, m.maxTransfer)))) }) | ||||
|  | ||||
|   lazy val module = new LazyModuleImp(this) { | ||||
|     val io = new Bundle { | ||||
|       val in  = node.bundleIn | ||||
|       val out = node.bundleOut | ||||
|     } | ||||
|  | ||||
|     ((io.in zip io.out) zip (node.edgesIn zip node.edgesOut)) foreach { case ((in, out), (edgeIn, edgeOut)) => | ||||
|     (node.in zip node.out) foreach { case ((in, edgeIn), (out, edgeOut)) => | ||||
|       // Don't add support for clients if there is no BCE channel | ||||
|       val bce = edgeOut.manager.anySupportAcquireB && edgeIn.client.anySupportProbe | ||||
|       require (!supportClients || bce) | ||||
| @@ -118,7 +113,7 @@ class TLRAMHintHandler(txns: Int)(implicit p: Parameters) extends LazyModule { | ||||
|   model.node := fuzz.node | ||||
|   ram.node := TLFragmenter(4, 256)(TLDelayer(0.1)(TLHintHandler()(TLDelayer(0.1)(model.node)))) | ||||
|  | ||||
|   lazy val module = new LazyModuleImp(this) with HasUnitTestIO { | ||||
|   lazy val module = new LazyModuleImp(this) with UnitTestModule { | ||||
|     io.finished := fuzz.module.io.finished | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -61,26 +61,13 @@ object IntSinkPortSimple | ||||
|     Seq.fill(ports)(IntSinkPortParameters(Seq.fill(sinks)(IntSinkParameters()))) | ||||
| } | ||||
|  | ||||
| case class IntEdge(source: IntSourcePortParameters, sink: IntSinkPortParameters) | ||||
| case class IntEdge(source: IntSourcePortParameters, sink: IntSinkPortParameters, params: Parameters, sourceInfo: SourceInfo) | ||||
|  | ||||
| object IntImp extends NodeImp[IntSourcePortParameters, IntSinkPortParameters, IntEdge, IntEdge, Vec[Bool]] | ||||
| object IntImp extends SimpleNodeImp[IntSourcePortParameters, IntSinkPortParameters, IntEdge, Vec[Bool]] | ||||
| { | ||||
|   def edgeO(pd: IntSourcePortParameters, pu: IntSinkPortParameters): IntEdge = IntEdge(pd, pu) | ||||
|   def edgeI(pd: IntSourcePortParameters, pu: IntSinkPortParameters): IntEdge = IntEdge(pd, pu) | ||||
|   def bundleO(eo: IntEdge): Vec[Bool] = Vec(eo.source.num, Bool()) | ||||
|   def bundleI(ei: IntEdge): Vec[Bool] = Vec(ei.source.num, Bool()) | ||||
|  | ||||
|   def colour = "#0000ff" // blue | ||||
|   override def reverse = true | ||||
|   override def labelI(ei: IntEdge) = ei.source.sources.map(_.range.size).sum.toString | ||||
|   override def labelO(eo: IntEdge) = eo.source.sources.map(_.range.size).sum.toString | ||||
|  | ||||
|   def connect(bo: => Vec[Bool], bi: => Vec[Bool], ei: => IntEdge)(implicit p: Parameters, sourceInfo: SourceInfo): (Option[LazyModule], () => Unit) = { | ||||
|     (None, () => { | ||||
|       // Cannot use bulk connect, because the widths could differ | ||||
|       (bo zip bi) foreach { case (o, i) => i := o } | ||||
|     }) | ||||
|   } | ||||
|   def edge(pd: IntSourcePortParameters, pu: IntSinkPortParameters, p: Parameters, sourceInfo: SourceInfo) = IntEdge(pd, pu, p, sourceInfo) | ||||
|   def bundle(e: IntEdge) = Vec(e.source.num, Bool()) | ||||
|   def render(e: IntEdge) = RenderedEdge(colour = "#0000ff" /* blue */, label = e.source.sources.map(_.range.size).sum.toString, flipped = true) | ||||
|  | ||||
|   override def mixO(pd: IntSourcePortParameters, node: OutwardNode[IntSourcePortParameters, IntSinkPortParameters, Vec[Bool]]): IntSourcePortParameters = | ||||
|    pd.copy(sources = pd.sources.map  { s => s.copy (nodePath = node +: s.nodePath) }) | ||||
| @@ -88,26 +75,24 @@ object IntImp extends NodeImp[IntSourcePortParameters, IntSinkPortParameters, In | ||||
|    pu.copy(sinks   = pu.sinks.map    { s => s.copy (nodePath = node +: s.nodePath) }) | ||||
| } | ||||
|  | ||||
| case class IntIdentityNode() extends IdentityNode(IntImp) | ||||
| case class IntSourceNode(portParams: Seq[IntSourcePortParameters]) extends SourceNode(IntImp)(portParams) | ||||
| case class IntSinkNode(portParams: Seq[IntSinkPortParameters]) extends SinkNode(IntImp)(portParams) | ||||
| case class IntSourceNode(portParams: Seq[IntSourcePortParameters])(implicit valName: ValName) extends SourceNode(IntImp)(portParams) | ||||
| case class IntSinkNode(portParams: Seq[IntSinkPortParameters])(implicit valName: ValName) extends SinkNode(IntImp)(portParams) | ||||
| case class IntAdapterNode( | ||||
|   sourceFn: IntSourcePortParameters => IntSourcePortParameters = { s => s }, | ||||
|   sinkFn:   IntSinkPortParameters   => IntSinkPortParameters   = { s => s }, | ||||
|   num:      Range.Inclusive = 0 to 999)( | ||||
|   implicit valName: ValName) | ||||
|   extends AdapterNode(IntImp)(sourceFn, sinkFn, num) | ||||
| case class IntIdentityNode()(implicit valName: ValName) extends IdentityNode(IntImp)() | ||||
|  | ||||
| case class IntNexusNode( | ||||
|   sourceFn:       Seq[IntSourcePortParameters] => IntSourcePortParameters, | ||||
|   sinkFn:         Seq[IntSinkPortParameters]   => IntSinkPortParameters, | ||||
|   numSourcePorts: Range.Inclusive = 0 to 128, | ||||
|   numSinkPorts:   Range.Inclusive = 0 to 128) | ||||
|   numSinkPorts:   Range.Inclusive = 0 to 128)( | ||||
|   implicit valName: ValName) | ||||
|   extends NexusNode(IntImp)(sourceFn, sinkFn, numSourcePorts, numSinkPorts) | ||||
|  | ||||
| case class IntOutputNode() extends OutputNode(IntImp) | ||||
| case class IntInputNode() extends InputNode(IntImp) | ||||
|  | ||||
| case class IntBlindOutputNode(portParams: Seq[IntSinkPortParameters]) extends BlindOutputNode(IntImp)(portParams) | ||||
| case class IntBlindInputNode(portParams: Seq[IntSourcePortParameters]) extends BlindInputNode(IntImp)(portParams) | ||||
|  | ||||
| case class IntInternalOutputNode(portParams: Seq[IntSinkPortParameters]) extends InternalOutputNode(IntImp)(portParams) | ||||
| case class IntInternalInputNode(portParams: Seq[IntSourcePortParameters]) extends InternalInputNode(IntImp)(portParams) | ||||
|  | ||||
| class IntXbar()(implicit p: Parameters) extends LazyModule | ||||
| { | ||||
|   val intnode = IntNexusNode( | ||||
| @@ -119,27 +104,17 @@ class IntXbar()(implicit p: Parameters) extends LazyModule | ||||
|     }) | ||||
|  | ||||
|   lazy val module = new LazyModuleImp(this) { | ||||
|     val io = new Bundle { | ||||
|       val in  = intnode.bundleIn | ||||
|       val out = intnode.bundleOut | ||||
|     } | ||||
|  | ||||
|     val cat = (intnode.edgesIn zip io.in).map{ case (e, i) => i.take(e.source.num) }.flatten | ||||
|     io.out.foreach { _ := cat } | ||||
|     val cat = intnode.in.map { case (i, e) => i.take(e.source.num) }.flatten | ||||
|     intnode.out.foreach { case (o, _) => o := cat } | ||||
|   } | ||||
| } | ||||
|  | ||||
| class IntXing(sync: Int = 3)(implicit p: Parameters) extends LazyModule | ||||
| { | ||||
|   val intnode = IntIdentityNode() | ||||
|   val intnode = IntAdapterNode() | ||||
|  | ||||
|   lazy val module = new LazyModuleImp(this) { | ||||
|     val io = new Bundle { | ||||
|       val in = intnode.bundleIn | ||||
|       val out = intnode.bundleOut | ||||
|     } | ||||
|  | ||||
|     (io.in zip io.out) foreach { case (in, out) => | ||||
|     (intnode.in zip intnode.out) foreach { case ((in, _), (out, _)) => | ||||
|       out := SynchronizerShiftReg(in, sync) | ||||
|     } | ||||
|   } | ||||
|   | ||||
| @@ -11,15 +11,13 @@ import freechips.rocketchip.util.AsyncBundle | ||||
| // READ the comments in the TLIsolation object before you instantiate this module | ||||
| class TLIsolation(fOut: (Bool, UInt) => UInt, fIn: (Bool, UInt) => UInt)(implicit p: Parameters) extends LazyModule | ||||
| { | ||||
|   val node = TLAsyncIdentityNode() | ||||
|   val node = TLAsyncAdapterNode() | ||||
|  | ||||
|   lazy val module = new LazyModuleImp(this) { | ||||
|     val io = new Bundle { | ||||
|       val in  = node.bundleIn | ||||
|       val out = node.bundleOut | ||||
|     val io = IO(new Bundle { | ||||
|       val iso_out = Bool(INPUT) // Isolate from client to manager | ||||
|       val iso_in  = Bool(INPUT) // Isolate from manager to client | ||||
|     } | ||||
|     }) | ||||
|  | ||||
|     def ISOo[T <: Data](x: T): T = x.fromBits(fOut(io.iso_out, x.asUInt)) | ||||
|     def ISOi[T <: Data](x: T): T = x.fromBits(fIn (io.iso_in,  x.asUInt)) | ||||
| @@ -53,7 +51,7 @@ class TLIsolation(fOut: (Bool, UInt) => UInt, fIn: (Bool, UInt) => UInt)(implici | ||||
|       y.sink_reset_n   := Bool(false) | ||||
|     } | ||||
|  | ||||
|     ((io.in zip io.out) zip (node.edgesIn zip node.edgesOut)) foreach { case ((in, out), (edgeIn, edgeOut)) => | ||||
|     (node.in zip node.out) foreach { case ((in, edgeIn), (out, edgeOut)) => | ||||
|       ABo(out.a, in .a) | ||||
|       ABi(in .d, out.d) | ||||
|  | ||||
|   | ||||
| @@ -20,14 +20,8 @@ class TLMap(fn: AddressSet => BigInt)(implicit p: Parameters) extends LazyModule | ||||
|           AddressSet(fn(a), a.mask)))))}) | ||||
|  | ||||
|   lazy val module = new LazyModuleImp(this) { | ||||
|     val io = new Bundle { | ||||
|       val in = node.bundleIn | ||||
|       val out = node.bundleOut | ||||
|     } | ||||
|  | ||||
|     io.out <> io.in | ||||
|  | ||||
|     ((io.in zip io.out) zip (node.edgesIn zip node.edgesOut)) foreach { case ((in, out), (edgeIn, edgeOut)) => | ||||
|     (node.in zip node.out) foreach { case ((in, edgeIn), (out, edgeOut)) => | ||||
|       out <> in | ||||
|       val convert = edgeIn.manager.managers.flatMap(_.address) zip edgeOut.manager.managers.flatMap(_.address) | ||||
|       def forward(x: UInt) = | ||||
|         convert.map { case (i, o) => Mux(i.contains(x), UInt(o.base) | (x & UInt(o.mask)), UInt(0)) }.reduce(_ | _) | ||||
|   | ||||
| @@ -8,26 +8,22 @@ import freechips.rocketchip.config.Parameters | ||||
| import freechips.rocketchip.diplomacy._ | ||||
| import freechips.rocketchip.util.{HeterogeneousBag, PlusArg} | ||||
|  | ||||
| case class TLMonitorArgs(edge: () => Seq[TLEdge], sourceInfo: SourceInfo, p: Parameters) | ||||
| case class TLMonitorArgs(edge: TLEdge) | ||||
|  | ||||
| abstract class TLMonitorBase(args: TLMonitorArgs) extends MonitorBase()(args.sourceInfo, args.p) | ||||
| abstract class TLMonitorBase(args: TLMonitorArgs) extends Module | ||||
| { | ||||
|   def legalize(bundle: TLBundleSnoop, edge: TLEdge, reset: Bool): Unit | ||||
|  | ||||
|   lazy val module = new LazyModuleImp(this) { | ||||
|     val edges = args.edge() | ||||
|   val io = new Bundle { | ||||
|       val in = HeterogeneousBag(edges.map(p => new TLBundleSnoop(p.bundle))).flip | ||||
|     val in = new TLBundleSnoop(args.edge.bundle).flip | ||||
|   } | ||||
|  | ||||
|     (edges zip io.in).foreach { case (e, in) => legalize(in, e, reset) } | ||||
|   } | ||||
|   def legalize(bundle: TLBundleSnoop, edge: TLEdge, reset: Bool): Unit | ||||
|   legalize(io.in, args.edge, reset) | ||||
| } | ||||
|  | ||||
| class TLMonitor(args: TLMonitorArgs) extends TLMonitorBase(args) | ||||
| { | ||||
|   def extra = { | ||||
|     sourceInfo match { | ||||
|     args.edge.sourceInfo match { | ||||
|       case SourceLine(filename, line, col) => s" (connected at $filename:$line:$col)" | ||||
|       case _ => "" | ||||
|     } | ||||
|   | ||||
| @@ -7,11 +7,8 @@ import chisel3.internal.sourceinfo.SourceInfo | ||||
| import freechips.rocketchip.config.Parameters | ||||
| import freechips.rocketchip.diplomacy._ | ||||
|  | ||||
| case class TLNodeNumbererNode(nodeAddressOffset: Option[Int] = None) extends TLCustomNode(0 to 999, 0 to 999) | ||||
| case class TLNodeNumbererNode(nodeAddressOffset: Option[Int] = None)(implicit valName: ValName) extends TLCustomNode(0 to 999, 0 to 999) | ||||
| { | ||||
|   val externalIn = true | ||||
|   val externalOut = true | ||||
|  | ||||
|   def resolveStar(iKnown: Int, oKnown: Int, iStars: Int, oStars: Int): (Int, Int) = { | ||||
|     require (oStars + iStars <= 1, s"${name} (a custom adapter) appears left of a :*= ${iStars} times and right of a :=* ${oStars} times; at most once is allowed${lazyModule.line}") | ||||
|     if (oStars > 0) { | ||||
| @@ -46,15 +43,10 @@ class TLNodeNumberer(nodeAddressOffset: Option[Int] = None)(implicit p: Paramete | ||||
|   val node = TLNodeNumbererNode(nodeAddressOffset) | ||||
|  | ||||
|   lazy val module = new LazyModuleImp(this) { | ||||
|     val io = new Bundle { | ||||
|       val in  = node.bundleIn | ||||
|       val out = node.bundleOut | ||||
|     } | ||||
|  | ||||
|     val minNodeOffset = log2Ceil(node.edgesOut.map(_.manager.maxAddress).max) | ||||
|     val minNodeOffset = log2Ceil(node.edges.out.map(_.manager.maxAddress).max) | ||||
|     val nodeOffset = nodeAddressOffset.getOrElse(minNodeOffset) | ||||
|  | ||||
|     (io.in zip io.out).zipWithIndex foreach { case ((in, out), i) => | ||||
|     (node.in zip node.out).zipWithIndex foreach { case (((in, _), (out, _)), i) => | ||||
|       out <> in | ||||
|       // a&c address already get truncated | ||||
|       in.b.bits.address := (UInt(i+1) << nodeOffset) | out.b.bits.address | ||||
|   | ||||
| @@ -9,40 +9,21 @@ import freechips.rocketchip.diplomacy._ | ||||
| import freechips.rocketchip.util.RationalDirection | ||||
| import scala.collection.mutable.ListBuffer | ||||
|  | ||||
| case object TLMonitorBuilder extends Field[TLMonitorArgs => TLMonitorBase](args => LazyModule(new TLMonitor(args))) | ||||
| case object TLCombinationalCheck extends Field[Boolean](false) | ||||
| case object TLMonitorBuilder extends Field[TLMonitorArgs => TLMonitorBase](args => new TLMonitor(args)) | ||||
|  | ||||
| object TLImp extends NodeImp[TLClientPortParameters, TLManagerPortParameters, TLEdgeOut, TLEdgeIn, TLBundle] | ||||
| { | ||||
|   def edgeO(pd: TLClientPortParameters, pu: TLManagerPortParameters): TLEdgeOut = new TLEdgeOut(pd, pu) | ||||
|   def edgeI(pd: TLClientPortParameters, pu: TLManagerPortParameters): TLEdgeIn  = new TLEdgeIn(pd, pu) | ||||
|   def edgeO(pd: TLClientPortParameters, pu: TLManagerPortParameters, p: Parameters, sourceInfo: SourceInfo) = new TLEdgeOut(pd, pu, p, sourceInfo) | ||||
|   def edgeI(pd: TLClientPortParameters, pu: TLManagerPortParameters, p: Parameters, sourceInfo: SourceInfo) = new TLEdgeIn (pd, pu, p, sourceInfo) | ||||
|  | ||||
|   def bundleO(eo: TLEdgeOut): TLBundle = TLBundle(eo.bundle) | ||||
|   def bundleI(ei: TLEdgeIn):  TLBundle = TLBundle(ei.bundle) | ||||
|   def bundleO(eo: TLEdgeOut) = TLBundle(eo.bundle) | ||||
|   def bundleI(ei: TLEdgeIn)  = TLBundle(ei.bundle) | ||||
|  | ||||
|   def colour = "#000000" // black | ||||
|   override def labelI(ei: TLEdgeIn)  = (ei.manager.beatBytes * 8).toString | ||||
|   override def labelO(eo: TLEdgeOut) = (eo.manager.beatBytes * 8).toString | ||||
|   def render(ei: TLEdgeIn) = RenderedEdge(colour = "#000000" /* black */, label = (ei.manager.beatBytes * 8).toString) | ||||
|  | ||||
|   override def connect(edges: () => Seq[TLEdgeIn], bundles: () => Seq[(TLBundle, TLBundle)], enableMonitoring: Boolean) | ||||
|                       (implicit p: Parameters, sourceInfo: SourceInfo): (Option[TLMonitorBase], () => Unit) = { | ||||
|     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) } } | ||||
|       eval.foreach { case (bi, bo) => | ||||
|         bi <> bo | ||||
|         if (p(TLCombinationalCheck)) { | ||||
|           // It is forbidden for valid to depend on ready in TL2 | ||||
|           // If someone did that, then this will create a detectable combinational loop | ||||
|           bo.a.ready := bi.a.ready && bo.a.valid | ||||
|           bi.b.ready := bo.b.ready && bi.b.valid | ||||
|           bo.c.ready := bi.c.ready && bo.c.valid | ||||
|           bi.d.ready := bo.d.ready && bi.d.valid | ||||
|           bo.e.ready := bi.e.ready && bo.e.valid | ||||
|         } | ||||
|       } | ||||
|     }) | ||||
|   override def monitor(bundle: TLBundle, edge: TLEdgeIn) { | ||||
|     val monitor = Module(edge.params(TLMonitorBuilder)(TLMonitorArgs(edge))) | ||||
|     monitor.io.in := TLBundleSnoop(bundle, bundle) | ||||
|   } | ||||
|  | ||||
|   override def mixO(pd: TLClientPortParameters, node: OutwardNode[TLClientPortParameters, TLManagerPortParameters, TLBundle]): TLClientPortParameters  = | ||||
| @@ -63,92 +44,39 @@ object TLImp extends NodeImp[TLClientPortParameters, TLManagerPortParameters, TL | ||||
|   } | ||||
| } | ||||
|  | ||||
| // Nodes implemented inside modules | ||||
| case class TLIdentityNode() extends IdentityNode(TLImp) | ||||
| case class TLClientNode(portParams: Seq[TLClientPortParameters]) extends SourceNode(TLImp)(portParams) | ||||
| case class TLManagerNode(portParams: Seq[TLManagerPortParameters]) extends SinkNode(TLImp)(portParams) | ||||
|  | ||||
| object TLClientNode | ||||
| { | ||||
|   def apply(params: TLClientParameters) = | ||||
|     new TLClientNode(Seq(TLClientPortParameters(Seq(params)))) | ||||
| } | ||||
|  | ||||
| object TLManagerNode | ||||
| { | ||||
|   def apply(beatBytes: Int, params: TLManagerParameters) = | ||||
|     new TLManagerNode(Seq(TLManagerPortParameters(Seq(params), beatBytes, minLatency = 0))) | ||||
| } | ||||
| case class TLClientNode(portParams: Seq[TLClientPortParameters])(implicit valName: ValName) extends SourceNode(TLImp)(portParams) | ||||
| case class TLManagerNode(portParams: Seq[TLManagerPortParameters])(implicit valName: ValName) extends SinkNode(TLImp)(portParams) | ||||
|  | ||||
| case class TLAdapterNode( | ||||
|   clientFn:  TLClientPortParameters  => TLClientPortParameters, | ||||
|   managerFn: TLManagerPortParameters => TLManagerPortParameters, | ||||
|   num:       Range.Inclusive = 0 to 999) | ||||
|   clientFn:  TLClientPortParameters  => TLClientPortParameters  = { s => s }, | ||||
|   managerFn: TLManagerPortParameters => TLManagerPortParameters = { s => s }, | ||||
|   num:       Range.Inclusive = 0 to 999)( | ||||
|   implicit valName: ValName) | ||||
|   extends AdapterNode(TLImp)(clientFn, managerFn, num) | ||||
|  | ||||
| case class TLIdentityNode()(implicit valName: ValName) extends IdentityNode(TLImp)() | ||||
|  | ||||
| case class TLNexusNode( | ||||
|   clientFn:        Seq[TLClientPortParameters]  => TLClientPortParameters, | ||||
|   managerFn:       Seq[TLManagerPortParameters] => TLManagerPortParameters, | ||||
|   numClientPorts:  Range.Inclusive = 1 to 999, | ||||
|   numManagerPorts: Range.Inclusive = 1 to 999) | ||||
|   numManagerPorts: Range.Inclusive = 1 to 999)( | ||||
|   implicit valName: ValName) | ||||
|   extends NexusNode(TLImp)(clientFn, managerFn, numClientPorts, numManagerPorts) | ||||
|  | ||||
| case class TLSplitterNode( | ||||
|   clientFn:        SplitterArg[TLClientPortParameters]  => Seq[TLClientPortParameters], | ||||
|   managerFn:       SplitterArg[TLManagerPortParameters] => Seq[TLManagerPortParameters], | ||||
|   numClientPorts:  Range.Inclusive = 0 to 999, | ||||
|   numManagerPorts: Range.Inclusive = 0 to 999) | ||||
|   extends SplitterNode(TLImp)(clientFn, managerFn, numClientPorts, numManagerPorts) | ||||
|  | ||||
| abstract class TLCustomNode( | ||||
|   numClientPorts:  Range.Inclusive, | ||||
|   numManagerPorts: Range.Inclusive) | ||||
|   numManagerPorts: Range.Inclusive)( | ||||
|   implicit valName: ValName) | ||||
|   extends CustomNode(TLImp)(numClientPorts, numManagerPorts) | ||||
|  | ||||
| // Nodes passed from an inner module | ||||
| case class TLOutputNode() extends OutputNode(TLImp) | ||||
| case class TLInputNode() extends InputNode(TLImp) | ||||
| // Asynchronous crossings | ||||
|  | ||||
| // Nodes used for external ports | ||||
| case class TLBlindOutputNode(portParams: Seq[TLManagerPortParameters]) extends BlindOutputNode(TLImp)(portParams) | ||||
| case class TLBlindInputNode(portParams: Seq[TLClientPortParameters]) extends BlindInputNode(TLImp)(portParams) | ||||
|  | ||||
| case class TLInternalOutputNode(portParams: Seq[TLManagerPortParameters]) extends InternalOutputNode(TLImp)(portParams) | ||||
| case class TLInternalInputNode(portParams: Seq[TLClientPortParameters]) extends InternalInputNode(TLImp)(portParams) | ||||
|  | ||||
| /** Synthesizeable unit tests */ | ||||
| import freechips.rocketchip.unittest._ | ||||
|  | ||||
| class TLInputNodeTest(txns: Int = 5000, timeout: Int = 500000)(implicit p: Parameters) extends UnitTest(timeout) { | ||||
|   class Acceptor extends LazyModule { | ||||
|     val node = TLInputNode() | ||||
|     val tlram = LazyModule(new TLRAM(AddressSet(0x54321000, 0xfff))) | ||||
|     tlram.node := node | ||||
|  | ||||
|     lazy val module = new LazyModuleImp(this) { | ||||
|       val io = new Bundle { | ||||
|         val in = node.bundleIn | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   val fuzzer = LazyModule(new TLFuzzer(txns)) | ||||
|   LazyModule(new Acceptor).node := TLFragmenter(4, 64)(fuzzer.node) | ||||
|  | ||||
|   io.finished := Module(fuzzer.module).io.finished | ||||
| } | ||||
|  | ||||
| object TLAsyncImp extends NodeImp[TLAsyncClientPortParameters, TLAsyncManagerPortParameters, TLAsyncEdgeParameters, TLAsyncEdgeParameters, TLAsyncBundle] | ||||
| object TLAsyncImp extends SimpleNodeImp[TLAsyncClientPortParameters, TLAsyncManagerPortParameters, TLAsyncEdgeParameters, TLAsyncBundle] | ||||
| { | ||||
|   def edgeO(pd: TLAsyncClientPortParameters, pu: TLAsyncManagerPortParameters): TLAsyncEdgeParameters = TLAsyncEdgeParameters(pd, pu) | ||||
|   def edgeI(pd: TLAsyncClientPortParameters, pu: TLAsyncManagerPortParameters): TLAsyncEdgeParameters = TLAsyncEdgeParameters(pd, pu) | ||||
|  | ||||
|   def bundleO(eo: TLAsyncEdgeParameters): TLAsyncBundle = new TLAsyncBundle(eo.bundle) | ||||
|   def bundleI(ei: TLAsyncEdgeParameters): TLAsyncBundle = new TLAsyncBundle(ei.bundle) | ||||
|  | ||||
|   def colour = "#ff0000" // red | ||||
|   override def labelI(ei: TLAsyncEdgeParameters) = ei.manager.depth.toString | ||||
|   override def labelO(eo: TLAsyncEdgeParameters) = eo.manager.depth.toString | ||||
|   def edge(pd: TLAsyncClientPortParameters, pu: TLAsyncManagerPortParameters, p: Parameters, sourceInfo: SourceInfo) = TLAsyncEdgeParameters(pd, pu, p, sourceInfo) | ||||
|   def bundle(e: TLAsyncEdgeParameters) = new TLAsyncBundle(e.bundle) | ||||
|   def render(e: TLAsyncEdgeParameters) = RenderedEdge(colour = "#ff0000" /* red */, label = e.manager.depth.toString) | ||||
|  | ||||
|   override def mixO(pd: TLAsyncClientPortParameters, node: OutwardNode[TLAsyncClientPortParameters, TLAsyncManagerPortParameters, TLAsyncBundle]): TLAsyncClientPortParameters  = | ||||
|    pd.copy(base = pd.base.copy(clients  = pd.base.clients.map  { c => c.copy (nodePath = node +: c.nodePath) })) | ||||
| @@ -156,29 +84,32 @@ object TLAsyncImp extends NodeImp[TLAsyncClientPortParameters, TLAsyncManagerPor | ||||
|    pu.copy(base = pu.base.copy(managers = pu.base.managers.map { m => m.copy (nodePath = node +: m.nodePath) })) | ||||
| } | ||||
|  | ||||
| case class TLAsyncIdentityNode() extends IdentityNode(TLAsyncImp) | ||||
| case class TLAsyncOutputNode() extends OutputNode(TLAsyncImp) | ||||
| case class TLAsyncInputNode() extends InputNode(TLAsyncImp) | ||||
| case class TLAsyncAdapterNode( | ||||
|   clientFn:  TLAsyncClientPortParameters  => TLAsyncClientPortParameters  = { s => s }, | ||||
|   managerFn: TLAsyncManagerPortParameters => TLAsyncManagerPortParameters = { s => s }, | ||||
|   num:       Range.Inclusive = 0 to 999)( | ||||
|   implicit valName: ValName) | ||||
|   extends AdapterNode(TLAsyncImp)(clientFn, managerFn, num) | ||||
|  | ||||
| case class TLAsyncSourceNode(sync: Int) | ||||
| case class TLAsyncIdentityNode()(implicit valName: ValName) extends IdentityNode(TLAsyncImp)() | ||||
|  | ||||
| case class TLAsyncSourceNode(sync: Int)(implicit valName: ValName) | ||||
|   extends MixedAdapterNode(TLImp, TLAsyncImp)( | ||||
|     dFn = { p => TLAsyncClientPortParameters(p) }, | ||||
|     uFn = { p => p.base.copy(minLatency = sync+1) }) // discard cycles in other clock domain | ||||
|  | ||||
| case class TLAsyncSinkNode(depth: Int, sync: Int) | ||||
| case class TLAsyncSinkNode(depth: Int, sync: Int)(implicit valName: ValName) | ||||
|   extends MixedAdapterNode(TLAsyncImp, TLImp)( | ||||
|     dFn = { p => p.base.copy(minLatency = sync+1) }, | ||||
|     uFn = { p => TLAsyncManagerPortParameters(depth, p) }) | ||||
|  | ||||
| object TLRationalImp extends NodeImp[TLRationalClientPortParameters, TLRationalManagerPortParameters, TLRationalEdgeParameters, TLRationalEdgeParameters, TLRationalBundle] | ||||
| // Rationally related crossings | ||||
|  | ||||
| object TLRationalImp extends SimpleNodeImp[TLRationalClientPortParameters, TLRationalManagerPortParameters, TLRationalEdgeParameters, TLRationalBundle] | ||||
| { | ||||
|   def edgeO(pd: TLRationalClientPortParameters, pu: TLRationalManagerPortParameters): TLRationalEdgeParameters = TLRationalEdgeParameters(pd, pu) | ||||
|   def edgeI(pd: TLRationalClientPortParameters, pu: TLRationalManagerPortParameters): TLRationalEdgeParameters = TLRationalEdgeParameters(pd, pu) | ||||
|  | ||||
|   def bundleO(eo: TLRationalEdgeParameters): TLRationalBundle = new TLRationalBundle(eo.bundle) | ||||
|   def bundleI(ei: TLRationalEdgeParameters): TLRationalBundle = new TLRationalBundle(ei.bundle) | ||||
|  | ||||
|   def colour = "#00ff00" // green | ||||
|   def edge(pd: TLRationalClientPortParameters, pu: TLRationalManagerPortParameters, p: Parameters, sourceInfo: SourceInfo) = TLRationalEdgeParameters(pd, pu, p, sourceInfo) | ||||
|   def bundle(e: TLRationalEdgeParameters) = new TLRationalBundle(e.bundle) | ||||
|   def render(e: TLRationalEdgeParameters) = RenderedEdge(colour = "#00ff00" /* green */) | ||||
|  | ||||
|   override def mixO(pd: TLRationalClientPortParameters, node: OutwardNode[TLRationalClientPortParameters, TLRationalManagerPortParameters, TLRationalBundle]): TLRationalClientPortParameters  = | ||||
|    pd.copy(base = pd.base.copy(clients  = pd.base.clients.map  { c => c.copy (nodePath = node +: c.nodePath) })) | ||||
| @@ -186,16 +117,21 @@ object TLRationalImp extends NodeImp[TLRationalClientPortParameters, TLRationalM | ||||
|    pu.copy(base = pu.base.copy(managers = pu.base.managers.map { m => m.copy (nodePath = node +: m.nodePath) })) | ||||
| } | ||||
|  | ||||
| case class TLRationalIdentityNode() extends IdentityNode(TLRationalImp) | ||||
| case class TLRationalOutputNode() extends OutputNode(TLRationalImp) | ||||
| case class TLRationalInputNode() extends InputNode(TLRationalImp) | ||||
| case class TLRationalAdapterNode( | ||||
|   clientFn:  TLRationalClientPortParameters  => TLRationalClientPortParameters  = { s => s }, | ||||
|   managerFn: TLRationalManagerPortParameters => TLRationalManagerPortParameters = { s => s }, | ||||
|   num:       Range.Inclusive = 0 to 999)( | ||||
|   implicit valName: ValName) | ||||
|   extends AdapterNode(TLRationalImp)(clientFn, managerFn, num) | ||||
|  | ||||
| case class TLRationalSourceNode() | ||||
| case class TLRationalIdentityNode()(implicit valName: ValName) extends IdentityNode(TLRationalImp)() | ||||
|  | ||||
| case class TLRationalSourceNode()(implicit valName: ValName) | ||||
|   extends MixedAdapterNode(TLImp, TLRationalImp)( | ||||
|     dFn = { p => TLRationalClientPortParameters(p) }, | ||||
|     uFn = { p => p.base.copy(minLatency = 1) }) // discard cycles from other clock domain | ||||
|  | ||||
| case class TLRationalSinkNode(direction: RationalDirection) | ||||
| case class TLRationalSinkNode(direction: RationalDirection)(implicit valName: ValName) | ||||
|   extends MixedAdapterNode(TLRationalImp, TLImp)( | ||||
|     dFn = { p => p.base.copy(minLatency = 1) }, | ||||
|     uFn = { p => TLRationalManagerPortParameters(direction, p) }) | ||||
|   | ||||
| @@ -3,6 +3,8 @@ | ||||
| package freechips.rocketchip.tilelink | ||||
|  | ||||
| import Chisel._ | ||||
| import chisel3.internal.sourceinfo.SourceInfo | ||||
| import freechips.rocketchip.config.Parameters | ||||
| import freechips.rocketchip.diplomacy._ | ||||
| import freechips.rocketchip.util.RationalDirection | ||||
| import scala.math.max | ||||
| @@ -312,7 +314,9 @@ object TLBundleParameters | ||||
|  | ||||
| case class TLEdgeParameters( | ||||
|   client:  TLClientPortParameters, | ||||
|   manager: TLManagerPortParameters) | ||||
|   manager: TLManagerPortParameters, | ||||
|   params:  Parameters, | ||||
|   sourceInfo: SourceInfo) | ||||
| { | ||||
|   val maxTransfer = max(client.maxTransfer, manager.maxTransfer) | ||||
|   val maxLgSize = log2Ceil(maxTransfer) | ||||
| @@ -340,7 +344,7 @@ object TLAsyncBundleParameters | ||||
|   def union(x: Seq[TLAsyncBundleParameters]) = x.foldLeft(emptyBundleParams)((x,y) => x.union(y)) | ||||
| } | ||||
|  | ||||
| case class TLAsyncEdgeParameters(client: TLAsyncClientPortParameters, manager: TLAsyncManagerPortParameters) | ||||
| case class TLAsyncEdgeParameters(client: TLAsyncClientPortParameters, manager: TLAsyncManagerPortParameters, params: Parameters, sourceInfo: SourceInfo) | ||||
| { | ||||
|   val bundle = TLAsyncBundleParameters(manager.depth, TLBundleParameters(client.base, manager.base)) | ||||
| } | ||||
| @@ -348,7 +352,7 @@ case class TLAsyncEdgeParameters(client: TLAsyncClientPortParameters, manager: T | ||||
| case class TLRationalManagerPortParameters(direction: RationalDirection, base: TLManagerPortParameters) | ||||
| case class TLRationalClientPortParameters(base: TLClientPortParameters) | ||||
|  | ||||
| case class TLRationalEdgeParameters(client: TLRationalClientPortParameters, manager: TLRationalManagerPortParameters) | ||||
| case class TLRationalEdgeParameters(client: TLRationalClientPortParameters, manager: TLRationalManagerPortParameters, params: Parameters, sourceInfo: SourceInfo) | ||||
| { | ||||
|   val bundle = TLBundleParameters(client.base, manager.base) | ||||
| } | ||||
|   | ||||
| @@ -38,13 +38,12 @@ class TLPatternPusher(name: String, pattern: Seq[Pattern])(implicit p: Parameter | ||||
|   val node = TLClientNode(Seq(TLClientPortParameters(Seq(TLClientParameters(name = name))))) | ||||
|  | ||||
|   lazy val module = new LazyModuleImp(this) { | ||||
|     val io = new Bundle { | ||||
|       val tl_out = node.bundleOut | ||||
|     val io = IO(new Bundle { | ||||
|       val run = Bool(INPUT) | ||||
|       val done = Bool(OUTPUT) | ||||
|     } | ||||
|     }) | ||||
|  | ||||
|     val edgeOut = node.edgesOut(0) | ||||
|     val (tl_out, edgeOut) = node.out(0) | ||||
|     pattern.foreach { p => | ||||
|       require (p.size <= log2Ceil(edgeOut.manager.beatBytes), "Patterns must fit in a single beat") | ||||
|     } | ||||
| @@ -56,8 +55,8 @@ class TLPatternPusher(name: String, pattern: Seq[Pattern])(implicit p: Parameter | ||||
|     val end = step === UInt(pattern.size) | ||||
|     io.done := end && !flight | ||||
|  | ||||
|     val a = io.tl_out(0).a | ||||
|     val d = io.tl_out(0).d | ||||
|     val a = tl_out.a | ||||
|     val d = tl_out.d | ||||
|  | ||||
|     // Expected response? | ||||
|     val check  = Vec(pattern.map(p => Bool(p.dataIn.isDefined)))(step) holdUnless a.fire() | ||||
| @@ -80,8 +79,8 @@ class TLPatternPusher(name: String, pattern: Seq[Pattern])(implicit p: Parameter | ||||
|     d.ready := Bool(true) | ||||
|  | ||||
|     // Tie off unused channels | ||||
|     io.tl_out(0).b.ready := Bool(true) | ||||
|     io.tl_out(0).c.valid := Bool(false) | ||||
|     io.tl_out(0).e.valid := Bool(false) | ||||
|     tl_out.b.ready := Bool(true) | ||||
|     tl_out.c.valid := Bool(false) | ||||
|     tl_out.e.valid := Bool(false) | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -24,15 +24,10 @@ import freechips.rocketchip.util._ | ||||
|  | ||||
| class TLRAMModel(log: String = "")(implicit p: Parameters) extends LazyModule | ||||
| { | ||||
|   val node = TLIdentityNode() | ||||
|   val node = TLAdapterNode() | ||||
|  | ||||
|   lazy val module = new LazyModuleImp(this) { | ||||
|     val io = new Bundle { | ||||
|       val in = node.bundleIn | ||||
|       val out = node.bundleOut | ||||
|     } | ||||
|  | ||||
|     ((io.in zip io.out) zip (node.edgesIn zip node.edgesOut)) foreach { case ((in, out), (edgeIn, edgeOut)) => | ||||
|     (node.in zip node.out) foreach { case ((in, edgeIn), (out, edgeOut)) => | ||||
|       val edge         = edgeIn | ||||
|       val endAddress   = edge.manager.maxAddress + 1 | ||||
|       val endSourceId  = edge.client.endSourceId | ||||
|   | ||||
| @@ -20,12 +20,7 @@ class TLRationalCrossingSource(implicit p: Parameters) extends LazyModule | ||||
|   val node = TLRationalSourceNode() | ||||
|  | ||||
|   lazy val module = new LazyModuleImp(this) { | ||||
|     val io = new Bundle { | ||||
|       val in  = node.bundleIn | ||||
|       val out = node.bundleOut | ||||
|     } | ||||
|  | ||||
|     ((io.in zip io.out) zip (node.edgesIn zip node.edgesOut)) foreach { case ((in, out), (edgeIn, edgeOut)) => | ||||
|     (node.in zip node.out) foreach { case ((in, edgeIn), (out, edgeOut)) => | ||||
|       val bce = edgeIn.manager.anySupportAcquireB && edgeIn.client.anySupportProbe | ||||
|       val direction = edgeOut.manager.direction | ||||
|  | ||||
| @@ -56,12 +51,7 @@ class TLRationalCrossingSink(direction: RationalDirection = Symmetric)(implicit | ||||
|   val node = TLRationalSinkNode(direction) | ||||
|  | ||||
|   lazy val module = new LazyModuleImp(this) { | ||||
|     val io = new Bundle { | ||||
|       val in  = node.bundleIn | ||||
|       val out = node.bundleOut | ||||
|     } | ||||
|  | ||||
|     ((io.in zip io.out) zip (node.edgesIn zip node.edgesOut)) foreach { case ((in, out), (edgeIn, edgeOut)) => | ||||
|     (node.in zip node.out) foreach { case ((in, edgeIn), (out, edgeOut)) => | ||||
|       val bce = edgeOut.manager.anySupportAcquireB && edgeOut.client.anySupportProbe | ||||
|       val direction = edgeIn.manager.direction | ||||
|  | ||||
| @@ -109,40 +99,24 @@ object TLRationalCrossingSink | ||||
|  | ||||
| class TLRationalCrossing(direction: RationalDirection = Symmetric)(implicit p: Parameters) extends LazyModule | ||||
| { | ||||
|   val nodeIn = TLInputNode() | ||||
|   val nodeOut = TLOutputNode() | ||||
|   val node = NodeHandle(nodeIn, nodeOut) | ||||
|  | ||||
|   val source = LazyModule(new TLRationalCrossingSource) | ||||
|   val sink = LazyModule(new TLRationalCrossingSink(direction)) | ||||
|   val node = NodeHandle(source.node, sink.node) | ||||
|  | ||||
|   val _    = (sink.node := source.node) // no monitor | ||||
|   val in   = (source.node := nodeIn) | ||||
|   val out  = (nodeOut := sink.node) | ||||
|   sink.node := source.node | ||||
|  | ||||
|   lazy val module = new LazyModuleImp(this) { | ||||
|     val io = new Bundle { | ||||
|       val in        = nodeIn.bundleIn | ||||
|     val io = IO(new Bundle { | ||||
|       val in_clock  = Clock(INPUT) | ||||
|       val in_reset  = Bool(INPUT) | ||||
|       val out       = nodeOut.bundleOut | ||||
|       val out_clock = Clock(INPUT) | ||||
|       val out_reset = Bool(INPUT) | ||||
|     } | ||||
|     }) | ||||
|  | ||||
|     source.module.clock := io.in_clock | ||||
|     source.module.reset := io.in_reset | ||||
|     in.foreach { lm => | ||||
|       lm.module.clock := io.in_clock | ||||
|       lm.module.reset := io.in_reset | ||||
|     } | ||||
|  | ||||
|     sink.module.clock := io.out_clock | ||||
|     sink.module.reset := io.out_reset | ||||
|     out.foreach { lm => | ||||
|       lm.module.clock := io.out_clock | ||||
|       lm.module.reset := io.out_reset | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  | ||||
| @@ -150,7 +124,7 @@ class TLRationalCrossing(direction: RationalDirection = Symmetric)(implicit p: P | ||||
| import freechips.rocketchip.unittest._ | ||||
|  | ||||
| class TLRAMRationalCrossingSource(name: String, txns: Int)(implicit p: Parameters) extends LazyModule { | ||||
|   val node = TLRationalOutputNode() | ||||
|   val node = TLRationalIdentityNode() | ||||
|   val fuzz  = LazyModule(new TLFuzzer(txns)) | ||||
|   val model = LazyModule(new TLRAMModel(name)) | ||||
|  | ||||
| @@ -158,25 +132,20 @@ class TLRAMRationalCrossingSource(name: String, txns: Int)(implicit p: Parameter | ||||
|   node := TLRationalCrossingSource()(TLDelayer(0.25)(model.node)) | ||||
|  | ||||
|   lazy val module = new LazyModuleImp(this) { | ||||
|     val io = new Bundle { | ||||
|     val io = IO(new Bundle { | ||||
|       val finished = Bool(OUTPUT) | ||||
|       val out = node.bundleOut | ||||
|     } | ||||
|     }) | ||||
|     io.finished := fuzz.module.io.finished | ||||
|   } | ||||
| } | ||||
|  | ||||
| class TLRAMRationalCrossingSink(direction: RationalDirection)(implicit p: Parameters) extends LazyModule { | ||||
|   val node = TLRationalInputNode() | ||||
|   val node = TLRationalIdentityNode() | ||||
|   val ram  = LazyModule(new TLRAM(AddressSet(0x0, 0x3ff))) | ||||
|  | ||||
|   ram.node := TLFragmenter(4, 256)(TLDelayer(0.25)(TLRationalCrossingSink(direction)(node))) | ||||
|  | ||||
|   lazy val module = new LazyModuleImp(this) { | ||||
|     val io = new Bundle { | ||||
|       val in = node.bundleIn | ||||
|     } | ||||
|   } | ||||
|   lazy val module = new LazyModuleImp(this) { } | ||||
| } | ||||
|  | ||||
| class TLRAMRationalCrossing(txns: Int)(implicit p: Parameters) extends LazyModule { | ||||
| @@ -196,7 +165,7 @@ class TLRAMRationalCrossing(txns: Int)(implicit p: Parameters) extends LazyModul | ||||
|   val fix_fast_sink   = LazyModule(new TLRAMRationalCrossingSink(SlowToFast)) | ||||
|   fix_fast_sink.node := fix_slow_source.node | ||||
|  | ||||
|   lazy val module = new LazyModuleImp(this) with HasUnitTestIO { | ||||
|   lazy val module = new LazyModuleImp(this) with UnitTestModule { | ||||
|     io.finished := | ||||
|       sym_fast_source.module.io.finished && | ||||
|       sym_slow_source.module.io.finished && | ||||
|   | ||||
| @@ -9,15 +9,16 @@ import freechips.rocketchip.regmapper._ | ||||
| import freechips.rocketchip.util.HeterogeneousBag | ||||
| import scala.math.{min,max} | ||||
|  | ||||
| class TLRegisterNode( | ||||
| case class TLRegisterNode( | ||||
|     address:     Seq[AddressSet], | ||||
|     device:      Device, | ||||
|     deviceKey:   String  = "reg/control", | ||||
|     concurrency: Int     = 0, | ||||
|     beatBytes:   Int     = 4, | ||||
|     undefZero:   Boolean = true, | ||||
|     executable:  Boolean = false) | ||||
|   extends TLManagerNode(Seq(TLManagerPortParameters( | ||||
|     executable:  Boolean = false)( | ||||
|     implicit valName: ValName) | ||||
|   extends SinkNode(TLImp)(Seq(TLManagerPortParameters( | ||||
|     Seq(TLManagerParameters( | ||||
|       address            = address, | ||||
|       resources          = Seq(Resource(device, deviceKey)), | ||||
| @@ -39,9 +40,9 @@ class TLRegisterNode( | ||||
|   // Calling this method causes the matching TL2 bundle to be | ||||
|   // configured to route all requests to the listed RegFields. | ||||
|   def regmap(mapping: RegField.Map*) = { | ||||
|     val a = bundleIn(0).a | ||||
|     val d = bundleIn(0).d | ||||
|     val edge = edgesIn(0) | ||||
|     val (bundleIn, edge) = this.in(0) | ||||
|     val a = bundleIn.a | ||||
|     val d = bundleIn.d | ||||
|  | ||||
|     // Please forgive me ... | ||||
|     val baseEnd = 0 | ||||
| @@ -75,26 +76,12 @@ class TLRegisterNode( | ||||
|     d.bits.opcode := Mux(out.bits.read, TLMessages.AccessAckData, TLMessages.AccessAck) | ||||
|  | ||||
|     // Tie off unused channels | ||||
|     bundleIn(0).b.valid := Bool(false) | ||||
|     bundleIn(0).c.ready := Bool(true) | ||||
|     bundleIn(0).e.ready := Bool(true) | ||||
|     bundleIn.b.valid := Bool(false) | ||||
|     bundleIn.c.ready := Bool(true) | ||||
|     bundleIn.e.ready := Bool(true) | ||||
|   } | ||||
| } | ||||
|  | ||||
| object TLRegisterNode | ||||
| { | ||||
|   def apply( | ||||
|       address:     Seq[AddressSet], | ||||
|       device:      Device, | ||||
|       deviceKey:   String  = "reg/control", | ||||
|       concurrency: Int     = 0, | ||||
|       beatBytes:   Int     = 4, | ||||
|       undefZero:   Boolean = true, | ||||
|       executable:  Boolean = false) = | ||||
|     new TLRegisterNode(address, device, deviceKey, concurrency, beatBytes, undefZero, executable) | ||||
| } | ||||
|  | ||||
| // These convenience methods below combine to make it possible to create a TL2  | ||||
| // register mapped device from a totally abstract register mapped device. | ||||
| // See GPIO.scala in this directory for an example | ||||
|  | ||||
| @@ -105,13 +92,11 @@ abstract class TLRegisterRouterBase(devname: String, devcompat: Seq[String], val | ||||
|   val intnode = IntSourceNode(IntSourcePortSimple(num = interrupts, resources = Seq(Resource(device, "int")))) | ||||
| } | ||||
|  | ||||
| case class TLRegBundleArg(interrupts: HeterogeneousBag[Vec[Bool]], in: HeterogeneousBag[TLBundle])(implicit val p: Parameters) | ||||
| case class TLRegBundleArg()(implicit val p: Parameters) | ||||
|  | ||||
| class TLRegBundleBase(arg: TLRegBundleArg) extends Bundle | ||||
| { | ||||
|   implicit val p = arg.p | ||||
|   val interrupts = arg.interrupts | ||||
|   val in = arg.in | ||||
| } | ||||
|  | ||||
| class TLRegBundle[P](val params: P, arg: TLRegBundleArg)(implicit p: Parameters) extends TLRegBundleBase(arg) | ||||
| @@ -119,8 +104,8 @@ class TLRegBundle[P](val params: P, arg: TLRegBundleArg)(implicit p: Parameters) | ||||
| class TLRegModule[P, B <: TLRegBundleBase](val params: P, bundleBuilder: => B, router: TLRegisterRouterBase) | ||||
|   extends LazyModuleImp(router) with HasRegMap | ||||
| { | ||||
|   val io = bundleBuilder | ||||
|   val interrupts = if (io.interrupts.isEmpty) Vec(0, Bool()) else io.interrupts(0) | ||||
|   val io = IO(bundleBuilder) | ||||
|   val interrupts = if (router.intnode.out.isEmpty) Vec(0, Bool()) else router.intnode.out(0)._1 | ||||
|   val address = router.address | ||||
|   def regmap(mapping: RegField.Map*) = router.node.regmap(mapping:_*) | ||||
| } | ||||
| @@ -142,5 +127,7 @@ class TLRegisterRouter[B <: TLRegBundleBase, M <: LazyModuleImp]( | ||||
|   require (isPow2(size)) | ||||
|   // require (size >= 4096) ... not absolutely required, but highly recommended | ||||
|  | ||||
|   lazy val module = moduleBuilder(bundleBuilder(TLRegBundleArg(intnode.bundleOut, node.bundleIn)), this) | ||||
|   lazy val module = moduleBuilder(bundleBuilder(TLRegBundleArg()), this) | ||||
| } | ||||
|  | ||||
| // !!! eliminate third trait | ||||
|   | ||||
| @@ -3,6 +3,7 @@ | ||||
| package freechips.rocketchip.tilelink | ||||
|  | ||||
| import Chisel._ | ||||
| import chisel3.experimental.MultiIOModule | ||||
| import freechips.rocketchip.config.Parameters | ||||
| import freechips.rocketchip.diplomacy._ | ||||
| import freechips.rocketchip.regmapper._ | ||||
| @@ -222,7 +223,7 @@ trait RRTest1Bundle | ||||
| { | ||||
| } | ||||
|  | ||||
| trait RRTest1Module extends Module with HasRegMap | ||||
| trait RRTest1Module extends MultiIOModule with HasRegMap | ||||
| { | ||||
|   val clocks = Module(new Pow2ClockDivider(2)) | ||||
|  | ||||
| @@ -261,7 +262,7 @@ class FuzzRRTest0(txns: Int)(implicit p: Parameters) extends LazyModule { | ||||
|  | ||||
|   rrtr.node := TLFragmenter(4, 32)(TLDelayer(0.1)(fuzz.node)) | ||||
|  | ||||
|   lazy val module = new LazyModuleImp(this) with HasUnitTestIO { | ||||
|   lazy val module = new LazyModuleImp(this) with UnitTestModule { | ||||
|     io.finished := fuzz.module.io.finished | ||||
|   } | ||||
| } | ||||
| @@ -276,7 +277,7 @@ class FuzzRRTest1(txns: Int)(implicit p: Parameters) extends LazyModule { | ||||
|  | ||||
|   rrtr.node := TLFragmenter(4, 32)(TLDelayer(0.1)(fuzz.node)) | ||||
|  | ||||
|   lazy val module = new LazyModuleImp(this) with HasUnitTestIO { | ||||
|   lazy val module = new LazyModuleImp(this) with UnitTestModule { | ||||
|     io.finished := fuzz.module.io.finished | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -29,18 +29,12 @@ class TLRAM(address: AddressSet, executable: Boolean = true, beatBytes: Int = 4, | ||||
|   // We require the address range to include an entire beat (for the write mask) | ||||
|   require ((address.mask & (beatBytes-1)) == beatBytes-1) | ||||
|  | ||||
|   lazy val module = new Implementation | ||||
|   @chiselName class Implementation extends LazyModuleImp(this) { | ||||
|     val io = new Bundle { | ||||
|       val in = node.bundleIn | ||||
|     } | ||||
|  | ||||
|   lazy val module = new LazyModuleImp(this) { | ||||
|     def bigBits(x: BigInt, tail: List[Boolean] = List.empty[Boolean]): List[Boolean] = | ||||
|       if (x == 0) tail.reverse else bigBits(x >> 1, ((x & 1) == 1) :: tail) | ||||
|     val mask = bigBits(address.mask >> log2Ceil(beatBytes)) | ||||
|  | ||||
|     val in = io.in(0) | ||||
|     val edge = node.edgesIn(0) | ||||
|     val (in, edge) = node.in(0) | ||||
|  | ||||
|     val addrBits = (mask zip edge.addr_hi(in.a.bits).toBools).filter(_._1).map(_._2) | ||||
|     val a_legal = address.contains(in.a.bits.address) | ||||
| @@ -101,7 +95,7 @@ class TLRAMSimple(ramBeatBytes: Int, txns: Int)(implicit p: Parameters) extends | ||||
|   model.node := fuzz.node | ||||
|   ram.node := TLDelayer(0.25)(model.node) | ||||
|  | ||||
|   lazy val module = new LazyModuleImp(this) with HasUnitTestIO { | ||||
|   lazy val module = new LazyModuleImp(this) with UnitTestModule { | ||||
|     io.finished := fuzz.module.io.finished | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -23,12 +23,7 @@ class TLSourceShrinker(maxInFlight: Int)(implicit p: Parameters) extends LazyMod | ||||
|     managerFn = { mp => mp.copy(managers = mp.managers.map(_.copy(fifoId = None)))  }) | ||||
|  | ||||
|   lazy val module = new LazyModuleImp(this) { | ||||
|     val io = new Bundle { | ||||
|       val in  = node.bundleIn | ||||
|       val out = node.bundleOut | ||||
|     } | ||||
|  | ||||
|     ((io.in zip io.out) zip (node.edgesIn zip node.edgesOut)) foreach { case ((in, out), (edgeIn, edgeOut)) => | ||||
|     (node.in zip node.out) foreach { case ((in, edgeIn), (out, edgeOut)) => | ||||
|       // Acquires cannot pass this adapter; it makes Probes impossible | ||||
|       require (!edgeIn.client.anySupportProbe ||  | ||||
|                !edgeOut.manager.anySupportAcquireB) | ||||
|   | ||||
| @@ -6,6 +6,34 @@ import Chisel._ | ||||
| import freechips.rocketchip.config.Parameters | ||||
| import freechips.rocketchip.diplomacy._ | ||||
|  | ||||
| case class SplitterArg[T](newSize: Int, ports: Seq[T]) | ||||
| case class TLSplitterNode( | ||||
|   clientFn:        SplitterArg[TLClientPortParameters]  => Seq[TLClientPortParameters], | ||||
|   managerFn:       SplitterArg[TLManagerPortParameters] => Seq[TLManagerPortParameters], | ||||
|   numClientPorts:  Range.Inclusive = 0 to 999, | ||||
|   numManagerPorts: Range.Inclusive = 0 to 999)( | ||||
|   implicit valName: ValName) | ||||
|   extends TLCustomNode(numClientPorts, numManagerPorts) | ||||
| { | ||||
|   def resolveStar(iKnown: Int, oKnown: Int, iStars: Int, oStars: Int): (Int, Int) = { | ||||
|     require (oKnown == 0, s"${name} (a splitter) appears right of a := or :*=; use a :=* instead${lazyModule.line}") | ||||
|     require (iStars == 0, s"${name} (a splitter) cannot appear left of a :*=; did you mean :=*?${lazyModule.line}") | ||||
|     (0, iKnown) | ||||
|   } | ||||
|   def mapParamsD(n: Int, p: Seq[TLClientPortParameters]): Seq[TLClientPortParameters] = { | ||||
|     require (p.size == 0 || n % p.size == 0, s"Diplomacy bug; splitter inputs do not divide outputs") | ||||
|     val out = clientFn(SplitterArg(n, p)) | ||||
|     require (out.size == n, s"${name} created the wrong number of outputs from inputs${lazyModule.line}") | ||||
|     out | ||||
|   } | ||||
|   def mapParamsU(n: Int, p: Seq[TLManagerPortParameters]): Seq[TLManagerPortParameters] = { | ||||
|     require (n == 0 || p.size % n == 0, s"Diplomacy bug; splitter outputs indivisable by inputs") | ||||
|     val out = managerFn(SplitterArg(n, p)) | ||||
|     require (out.size == n, s"${name} created the wrong number of inputs from outputs${lazyModule.line}") | ||||
|     out | ||||
|   } | ||||
| } | ||||
|  | ||||
| class TLSplitter(policy: TLArbiter.Policy = TLArbiter.roundRobin)(implicit p: Parameters) extends LazyModule | ||||
| { | ||||
|   val node = TLSplitterNode( | ||||
| @@ -34,18 +62,14 @@ class TLSplitter(policy: TLArbiter.Policy = TLArbiter.roundRobin)(implicit p: Pa | ||||
|     }) | ||||
|  | ||||
|   lazy val module = new LazyModuleImp(this) { | ||||
|     val io = new Bundle { | ||||
|       val in  = node.bundleIn | ||||
|       val out = node.bundleOut | ||||
|     } | ||||
|  | ||||
|     def group[T](x: Seq[T]) = | ||||
|       if (x.isEmpty) Nil else x.grouped(node.edgesIn.size).toList.transpose | ||||
|       if (x.isEmpty) Nil else x.grouped(node.in.size).toList.transpose | ||||
|  | ||||
|     if (node.edgesOut.size == node.edgesIn.size) { | ||||
|       io.out <> io.in | ||||
|     } else ((node.edgesIn zip io.in) zip (group(node.edgesOut) zip group(io.out))) foreach { | ||||
|       case ((edgeIn, io_in), (edgesOut, io_out)) => | ||||
|     if (node.out.size == node.in.size) { | ||||
|       (node.in zip node.out) foreach { case ((i, _), (o, _)) => o <> i } | ||||
|     } else (node.in zip group(node.out)) foreach { | ||||
|       case ((io_in, edgeIn), seq) => | ||||
|       val (io_out, edgesOut) = seq.unzip | ||||
|  | ||||
|       // Grab the port ID mapping | ||||
|       val outputIdRanges = TLXbar.mapOutputIds(edgesOut.map(_.manager)) | ||||
|   | ||||
| @@ -11,7 +11,7 @@ import freechips.rocketchip.util._ | ||||
| import scala.math.{min, max} | ||||
| import AHBParameters._ | ||||
|  | ||||
| case class TLToAHBNode() extends MixedAdapterNode(TLImp, AHBImp)( | ||||
| case class TLToAHBNode()(implicit valName: ValName) extends MixedAdapterNode(TLImp, AHBImp)( | ||||
|   dFn = { case TLClientPortParameters(clients, unsafeAtomics, minLatency) => | ||||
|     val masters = clients.map { case c => AHBMasterParameters(name = c.name, nodePath = c.nodePath) } | ||||
|     AHBMasterPortParameters(masters) | ||||
| @@ -53,12 +53,7 @@ class TLToAHB(val aFlow: Boolean = false)(implicit p: Parameters) extends LazyMo | ||||
|   val node = TLToAHBNode() | ||||
|  | ||||
|   lazy val module = new LazyModuleImp(this) { | ||||
|     val io = new Bundle { | ||||
|       val in = node.bundleIn | ||||
|       val out = node.bundleOut | ||||
|     } | ||||
|  | ||||
|    ((io.in zip io.out) zip (node.edgesIn zip node.edgesOut)) foreach { case ((in, out), (edgeIn, edgeOut)) => | ||||
|    (node.in zip node.out) foreach { case ((in, edgeIn), (out, edgeOut)) => | ||||
|       val beatBytes = edgeOut.slave.beatBytes | ||||
|       val maxTransfer = edgeOut.slave.maxTransfer | ||||
|       val lgMax = log2Ceil(maxTransfer) | ||||
|   | ||||
| @@ -10,7 +10,7 @@ import freechips.rocketchip.amba.apb._ | ||||
| import scala.math.{min, max} | ||||
| import APBParameters._ | ||||
|  | ||||
| case class TLToAPBNode() extends MixedAdapterNode(TLImp, APBImp)( | ||||
| case class TLToAPBNode()(implicit valName: ValName) extends MixedAdapterNode(TLImp, APBImp)( | ||||
|   dFn = { case TLClientPortParameters(clients, unsafeAtomics, minLatency) => | ||||
|     val masters = clients.map { case c => APBMasterParameters(name = c.name, nodePath = c.nodePath) } | ||||
|     APBMasterPortParameters(masters) | ||||
| @@ -38,12 +38,7 @@ class TLToAPB(val aFlow: Boolean = true)(implicit p: Parameters) extends LazyMod | ||||
|   val node = TLToAPBNode() | ||||
|  | ||||
|   lazy val module = new LazyModuleImp(this) { | ||||
|     val io = new Bundle { | ||||
|       val in = node.bundleIn | ||||
|       val out = node.bundleOut | ||||
|     } | ||||
|  | ||||
|     ((io.in zip io.out) zip (node.edgesIn zip node.edgesOut)) foreach { case ((in, out), (edgeIn, edgeOut)) => | ||||
|     (node.in zip node.out) foreach { case ((in, edgeIn), (out, edgeOut)) => | ||||
|       val beatBytes = edgeOut.slave.beatBytes | ||||
|       val lgBytes = log2Ceil(beatBytes) | ||||
|  | ||||
|   | ||||
| @@ -10,7 +10,7 @@ import freechips.rocketchip.util._ | ||||
| import freechips.rocketchip.amba.axi4._ | ||||
| import scala.math.{min, max} | ||||
|  | ||||
| case class TLToAXI4Node(beatBytes: Int, stripBits: Int = 0) extends MixedAdapterNode(TLImp, AXI4Imp)( | ||||
| case class TLToAXI4Node(beatBytes: Int, stripBits: Int = 0)(implicit valName: ValName) extends MixedAdapterNode(TLImp, AXI4Imp)( | ||||
|   dFn = { p => | ||||
|     p.clients.foreach { c => | ||||
|       require (c.sourceId.start % (1 << stripBits) == 0 && | ||||
| @@ -53,12 +53,7 @@ class TLToAXI4(val beatBytes: Int, val combinational: Boolean = true, val adapte | ||||
|   val node = TLToAXI4Node(beatBytes, stripBits) | ||||
|  | ||||
|   lazy val module = new LazyModuleImp(this) { | ||||
|     val io = new Bundle { | ||||
|       val in = node.bundleIn | ||||
|       val out = node.bundleOut | ||||
|     } | ||||
|  | ||||
|     ((io.in zip io.out) zip (node.edgesIn zip node.edgesOut)) foreach { case ((in, out), (edgeIn, edgeOut)) => | ||||
|     (node.in zip node.out) foreach { case ((in, edgeIn), (out, edgeOut)) => | ||||
|       val slaves  = edgeOut.slave.slaves | ||||
|  | ||||
|       // All pairs of slaves must promise that they will never interleave data | ||||
|   | ||||
| @@ -17,11 +17,6 @@ class TLWidthWidget(innerBeatBytes: Int)(implicit p: Parameters) extends LazyMod | ||||
|     managerFn = { case m => m.copy(beatBytes = innerBeatBytes) }) | ||||
|  | ||||
|   lazy val module = new LazyModuleImp(this) { | ||||
|     val io = new Bundle { | ||||
|       val in  = node.bundleIn | ||||
|       val out = node.bundleOut | ||||
|     } | ||||
|  | ||||
|     def merge[T <: TLDataChannel](edgeIn: TLEdge, in: DecoupledIO[T], edgeOut: TLEdge, out: DecoupledIO[T]) = { | ||||
|       val inBytes = edgeIn.manager.beatBytes | ||||
|       val outBytes = edgeOut.manager.beatBytes | ||||
| @@ -154,7 +149,7 @@ class TLWidthWidget(innerBeatBytes: Int)(implicit p: Parameters) extends LazyMod | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     ((io.in zip io.out) zip (node.edgesIn zip node.edgesOut)) foreach { case ((in, out), (edgeIn, edgeOut)) => | ||||
|     (node.in zip node.out) foreach { case ((in, edgeIn), (out, edgeOut)) => | ||||
|  | ||||
|       // If the master is narrower than the slave, the D channel must be narrowed. | ||||
|       // This is tricky, because the D channel has no address data. | ||||
| @@ -220,7 +215,7 @@ class TLRAMWidthWidget(first: Int, second: Int, txns: Int)(implicit p: Parameter | ||||
|                   TLWidthWidget(second)( | ||||
|                     TLWidthWidget(first)(TLDelayer(0.1)(model.node)))})) | ||||
|  | ||||
|   lazy val module = new LazyModuleImp(this) with HasUnitTestIO { | ||||
|   lazy val module = new LazyModuleImp(this) with UnitTestModule { | ||||
|     io.finished := fuzz.module.io.finished | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -63,22 +63,21 @@ class TLXbar(policy: TLArbiter.Policy = TLArbiter.roundRobin)(implicit p: Parame | ||||
|     }) | ||||
|  | ||||
|   lazy val module = new LazyModuleImp(this) { | ||||
|     val io = new Bundle { | ||||
|       val in  = node.bundleIn | ||||
|       val out = node.bundleOut | ||||
|     if ((node.in.size * node.out.size) > (8*32)) { | ||||
|       println (s"!!! WARNING !!!") | ||||
|       println (s" Your TLXbar ($name) is very large, with ${node.in.size} Masters and ${node.out.size} Slaves.") | ||||
|       println (s"!!! WARNING !!!") | ||||
|     } | ||||
|  | ||||
|     if ((io.in.size * io.out.size) > (8*32)) { | ||||
|       println (s"!!! WARNING !!!") | ||||
|       println (s" Your TLXbar ($name) is very large, with ${io.in.size} Masters and ${io.out.size} Slaves.") | ||||
|       println (s"!!! WARNING !!!") | ||||
|     } | ||||
|     val (io_in, edgesIn) = node.in.unzip | ||||
|     val (io_out, edgesOut) = node.out.unzip | ||||
|  | ||||
|     // Grab the port ID mapping | ||||
|     val inputIdRanges = TLXbar.mapInputIds(node.edgesIn.map(_.client)) | ||||
|     val outputIdRanges = TLXbar.mapOutputIds(node.edgesOut.map(_.manager)) | ||||
|     val inputIdRanges = TLXbar.mapInputIds(edgesIn.map(_.client)) | ||||
|     val outputIdRanges = TLXbar.mapOutputIds(edgesOut.map(_.manager)) | ||||
|  | ||||
|     // Find a good mask for address decoding | ||||
|     val port_addrs = node.edgesOut.map(_.manager.managers.map(_.address).flatten) | ||||
|     val port_addrs = edgesOut.map(_.manager.managers.map(_.address).flatten) | ||||
|     val routingMask = AddressDecoder(port_addrs) | ||||
|     val route_addrs = port_addrs.map(seq => AddressSet.unify(seq.map(_.widen(~routingMask)).distinct)) | ||||
|     val outputPorts = route_addrs.map(seq => (addr: UInt) => seq.map(_.contains(addr)).reduce(_ || _)) | ||||
| @@ -97,70 +96,70 @@ class TLXbar(policy: TLArbiter.Policy = TLArbiter.roundRobin)(implicit p: Parame | ||||
|     // Print the ID mapping | ||||
|     if (false) { | ||||
|       println(s"XBar ${name} mapping:") | ||||
|       (node.edgesIn zip inputIdRanges).zipWithIndex.foreach { case ((edge, id), i) => | ||||
|       (edgesIn zip inputIdRanges).zipWithIndex.foreach { case ((edge, id), i) => | ||||
|         println(s"\t$i assigned ${id} for ${edge.client.clients.map(_.name).mkString(", ")}") | ||||
|       } | ||||
|       println("") | ||||
|     } | ||||
|  | ||||
|     // We need an intermediate size of bundle with the widest possible identifiers | ||||
|     val wide_bundle = TLBundleParameters.union(io.in.map(_.params) ++ io.out.map(_.params)) | ||||
|     val wide_bundle = TLBundleParameters.union(io_in.map(_.params) ++ io_out.map(_.params)) | ||||
|  | ||||
|     // Handle size = 1 gracefully (Chisel3 empty range is broken) | ||||
|     def trim(id: UInt, size: Int) = if (size <= 1) UInt(0) else id(log2Ceil(size)-1, 0) | ||||
|  | ||||
|     // Transform input bundle sources (sinks use global namespace on both sides) | ||||
|     val in = Wire(Vec(io.in.size, TLBundle(wide_bundle))) | ||||
|     val in = Wire(Vec(io_in.size, TLBundle(wide_bundle))) | ||||
|     for (i <- 0 until in.size) { | ||||
|       val r = inputIdRanges(i) | ||||
|  | ||||
|       in(i).a <> io.in(i).a | ||||
|       io.in(i).d <> in(i).d | ||||
|       in(i).a.bits.source := io.in(i).a.bits.source | UInt(r.start) | ||||
|       io.in(i).d.bits.source := trim(in(i).d.bits.source, r.size) | ||||
|       in(i).a <> io_in(i).a | ||||
|       io_in(i).d <> in(i).d | ||||
|       in(i).a.bits.source := io_in(i).a.bits.source | UInt(r.start) | ||||
|       io_in(i).d.bits.source := trim(in(i).d.bits.source, r.size) | ||||
|  | ||||
|       if (node.edgesIn(i).client.anySupportProbe && node.edgesOut.exists(_.manager.anySupportAcquireB)) { | ||||
|         in(i).c <> io.in(i).c | ||||
|         in(i).e <> io.in(i).e | ||||
|         io.in(i).b <> in(i).b | ||||
|         in(i).c.bits.source := io.in(i).c.bits.source | UInt(r.start) | ||||
|         io.in(i).b.bits.source := trim(in(i).b.bits.source, r.size) | ||||
|       if (edgesIn(i).client.anySupportProbe && edgesOut.exists(_.manager.anySupportAcquireB)) { | ||||
|         in(i).c <> io_in(i).c | ||||
|         in(i).e <> io_in(i).e | ||||
|         io_in(i).b <> in(i).b | ||||
|         in(i).c.bits.source := io_in(i).c.bits.source | UInt(r.start) | ||||
|         io_in(i).b.bits.source := trim(in(i).b.bits.source, r.size) | ||||
|       } else { | ||||
|         in(i).c.valid := Bool(false) | ||||
|         in(i).e.valid := Bool(false) | ||||
|         in(i).b.ready := Bool(false) | ||||
|         io.in(i).c.ready := Bool(true) | ||||
|         io.in(i).e.ready := Bool(true) | ||||
|         io.in(i).b.valid := Bool(false) | ||||
|         io_in(i).c.ready := Bool(true) | ||||
|         io_in(i).e.ready := Bool(true) | ||||
|         io_in(i).b.valid := Bool(false) | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     // Transform output bundle sinks (sources use global namespace on both sides) | ||||
|     val out = Wire(Vec(io.out.size, TLBundle(wide_bundle))) | ||||
|     val out = Wire(Vec(io_out.size, TLBundle(wide_bundle))) | ||||
|     for (i <- 0 until out.size) { | ||||
|       val r = outputIdRanges(i) | ||||
|  | ||||
|       io.out(i).a <> out(i).a | ||||
|       out(i).d <> io.out(i).d | ||||
|       out(i).d.bits.sink := io.out(i).d.bits.sink | UInt(r.map(_.start).getOrElse(0)) | ||||
|       io_out(i).a <> out(i).a | ||||
|       out(i).d <> io_out(i).d | ||||
|       out(i).d.bits.sink := io_out(i).d.bits.sink | UInt(r.map(_.start).getOrElse(0)) | ||||
|  | ||||
|       if (node.edgesOut(i).manager.anySupportAcquireB && node.edgesIn.exists(_.client.anySupportProbe)) { | ||||
|         io.out(i).c <> out(i).c | ||||
|         io.out(i).e <> out(i).e | ||||
|         out(i).b <> io.out(i).b | ||||
|         io.out(i).e.bits.sink := trim(out(i).e.bits.sink, r.map(_.size).getOrElse(0)) | ||||
|       if (edgesOut(i).manager.anySupportAcquireB && edgesIn.exists(_.client.anySupportProbe)) { | ||||
|         io_out(i).c <> out(i).c | ||||
|         io_out(i).e <> out(i).e | ||||
|         out(i).b <> io_out(i).b | ||||
|         io_out(i).e.bits.sink := trim(out(i).e.bits.sink, r.map(_.size).getOrElse(0)) | ||||
|       } else { | ||||
|         out(i).c.ready := Bool(false) | ||||
|         out(i).e.ready := Bool(false) | ||||
|         out(i).b.valid := Bool(false) | ||||
|         io.out(i).c.valid := Bool(false) | ||||
|         io.out(i).e.valid := Bool(false) | ||||
|         io.out(i).b.ready := Bool(true) | ||||
|         io_out(i).c.valid := Bool(false) | ||||
|         io_out(i).e.valid := Bool(false) | ||||
|         io_out(i).b.ready := Bool(true) | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     val addressA = (in zip node.edgesIn) map { case (i, e) => e.address(i.a.bits) } | ||||
|     val addressC = (in zip node.edgesIn) map { case (i, e) => e.address(i.c.bits) } | ||||
|     val addressA = (in zip edgesIn) map { case (i, e) => e.address(i.a.bits) } | ||||
|     val addressC = (in zip edgesIn) map { case (i, e) => e.address(i.c.bits) } | ||||
|  | ||||
|     val requestAIO = Vec(addressA.map { i => Vec(outputPorts.map { o => o(i) }) }) | ||||
|     val requestCIO = Vec(addressC.map { i => Vec(outputPorts.map { o => o(i) }) }) | ||||
| @@ -168,28 +167,28 @@ class TLXbar(policy: TLArbiter.Policy = TLArbiter.roundRobin)(implicit p: Parame | ||||
|     val requestDOI = Vec(out.map { o => Vec(inputIdRanges.map  { i => i.contains(o.d.bits.source) }) }) | ||||
|     val requestEIO = Vec(in.map  { i => Vec(outputIdRanges.map { o => o.map(_.contains(i.e.bits.sink)).getOrElse(Bool(false)) }) }) | ||||
|  | ||||
|     val beatsAI = Vec((in  zip node.edgesIn)  map { case (i, e) => e.numBeats1(i.a.bits) }) | ||||
|     val beatsBO = Vec((out zip node.edgesOut) map { case (o, e) => e.numBeats1(o.b.bits) }) | ||||
|     val beatsCI = Vec((in  zip node.edgesIn)  map { case (i, e) => e.numBeats1(i.c.bits) }) | ||||
|     val beatsDO = Vec((out zip node.edgesOut) map { case (o, e) => e.numBeats1(o.d.bits) }) | ||||
|     val beatsEI = Vec((in  zip node.edgesIn)  map { case (i, e) => e.numBeats1(i.e.bits) }) | ||||
|     val beatsAI = Vec((in  zip edgesIn)  map { case (i, e) => e.numBeats1(i.a.bits) }) | ||||
|     val beatsBO = Vec((out zip edgesOut) map { case (o, e) => e.numBeats1(o.b.bits) }) | ||||
|     val beatsCI = Vec((in  zip edgesIn)  map { case (i, e) => e.numBeats1(i.c.bits) }) | ||||
|     val beatsDO = Vec((out zip edgesOut) map { case (o, e) => e.numBeats1(o.d.bits) }) | ||||
|     val beatsEI = Vec((in  zip edgesIn)  map { case (i, e) => e.numBeats1(i.e.bits) }) | ||||
|  | ||||
|     // Which pairs support support transfers | ||||
|     def transpose[T](x: Seq[Seq[T]]) = Seq.tabulate(x(0).size) { i => Seq.tabulate(x.size) { j => x(j)(i) } } | ||||
|     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, 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)) }) | ||||
|     val portsAOI = transpose((in  zip requestAIO) map { case (i, r) => TLXbar.fanout(i.a, r, edgesOut.map(_.params(ForceFanoutKey).a)) }) | ||||
|     val portsBIO = transpose((out zip requestBOI) map { case (o, r) => TLXbar.fanout(o.b, r, edgesIn .map(_.params(ForceFanoutKey).b)) }) | ||||
|     val portsCOI = transpose((in  zip requestCIO) map { case (i, r) => TLXbar.fanout(i.c, r, edgesOut.map(_.params(ForceFanoutKey).c)) }) | ||||
|     val portsDIO = transpose((out zip requestDOI) map { case (o, r) => TLXbar.fanout(o.d, r, edgesIn .map(_.params(ForceFanoutKey).d)) }) | ||||
|     val portsEOI = transpose((in  zip requestEIO) map { case (i, r) => TLXbar.fanout(i.e, r, edgesOut.map(_.params(ForceFanoutKey).e)) }) | ||||
|  | ||||
|     // Arbitrate amongst the sources | ||||
|     for (o <- 0 until out.size) { | ||||
|       val allowI = Seq.tabulate(in.size) { i => | ||||
|         node.edgesIn(i).client.anySupportProbe && | ||||
|         node.edgesOut(o).manager.anySupportAcquireB | ||||
|         edgesIn(i).client.anySupportProbe && | ||||
|         edgesOut(o).manager.anySupportAcquireB | ||||
|       } | ||||
|       TLArbiter(policy)(out(o).a,       (beatsAI zip portsAOI(o)        ):_*) | ||||
|       TLArbiter(policy)(out(o).c, filter(beatsCI zip portsCOI(o), allowI):_*) | ||||
| @@ -198,8 +197,8 @@ class TLXbar(policy: TLArbiter.Policy = TLArbiter.roundRobin)(implicit p: Parame | ||||
|  | ||||
|     for (i <- 0 until in.size) { | ||||
|       val allowO = Seq.tabulate(out.size) { o => | ||||
|         node.edgesIn(i).client.anySupportProbe && | ||||
|         node.edgesOut(o).manager.anySupportAcquireB | ||||
|         edgesIn(i).client.anySupportProbe && | ||||
|         edgesOut(o).manager.anySupportAcquireB | ||||
|       } | ||||
|       TLArbiter(policy)(in(i).b, filter(beatsBO zip portsBIO(i), allowO):_*) | ||||
|       TLArbiter(policy)(in(i).d,       (beatsDO zip portsDIO(i)        ):_*) | ||||
| @@ -264,7 +263,7 @@ class TLRAMXbar(nManagers: Int, txns: Int)(implicit p: Parameters) extends LazyM | ||||
|     ram.node := TLFragmenter(4, 256)(TLDelayer(0.1)(xbar.node)) | ||||
|   } | ||||
|  | ||||
|   lazy val module = new LazyModuleImp(this) with HasUnitTestIO { | ||||
|   lazy val module = new LazyModuleImp(this) with UnitTestModule { | ||||
|     io.finished := fuzz.module.io.finished | ||||
|   } | ||||
| } | ||||
| @@ -287,7 +286,7 @@ class TLMulticlientXbar(nManagers: Int, nClients: Int, txns: Int)(implicit p: Pa | ||||
|     ram.node := TLFragmenter(4, 256)(TLDelayer(0.1)(xbar.node)) | ||||
|   } | ||||
|  | ||||
|   lazy val module = new LazyModuleImp(this) with HasUnitTestIO { | ||||
|   lazy val module = new LazyModuleImp(this) with UnitTestModule { | ||||
|     io.finished := fuzzers.last.module.io.finished | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -3,17 +3,28 @@ | ||||
| package freechips.rocketchip.unittest | ||||
|  | ||||
| import Chisel._ | ||||
| import chisel3.experimental.MultiIOModule | ||||
| import freechips.rocketchip.config._ | ||||
| import freechips.rocketchip.util.SimpleTimer | ||||
|  | ||||
| trait HasUnitTestIO { | ||||
|   val io = new Bundle { | ||||
| trait UnitTestIO { | ||||
|   val finished = Bool(OUTPUT) | ||||
|   val start = Bool(INPUT) | ||||
| } | ||||
|  | ||||
| trait HasUnitTestIO { | ||||
|   val io: UnitTestIO | ||||
| } | ||||
|  | ||||
| abstract class UnitTest(val timeout: Int = 4096) extends Module with HasUnitTestIO { | ||||
| trait UnitTestLegacyModule extends HasUnitTestIO { | ||||
|   val io = new Bundle with UnitTestIO | ||||
| } | ||||
|  | ||||
| trait UnitTestModule extends MultiIOModule with HasUnitTestIO { | ||||
|   val io = IO(new Bundle with UnitTestIO) | ||||
| } | ||||
|  | ||||
| abstract class UnitTest(val timeout: Int = 4096) extends Module with UnitTestLegacyModule { | ||||
|   val testName = this.getClass.getSimpleName | ||||
|  | ||||
|   when (io.start) { printf(s"Started UnitTest $testName\n") } | ||||
|   | ||||
| @@ -17,3 +17,8 @@ final case class HeterogeneousBag[T <: Data](elts: Seq[T]) extends Record with c | ||||
|   override def hashCode: Int = super[Record].hashCode | ||||
|   override def equals(that: Any): Boolean = super[Record].equals(that) | ||||
| } | ||||
|  | ||||
| object HeterogeneousBag | ||||
| { | ||||
|   def fromNode[D <: Data, E](elts: Seq[(D, E)]) = new HeterogeneousBag(elts.map(_._1.cloneType)) | ||||
| } | ||||
|   | ||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user