subsystem: new bus attachment api
This commit is contained in:
		| @@ -31,7 +31,7 @@ trait HasPeripheryDebug extends HasPeripheryBus { | ||||
|  | ||||
|   val debug = LazyModule(new TLDebugModule(pbus.beatBytes)) | ||||
|  | ||||
|   debug.node := pbus.toVariableWidthSlaves | ||||
|   pbus.toVariableWidthSlave(Some("Debug")){ debug.node } | ||||
| } | ||||
|  | ||||
| trait HasPeripheryDebugBundle { | ||||
|   | ||||
| @@ -71,7 +71,7 @@ trait HasPeripheryBootROM extends HasPeripheryBus { | ||||
|  | ||||
|   val bootrom = LazyModule(new TLROM(params.address, params.size, contents, true, pbus.beatBytes)) | ||||
|  | ||||
|   bootrom.node := pbus.toVariableWidthSlaves | ||||
|   pbus.toVariableWidthSlave(Some("BootROM")){ bootrom.node } | ||||
| } | ||||
|  | ||||
| /** Subsystem will power-on running at 0x10040 (BootROM) */ | ||||
|   | ||||
| @@ -93,5 +93,5 @@ class CLINT(params: CLINTParams, beatBytes: Int)(implicit p: Parameters) extends | ||||
| /** Trait that will connect a CLINT to a subsystem */ | ||||
| trait HasPeripheryCLINT extends HasPeripheryBus { | ||||
|   val clint = LazyModule(new CLINT(p(CLINTKey), pbus.beatBytes)) | ||||
|   clint.node := pbus.toVariableWidthSlaves | ||||
|   pbus.toVariableWidthSlave(Some("CLINT")) { clint.node } | ||||
| } | ||||
|   | ||||
| @@ -121,6 +121,5 @@ class DeadlockDevice(params: ErrorParams, beatBytes: Int = 4)(implicit p: Parame | ||||
| trait HasSystemErrorSlave extends HasSystemBus { | ||||
|   private val params = p(ErrorParams) | ||||
|   val error = LazyModule(new TLError(params, sbus.beatBytes)) | ||||
|  | ||||
|   error.node := sbus.toSlave | ||||
|   sbus.toSlave(Some("Error")){ error.node } | ||||
| } | ||||
|   | ||||
| @@ -17,7 +17,7 @@ trait HasPeripheryMaskROMSlave extends HasPeripheryBus { | ||||
|   val maskROMParams = p(PeripheryMaskROMKey) | ||||
|   val maskROMs = maskROMParams map { params => | ||||
|     val maskROM = LazyModule(new TLMaskROM(params)) | ||||
|     maskROM.node := pbus.toFixedWidthSingleBeatSlave(maskROM.beatBytes) | ||||
|     pbus.toFixedWidthSingleBeatSlave(maskROM.beatBytes, Some("MaskROM")) { maskROM.node } | ||||
|     maskROM | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -270,7 +270,7 @@ class TLPLIC(params: PLICParams, beatBytes: Int)(implicit p: Parameters) extends | ||||
|  | ||||
| /** Trait that will connect a PLIC to a subsystem */ | ||||
| trait HasPeripheryPLIC extends HasInterruptBus with HasPeripheryBus { | ||||
|   val plic  = LazyModule(new TLPLIC(p(PLICKey), pbus.beatBytes)) | ||||
|   plic.node := pbus.toVariableWidthSlaves | ||||
|   val plic  = LazyModule(new TLPLIC(p(PLICKey), pbus.beatBytes))) | ||||
|   pbus.toVariableWidthSlave(Some("PLIC")) { plic.node } | ||||
|   plic.intnode := ibus.toPLIC | ||||
| } | ||||
|   | ||||
| @@ -50,13 +50,16 @@ trait HasMemoryZeroSlave extends HasMemoryBus { | ||||
|   private val params = p(ZeroParams) | ||||
|   private val device = new SimpleDevice("rom", Seq("ucbbar,cacheable-zero0")) | ||||
|  | ||||
|   val zeros = memBuses.map(_.toVariableWidthSlave).zipWithIndex.map { case (node, channel) => | ||||
|   val zeros = memBuses | ||||
|                 .map(m => m.toVariableWidthSlave(Some("Zero"))(_)) | ||||
|                 .zipWithIndex | ||||
|                 .map { case (attach, channel) => | ||||
|     val channels = memBuses.size | ||||
|     val base = AddressSet(params.base, params.size-1) | ||||
|     val filter = AddressSet(channel * cacheBlockBytes, ~((channels-1) * cacheBlockBytes)) | ||||
|     val address = base.intersect(filter).get | ||||
|     val zero = LazyModule(new TLZero(address, beatBytes = params.beatBytes, resources = device.reg("mem"))) | ||||
|     zero.node := node | ||||
|     attach { zero.node } | ||||
|     zero | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -28,15 +28,12 @@ class GroundTestSubsystem(implicit p: Parameters) extends BaseSubsystem | ||||
|   )} | ||||
|  | ||||
|   tiles.flatMap(_.dcacheOpt).foreach { dc => | ||||
|     sbus.fromTile(None) { implicit p => TileMasterPortParams(addBuffers = 1).adapt(this)(dc.node) } | ||||
|     sbus.fromTile(None, buffers = 1){ dc.node } | ||||
|   } | ||||
|  | ||||
|   // No PLIC in ground test; so just sink the interrupts to nowhere | ||||
|   IntSinkNode(IntSinkPortSimple()) := ibus.toPLIC | ||||
|  | ||||
|   val pbusRAM = LazyModule(new TLRAM(AddressSet(testRamAddr, 0xffff), true, false, pbus.beatBytes)) | ||||
|   pbusRAM.node := pbus.toVariableWidthSlaves | ||||
|  | ||||
|   override lazy val module = new GroundTestSubsystemModule(this) | ||||
| } | ||||
|  | ||||
| @@ -53,11 +50,11 @@ class GroundTestSubsystemModule[+L <: GroundTestSubsystem](_outer: L) extends Ba | ||||
| /** Adds a SRAM to the system for testing purposes. */ | ||||
| trait HasPeripheryTestRAMSlave extends HasPeripheryBus { | ||||
|   val testram = LazyModule(new TLRAM(AddressSet(0x52000000, 0xfff), true, true, pbus.beatBytes)) | ||||
|   testram.node := pbus.toVariableWidthSlaves | ||||
|   pbus.toVariableWidthSlave(Some("TestRAM")) { testram.node } | ||||
| } | ||||
|  | ||||
| /** Adds a fuzzing master to the system for testing purposes. */ | ||||
| trait HasPeripheryTestFuzzMaster extends HasPeripheryBus { | ||||
|   val fuzzer = LazyModule(new TLFuzzer(5000)) | ||||
|   pbus.bufferFromMasters := fuzzer.node | ||||
|   pbus.fromOtherMaster(Some("Fuzzer")) { fuzzer.node } | ||||
| } | ||||
|   | ||||
| @@ -270,10 +270,6 @@ class WithJtagDTM extends Config ((site, here, up) => { | ||||
|   case IncludeJtagDTM => true | ||||
| }) | ||||
|  | ||||
| class WithNoPeripheryArithAMO extends Config ((site, here, up) => { | ||||
|   case PeripheryBusKey => up(PeripheryBusKey, site).copy(arithmetic = false) | ||||
| }) | ||||
|  | ||||
| class WithNBitPeripheryBus(nBits: Int) extends Config ((site, here, up) => { | ||||
|   case PeripheryBusKey => up(PeripheryBusKey, site).copy(beatBytes = nBits/8) | ||||
| }) | ||||
|   | ||||
| @@ -8,38 +8,40 @@ import freechips.rocketchip.diplomacy._ | ||||
| import freechips.rocketchip.tilelink._ | ||||
| import freechips.rocketchip.util._ | ||||
|  | ||||
| case class FrontBusParams( | ||||
|   beatBytes: Int, | ||||
|   blockBytes: Int, | ||||
|   masterBuffering: BufferParams = BufferParams.default, | ||||
|   slaveBuffering: BufferParams = BufferParams.default | ||||
| ) extends TLBusParams | ||||
| case class FrontBusParams(beatBytes: Int, blockBytes: Int) extends HasTLBusParams | ||||
|  | ||||
| case object FrontBusKey extends Field[FrontBusParams] | ||||
|  | ||||
| class FrontBus(params: FrontBusParams)(implicit p: Parameters) extends TLBusWrapper(params, "FrontBus") { | ||||
| class FrontBus(params: FrontBusParams, val crossing: SubsystemClockCrossing = SynchronousCrossing()) | ||||
|               (implicit p: Parameters) extends TLBusWrapper(params, "FrontBus") | ||||
|     with HasTLXbarPhy | ||||
|     with HasCrossing { | ||||
|  | ||||
|   private val master_buffer = LazyModule(new TLBuffer(params.masterBuffering)) | ||||
|   private val master_fixer = LazyModule(new TLFIFOFixer(TLFIFOFixer.all)) | ||||
|  | ||||
|   master_buffer.suggestName(s"${busName}_master_TLBuffer") | ||||
|   master_fixer.suggestName(s"${busName}_master_TLFIFOFixer") | ||||
|  | ||||
|   master_fixer.node :=* master_buffer.node | ||||
|   inwardNode :=* master_fixer.node | ||||
|  | ||||
|   def fromSyncPorts(addBuffers: Int = 0, name: Option[String] = None): TLInwardNode = { | ||||
|     TLBuffer.chain(addBuffers).foldLeft(master_buffer.node:TLInwardNode)(_ :=* _) | ||||
|   def fromPort[D,U,E,B <: Data]( | ||||
|         name: Option[String] = None, | ||||
|         buffers: Int = 1) | ||||
|       (gen: => NodeHandle[D,U,E,B,TLClientPortParameters,TLManagerPortParameters,TLEdgeOut,TLBundle]): InwardNodeHandle[D,U,E,B] = { | ||||
|     from(s"Port${name.getOrElse("")}") { | ||||
|       val nodes = TLFIFOFixer(TLFIFOFixer.all) +: TLBuffer.chain(buffers) | ||||
|       inwardNode :=* nodes.reduce(_ :=* _) :=* gen | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   def fromSyncMasters(addBuffers: Int = 0, name: Option[String] = None): TLInwardNode = { | ||||
|     TLBuffer.chain(addBuffers).foldLeft(master_buffer.node:TLInwardNode)(_ :=* _) | ||||
|   def fromMaster(name: Option[String] = None, buffers: Int = 1) | ||||
|                 (gen: => TLNode): TLInwardNode = { | ||||
|     from(s"Master${name.getOrElse("")}") { | ||||
|       inwardNode :=* TLBuffer.chain(buffers).reduce(_ :=* _) :=* gen | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   def fromCoherentChip: TLInwardNode = inwardNode | ||||
|  | ||||
|   def toSystemBus : TLOutwardNode = TLBuffer(params.slaveBuffering) :=* xbar.node | ||||
|   def fromCoherentChip(gen: => TLNode): TLInwardNode = { | ||||
|     from("CoherentChip") { inwardNode :=* gen } | ||||
|   } | ||||
|  | ||||
|   def toSystemBus(buffer: BufferParams = BufferParams.none) | ||||
|                  (gen: => TLInwardNode) { | ||||
|     to("SystemBus") { gen :*= TLBuffer(buffer) :*= outwardNode } | ||||
|   } | ||||
| } | ||||
|  | ||||
| /** Provides buses that serve as attachment points, | ||||
| @@ -51,5 +53,7 @@ trait HasFrontBus extends HasSystemBus { | ||||
|  | ||||
|   val fbus = LazyModule(new FrontBus(frontbusParams)) | ||||
|  | ||||
|   FlipRendering { implicit p => sbus.fromFrontBus :=* fbus.toSystemBus } | ||||
|   FlipRendering { implicit p => | ||||
|     fbus.toSystemBus() { sbus.fromFrontBus { fbus.crossTLOut } } | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -36,26 +36,47 @@ case class BankedL2Params( | ||||
| case object BankedL2Key extends Field(BankedL2Params()) | ||||
|  | ||||
| /** Parameterization of the memory-side bus created for each memory channel */ | ||||
| case class MemoryBusParams( | ||||
|   beatBytes: Int, | ||||
|   blockBytes: Int, | ||||
|   masterBuffering: BufferParams = BufferParams.none, | ||||
|   slaveBuffering: BufferParams = BufferParams.none | ||||
| ) extends TLBusParams | ||||
| case class MemoryBusParams(beatBytes: Int, blockBytes: Int) extends HasTLBusParams | ||||
|  | ||||
| case object MemoryBusKey extends Field[MemoryBusParams] | ||||
|  | ||||
| /** Wrapper for creating TL nodes from a bus connected to the back of each mem channel */ | ||||
| class MemoryBus(params: MemoryBusParams)(implicit p: Parameters) extends TLBusWrapper(params, "MemoryBus")(p) { | ||||
|   def fromCoherenceManager: TLInwardNode = inwardBufNode | ||||
|   def toDRAMController: TLOutwardNode = outwardBufNode | ||||
|   def toVariableWidthSlave: TLOutwardNode = outwardFragNode | ||||
| class MemoryBus(params: MemoryBusParams)(implicit p: Parameters) extends TLBusWrapper(params, "MemoryBus")(p) | ||||
|     with HasTLXbarPhy { | ||||
|  | ||||
|   private def bufferTo(buffer: BufferParams): TLOutwardNode = | ||||
|     TLBuffer(buffer) :*= delayNode :*= outwardNode | ||||
|  | ||||
|   def fromCoherenceManager( | ||||
|         name: Option[String] = None, | ||||
|         buffer: BufferParams = BufferParams.none) | ||||
|       (gen: => TLNode): TLInwardNode = { | ||||
|     from(s"CoherenceManager${name.getOrElse("")}") { | ||||
|       inwardNode :*= TLBuffer(buffer) :*= gen | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   def toDRAMController[D,U,E,B <: Data]( | ||||
|         name: Option[String] = None, | ||||
|         buffer: BufferParams = BufferParams.none) | ||||
|       (gen: => NodeHandle[TLClientPortParameters,TLManagerPortParameters,TLEdgeIn,TLBundle,D,U,E,B]): OutwardNodeHandle[D,U,E,B] = { | ||||
|     to(s"DRAMController${name.getOrElse("")}") { gen := bufferTo(buffer) } | ||||
|   } | ||||
|  | ||||
|   def toVariableWidthSlave( | ||||
|         name: Option[String] = None, | ||||
|         buffer: BufferParams = BufferParams.none) | ||||
|       (gen: => TLNode): TLOutwardNode = { | ||||
|     to(s"Slave${name.getOrElse("")}") { | ||||
|       gen :*= TLFragmenter(params.beatBytes, params.blockBytes) :*= bufferTo(buffer) | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  | ||||
| trait HasMemoryBus extends HasSystemBus with HasPeripheryBus with HasInterruptBus { | ||||
|   private val mbusParams = p(MemoryBusKey) | ||||
|   private val l2Params = p(BankedL2Key) | ||||
|   val MemoryBusParams(memBusBeatBytes, memBusBlockBytes, _, _) = mbusParams | ||||
|   val MemoryBusParams(memBusBeatBytes, memBusBlockBytes) = mbusParams | ||||
|   val BankedL2Params(nMemoryChannels, nBanksPerChannel, coherenceManager) = l2Params | ||||
|   val nBanks = l2Params.nBanks | ||||
|   val cacheBlockBytes = memBusBlockBytes | ||||
| @@ -71,8 +92,8 @@ trait HasMemoryBus extends HasSystemBus with HasPeripheryBus with HasInterruptBu | ||||
|     val mbus = LazyModule(new MemoryBus(mbusParams)) | ||||
|     for (bank <- 0 until nBanksPerChannel) { | ||||
|       val offset = (bank * nMemoryChannels) + channel | ||||
|       ForceFanout(a = true) { implicit p => in := sbus.toMemoryBus } | ||||
|       mbus.fromCoherenceManager := TLFilter(TLFilter.Mmask(AddressSet(offset * memBusBlockBytes, mask))) := out | ||||
|       ForceFanout(a = true) { implicit p => sbus.toMemoryBus { in } } | ||||
|       mbus.fromCoherenceManager(None) { TLFilter(TLFilter.Mmask(AddressSet(offset * memBusBlockBytes, mask))) } := out | ||||
|     } | ||||
|     mbus | ||||
|   } | ||||
|   | ||||
| @@ -7,41 +7,97 @@ import freechips.rocketchip.config.{Field, Parameters} | ||||
| import freechips.rocketchip.diplomacy._ | ||||
| import freechips.rocketchip.tilelink._ | ||||
|  | ||||
| import freechips.rocketchip.config.Field | ||||
|  | ||||
| case class PeripheryBusParams( | ||||
|   beatBytes: Int, | ||||
|   blockBytes: Int, | ||||
|   masterBuffering: BufferParams = BufferParams.default, | ||||
|   slaveBuffering: BufferParams = BufferParams.none, | ||||
|   arithmetic: Boolean = true, | ||||
|   frequency: BigInt = BigInt(100000000) // 100 MHz as default bus frequency | ||||
| ) extends TLBusParams { | ||||
| } | ||||
| ) extends HasTLBusParams | ||||
|  | ||||
| case object PeripheryBusKey extends Field[PeripheryBusParams] | ||||
|  | ||||
| class PeripheryBus(params: PeripheryBusParams)(implicit p: Parameters) extends TLBusWrapper(params, "PeripheryBus") { | ||||
| class PeripheryBus(params: PeripheryBusParams, val crossing: SubsystemClockCrossing = SynchronousCrossing()) | ||||
|                   (implicit p: Parameters) extends TLBusWrapper(params, "PeripheryBus") | ||||
|     with HasTLXbarPhy | ||||
|     with HasCrossing { | ||||
|  | ||||
|   def toFixedWidthSingleBeatSlave(widthBytes: Int) = { | ||||
|     TLFragmenter(widthBytes, params.blockBytes) := outwardWWNode | ||||
|   private def bufferTo(buffer: BufferParams): TLOutwardNode = | ||||
|     TLBuffer(buffer) :*= delayNode :*= outwardNode | ||||
|  | ||||
|   private def fragmentTo(minSize: Int, maxSize: Int, buffer: BufferParams): TLOutwardNode = | ||||
|     TLFragmenter(minSize, maxSize) :*= bufferTo(buffer) | ||||
|  | ||||
|   private def fixedWidthTo(buffer: BufferParams): TLOutwardNode = | ||||
|     TLWidthWidget(params.beatBytes) :*= bufferTo(buffer) | ||||
|  | ||||
|   def toSlave( | ||||
|         name: Option[String] = None, | ||||
|         buffer: BufferParams = BufferParams.none) | ||||
|       (gen: => TLNode): TLOutwardNode = { | ||||
|     to(s"Slave${name.getOrElse("")}") { gen :*= bufferTo(buffer) } | ||||
|   } | ||||
|  | ||||
|   def toLargeBurstSlave(maxXferBytes: Int) = { | ||||
|     TLFragmenter(params.beatBytes, maxXferBytes) := outwardBufNode | ||||
|   def toVariableWidthSlave( | ||||
|         name: Option[String] = None, | ||||
|         buffer: BufferParams = BufferParams.none) | ||||
|       (gen: => TLNode): TLOutwardNode = { | ||||
|     to(s"Slave${name.getOrElse("")}") { | ||||
|       gen :*= fragmentTo(params.beatBytes, params.blockBytes, buffer) | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   val fromSystemBus: TLInwardNode = { | ||||
|     val atomics = LazyModule(new TLAtomicAutomata(arithmetic = params.arithmetic)) | ||||
|     xbar.node :*= TLBuffer(params.masterBuffering) :*= atomics.node | ||||
|   def toFixedWidthSlave( | ||||
|         name: Option[String] = None, | ||||
|         buffer: BufferParams = BufferParams.none) | ||||
|       (gen: => TLNode): TLOutwardNode = { | ||||
|     to(s"Slave${name.getOrElse("")}") { | ||||
|       gen :*= fixedWidthTo(buffer) | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   def toTile(name: Option[String] = None)(gen: Parameters => TLInwardNode) { | ||||
|     this { | ||||
|       LazyScope(s"${busName}ToTile${name.getOrElse("")}") { | ||||
|         FlipRendering { implicit p => | ||||
|           gen(p) :*= outwardNode | ||||
|         } | ||||
|   def toFixedWidthSingleBeatSlave( | ||||
|         widthBytes: Int, | ||||
|         name: Option[String] = None, | ||||
|         buffer: BufferParams = BufferParams.none) | ||||
|       (gen: => TLNode): TLOutwardNode = { | ||||
|     to(s"Slave${name.getOrElse("")}") { | ||||
|       gen :*= TLFragmenter(widthBytes, params.blockBytes) :*= fixedWidthTo(buffer) | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   def toLargeBurstSlave( | ||||
|         maxXferBytes: Int, | ||||
|         name: Option[String] = None, | ||||
|         buffer: BufferParams = BufferParams.none) | ||||
|       (gen: => TLNode): TLOutwardNode = { | ||||
|     to(s"Slave${name.getOrElse("")}") { | ||||
|       gen :*= fragmentTo(params.beatBytes, maxXferBytes, buffer) | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   def fromSystemBus( | ||||
|         arithmetic: Boolean = true, | ||||
|         buffer: BufferParams = BufferParams.default) | ||||
|       (gen: => TLOutwardNode) { | ||||
|     from("SystemBus") { | ||||
|       (inwardNode | ||||
|         :*= TLBuffer(buffer) | ||||
|         :*= TLAtomicAutomata(arithmetic = arithmetic) | ||||
|         :*= gen) | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   def fromOtherMaster( | ||||
|         name: Option[String] = None, | ||||
|         buffer: BufferParams = BufferParams.none) | ||||
|       (gen: => TLNode): TLInwardNode = { | ||||
|     from(s"OtherMaster${name.getOrElse("")}") { inwardNode :*= TLBuffer(buffer) :*= gen } | ||||
|   } | ||||
|  | ||||
|  | ||||
|   def toTile(name: Option[String] = None)(gen: => TLNode): TLOutwardNode = { | ||||
|     to(s"Tile${name.getOrElse("")}") { | ||||
|       FlipRendering { implicit p => | ||||
|         gen :*= delayNode :*= outwardNode | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| @@ -57,5 +113,5 @@ trait HasPeripheryBus extends HasSystemBus { | ||||
|   val pbus = LazyModule(new PeripheryBus(pbusParams)) | ||||
|  | ||||
|   // The peripheryBus hangs off of systemBus; here we convert TL-UH -> TL-UL | ||||
|   pbus.fromSystemBus :*= sbus.toPeripheryBus() | ||||
|   pbus.fromSystemBus() { sbus.toPeripheryBus() { pbus.crossTLIn } } | ||||
| } | ||||
|   | ||||
| @@ -49,13 +49,10 @@ trait HasMasterAXI4MemPort extends HasMemoryBus { | ||||
|       beatBytes = params.beatBytes) | ||||
|   }) | ||||
|  | ||||
|   val converter = LazyModule(new TLToAXI4()) | ||||
|   val trim = LazyModule(new AXI4IdIndexer(params.idBits)) | ||||
|   val yank = LazyModule(new AXI4UserYanker) | ||||
|   val buffer = LazyModule(new AXI4Buffer) | ||||
|  | ||||
|   memBuses.map(_.toDRAMController).foreach { case node => | ||||
|     mem_axi4 := buffer.node := yank.node := trim.node := converter.node := node | ||||
|   memBuses.map { m => | ||||
|     mem_axi4 := m.toDRAMController(Some("AXI4DRAM")) { | ||||
|       (AXI4UserYanker() := AXI4IdIndexer(params.idBits) := TLToAXI4()) | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  | ||||
| @@ -93,13 +90,13 @@ trait HasMasterAXI4MMIOPort extends HasSystemBus { | ||||
|       supportsRead  = TransferSizes(1, params.maxXferBytes))), | ||||
|     beatBytes = params.beatBytes))) | ||||
|  | ||||
|   (mmio_axi4 | ||||
|     := AXI4Buffer() | ||||
|     := AXI4UserYanker() | ||||
|     := AXI4Deinterleaver(sbus.blockBytes) | ||||
|     := AXI4IdIndexer(params.idBits) | ||||
|     := TLToAXI4() | ||||
|     := sbus.toFixedWidthPorts) | ||||
|   mmio_axi4 := sbus.toFixedWidthPort(Some("AXI4MMIO")) { | ||||
|     (AXI4Buffer() | ||||
|       := AXI4UserYanker() | ||||
|       := AXI4Deinterleaver(sbus.blockBytes) | ||||
|       := AXI4IdIndexer(params.idBits) | ||||
|       := TLToAXI4()) | ||||
|   } | ||||
| } | ||||
|  | ||||
| /** Common io name and methods for propagating or tying off the port bundle */ | ||||
| @@ -128,13 +125,13 @@ trait HasSlaveAXI4Port extends HasSystemBus { | ||||
|       id   = IdRange(0, 1 << params.idBits)))))) | ||||
|  | ||||
|   private val fifoBits = 1 | ||||
|   (sbus.fromSyncPorts() | ||||
|     := TLWidthWidget(params.beatBytes) | ||||
|     := AXI4ToTL() | ||||
|     := AXI4UserYanker(Some(1 << (params.sourceBits - fifoBits - 1))) | ||||
|     := AXI4Fragmenter() | ||||
|     := AXI4IdIndexer(fifoBits) | ||||
|     := l2FrontendAXI4Node) | ||||
|   sbus.fromPort(Some("AXI4Front")) { | ||||
|     (TLWidthWidget(params.beatBytes) | ||||
|       := AXI4ToTL() | ||||
|       := AXI4UserYanker(Some(1 << (params.sourceBits - fifoBits - 1))) | ||||
|       := AXI4Fragmenter() | ||||
|       := AXI4IdIndexer(fifoBits)) | ||||
|   } := l2FrontendAXI4Node | ||||
| } | ||||
|  | ||||
| /** Common io name and methods for propagating or tying off the port bundle */ | ||||
| @@ -173,7 +170,9 @@ trait HasMasterTLMMIOPort extends HasSystemBus { | ||||
|       supportsPutPartial = TransferSizes(1, sbus.blockBytes))), | ||||
|     beatBytes = params.beatBytes))) | ||||
|  | ||||
|   mmio_tl := TLBuffer() := TLSourceShrinker(1 << params.idBits) := sbus.toFixedWidthPorts | ||||
|   mmio_tl := sbus.toFixedWidthPort(Some("TLMMIO")) { | ||||
|     TLBuffer() := TLSourceShrinker(1 << params.idBits) | ||||
|   } | ||||
| } | ||||
|  | ||||
| /** Common io name and methods for propagating or tying off the port bundle */ | ||||
| @@ -208,7 +207,9 @@ trait HasSlaveTLPort extends HasSystemBus { | ||||
|       name     = "Front Port (TL)", | ||||
|       sourceId = IdRange(0, 1 << params.idBits)))))) | ||||
|  | ||||
|   sbus.fromSyncPorts() := TLSourceShrinker(1 << params.sourceBits) := TLWidthWidget(params.beatBytes) := l2FrontendTLNode | ||||
|   sbus.fromPort(Some("TLFront")) { | ||||
|     TLSourceShrinker(1 << params.sourceBits) := TLWidthWidget(params.beatBytes) | ||||
|   } := l2FrontendTLNode | ||||
| } | ||||
|  | ||||
| /** Common io name and methods for propagating or tying off the port bundle */ | ||||
|   | ||||
| @@ -15,19 +15,8 @@ import freechips.rocketchip.util._ | ||||
|  | ||||
| // TODO: how specific are these to RocketTiles? | ||||
| case class TileMasterPortParams( | ||||
|     addBuffers: Int = 0, | ||||
|     cork: Option[Boolean] = None) { | ||||
|  | ||||
|   def adapt(subsystem: HasPeripheryBus) | ||||
|            (masterNode: TLOutwardNode) | ||||
|            (implicit p: Parameters, sourceInfo: SourceInfo): TLOutwardNode = { | ||||
|     val tile_master_cork = cork.map(u => (LazyModule(new TLCacheCork(unsafe = u)))) | ||||
|     val tile_master_fixer = LazyModule(new TLFIFOFixer(TLFIFOFixer.allUncacheable)) | ||||
|  | ||||
|     (Seq(tile_master_fixer.node) ++ TLBuffer.chain(addBuffers) ++ tile_master_cork.map(_.node)) | ||||
|       .foldRight(masterNode)(_ :=* _) | ||||
|   } | ||||
| } | ||||
|     buffers: Int = 0, | ||||
|     cork: Option[Boolean] = None) | ||||
|  | ||||
| case class TileSlavePortParams( | ||||
|     addBuffers: Int = 0, | ||||
| @@ -41,9 +30,12 @@ case class TileSlavePortParams( | ||||
|         .map(BasicBusBlockerParams(_, subsystem.pbus.beatBytes, subsystem.sbus.beatBytes)) | ||||
|         .map(bp => LazyModule(new BasicBusBlocker(bp))) | ||||
|  | ||||
|     tile_slave_blocker.foreach { _.controlNode := subsystem.pbus.toVariableWidthSlaves } | ||||
|     tile_slave_blocker.foreach { b => | ||||
|       subsystem.pbus.toVariableWidthSlave(Some("TileSlavePortBusBlocker")) { b.controlNode } | ||||
|     } | ||||
|  | ||||
|     (Seq() ++ tile_slave_blocker.map(_.node) ++ TLBuffer.chain(addBuffers)) | ||||
|     .foldLeft(slaveNode)(_ :*= _) | ||||
|       .foldLeft(slaveNode)(_ :*= _) | ||||
|   } | ||||
| } | ||||
|  | ||||
| @@ -111,7 +103,9 @@ trait HasRocketTiles extends HasTiles | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     sbus.fromTile(tp.name) { implicit p => crossing.master.adapt(this)(rocket.crossTLOut :=* tileMasterBuffering) } | ||||
|     sbus.fromTile(tp.name, crossing.master.buffers, crossing.master.cork) { | ||||
|       rocket.crossTLOut | ||||
|     } :=* tileMasterBuffering | ||||
|  | ||||
|     // Connect the slave ports of the tile to the periphery bus | ||||
|  | ||||
| @@ -123,9 +117,9 @@ trait HasRocketTiles extends HasTiles | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     pbus.toTile(tp.name) { implicit p => crossing.slave.adapt(this)( DisableMonitors { implicit p => | ||||
|       tileSlaveBuffering :*= rocket.crossTLIn | ||||
|     })} | ||||
|     DisableMonitors { implicit p => | ||||
|       tileSlaveBuffering :*= pbus.toTile(tp.name) { rocket.crossTLIn } | ||||
|     } | ||||
|  | ||||
|     // Handle all the different types of interrupts crossing to or from the tile: | ||||
|     // 1. Debug interrupt is definitely asynchronous in all cases. | ||||
|   | ||||
| @@ -8,65 +8,94 @@ import freechips.rocketchip.diplomacy._ | ||||
| import freechips.rocketchip.tilelink._ | ||||
| import freechips.rocketchip.util._ | ||||
|  | ||||
| case class SystemBusParams( | ||||
|   beatBytes: Int, | ||||
|   blockBytes: Int, | ||||
|   masterBuffering: BufferParams = BufferParams.default, | ||||
|   slaveBuffering: BufferParams = BufferParams.default | ||||
| ) extends TLBusParams | ||||
| case class SystemBusParams(beatBytes: Int, blockBytes: Int) extends HasTLBusParams | ||||
|  | ||||
| case object SystemBusKey extends Field[SystemBusParams] | ||||
|  | ||||
| class SystemBus(params: SystemBusParams)(implicit p: Parameters) extends TLBusWrapper(params, "SystemBus") { | ||||
| class SystemBus(params: SystemBusParams)(implicit p: Parameters) extends TLBusWrapper(params, "SystemBus") | ||||
|     with HasTLXbarPhy { | ||||
|  | ||||
|   private val master_splitter = LazyModule(new TLSplitter)  // Allows cycle-free connection to external networks | ||||
|   master_splitter.suggestName(s"${busName}_master_TLSplitter") | ||||
|   private val master_splitter = LazyModule(new TLSplitter) | ||||
|   inwardNode :=* master_splitter.node | ||||
|  | ||||
|   def busView = master_splitter.node.edges.in.head | ||||
|  | ||||
|   protected def inwardSplitNode: TLInwardNode = master_splitter.node | ||||
|   protected def outwardSplitNode: TLOutwardNode = master_splitter.node | ||||
|   private def bufferTo(buffer: BufferParams): TLOutwardNode = | ||||
|     TLBuffer(buffer) :*= delayNode :*= outwardNode | ||||
|  | ||||
|  | ||||
|   private val port_fixer = LazyModule(new TLFIFOFixer(TLFIFOFixer.all)) | ||||
|   port_fixer.suggestName(s"${busName}_port_TLFIFOFixer") | ||||
|   master_splitter.node :=* port_fixer.node | ||||
|  | ||||
|   private val pbus_fixer = LazyModule(new TLFIFOFixer(TLFIFOFixer.all)) | ||||
|   pbus_fixer.suggestName(s"${busName}_pbus_TLFIFOFixer") | ||||
|   pbus_fixer.node :*= outwardWWNode | ||||
|  | ||||
|   def toSplitSlaves: TLOutwardNode = outwardSplitNode | ||||
|  | ||||
|   def toPeripheryBus(addBuffers: Int = 0): TLOutwardNode = { | ||||
|     TLBuffer.chain(addBuffers).foldRight(pbus_fixer.node:TLOutwardNode)(_ :*= _) | ||||
|   } | ||||
|  | ||||
|   val toMemoryBus: TLOutwardNode = outwardNode | ||||
|  | ||||
|   val toSlave: TLOutwardNode = outwardBufNode | ||||
|  | ||||
|   def fromCoherentChip: TLInwardNode = inwardNode | ||||
|  | ||||
|   def fromFrontBus: TLInwardNode = master_splitter.node | ||||
|  | ||||
|   def fromTile(name: Option[String])(gen: Parameters => TLOutwardNode) { | ||||
|     this { | ||||
|       LazyScope(s"${busName}FromTile${name.getOrElse("")}") { | ||||
|         master_splitter.node :=* gen(p) | ||||
|       } | ||||
|   def toPeripheryBus(buffer: BufferParams = BufferParams.none) | ||||
|                     (gen: => TLNode): TLOutwardNode = { | ||||
|     to("PeripheryBus") { | ||||
|       (gen | ||||
|         := TLFIFOFixer(TLFIFOFixer.all) | ||||
|         := TLWidthWidget(params.beatBytes) | ||||
|         := bufferTo(buffer)) | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   def fromSyncPorts(params: BufferParams =  BufferParams.default, name: Option[String] = None): TLInwardNode = { | ||||
|     val buffer = LazyModule(new TLBuffer(params)) | ||||
|     name.foreach { n => buffer.suggestName(s"${busName}_${n}_TLBuffer") } | ||||
|     port_fixer.node :=* buffer.node | ||||
|     buffer.node | ||||
|   def toMemoryBus(gen: => TLInwardNode) { | ||||
|     to("MemoryBus") { gen :*= delayNode :*= outwardNode } | ||||
|   } | ||||
|  | ||||
|   def fromSyncFIFOMaster(params: BufferParams =  BufferParams.default, name: Option[String] = None): TLInwardNode = { | ||||
|     fromSyncPorts(params, name) | ||||
|   def toSlave(name: Option[String] = None, buffer: BufferParams = BufferParams.default) | ||||
|              (gen: => TLNode): TLOutwardNode = { | ||||
|     to(s"Slave${name.getOrElse("")}") { gen :*= bufferTo(buffer) } | ||||
|   } | ||||
|   | ||||
|   def toSplitSlave(name: Option[String] = None) | ||||
|                   (gen: => TLNode): TLOutwardNode = { | ||||
|     to(s"Slave${name.getOrElse("")}") { gen :*= master_splitter.node } | ||||
|   } | ||||
|  | ||||
|   def toVariableWidthSlave( | ||||
|         name: Option[String] = None, | ||||
|         buffer: BufferParams = BufferParams.default) | ||||
|       (gen: => TLNode): TLOutwardNode = { | ||||
|     to(s"Slave${name.getOrElse("")}") { | ||||
|       gen :*= TLFragmenter(params.beatBytes, params.blockBytes) :*= bufferTo(buffer) | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   def fromCoherentChip(gen: => TLNode): TLInwardNode = { | ||||
|     from("CoherentChip") { inwardNode :=* gen } | ||||
|   } | ||||
|  | ||||
|   def fromFrontBus(gen: => TLNode): TLInwardNode = { | ||||
|     from("FrontBus") { master_splitter.node :=* gen } | ||||
|   } | ||||
|  | ||||
|   def fromTile( | ||||
|         name: Option[String], | ||||
|         buffers: Int = 0, | ||||
|         cork: Option[Boolean] = None) | ||||
|       (gen: => TLNode): TLInwardNode = { | ||||
|     from(s"Tile${name.getOrElse("")}") { | ||||
|       (List(master_splitter.node, TLFIFOFixer(TLFIFOFixer.allUncacheable)) ++ | ||||
|         TLBuffer.chain(buffers) ++ | ||||
|         cork.map(u => TLCacheCork(unsafe = u)) | ||||
|       ).reduce(_ :=* _) :=* gen | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   def toFixedWidthPort[D,U,E,B <: Data]( | ||||
|         name: Option[String] = None, | ||||
|         buffer: BufferParams = BufferParams.default) | ||||
|       (gen: => NodeHandle[TLClientPortParameters,TLManagerPortParameters,TLEdgeIn,TLBundle,D,U,E,B]): OutwardNodeHandle[D,U,E,B] = { | ||||
|     to(s"Port${name.getOrElse("")}") { | ||||
|       gen := TLWidthWidget(params.beatBytes) := bufferTo(buffer) | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   def fromPort[D,U,E,B <: Data]( | ||||
|         name: Option[String] = None, | ||||
|         buffers: Int = 0) | ||||
|       (gen: => NodeHandle[D,U,E,B,TLClientPortParameters,TLManagerPortParameters,TLEdgeOut,TLBundle]): InwardNodeHandle[D,U,E,B] = { | ||||
|     from(s"Port${name.getOrElse("")}") { | ||||
|       (List( | ||||
|         master_splitter.node, | ||||
|         TLFIFOFixer(TLFIFOFixer.all)) ++ | ||||
|         TLBuffer.chain(buffers)).reduce(_ :=* _) :=* gen | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -1,85 +0,0 @@ | ||||
| // See LICENSE.SiFive for license details. | ||||
|  | ||||
| package freechips.rocketchip.tilelink | ||||
|  | ||||
| import Chisel._ | ||||
| import freechips.rocketchip.config.{Field, Parameters} | ||||
| import freechips.rocketchip.diplomacy._ | ||||
|  | ||||
| case object TLBusDelayProbability extends Field[Double](0.0) | ||||
|  | ||||
| /** Specifies widths of various attachement points in the SoC */ | ||||
| trait TLBusParams { | ||||
|   val beatBytes: Int | ||||
|   val blockBytes: Int | ||||
|   val masterBuffering: BufferParams | ||||
|   val slaveBuffering: BufferParams | ||||
|  | ||||
|   def beatBits: Int = beatBytes * 8 | ||||
|   def blockBits: Int = blockBytes * 8 | ||||
|   def blockBeats: Int = blockBytes / beatBytes | ||||
|   def blockOffset: Int = log2Up(blockBytes) | ||||
| } | ||||
|  | ||||
| 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 | ||||
|   val masterBuffering = params.masterBuffering | ||||
|   val slaveBuffering = params.slaveBuffering | ||||
|   require(blockBytes % beatBytes == 0) | ||||
|   private val delayProb = p(TLBusDelayProbability) | ||||
|  | ||||
|   protected val xbar = LazyModule(new TLXbar) | ||||
|   xbar.suggestName(busName) | ||||
|  | ||||
|   private val master_buffer = LazyModule(new TLBuffer(masterBuffering)) | ||||
|   master_buffer.suggestName(s"${busName}_master_TLBuffer") | ||||
|   private val slave_buffer = LazyModule(new TLBuffer(slaveBuffering)) | ||||
|   slave_buffer.suggestName(s"${busName}_slave_TLBuffer") | ||||
|   private val slave_frag = LazyModule(new TLFragmenter(beatBytes, blockBytes)) | ||||
|   slave_frag.suggestName(s"${busName}_slave_TLFragmenter") | ||||
|    | ||||
|   private val slave_ww = LazyModule(new TLWidthWidget(beatBytes)) | ||||
|   slave_ww.suggestName(s"${busName}_slave_TLWidthWidget") | ||||
|  | ||||
|   private val delayedNode = if (delayProb > 0.0) { | ||||
|     val firstDelay = LazyModule(new TLDelayer(delayProb)) | ||||
|     val flowDelay = LazyModule(new TLBuffer(BufferParams.flow)) | ||||
|     val secondDelay = LazyModule(new TLDelayer(delayProb)) | ||||
|     firstDelay.node :*= xbar.node | ||||
|     flowDelay.node :*= firstDelay.node | ||||
|     secondDelay.node :*= flowDelay.node | ||||
|     secondDelay.node | ||||
|   } else { | ||||
|     xbar.node | ||||
|   } | ||||
|  | ||||
|   xbar.node :=* master_buffer.node | ||||
|   slave_buffer.node :*= delayedNode | ||||
|   slave_frag.node :*= slave_buffer.node | ||||
|   slave_ww.node :*= slave_buffer.node | ||||
|  | ||||
|   protected def outwardNode: TLOutwardNode = delayedNode | ||||
|   protected def outwardBufNode: TLOutwardNode = slave_buffer.node | ||||
|   protected def outwardFragNode: TLOutwardNode = slave_frag.node | ||||
|   protected def outwardWWNode: TLOutwardNode = slave_ww.node | ||||
|   protected def inwardNode: TLInwardNode = xbar.node | ||||
|   protected def inwardBufNode: TLInwardNode = master_buffer.node | ||||
|  | ||||
|   def bufferFromMasters: TLInwardNode = inwardBufNode | ||||
|  | ||||
|   def bufferToSlaves: TLOutwardNode = outwardBufNode  | ||||
|  | ||||
|   def toSyncSlaves(name: Option[String] = None, addBuffers: Int = 0): TLOutwardNode = { | ||||
|     TLBuffer.chain(addBuffers).foldRight(outwardBufNode)(_ :*= _) | ||||
|   } | ||||
|  | ||||
|   def toVariableWidthSlaves: TLOutwardNode = outwardFragNode | ||||
|  | ||||
|   def toFixedWidthSlaves: TLOutwardNode = outwardWWNode | ||||
|  | ||||
|   def toFixedWidthPorts: TLOutwardNode = outwardWWNode // TODO, do/don't buffer here; knowing we will after the necessary port conversions | ||||
|  | ||||
| } | ||||
							
								
								
									
										57
									
								
								src/main/scala/tilelink/BusWrapper.scala
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								src/main/scala/tilelink/BusWrapper.scala
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,57 @@ | ||||
| // See LICENSE.SiFive for license details. | ||||
|  | ||||
| package freechips.rocketchip.tilelink | ||||
|  | ||||
| import Chisel._ | ||||
| import freechips.rocketchip.config.{Field, Parameters} | ||||
| import freechips.rocketchip.diplomacy._ | ||||
|  | ||||
| case object TLBusDelayProbability extends Field[Double](0.0) | ||||
|  | ||||
| /** Specifies widths of various attachement points in the SoC */ | ||||
| trait HasTLBusParams { | ||||
|   val beatBytes: Int | ||||
|   val blockBytes: Int | ||||
|  | ||||
|   def beatBits: Int = beatBytes * 8 | ||||
|   def blockBits: Int = blockBytes * 8 | ||||
|   def blockBeats: Int = blockBytes / beatBytes | ||||
|   def blockOffset: Int = log2Up(blockBytes) | ||||
| } | ||||
|  | ||||
| abstract class TLBusWrapper(params: HasTLBusParams, val busName: String)(implicit p: Parameters) | ||||
|     extends SimpleLazyModule with LazyScope with HasTLBusParams { | ||||
|  | ||||
|   val beatBytes = params.beatBytes | ||||
|   val blockBytes = params.blockBytes | ||||
|   require(blockBytes % beatBytes == 0) | ||||
|  | ||||
|   protected def inwardNode: TLInwardNode | ||||
|   protected def outwardNode: TLOutwardNode | ||||
|  | ||||
|   protected def delayNode(implicit p: Parameters): TLNode = { | ||||
|     val delayProb = p(TLBusDelayProbability) | ||||
|     if (delayProb > 0.0) { | ||||
|       TLDelayer(delayProb) :*=* TLBuffer(BufferParams.flow) :*=* TLDelayer(delayProb) | ||||
|     } else { | ||||
|       val nodelay = TLIdentityNode() | ||||
|       nodelay | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   protected def to[T](name: String)(body: => T): T = { | ||||
|     this { LazyScope(s"${busName}To${name}") { body } } | ||||
|   } | ||||
|  | ||||
|   protected def from[T](name: String)(body: => T): T = { | ||||
|     this { LazyScope(s"${busName}From${name}") { body } } | ||||
|   } | ||||
| } | ||||
|  | ||||
| trait HasTLXbarPhy { this: TLBusWrapper => | ||||
|   private val xbar = LazyModule(new TLXbar) | ||||
|   xbar.suggestName(busName) | ||||
|  | ||||
|   protected def inwardNode: TLInwardNode = xbar.node | ||||
|   protected def outwardNode: TLOutwardNode = xbar.node | ||||
| } | ||||
		Reference in New Issue
	
	Block a user