From 9bbde9767c5f4f0ad38841f653ac5340ab49939c Mon Sep 17 00:00:00 2001 From: Henry Cook Date: Thu, 1 Jun 2017 16:06:36 -0700 Subject: [PATCH] rocketchip: top-level systems are now multi-IO modules Cake pattern only 2 layers instead of 3. Standardized naming convention. Comments for periphery mix-ins. Testharnesses use new periphery helper methods. --- src/main/scala/groundtest/TestHarness.scala | 11 +- src/main/scala/groundtest/Top.scala | 27 +- src/main/scala/rocketchip/BaseTop.scala | 71 ---- src/main/scala/rocketchip/ExampleTop.scala | 70 ++-- src/main/scala/rocketchip/Periphery.scala | 372 ++++++++---------- src/main/scala/rocketchip/RISCVPlatform.scala | 187 ++++----- .../scala/rocketchip/RocketPlexMaster.scala | 17 +- src/main/scala/rocketchip/System.scala | 24 ++ src/main/scala/rocketchip/TestHarness.scala | 29 +- 9 files changed, 303 insertions(+), 505 deletions(-) delete mode 100644 src/main/scala/rocketchip/BaseTop.scala create mode 100644 src/main/scala/rocketchip/System.scala diff --git a/src/main/scala/groundtest/TestHarness.scala b/src/main/scala/groundtest/TestHarness.scala index 615a13dc..23267af6 100644 --- a/src/main/scala/groundtest/TestHarness.scala +++ b/src/main/scala/groundtest/TestHarness.scala @@ -9,13 +9,8 @@ import rocketchip._ import util._ class TestHarness(implicit p: Parameters) extends Module { - val io = new Bundle { - val success = Bool(OUTPUT) - } - + val io = new Bundle { val success = Bool(OUTPUT) } val dut = Module(LazyModule(new GroundTestTop).module) - io.success := dut.io.success - - val channels = p(coreplex.BankedL2Config).nMemoryChannels - if (channels > 0) Module(LazyModule(new SimAXIMem(channels)).module).io.axi4 <> dut.io.mem_axi4 + io.success := dut.io_success + dut.connectSimAXIMem() } diff --git a/src/main/scala/groundtest/Top.scala b/src/main/scala/groundtest/Top.scala index 9fb40686..fd2d65ad 100644 --- a/src/main/scala/groundtest/Top.scala +++ b/src/main/scala/groundtest/Top.scala @@ -3,15 +3,14 @@ package groundtest import Chisel._ -import config._ -import diplomacy._ -import coreplex._ +import config.Parameters +import diplomacy.LazyModule import rocketchip._ -class GroundTestTop(implicit p: Parameters) extends BaseTop - with PeripheryMasterAXI4Mem - with PeripheryTestRAM { - override lazy val module = new GroundTestTopModule(this, () => new GroundTestTopBundle(this)) +class GroundTestTop(implicit p: Parameters) extends BaseSystem + with HasPeripheryMasterAXI4MemPort + with HasPeripheryTestRAMSlave { + override lazy val module = new GroundTestTopModule(this) val coreplex = LazyModule(new GroundTestCoreplex) @@ -20,14 +19,8 @@ class GroundTestTop(implicit p: Parameters) extends BaseTop (mem zip coreplex.mem) foreach { case (xbar, channel) => xbar.node :=* channel } } -class GroundTestTopBundle[+L <: GroundTestTop](_outer: L) extends BaseTopBundle(_outer) - with PeripheryMasterAXI4MemBundle - with PeripheryTestRAMBundle { - val success = Bool(OUTPUT) -} - -class GroundTestTopModule[+L <: GroundTestTop, +B <: GroundTestTopBundle[L]](_outer: L, _io: () => B) extends BaseTopModule(_outer, _io) - with PeripheryMasterAXI4MemModule - with PeripheryTestRAMModule { - io.success := outer.coreplex.module.io.success +class GroundTestTopModule[+L <: GroundTestTop](_outer: L) extends BaseSystemModule(_outer) + with HasPeripheryMasterAXI4MemPortModuleImp { + val io_success = IO(Bool(OUTPUT)) + io_success := outer.coreplex.module.io.success } diff --git a/src/main/scala/rocketchip/BaseTop.scala b/src/main/scala/rocketchip/BaseTop.scala deleted file mode 100644 index d97f8c5f..00000000 --- a/src/main/scala/rocketchip/BaseTop.scala +++ /dev/null @@ -1,71 +0,0 @@ -// See LICENSE.SiFive for license details. - -package rocketchip - -import Chisel._ -import config._ -import junctions._ -import diplomacy._ -import uncore.tilelink._ -import uncore.tilelink2._ -import uncore.devices._ -import util._ -import rocket._ - -/** BareTop is the root class for creating a top-level RTL module */ -abstract class BareTop(implicit p: Parameters) extends LazyModule { - ElaborationArtefacts.add("graphml", graphML) -} - -abstract class BareTopBundle[+L <: BareTop](_outer: L) extends GenericParameterizedBundle(_outer) { - val outer = _outer - implicit val p = outer.p -} - -abstract class BareTopModule[+L <: BareTop, +B <: BareTopBundle[L]](_outer: L, _io: () => B) extends LazyMultiIOModuleImp(_outer) { - val outer = _outer - val io = IO(_io()) -} - -/** HasTopLevelNetworks provides buses that will serve as attachment points, - * for use in sub-traits that connect individual agents or external ports. - */ -trait HasTopLevelNetworks extends HasPeripheryParameters { - val module: HasTopLevelNetworksModule - - val socBus = LazyModule(new TLXbar) // Wide or unordered-access slave devices (TL-UH) - val peripheryBus = LazyModule(new TLXbar) // Narrow and ordered-access slave devices (TL-UL) - val intBus = LazyModule(new IntXbar) // Device and global external interrupts - val fsb = LazyModule(new TLBuffer(BufferParams.none)) // Master devices talking to the frontside of the L2 - val bsb = LazyModule(new TLBuffer(BufferParams.none)) // Slave devices talking to the backside of the L2 - val mem = Seq.fill(nMemoryChannels) { LazyModule(new TLXbar) } // Ports out to DRAM - - // The peripheryBus hangs off of socBus; - // here we convert TL-UH -> TL-UL - peripheryBus.node := - TLBuffer()( - TLWidthWidget(socBusConfig.beatBytes)( - TLAtomicAutomata(arithmetic = peripheryBusArithmetic)( - socBus.node))) -} - -trait HasTopLevelNetworksBundle extends HasPeripheryParameters { - val outer: HasTopLevelNetworks -} - -trait HasTopLevelNetworksModule extends HasPeripheryParameters { - val outer: HasTopLevelNetworks - val io: HasTopLevelNetworksBundle -} - -/** Base Top class with no peripheral devices or ports added */ -abstract class BaseTop(implicit p: Parameters) extends BareTop - with HasTopLevelNetworks { - override val module: BaseTopModule[BaseTop, BaseTopBundle[BaseTop]] -} - -abstract class BaseTopBundle[+L <: BaseTop](_outer: L) extends BareTopBundle(_outer) - with HasTopLevelNetworksBundle - -abstract class BaseTopModule[+L <: BaseTop, +B <: BaseTopBundle[L]](_outer: L, _io: () => B) extends BareTopModule(_outer, _io) - with HasTopLevelNetworksModule diff --git a/src/main/scala/rocketchip/ExampleTop.scala b/src/main/scala/rocketchip/ExampleTop.scala index cdf49871..2d146220 100644 --- a/src/main/scala/rocketchip/ExampleTop.scala +++ b/src/main/scala/rocketchip/ExampleTop.scala @@ -7,52 +7,34 @@ import config._ import junctions._ import rocketchip._ -/** Example Top with Periphery (w/o coreplex) */ -abstract class ExampleTop(implicit p: Parameters) extends BaseTop - with PeripheryAsyncExtInterrupts - with PeripheryErrorSlave - with PeripheryMasterAXI4Mem - with PeripheryMasterAXI4MMIO - with PeripherySlaveAXI4 { - override lazy val module = new ExampleTopModule(this, () => new ExampleTopBundle(this)) +/** Example system with periphery devices (w/o coreplex) */ +abstract class ExampleSystem(implicit p: Parameters) extends BaseSystem + with HasPeripheryAsyncExtInterrupts + with HasPeripheryMasterAXI4MemPort + with HasPeripheryMasterAXI4MMIOPort + with HasPeripherySlaveAXI4Port + with HasPeripheryErrorSlave + with HasPeripheryZeroSlave { + override lazy val module = new ExampleSystemModule(this) } -class ExampleTopBundle[+L <: ExampleTop](_outer: L) extends BaseTopBundle(_outer) - with PeripheryExtInterruptsBundle - with PeripheryErrorSlaveBundle - with PeripheryMasterAXI4MemBundle - with PeripheryMasterAXI4MMIOBundle - with PeripherySlaveAXI4Bundle +class ExampleSystemModule[+L <: ExampleSystem](_outer: L) extends BaseSystemModule(_outer) + with HasPeripheryExtInterruptsModuleImp + with HasPeripheryMasterAXI4MemPortModuleImp + with HasPeripheryMasterAXI4MMIOPortModuleImp + with HasPeripherySlaveAXI4PortModuleImp -class ExampleTopModule[+L <: ExampleTop, +B <: ExampleTopBundle[L]](_outer: L, _io: () => B) extends BaseTopModule(_outer, _io) - with PeripheryExtInterruptsModule - with PeripheryErrorSlaveModule - with PeripheryMasterAXI4MemModule - with PeripheryMasterAXI4MMIOModule - with PeripherySlaveAXI4Module - -class ExampleRocketTop(implicit p: Parameters) extends ExampleTop - with PeripheryBootROM - with PeripheryZero - with PeripheryDebug - with PeripheryCounter - with HardwiredResetVector - with RocketPlexMaster { - override lazy val module = new ExampleRocketTopModule(this, () => new ExampleRocketTopBundle(this)) +/** Example Top with periphery and a Rocket coreplex */ +class ExampleRocketTop(implicit p: Parameters) extends ExampleSystem + with HasPeripheryBootROM + with HasPeripheryDebug + with HasPeripheryRTCCounter + with HasRocketPlexMaster { + override lazy val module = new ExampleRocketTopModule(this) } -class ExampleRocketTopBundle[+L <: ExampleRocketTop](_outer: L) extends ExampleTopBundle(_outer) - with PeripheryBootROMBundle - with PeripheryZeroBundle - with PeripheryDebugBundle - with PeripheryCounterBundle - with HardwiredResetVectorBundle - with RocketPlexMasterBundle - -class ExampleRocketTopModule[+L <: ExampleRocketTop, +B <: ExampleRocketTopBundle[L]](_outer: L, _io: () => B) extends ExampleTopModule(_outer, _io) - with PeripheryBootROMModule - with PeripheryZeroModule - with PeripheryDebugModule - with PeripheryCounterModule - with HardwiredResetVectorModule - with RocketPlexMasterModule +class ExampleRocketTopModule[+L <: ExampleRocketTop](_outer: L) extends ExampleSystemModule(_outer) + with HasPeripheryBootROMModuleImp + with HasPeripheryDebugModuleImp + with HasPeripheryRTCCounterModuleImp + with HasRocketPlexMasterModuleImp diff --git a/src/main/scala/rocketchip/Periphery.scala b/src/main/scala/rocketchip/Periphery.scala index 0a4c9ebf..91c87ceb 100644 --- a/src/main/scala/rocketchip/Periphery.scala +++ b/src/main/scala/rocketchip/Periphery.scala @@ -6,12 +6,8 @@ import Chisel._ import config._ import coreplex._ import diplomacy._ -import tile.XLen import uncore.tilelink2._ import uncore.axi4._ -import uncore.converters._ -import uncore.devices._ -import uncore.util._ import util._ import scala.math.{min,max} @@ -47,80 +43,96 @@ trait HasPeripheryParameters { def cacheBlockBytes = p(CacheBlockBytes) def peripheryBusArithmetic = p(PeripheryBusArithmetic) def nMemoryChannels = p(coreplex.BankedL2Config).nMemoryChannels + def nExtInterrupts = p(NExtTopInterrupts) } -///// -abstract trait PeripheryExtInterrupts { - this: HasTopLevelNetworks => +/** HasSystemNetworks provides buses that will serve as attachment points, + * for use in the following child traits that connect individual agents or external ports. + */ +trait HasSystemNetworks extends HasPeripheryParameters { + val socBus = LazyModule(new TLXbar) // Wide or unordered-access slave devices (TL-UH) + val peripheryBus = LazyModule(new TLXbar) // Narrow and ordered-access slave devices (TL-UL) + val intBus = LazyModule(new IntXbar) // Device and global external interrupts + val fsb = LazyModule(new TLBuffer(BufferParams.none)) // Master devices talking to the frontside of the L2 + val bsb = LazyModule(new TLBuffer(BufferParams.none)) // Slave devices talking to the backside of the L2 + val mem = Seq.fill(nMemoryChannels) { LazyModule(new TLXbar) } // Ports out to DRAM + // The peripheryBus hangs off of socBus; + // here we convert TL-UH -> TL-UL + peripheryBus.node := + TLBuffer()( + TLWidthWidget(socBusConfig.beatBytes)( + TLAtomicAutomata(arithmetic = peripheryBusArithmetic)( + socBus.node))) +} + +/** This trait adds externally driven interrupts to the system. + * However, it should not be used directly; instead one of the below + * synchronization wiring child traits should be used. + */ +abstract trait HasPeripheryExtInterrupts extends HasSystemNetworks { private val device = new Device with DeviceInterrupts { def describe(resources: ResourceBindings): Description = { Description("soc/offchip-interrupts", describeInterrupts(resources)) } } - val nExtInterrupts = p(NExtTopInterrupts) val extInterrupts = IntInternalInputNode(IntSourcePortSimple(num = nExtInterrupts, resources = device.int)) - } -trait PeripheryExtInterruptsBundle { - this: HasTopLevelNetworksBundle { - val outer: PeripheryExtInterrupts - } => - val interrupts = UInt(INPUT, width = outer.nExtInterrupts) -} - -trait PeripheryExtInterruptsModule { - this: HasTopLevelNetworksModule { - val outer: PeripheryExtInterrupts - val io: PeripheryExtInterruptsBundle - } => - outer.extInterrupts.bundleIn.flatten.zipWithIndex.foreach { case(o, i) => o := io.interrupts(i) } -} - -// This trait should be used if the External Interrupts have NOT -// already been synchronized -// to the Periphery (PLIC) Clock. - -trait PeripheryAsyncExtInterrupts extends PeripheryExtInterrupts { - this: HasTopLevelNetworks => - +/** This trait should be used if the External Interrupts have NOT + * already been synchronized to the Periphery (PLIC) Clock. + */ +trait HasPeripheryAsyncExtInterrupts extends HasPeripheryExtInterrupts { if (nExtInterrupts > 0) { val extInterruptXing = LazyModule(new IntXing) intBus.intnode := extInterruptXing.intnode extInterruptXing.intnode := extInterrupts } - } -// This trait can be used if the External Interrupts have already been synchronized -// to the Periphery (PLIC) Clock. - -trait PeripherySyncExtInterrupts extends PeripheryExtInterrupts { - this: HasTopLevelNetworks => - +/** This trait can be used if the External Interrupts have already been synchronized + * to the Periphery (PLIC) Clock. + */ +trait HasPeripherySyncExtInterrupts extends HasPeripheryExtInterrupts { if (nExtInterrupts > 0) { intBus.intnode := extInterrupts } } -///// +/** Common io name and methods for propagating or tying off the port bundle */ +trait HasPeripheryExtInterruptsBundle extends HasPeripheryParameters { + val interrupts: UInt + def tieOffInterrupts(dummy: Int = 1) { + interrupts := UInt(0) + } +} +/** This trait performs the translation from a UInt IO into Diplomatic Interrupts. + * The wiring must be done in the concrete LazyModuleImp. + */ +trait HasPeripheryExtInterruptsModuleImp extends LazyMultiIOModuleImp with HasPeripheryExtInterruptsBundle { + val outer: HasPeripheryExtInterrupts + val interrupts = IO(UInt(INPUT, width = outer.nExtInterrupts)) -trait PeripheryMasterAXI4Mem { - this: HasTopLevelNetworks => - val module: PeripheryMasterAXI4MemModule + outer.extInterrupts.bundleIn.flatten.zipWithIndex.foreach { case(o, i) => o := interrupts(i) } +} + +///// The following traits add ports to the sytem, in some cases converting to different interconnect standards + +/** Adds a port to the system intended to master an AXI4 DRAM controller. */ +trait HasPeripheryMasterAXI4MemPort extends HasSystemNetworks { + val module: HasPeripheryMasterAXI4MemPortModuleImp private val config = p(ExtMem) private val channels = p(BankedL2Config).nMemoryChannels - private val lineBytes = p(CacheBlockBytes) + private val blockBytes = p(CacheBlockBytes) private val device = new MemoryDevice val mem_axi4 = AXI4BlindOutputNode(Seq.tabulate(channels) { channel => val base = AddressSet(config.base, config.size-1) - val filter = AddressSet(channel * lineBytes, ~((channels-1) * lineBytes)) + val filter = AddressSet(channel * blockBytes, ~((channels-1) * blockBytes)) AXI4SlavePortParameters( slaves = Seq(AXI4SlaveParameters( @@ -148,56 +160,22 @@ trait PeripheryMasterAXI4Mem { } } -trait PeripheryMasterAXI4MemBundle { - this: HasTopLevelNetworksBundle { - val outer: PeripheryMasterAXI4Mem - } => - val mem_axi4 = outer.mem_axi4.bundleOut -} - -trait PeripheryMasterAXI4MemModule { - this: HasTopLevelNetworksModule { - val outer: PeripheryMasterAXI4Mem - val io: PeripheryMasterAXI4MemBundle - } => -} - -///// - -trait PeripheryZero { - this: HasTopLevelNetworks => - val module: PeripheryZeroModule - - private val config = p(ZeroConfig) - private val address = AddressSet(config.base, config.size-1) - private val lineBytes = p(CacheBlockBytes) - - val zeros = mem map { case xbar => - val zero = LazyModule(new TLZero(address, beatBytes = config.beatBytes)) - zero.node := TLFragmenter(config.beatBytes, lineBytes)(xbar.node) - zero +/** Common io name and methods for propagating or tying off the port bundle */ +trait HasPeripheryMasterAXI4MemPortBundle extends HasPeripheryParameters { + val mem_axi4: HeterogeneousBag[AXI4Bundle] + def connectSimAXIMem(dummy: Int = 1) = { + if (nMemoryChannels > 0) Module(LazyModule(new SimAXIMem(nMemoryChannels)).module).io.axi4 <> mem_axi4 } } -trait PeripheryZeroBundle { - this: HasTopLevelNetworksBundle { - val outer: PeripheryZero - } => +/** Actually generates the corresponding IO in the concrete Module */ +trait HasPeripheryMasterAXI4MemPortModuleImp extends LazyMultiIOModuleImp with HasPeripheryMasterAXI4MemPortBundle { + val outer: HasPeripheryMasterAXI4MemPort + val mem_axi4 = IO(outer.mem_axi4.bundleOut) } -trait PeripheryZeroModule { - this: HasTopLevelNetworksModule { - val outer: PeripheryZero - val io: PeripheryZeroBundle - } => -} - -///// - -// PeripheryMasterAXI4MMIO is an example, make your own cake pattern like this one. -trait PeripheryMasterAXI4MMIO { - this: HasTopLevelNetworks => - +/** Adds a AXI4 port to the system intended to master an MMIO device bus */ +trait HasPeripheryMasterAXI4MMIOPort extends HasSystemNetworks { private val config = p(ExtBus) private val device = new SimpleDevice("mmio", Nil) val mmio_axi4 = AXI4BlindOutputNode(Seq(AXI4SlavePortParameters( @@ -219,25 +197,22 @@ trait PeripheryMasterAXI4MMIO { socBus.node)))))) } -trait PeripheryMasterAXI4MMIOBundle { - this: HasTopLevelNetworksBundle { - val outer: PeripheryMasterAXI4MMIO - } => - val mmio_axi4 = outer.mmio_axi4.bundleOut +/** Common io name and methods for propagating or tying off the port bundle */ +trait HasPeripheryMasterAXI4MMIOPortBundle extends HasPeripheryParameters { + val mmio_axi4: HeterogeneousBag[AXI4Bundle] + def connectSimAXIMMIO(dummy: Int = 1) { + Module(LazyModule(new SimAXIMem(1, 4096)).module).io.axi4 <> mmio_axi4 + } } -trait PeripheryMasterAXI4MMIOModule { - this: HasTopLevelNetworksModule { - val outer: PeripheryMasterAXI4MMIO - val io: PeripheryMasterAXI4MMIOBundle - } => - // nothing to do +/** Actually generates the corresponding IO in the concrete Module */ +trait HasPeripheryMasterAXI4MMIOPortModuleImp extends LazyMultiIOModuleImp with HasPeripheryMasterAXI4MMIOPortBundle { + val outer: HasPeripheryMasterAXI4MMIOPort + val mmio_axi4 = IO(outer.mmio_axi4.bundleOut) } -///// - -// PeripherySlaveAXI4 is an example, make your own cake pattern like this one. -trait PeripherySlaveAXI4 extends HasTopLevelNetworks { +/** Adds an AXI4 port to the system intended to be a slave on an MMIO device bus */ +trait HasPeripherySlaveAXI4Port extends HasSystemNetworks { private val config = p(ExtIn) val l2FrontendAXI4Node = AXI4BlindInputNode(Seq(AXI4MasterPortParameters( masters = Seq(AXI4MasterParameters( @@ -254,23 +229,28 @@ trait PeripherySlaveAXI4 extends HasTopLevelNetworks { l2FrontendAXI4Node))))) } -trait PeripherySlaveAXI4Bundle extends HasTopLevelNetworksBundle { - val outer: PeripherySlaveAXI4 - val l2_frontend_bus_axi4 = outer.l2FrontendAXI4Node.bundleIn +/** Common io name and methods for propagating or tying off the port bundle */ +trait HasPeripherySlaveAXI4PortBundle extends HasPeripheryParameters { + val l2_frontend_bus_axi4: HeterogeneousBag[AXI4Bundle] + def tieOffAXI4SlavePort(dummy: Int = 1) { + l2_frontend_bus_axi4.foreach { l2_axi4 => + l2_axi4.ar.valid := Bool(false) + l2_axi4.aw.valid := Bool(false) + l2_axi4.w .valid := Bool(false) + l2_axi4.r .ready := Bool(true) + l2_axi4.b .ready := Bool(true) + } + } } -trait PeripherySlaveAXI4Module extends HasTopLevelNetworksModule { - val outer: PeripherySlaveAXI4 - val io: PeripherySlaveAXI4Bundle - // nothing to do +/** Actually generates the corresponding IO in the concrete Module */ +trait HasPeripherySlaveAXI4PortModuleImp extends LazyMultiIOModuleImp with HasPeripherySlaveAXI4PortBundle { + val outer: HasPeripherySlaveAXI4Port + val l2_frontend_bus_axi4 = IO(outer.l2FrontendAXI4Node.bundleIn) } -///// - -// Add an external TL-UL slave -trait PeripheryMasterTLMMIO { - this: HasTopLevelNetworks => - +/** Adds a TileLink port to the system intended to master an MMIO device bus */ +trait HasPeripheryMasterTLMMIOPort extends HasSystemNetworks { private val config = p(ExtBus) private val device = new SimpleDevice("mmio", Nil) val mmio_tl = TLBlindOutputNode(Seq(TLManagerPortParameters( @@ -290,25 +270,30 @@ trait PeripheryMasterTLMMIO { socBus.node))) } -trait PeripheryMasterTLMMIOBundle { - this: HasTopLevelNetworksBundle { - val outer: PeripheryMasterTLMMIO - } => - val mmio_tl = outer.mmio_tl.bundleOut +/** Common io name and methods for propagating or tying off the port bundle */ +trait HasPeripheryMasterTLMMIOPortBundle extends HasPeripheryParameters { + val mmio_tl: HeterogeneousBag[TLBundle] + def tieOffTLMMIO(dummy: Int = 1) { + mmio_tl.foreach { tl => + tl.a.ready := Bool(true) + tl.b.valid := Bool(false) + tl.c.ready := Bool(true) + tl.d.valid := Bool(false) + tl.e.ready := Bool(true) + } + } } -trait PeripheryMasterTLMMIOModule { - this: HasTopLevelNetworksModule { - val outer: PeripheryMasterTLMMIO - val io: PeripheryMasterTLMMIOBundle - } => - // nothing to do +/** Actually generates the corresponding IO in the concrete Module */ +trait HasPeripheryMasterTLMMIOPortModuleImp extends LazyMultiIOModuleImp with HasPeripheryMasterTLMMIOPortBundle { + val outer: HasPeripheryMasterTLMMIOPort + val mmio_tl = IO(outer.mmio_tl.bundleOut) } -///// - -// NOTE: this port is NOT allowed to issue Acquires -trait PeripherySlaveTL extends HasTopLevelNetworks { +/** Adds an AXI4 port to the system intended to be a slave on an MMIO device bus. + * NOTE: this port is NOT allowed to issue Acquires. + */ +trait HasPeripherySlaveTLPort extends HasSystemNetworks { private val config = p(ExtIn) val l2FrontendTLNode = TLBlindInputNode(Seq(TLClientPortParameters( clients = Seq(TLClientParameters( @@ -321,105 +306,58 @@ trait PeripherySlaveTL extends HasTopLevelNetworks { l2FrontendTLNode)) } -trait PeripherySlaveTLBundle extends HasTopLevelNetworksBundle { - val outer: PeripherySlaveTL - val l2_frontend_bus_tl = outer.l2FrontendTLNode.bundleIn +/** Common io name and methods for propagating or tying off the port bundle */ +trait HasPeripherySlaveTLPortBundle extends HasPeripheryParameters { + val l2_frontend_bus_tl: HeterogeneousBag[TLBundle] + def tieOffSlaveTLPort(dummy: Int = 1) { + l2_frontend_bus_tl.foreach { tl => + tl.a.valid := Bool(false) + tl.b.ready := Bool(true) + tl.c.valid := Bool(false) + tl.d.ready := Bool(true) + tl.e.valid := Bool(false) + } + } } -trait PeripherySlaveTLModule extends HasTopLevelNetworksModule { - val outer: PeripherySlaveTL - val io: PeripherySlaveTLBundle - // nothing to do +/** Actually generates the corresponding IO in the concrete Module */ +trait HasPeripherySlaveTLPortModuleImp extends LazyMultiIOModuleImp with HasPeripherySlaveTLPortBundle { + val outer: HasPeripherySlaveTLPort + val l2_frontend_bus_tl = IO(outer.l2FrontendTLNode.bundleIn) } -///// +///// The following traits add specific devices to the periphery of the system. -trait PeripheryBootROM { - this: HasTopLevelNetworks => - val coreplex: CoreplexRISCVPlatform +/** Adds a /dev/null slave that generates */ +trait HasPeripheryZeroSlave extends HasSystemNetworks { + private val config = p(ZeroConfig) + private val address = AddressSet(config.base, config.size-1) + private val blockBytes = p(CacheBlockBytes) - private val bootrom_address = 0x10000 - private val bootrom_size = 0x10000 - private lazy val bootrom_contents = GenerateBootROM(coreplex.dtb) - val bootrom = LazyModule(new TLROM(bootrom_address, bootrom_size, bootrom_contents, true, peripheryBusConfig.beatBytes)) - bootrom.node := TLFragmenter(peripheryBusConfig.beatBytes, cacheBlockBytes)(peripheryBus.node) + val zeros = mem map { case xbar => + val zero = LazyModule(new TLZero(address, beatBytes = config.beatBytes)) + zero.node := TLFragmenter(config.beatBytes, blockBytes)(xbar.node) + zero + } } -trait PeripheryBootROMBundle { - this: HasTopLevelNetworksBundle { - val outer: PeripheryBootROM - } => -} - -trait PeripheryBootROMModule { - this: HasTopLevelNetworksModule { - val outer: PeripheryBootROM - val io: PeripheryBootROMBundle - } => -} - -///// - -trait PeripheryTestRAM { - this: HasTopLevelNetworks => - - val testram = LazyModule(new TLRAM(AddressSet(0x52000000, 0xfff), true, peripheryBusConfig.beatBytes)) - testram.node := TLFragmenter(peripheryBusConfig.beatBytes, cacheBlockBytes)(peripheryBus.node) -} - -trait PeripheryTestRAMBundle { - this: HasTopLevelNetworksBundle { - val outer: PeripheryTestRAM - } => -} - -trait PeripheryTestRAMModule { - this: HasTopLevelNetworksModule { - val outer: PeripheryTestRAM - val io: PeripheryTestRAMBundle - } => -} - -///// - -trait PeripheryTestBusMaster { - this: HasTopLevelNetworks => - val fuzzer = LazyModule(new TLFuzzer(5000)) - peripheryBus.node := fuzzer.node -} - -trait PeripheryTestBusMasterBundle { - this: HasTopLevelNetworksBundle { - val outer: PeripheryTestBusMaster - } => -} - -trait PeripheryTestBusMasterModule { - this: HasTopLevelNetworksModule { - val outer: PeripheryTestBusMaster - val io: PeripheryTestBusMasterBundle - } => -} - -///// - -trait PeripheryErrorSlave { - this: HasTopLevelNetworks => +/** Adds a /dev/null slave that generates TL2 error response messages. */ +trait HasPeripheryErrorSlave extends HasSystemNetworks { private val config = p(ErrorConfig) private val maxXfer = min(config.address.map(_.alignment).max.toInt, 4096) val error = LazyModule(new TLError(config.address, peripheryBusConfig.beatBytes)) error.node := TLFragmenter(peripheryBusConfig.beatBytes, maxXfer)(peripheryBus.node) } -trait PeripheryErrorSlaveBundle { - this: HasTopLevelNetworksBundle { - val outer: PeripheryErrorSlave - } => + +/** Adds a SRAM to the system for testing purposes. */ +trait HasPeripheryTestRAMSlave extends HasSystemNetworks { + val testram = LazyModule(new TLRAM(AddressSet(0x52000000, 0xfff), true, peripheryBusConfig.beatBytes)) + testram.node := TLFragmenter(peripheryBusConfig.beatBytes, cacheBlockBytes)(peripheryBus.node) } -trait PeripheryErrorSlaveModule { - this: HasTopLevelNetworksModule { - val outer: PeripheryErrorSlave - val io: PeripheryErrorSlaveBundle - } => +/** Adds a fuzzing master to the system for testing purposes. */ +trait HasPeripheryTestFuzzMaster extends HasSystemNetworks { + val fuzzer = LazyModule(new TLFuzzer(5000)) + peripheryBus.node := fuzzer.node } diff --git a/src/main/scala/rocketchip/RISCVPlatform.scala b/src/main/scala/rocketchip/RISCVPlatform.scala index 91f23639..30d78f98 100644 --- a/src/main/scala/rocketchip/RISCVPlatform.scala +++ b/src/main/scala/rocketchip/RISCVPlatform.scala @@ -4,153 +4,112 @@ package rocketchip import Chisel._ import config._ +import coreplex._ import diplomacy._ +import jtag.JTAGIO import uncore.tilelink2._ import uncore.devices._ import util._ -import jtag.JTAGIO -import coreplex._ -// System with JTAG DTM Instantiated inside. JTAG interface is -// exported outside. - -trait PeripheryJTAGDTM extends HasTopLevelNetworks { - val module: PeripheryJTAGDTMModule +/** All the traits defined in this file assume that they are being mixed in + * to a system that has a standard RISCV-based coreplex platform. + */ +trait HasCoreplexRISCVPlatform { + implicit val p: Parameters val coreplex: CoreplexRISCVPlatform } -trait PeripheryJTAGDTMBundle extends HasTopLevelNetworksBundle { - val outer: PeripheryJTAGDTM - +/** A wrapper around JTAG providing a reset signal and manufacturer id. */ +class SystemJTAGIO extends Bundle { val jtag = new JTAGIO(hasTRSTn = false).flip - val jtag_reset = Bool(INPUT) - val jtag_mfr_id = UInt(INPUT, 11) - + val reset = Bool(INPUT) + val mfr_id = UInt(INPUT, 11) } -trait PeripheryJTAGDTMModule extends HasTopLevelNetworksModule { - val outer: PeripheryJTAGDTM - val io: PeripheryJTAGDTMBundle - - val dtm = Module (new DebugTransportModuleJTAG(p(DMKey).nDMIAddrSize, p(JtagDTMKey))) - dtm.io.jtag <> io.jtag - - dtm.clock := io.jtag.TCK - dtm.io.jtag_reset := io.jtag_reset - dtm.io.jtag_mfr_id := io.jtag_mfr_id - dtm.reset := dtm.io.fsmReset - - outer.coreplex.module.io.debug.dmi <> dtm.io.dmi - outer.coreplex.module.io.debug.dmiClock := io.jtag.TCK - outer.coreplex.module.io.debug.dmiReset := ResetCatchAndSync(io.jtag.TCK, io.jtag_reset, "dmiResetCatch") - +/** A wrapper bundle containing one of the two possible debug interfaces */ +class DebugIO(implicit p: Parameters) extends ParameterizedBundle()(p) { + val clockeddmi = (!p(IncludeJtagDTM)).option(new ClockedDMIIO().flip) + val systemjtag = (p(IncludeJtagDTM)).option(new SystemJTAGIO) + val ndreset = Bool(OUTPUT) + val dmactive = Bool(OUTPUT) } -// System with Debug Module Interface Only. Any sort of DTM -// can be connected outside. DMI Clock and Reset must be provided. - -trait PeripheryDMI extends HasTopLevelNetworks { - val module: PeripheryDMIModule - val coreplex: CoreplexRISCVPlatform +/** Either adds a JTAG DTM to system, and exports a JTAG interface, + * or exports the Debug Module Interface (DMI), based on a global parameter. + */ +trait HasPeripheryDebug extends HasSystemNetworks with HasCoreplexRISCVPlatform { + val module: HasPeripheryDebugModuleImp } -trait PeripheryDMIBundle extends HasTopLevelNetworksBundle { - val outer: PeripheryDMI - - val debug = new ClockedDMIIO().flip +trait HasPeripheryDebugBundle extends HasPeripheryParameters { + val debug: DebugIO + def connectDebug(c: Clock, r: Bool, out: Bool) { + debug.clockeddmi.foreach { d => + val dtm = Module(new SimDTM).connect(c, r, d, out) + } + debug.systemjtag.foreach { sj => + val jtag = Module(new JTAGVPI).connect(sj.jtag, sj.reset, r, out) + sj.mfr_id := p(JtagDTMKey).idcodeManufId.U(11.W) + } + } } -trait PeripheryDMIModule extends HasTopLevelNetworksModule { - val outer: PeripheryDMI - val io: PeripheryDMIBundle +trait HasPeripheryDebugModuleImp extends LazyMultiIOModuleImp with HasPeripheryDebugBundle { + val outer: HasPeripheryDebug - outer.coreplex.module.io.debug <> io.debug -} + val debug = IO(new DebugIO) -// System with DMI or JTAG interface based on a parameter + debug.clockeddmi.foreach { dbg => outer.coreplex.module.io.debug <> dbg } -trait PeripheryDebug extends HasTopLevelNetworks { - val module: PeripheryDebugModule - val coreplex: CoreplexRISCVPlatform -} + val dtm = debug.systemjtag.map { sj => + val dtm = Module(new DebugTransportModuleJTAG(p(DMKey).nDMIAddrSize, p(JtagDTMKey))) + dtm.io.jtag <> sj.jtag -trait PeripheryDebugBundle extends HasTopLevelNetworksBundle { - val outer: PeripheryDebug - - val debug = (!p(IncludeJtagDTM)).option(new ClockedDMIIO().flip) - - val jtag = (p(IncludeJtagDTM)).option(new JTAGIO(hasTRSTn = false).flip) - val jtag_reset = (p(IncludeJtagDTM)).option(Bool(INPUT)) - val jtag_mfr_id = (p(IncludeJtagDTM)).option(UInt(INPUT, 11)) - - val ndreset = Bool(OUTPUT) - val dmactive = Bool(OUTPUT) -} - -trait PeripheryDebugModule extends HasTopLevelNetworksModule { - val outer: PeripheryDebug - val io: PeripheryDebugBundle - - io.debug.foreach { dbg => outer.coreplex.module.io.debug <> dbg } - - val dtm = if (io.jtag.isDefined) Some[DebugTransportModuleJTAG](Module (new DebugTransportModuleJTAG(p(DMKey).nDMIAddrSize, p(JtagDTMKey)))) else None - dtm.foreach { dtm => - dtm.io.jtag <> io.jtag.get - - dtm.clock := io.jtag.get.TCK - dtm.io.jtag_reset := io.jtag_reset.get - dtm.io.jtag_mfr_id := io.jtag_mfr_id.get + dtm.clock := sj.jtag.TCK + dtm.io.jtag_reset := sj.reset + dtm.io.jtag_mfr_id := sj.mfr_id dtm.reset := dtm.io.fsmReset outer.coreplex.module.io.debug.dmi <> dtm.io.dmi - outer.coreplex.module.io.debug.dmiClock := io.jtag.get.TCK - outer.coreplex.module.io.debug.dmiReset := ResetCatchAndSync(io.jtag.get.TCK, io.jtag_reset.get, "dmiResetCatch") + outer.coreplex.module.io.debug.dmiClock := sj.jtag.TCK + outer.coreplex.module.io.debug.dmiReset := ResetCatchAndSync(sj.jtag.TCK, sj.reset, "dmiResetCatch") + dtm } - io.ndreset := outer.coreplex.module.io.ndreset - io.dmactive := outer.coreplex.module.io.dmactive - + debug.ndreset := outer.coreplex.module.io.ndreset + debug.dmactive := outer.coreplex.module.io.dmactive } -/// Real-time clock is based on RTCPeriod relative to Top clock - -trait PeripheryCounter extends HasTopLevelNetworks { - val module: PeripheryCounterModule - val coreplex: CoreplexRISCVPlatform +/** Real-time clock is based on RTCPeriod relative to system clock. + * Note: nothing about this is diplomatic, all the work is done in the ModuleImp + */ +trait HasPeripheryRTCCounter extends HasSystemNetworks with HasCoreplexRISCVPlatform { + val module: HasPeripheryRTCCounterModuleImp } -trait PeripheryCounterBundle extends HasTopLevelNetworksBundle { - val outer: PeripheryCounter +trait HasPeripheryRTCCounterModuleImp extends LazyMultiIOModuleImp { + val outer: HasPeripheryRTCCounter + val period = p(rocketchip.RTCPeriod) + val rtcCounter = RegInit(UInt(0, width = log2Up(period))) + val rtcWrap = rtcCounter === UInt(period-1) + + rtcCounter := Mux(rtcWrap, UInt(0), rtcCounter + UInt(1)) + outer.coreplex.module.io.rtcToggle := rtcCounter(log2Up(period)-1) } -trait PeripheryCounterModule extends HasTopLevelNetworksModule { - val outer: PeripheryCounter - val io: PeripheryCounterBundle - - { - val period = p(rocketchip.RTCPeriod) - val rtcCounter = RegInit(UInt(0, width = log2Up(period))) - val rtcWrap = rtcCounter === UInt(period-1) - rtcCounter := Mux(rtcWrap, UInt(0), rtcCounter + UInt(1)) +/** Adds a boot ROM that contains the DTB describing the system's coreplex. */ +trait HasPeripheryBootROM extends HasSystemNetworks with HasCoreplexRISCVPlatform { + val bootrom_address = 0x10000 + val bootrom_size = 0x10000 + val bootrom_hang = 0x10040 + private lazy val bootrom_contents = GenerateBootROM(coreplex.dtb) + val bootrom = LazyModule(new TLROM(bootrom_address, bootrom_size, bootrom_contents, true, peripheryBusConfig.beatBytes)) - outer.coreplex.module.io.rtcToggle := rtcCounter(log2Up(period)-1) - } + bootrom.node := TLFragmenter(peripheryBusConfig.beatBytes, cacheBlockBytes)(peripheryBus.node) } -/// Coreplex will power-on running at 0x1000 (BootROM) - -trait HardwiredResetVector extends HasTopLevelNetworks { - val module: HardwiredResetVectorModule - val coreplex: CoreplexRISCVPlatform -} - -trait HardwiredResetVectorBundle extends HasTopLevelNetworksBundle { - val outer: HardwiredResetVector -} - -trait HardwiredResetVectorModule extends HasTopLevelNetworksModule { - val outer: HardwiredResetVector - val io: HardwiredResetVectorBundle - - outer.coreplex.module.io.resetVector := UInt(0x10040) // boot ROM: hang +/** Coreplex will power-on running at 0x10040 (BootROM) */ +trait HasPeripheryBootROMModuleImp extends LazyMultiIOModuleImp { + val outer: HasPeripheryBootROM + outer.coreplex.module.io.resetVector := UInt(outer.bootrom_hang) } diff --git a/src/main/scala/rocketchip/RocketPlexMaster.scala b/src/main/scala/rocketchip/RocketPlexMaster.scala index 54731d56..6af16081 100644 --- a/src/main/scala/rocketchip/RocketPlexMaster.scala +++ b/src/main/scala/rocketchip/RocketPlexMaster.scala @@ -4,10 +4,11 @@ package rocketchip import Chisel._ import coreplex.RocketPlex -import diplomacy.LazyModule +import diplomacy.{LazyModule, LazyMultiIOModuleImp} -trait RocketPlexMaster extends HasTopLevelNetworks { - val module: RocketPlexMasterModule +/** Add a RocketPlex to the system */ +trait HasRocketPlexMaster extends HasSystemNetworks with HasCoreplexRISCVPlatform { + val module: HasRocketPlexMasterModuleImp val coreplex = LazyModule(new RocketPlex) @@ -20,15 +21,9 @@ trait RocketPlexMaster extends HasTopLevelNetworks { (mem zip coreplex.mem) foreach { case (xbar, channel) => xbar.node :=* channel } } -trait RocketPlexMasterBundle extends HasTopLevelNetworksBundle { - val outer: RocketPlexMaster -} -trait RocketPlexMasterModule extends HasTopLevelNetworksModule { - val outer: RocketPlexMaster - val io: RocketPlexMasterBundle - val clock: Clock - val reset: Bool +trait HasRocketPlexMasterModuleImp extends LazyMultiIOModuleImp { + val outer: HasRocketPlexMaster outer.coreplex.module.io.tcrs.foreach { case tcr => tcr.clock := clock diff --git a/src/main/scala/rocketchip/System.scala b/src/main/scala/rocketchip/System.scala new file mode 100644 index 00000000..2486f763 --- /dev/null +++ b/src/main/scala/rocketchip/System.scala @@ -0,0 +1,24 @@ +// See LICENSE.SiFive for license details. + +package rocketchip + +import Chisel._ +import config.Parameters +import diplomacy._ +import util._ + +/** BareSystem is the root class for creating a top-level RTL module */ +abstract class BareSystem(implicit p: Parameters) extends LazyModule { + ElaborationArtefacts.add("graphml", graphML) +} + +abstract class BareSystemModule[+L <: BareSystem](_outer: L) extends LazyMultiIOModuleImp(_outer) { + val outer = _outer +} + +/** Base System class with no peripheral devices or ports added */ +abstract class BaseSystem(implicit p: Parameters) extends BareSystem with HasSystemNetworks { + override val module: BaseSystemModule[BaseSystem] +} + +abstract class BaseSystemModule[+L <: BaseSystem](_outer: L) extends BareSystemModule(_outer) diff --git a/src/main/scala/rocketchip/TestHarness.scala b/src/main/scala/rocketchip/TestHarness.scala index 4fda21f1..751e6359 100644 --- a/src/main/scala/rocketchip/TestHarness.scala +++ b/src/main/scala/rocketchip/TestHarness.scala @@ -16,30 +16,13 @@ class TestHarness()(implicit p: Parameters) extends Module { } val dut = Module(LazyModule(new ExampleRocketTop).module) - dut.reset := reset | dut.io.ndreset + dut.reset := reset | dut.debug.ndreset - - dut.io.interrupts := UInt(0) - - val channels = p(coreplex.BankedL2Config).nMemoryChannels - if (channels > 0) Module(LazyModule(new SimAXIMem(channels)).module).io.axi4 <> dut.io.mem_axi4 - - if (!p(IncludeJtagDTM)) { - val dtm = Module(new SimDTM).connect(clock, reset, dut.io.debug.get, io.success) - } else { - val jtag = Module(new JTAGVPI).connect(dut.io.jtag.get, dut.io.jtag_reset.get, reset, io.success) - dut.io.jtag_mfr_id.get := p(JtagDTMKey).idcodeManufId.U(11.W) - } - - val mmio_sim = Module(LazyModule(new SimAXIMem(1, 4096)).module) - mmio_sim.io.axi4 <> dut.io.mmio_axi4 - - val l2_axi4 = dut.io.l2_frontend_bus_axi4(0) - l2_axi4.ar.valid := Bool(false) - l2_axi4.aw.valid := Bool(false) - l2_axi4.w .valid := Bool(false) - l2_axi4.r .ready := Bool(true) - l2_axi4.b .ready := Bool(true) + dut.tieOffInterrupts() + dut.connectSimAXIMem() + dut.connectSimAXIMMIO() + dut.tieOffAXI4SlavePort() + dut.connectDebug(clock, reset, io.success) } class SimAXIMem(channels: Int, forceSize: BigInt = 0)(implicit p: Parameters) extends LazyModule {