1
0

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.
This commit is contained in:
Henry Cook 2017-06-01 16:06:36 -07:00
parent 2e8a40a23f
commit 9bbde9767c
9 changed files with 303 additions and 505 deletions

View File

@ -9,13 +9,8 @@ import rocketchip._
import util._ import util._
class TestHarness(implicit p: Parameters) extends Module { class TestHarness(implicit p: Parameters) extends Module {
val io = new Bundle { val io = new Bundle { val success = Bool(OUTPUT) }
val success = Bool(OUTPUT)
}
val dut = Module(LazyModule(new GroundTestTop).module) val dut = Module(LazyModule(new GroundTestTop).module)
io.success := dut.io.success io.success := dut.io_success
dut.connectSimAXIMem()
val channels = p(coreplex.BankedL2Config).nMemoryChannels
if (channels > 0) Module(LazyModule(new SimAXIMem(channels)).module).io.axi4 <> dut.io.mem_axi4
} }

View File

@ -3,15 +3,14 @@
package groundtest package groundtest
import Chisel._ import Chisel._
import config._ import config.Parameters
import diplomacy._ import diplomacy.LazyModule
import coreplex._
import rocketchip._ import rocketchip._
class GroundTestTop(implicit p: Parameters) extends BaseTop class GroundTestTop(implicit p: Parameters) extends BaseSystem
with PeripheryMasterAXI4Mem with HasPeripheryMasterAXI4MemPort
with PeripheryTestRAM { with HasPeripheryTestRAMSlave {
override lazy val module = new GroundTestTopModule(this, () => new GroundTestTopBundle(this)) override lazy val module = new GroundTestTopModule(this)
val coreplex = LazyModule(new GroundTestCoreplex) 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 } (mem zip coreplex.mem) foreach { case (xbar, channel) => xbar.node :=* channel }
} }
class GroundTestTopBundle[+L <: GroundTestTop](_outer: L) extends BaseTopBundle(_outer) class GroundTestTopModule[+L <: GroundTestTop](_outer: L) extends BaseSystemModule(_outer)
with PeripheryMasterAXI4MemBundle with HasPeripheryMasterAXI4MemPortModuleImp {
with PeripheryTestRAMBundle { val io_success = IO(Bool(OUTPUT))
val success = Bool(OUTPUT) io_success := outer.coreplex.module.io.success
}
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
} }

View File

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

View File

@ -7,52 +7,34 @@ import config._
import junctions._ import junctions._
import rocketchip._ import rocketchip._
/** Example Top with Periphery (w/o coreplex) */ /** Example system with periphery devices (w/o coreplex) */
abstract class ExampleTop(implicit p: Parameters) extends BaseTop abstract class ExampleSystem(implicit p: Parameters) extends BaseSystem
with PeripheryAsyncExtInterrupts with HasPeripheryAsyncExtInterrupts
with PeripheryErrorSlave with HasPeripheryMasterAXI4MemPort
with PeripheryMasterAXI4Mem with HasPeripheryMasterAXI4MMIOPort
with PeripheryMasterAXI4MMIO with HasPeripherySlaveAXI4Port
with PeripherySlaveAXI4 { with HasPeripheryErrorSlave
override lazy val module = new ExampleTopModule(this, () => new ExampleTopBundle(this)) with HasPeripheryZeroSlave {
override lazy val module = new ExampleSystemModule(this)
} }
class ExampleTopBundle[+L <: ExampleTop](_outer: L) extends BaseTopBundle(_outer) class ExampleSystemModule[+L <: ExampleSystem](_outer: L) extends BaseSystemModule(_outer)
with PeripheryExtInterruptsBundle with HasPeripheryExtInterruptsModuleImp
with PeripheryErrorSlaveBundle with HasPeripheryMasterAXI4MemPortModuleImp
with PeripheryMasterAXI4MemBundle with HasPeripheryMasterAXI4MMIOPortModuleImp
with PeripheryMasterAXI4MMIOBundle with HasPeripherySlaveAXI4PortModuleImp
with PeripherySlaveAXI4Bundle
class ExampleTopModule[+L <: ExampleTop, +B <: ExampleTopBundle[L]](_outer: L, _io: () => B) extends BaseTopModule(_outer, _io) /** Example Top with periphery and a Rocket coreplex */
with PeripheryExtInterruptsModule class ExampleRocketTop(implicit p: Parameters) extends ExampleSystem
with PeripheryErrorSlaveModule with HasPeripheryBootROM
with PeripheryMasterAXI4MemModule with HasPeripheryDebug
with PeripheryMasterAXI4MMIOModule with HasPeripheryRTCCounter
with PeripherySlaveAXI4Module with HasRocketPlexMaster {
override lazy val module = new ExampleRocketTopModule(this)
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))
} }
class ExampleRocketTopBundle[+L <: ExampleRocketTop](_outer: L) extends ExampleTopBundle(_outer) class ExampleRocketTopModule[+L <: ExampleRocketTop](_outer: L) extends ExampleSystemModule(_outer)
with PeripheryBootROMBundle with HasPeripheryBootROMModuleImp
with PeripheryZeroBundle with HasPeripheryDebugModuleImp
with PeripheryDebugBundle with HasPeripheryRTCCounterModuleImp
with PeripheryCounterBundle with HasRocketPlexMasterModuleImp
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

View File

@ -6,12 +6,8 @@ import Chisel._
import config._ import config._
import coreplex._ import coreplex._
import diplomacy._ import diplomacy._
import tile.XLen
import uncore.tilelink2._ import uncore.tilelink2._
import uncore.axi4._ import uncore.axi4._
import uncore.converters._
import uncore.devices._
import uncore.util._
import util._ import util._
import scala.math.{min,max} import scala.math.{min,max}
@ -47,80 +43,96 @@ trait HasPeripheryParameters {
def cacheBlockBytes = p(CacheBlockBytes) def cacheBlockBytes = p(CacheBlockBytes)
def peripheryBusArithmetic = p(PeripheryBusArithmetic) def peripheryBusArithmetic = p(PeripheryBusArithmetic)
def nMemoryChannels = p(coreplex.BankedL2Config).nMemoryChannels def nMemoryChannels = p(coreplex.BankedL2Config).nMemoryChannels
def nExtInterrupts = p(NExtTopInterrupts)
} }
///// /** HasSystemNetworks provides buses that will serve as attachment points,
abstract trait PeripheryExtInterrupts { * for use in the following child traits that connect individual agents or external ports.
this: HasTopLevelNetworks => */
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 { private val device = new Device with DeviceInterrupts {
def describe(resources: ResourceBindings): Description = { def describe(resources: ResourceBindings): Description = {
Description("soc/offchip-interrupts", describeInterrupts(resources)) Description("soc/offchip-interrupts", describeInterrupts(resources))
} }
} }
val nExtInterrupts = p(NExtTopInterrupts)
val extInterrupts = IntInternalInputNode(IntSourcePortSimple(num = nExtInterrupts, resources = device.int)) val extInterrupts = IntInternalInputNode(IntSourcePortSimple(num = nExtInterrupts, resources = device.int))
} }
trait PeripheryExtInterruptsBundle { /** This trait should be used if the External Interrupts have NOT
this: HasTopLevelNetworksBundle { * already been synchronized to the Periphery (PLIC) Clock.
val outer: PeripheryExtInterrupts */
} => trait HasPeripheryAsyncExtInterrupts extends HasPeripheryExtInterrupts {
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 =>
if (nExtInterrupts > 0) { if (nExtInterrupts > 0) {
val extInterruptXing = LazyModule(new IntXing) val extInterruptXing = LazyModule(new IntXing)
intBus.intnode := extInterruptXing.intnode intBus.intnode := extInterruptXing.intnode
extInterruptXing.intnode := extInterrupts extInterruptXing.intnode := extInterrupts
} }
} }
// This trait can be used if the External Interrupts have already been synchronized /** This trait can be used if the External Interrupts have already been synchronized
// to the Periphery (PLIC) Clock. * to the Periphery (PLIC) Clock.
*/
trait PeripherySyncExtInterrupts extends PeripheryExtInterrupts { trait HasPeripherySyncExtInterrupts extends HasPeripheryExtInterrupts {
this: HasTopLevelNetworks =>
if (nExtInterrupts > 0) { if (nExtInterrupts > 0) {
intBus.intnode := extInterrupts 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 { outer.extInterrupts.bundleIn.flatten.zipWithIndex.foreach { case(o, i) => o := interrupts(i) }
this: HasTopLevelNetworks => }
val module: PeripheryMasterAXI4MemModule
///// 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 config = p(ExtMem)
private val channels = p(BankedL2Config).nMemoryChannels private val channels = p(BankedL2Config).nMemoryChannels
private val lineBytes = p(CacheBlockBytes) private val blockBytes = p(CacheBlockBytes)
private val device = new MemoryDevice private val device = new MemoryDevice
val mem_axi4 = AXI4BlindOutputNode(Seq.tabulate(channels) { channel => val mem_axi4 = AXI4BlindOutputNode(Seq.tabulate(channels) { channel =>
val base = AddressSet(config.base, config.size-1) 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( AXI4SlavePortParameters(
slaves = Seq(AXI4SlaveParameters( slaves = Seq(AXI4SlaveParameters(
@ -148,56 +160,22 @@ trait PeripheryMasterAXI4Mem {
} }
} }
trait PeripheryMasterAXI4MemBundle { /** Common io name and methods for propagating or tying off the port bundle */
this: HasTopLevelNetworksBundle { trait HasPeripheryMasterAXI4MemPortBundle extends HasPeripheryParameters {
val outer: PeripheryMasterAXI4Mem val mem_axi4: HeterogeneousBag[AXI4Bundle]
} => def connectSimAXIMem(dummy: Int = 1) = {
val mem_axi4 = outer.mem_axi4.bundleOut if (nMemoryChannels > 0) Module(LazyModule(new SimAXIMem(nMemoryChannels)).module).io.axi4 <> mem_axi4
}
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
} }
} }
trait PeripheryZeroBundle { /** Actually generates the corresponding IO in the concrete Module */
this: HasTopLevelNetworksBundle { trait HasPeripheryMasterAXI4MemPortModuleImp extends LazyMultiIOModuleImp with HasPeripheryMasterAXI4MemPortBundle {
val outer: PeripheryZero val outer: HasPeripheryMasterAXI4MemPort
} => val mem_axi4 = IO(outer.mem_axi4.bundleOut)
} }
trait PeripheryZeroModule { /** Adds a AXI4 port to the system intended to master an MMIO device bus */
this: HasTopLevelNetworksModule { trait HasPeripheryMasterAXI4MMIOPort extends HasSystemNetworks {
val outer: PeripheryZero
val io: PeripheryZeroBundle
} =>
}
/////
// PeripheryMasterAXI4MMIO is an example, make your own cake pattern like this one.
trait PeripheryMasterAXI4MMIO {
this: HasTopLevelNetworks =>
private val config = p(ExtBus) private val config = p(ExtBus)
private val device = new SimpleDevice("mmio", Nil) private val device = new SimpleDevice("mmio", Nil)
val mmio_axi4 = AXI4BlindOutputNode(Seq(AXI4SlavePortParameters( val mmio_axi4 = AXI4BlindOutputNode(Seq(AXI4SlavePortParameters(
@ -219,25 +197,22 @@ trait PeripheryMasterAXI4MMIO {
socBus.node)))))) socBus.node))))))
} }
trait PeripheryMasterAXI4MMIOBundle { /** Common io name and methods for propagating or tying off the port bundle */
this: HasTopLevelNetworksBundle { trait HasPeripheryMasterAXI4MMIOPortBundle extends HasPeripheryParameters {
val outer: PeripheryMasterAXI4MMIO val mmio_axi4: HeterogeneousBag[AXI4Bundle]
} => def connectSimAXIMMIO(dummy: Int = 1) {
val mmio_axi4 = outer.mmio_axi4.bundleOut Module(LazyModule(new SimAXIMem(1, 4096)).module).io.axi4 <> mmio_axi4
}
} }
trait PeripheryMasterAXI4MMIOModule { /** Actually generates the corresponding IO in the concrete Module */
this: HasTopLevelNetworksModule { trait HasPeripheryMasterAXI4MMIOPortModuleImp extends LazyMultiIOModuleImp with HasPeripheryMasterAXI4MMIOPortBundle {
val outer: PeripheryMasterAXI4MMIO val outer: HasPeripheryMasterAXI4MMIOPort
val io: PeripheryMasterAXI4MMIOBundle val mmio_axi4 = IO(outer.mmio_axi4.bundleOut)
} =>
// nothing to do
} }
///// /** Adds an AXI4 port to the system intended to be a slave on an MMIO device bus */
trait HasPeripherySlaveAXI4Port extends HasSystemNetworks {
// PeripherySlaveAXI4 is an example, make your own cake pattern like this one.
trait PeripherySlaveAXI4 extends HasTopLevelNetworks {
private val config = p(ExtIn) private val config = p(ExtIn)
val l2FrontendAXI4Node = AXI4BlindInputNode(Seq(AXI4MasterPortParameters( val l2FrontendAXI4Node = AXI4BlindInputNode(Seq(AXI4MasterPortParameters(
masters = Seq(AXI4MasterParameters( masters = Seq(AXI4MasterParameters(
@ -254,23 +229,28 @@ trait PeripherySlaveAXI4 extends HasTopLevelNetworks {
l2FrontendAXI4Node))))) l2FrontendAXI4Node)))))
} }
trait PeripherySlaveAXI4Bundle extends HasTopLevelNetworksBundle { /** Common io name and methods for propagating or tying off the port bundle */
val outer: PeripherySlaveAXI4 trait HasPeripherySlaveAXI4PortBundle extends HasPeripheryParameters {
val l2_frontend_bus_axi4 = outer.l2FrontendAXI4Node.bundleIn 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 { /** Actually generates the corresponding IO in the concrete Module */
val outer: PeripherySlaveAXI4 trait HasPeripherySlaveAXI4PortModuleImp extends LazyMultiIOModuleImp with HasPeripherySlaveAXI4PortBundle {
val io: PeripherySlaveAXI4Bundle val outer: HasPeripherySlaveAXI4Port
// nothing to do val l2_frontend_bus_axi4 = IO(outer.l2FrontendAXI4Node.bundleIn)
} }
///// /** Adds a TileLink port to the system intended to master an MMIO device bus */
trait HasPeripheryMasterTLMMIOPort extends HasSystemNetworks {
// Add an external TL-UL slave
trait PeripheryMasterTLMMIO {
this: HasTopLevelNetworks =>
private val config = p(ExtBus) private val config = p(ExtBus)
private val device = new SimpleDevice("mmio", Nil) private val device = new SimpleDevice("mmio", Nil)
val mmio_tl = TLBlindOutputNode(Seq(TLManagerPortParameters( val mmio_tl = TLBlindOutputNode(Seq(TLManagerPortParameters(
@ -290,25 +270,30 @@ trait PeripheryMasterTLMMIO {
socBus.node))) socBus.node)))
} }
trait PeripheryMasterTLMMIOBundle { /** Common io name and methods for propagating or tying off the port bundle */
this: HasTopLevelNetworksBundle { trait HasPeripheryMasterTLMMIOPortBundle extends HasPeripheryParameters {
val outer: PeripheryMasterTLMMIO val mmio_tl: HeterogeneousBag[TLBundle]
} => def tieOffTLMMIO(dummy: Int = 1) {
val mmio_tl = outer.mmio_tl.bundleOut 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 { /** Actually generates the corresponding IO in the concrete Module */
this: HasTopLevelNetworksModule { trait HasPeripheryMasterTLMMIOPortModuleImp extends LazyMultiIOModuleImp with HasPeripheryMasterTLMMIOPortBundle {
val outer: PeripheryMasterTLMMIO val outer: HasPeripheryMasterTLMMIOPort
val io: PeripheryMasterTLMMIOBundle val mmio_tl = IO(outer.mmio_tl.bundleOut)
} =>
// nothing to do
} }
///// /** 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.
// NOTE: this port is NOT allowed to issue Acquires */
trait PeripherySlaveTL extends HasTopLevelNetworks { trait HasPeripherySlaveTLPort extends HasSystemNetworks {
private val config = p(ExtIn) private val config = p(ExtIn)
val l2FrontendTLNode = TLBlindInputNode(Seq(TLClientPortParameters( val l2FrontendTLNode = TLBlindInputNode(Seq(TLClientPortParameters(
clients = Seq(TLClientParameters( clients = Seq(TLClientParameters(
@ -321,105 +306,58 @@ trait PeripherySlaveTL extends HasTopLevelNetworks {
l2FrontendTLNode)) l2FrontendTLNode))
} }
trait PeripherySlaveTLBundle extends HasTopLevelNetworksBundle { /** Common io name and methods for propagating or tying off the port bundle */
val outer: PeripherySlaveTL trait HasPeripherySlaveTLPortBundle extends HasPeripheryParameters {
val l2_frontend_bus_tl = outer.l2FrontendTLNode.bundleIn 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 { /** Actually generates the corresponding IO in the concrete Module */
val outer: PeripherySlaveTL trait HasPeripherySlaveTLPortModuleImp extends LazyMultiIOModuleImp with HasPeripherySlaveTLPortBundle {
val io: PeripherySlaveTLBundle val outer: HasPeripherySlaveTLPort
// nothing to do val l2_frontend_bus_tl = IO(outer.l2FrontendTLNode.bundleIn)
} }
///// ///// The following traits add specific devices to the periphery of the system.
trait PeripheryBootROM { /** Adds a /dev/null slave that generates */
this: HasTopLevelNetworks => trait HasPeripheryZeroSlave extends HasSystemNetworks {
val coreplex: CoreplexRISCVPlatform private val config = p(ZeroConfig)
private val address = AddressSet(config.base, config.size-1)
private val blockBytes = p(CacheBlockBytes)
private val bootrom_address = 0x10000 val zeros = mem map { case xbar =>
private val bootrom_size = 0x10000 val zero = LazyModule(new TLZero(address, beatBytes = config.beatBytes))
private lazy val bootrom_contents = GenerateBootROM(coreplex.dtb) zero.node := TLFragmenter(config.beatBytes, blockBytes)(xbar.node)
val bootrom = LazyModule(new TLROM(bootrom_address, bootrom_size, bootrom_contents, true, peripheryBusConfig.beatBytes)) zero
bootrom.node := TLFragmenter(peripheryBusConfig.beatBytes, cacheBlockBytes)(peripheryBus.node) }
} }
trait PeripheryBootROMBundle { /** Adds a /dev/null slave that generates TL2 error response messages. */
this: HasTopLevelNetworksBundle { trait HasPeripheryErrorSlave extends HasSystemNetworks {
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 =>
private val config = p(ErrorConfig) private val config = p(ErrorConfig)
private val maxXfer = min(config.address.map(_.alignment).max.toInt, 4096) private val maxXfer = min(config.address.map(_.alignment).max.toInt, 4096)
val error = LazyModule(new TLError(config.address, peripheryBusConfig.beatBytes)) val error = LazyModule(new TLError(config.address, peripheryBusConfig.beatBytes))
error.node := TLFragmenter(peripheryBusConfig.beatBytes, maxXfer)(peripheryBus.node) error.node := TLFragmenter(peripheryBusConfig.beatBytes, maxXfer)(peripheryBus.node)
} }
trait PeripheryErrorSlaveBundle {
this: HasTopLevelNetworksBundle { /** Adds a SRAM to the system for testing purposes. */
val outer: PeripheryErrorSlave 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 { /** Adds a fuzzing master to the system for testing purposes. */
this: HasTopLevelNetworksModule { trait HasPeripheryTestFuzzMaster extends HasSystemNetworks {
val outer: PeripheryErrorSlave val fuzzer = LazyModule(new TLFuzzer(5000))
val io: PeripheryErrorSlaveBundle peripheryBus.node := fuzzer.node
} =>
} }

View File

@ -4,153 +4,112 @@ package rocketchip
import Chisel._ import Chisel._
import config._ import config._
import coreplex._
import diplomacy._ import diplomacy._
import jtag.JTAGIO
import uncore.tilelink2._ import uncore.tilelink2._
import uncore.devices._ import uncore.devices._
import util._ import util._
import jtag.JTAGIO
import coreplex._
// System with JTAG DTM Instantiated inside. JTAG interface is /** All the traits defined in this file assume that they are being mixed in
// exported outside. * to a system that has a standard RISCV-based coreplex platform.
*/
trait PeripheryJTAGDTM extends HasTopLevelNetworks { trait HasCoreplexRISCVPlatform {
val module: PeripheryJTAGDTMModule implicit val p: Parameters
val coreplex: CoreplexRISCVPlatform val coreplex: CoreplexRISCVPlatform
} }
trait PeripheryJTAGDTMBundle extends HasTopLevelNetworksBundle { /** A wrapper around JTAG providing a reset signal and manufacturer id. */
val outer: PeripheryJTAGDTM class SystemJTAGIO extends Bundle {
val jtag = new JTAGIO(hasTRSTn = false).flip val jtag = new JTAGIO(hasTRSTn = false).flip
val jtag_reset = Bool(INPUT) val reset = Bool(INPUT)
val jtag_mfr_id = UInt(INPUT, 11) val mfr_id = UInt(INPUT, 11)
} }
trait PeripheryJTAGDTMModule extends HasTopLevelNetworksModule { /** A wrapper bundle containing one of the two possible debug interfaces */
val outer: PeripheryJTAGDTM class DebugIO(implicit p: Parameters) extends ParameterizedBundle()(p) {
val io: PeripheryJTAGDTMBundle val clockeddmi = (!p(IncludeJtagDTM)).option(new ClockedDMIIO().flip)
val systemjtag = (p(IncludeJtagDTM)).option(new SystemJTAGIO)
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")
}
// 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
}
trait PeripheryDMIBundle extends HasTopLevelNetworksBundle {
val outer: PeripheryDMI
val debug = new ClockedDMIIO().flip
}
trait PeripheryDMIModule extends HasTopLevelNetworksModule {
val outer: PeripheryDMI
val io: PeripheryDMIBundle
outer.coreplex.module.io.debug <> io.debug
}
// System with DMI or JTAG interface based on a parameter
trait PeripheryDebug extends HasTopLevelNetworks {
val module: PeripheryDebugModule
val coreplex: CoreplexRISCVPlatform
}
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 ndreset = Bool(OUTPUT)
val dmactive = Bool(OUTPUT) val dmactive = Bool(OUTPUT)
} }
trait PeripheryDebugModule extends HasTopLevelNetworksModule { /** Either adds a JTAG DTM to system, and exports a JTAG interface,
val outer: PeripheryDebug * or exports the Debug Module Interface (DMI), based on a global parameter.
val io: PeripheryDebugBundle */
trait HasPeripheryDebug extends HasSystemNetworks with HasCoreplexRISCVPlatform {
val module: HasPeripheryDebugModuleImp
}
io.debug.foreach { dbg => outer.coreplex.module.io.debug <> dbg } 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)
}
}
}
val dtm = if (io.jtag.isDefined) Some[DebugTransportModuleJTAG](Module (new DebugTransportModuleJTAG(p(DMKey).nDMIAddrSize, p(JtagDTMKey)))) else None trait HasPeripheryDebugModuleImp extends LazyMultiIOModuleImp with HasPeripheryDebugBundle {
dtm.foreach { dtm => val outer: HasPeripheryDebug
dtm.io.jtag <> io.jtag.get
dtm.clock := io.jtag.get.TCK val debug = IO(new DebugIO)
dtm.io.jtag_reset := io.jtag_reset.get
dtm.io.jtag_mfr_id := io.jtag_mfr_id.get debug.clockeddmi.foreach { dbg => outer.coreplex.module.io.debug <> dbg }
val dtm = debug.systemjtag.map { sj =>
val dtm = Module(new DebugTransportModuleJTAG(p(DMKey).nDMIAddrSize, p(JtagDTMKey)))
dtm.io.jtag <> sj.jtag
dtm.clock := sj.jtag.TCK
dtm.io.jtag_reset := sj.reset
dtm.io.jtag_mfr_id := sj.mfr_id
dtm.reset := dtm.io.fsmReset dtm.reset := dtm.io.fsmReset
outer.coreplex.module.io.debug.dmi <> dtm.io.dmi outer.coreplex.module.io.debug.dmi <> dtm.io.dmi
outer.coreplex.module.io.debug.dmiClock := io.jtag.get.TCK outer.coreplex.module.io.debug.dmiClock := sj.jtag.TCK
outer.coreplex.module.io.debug.dmiReset := ResetCatchAndSync(io.jtag.get.TCK, io.jtag_reset.get, "dmiResetCatch") outer.coreplex.module.io.debug.dmiReset := ResetCatchAndSync(sj.jtag.TCK, sj.reset, "dmiResetCatch")
dtm
} }
io.ndreset := outer.coreplex.module.io.ndreset debug.ndreset := outer.coreplex.module.io.ndreset
io.dmactive := outer.coreplex.module.io.dmactive debug.dmactive := outer.coreplex.module.io.dmactive
} }
/// Real-time clock is based on RTCPeriod relative to Top clock /** 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 PeripheryCounter extends HasTopLevelNetworks { */
val module: PeripheryCounterModule trait HasPeripheryRTCCounter extends HasSystemNetworks with HasCoreplexRISCVPlatform {
val coreplex: CoreplexRISCVPlatform val module: HasPeripheryRTCCounterModuleImp
} }
trait PeripheryCounterBundle extends HasTopLevelNetworksBundle { trait HasPeripheryRTCCounterModuleImp extends LazyMultiIOModuleImp {
val outer: PeripheryCounter val outer: HasPeripheryRTCCounter
}
trait PeripheryCounterModule extends HasTopLevelNetworksModule {
val outer: PeripheryCounter
val io: PeripheryCounterBundle
{
val period = p(rocketchip.RTCPeriod) val period = p(rocketchip.RTCPeriod)
val rtcCounter = RegInit(UInt(0, width = log2Up(period))) val rtcCounter = RegInit(UInt(0, width = log2Up(period)))
val rtcWrap = rtcCounter === UInt(period-1) val rtcWrap = rtcCounter === UInt(period-1)
rtcCounter := Mux(rtcWrap, UInt(0), rtcCounter + UInt(1))
rtcCounter := Mux(rtcWrap, UInt(0), rtcCounter + UInt(1))
outer.coreplex.module.io.rtcToggle := rtcCounter(log2Up(period)-1) outer.coreplex.module.io.rtcToggle := rtcCounter(log2Up(period)-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))
bootrom.node := TLFragmenter(peripheryBusConfig.beatBytes, cacheBlockBytes)(peripheryBus.node)
} }
/// Coreplex will power-on running at 0x1000 (BootROM) /** Coreplex will power-on running at 0x10040 (BootROM) */
trait HasPeripheryBootROMModuleImp extends LazyMultiIOModuleImp {
trait HardwiredResetVector extends HasTopLevelNetworks { val outer: HasPeripheryBootROM
val module: HardwiredResetVectorModule outer.coreplex.module.io.resetVector := UInt(outer.bootrom_hang)
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
} }

View File

@ -4,10 +4,11 @@ package rocketchip
import Chisel._ import Chisel._
import coreplex.RocketPlex import coreplex.RocketPlex
import diplomacy.LazyModule import diplomacy.{LazyModule, LazyMultiIOModuleImp}
trait RocketPlexMaster extends HasTopLevelNetworks { /** Add a RocketPlex to the system */
val module: RocketPlexMasterModule trait HasRocketPlexMaster extends HasSystemNetworks with HasCoreplexRISCVPlatform {
val module: HasRocketPlexMasterModuleImp
val coreplex = LazyModule(new RocketPlex) val coreplex = LazyModule(new RocketPlex)
@ -20,15 +21,9 @@ trait RocketPlexMaster extends HasTopLevelNetworks {
(mem zip coreplex.mem) foreach { case (xbar, channel) => xbar.node :=* channel } (mem zip coreplex.mem) foreach { case (xbar, channel) => xbar.node :=* channel }
} }
trait RocketPlexMasterBundle extends HasTopLevelNetworksBundle {
val outer: RocketPlexMaster
}
trait RocketPlexMasterModule extends HasTopLevelNetworksModule { trait HasRocketPlexMasterModuleImp extends LazyMultiIOModuleImp {
val outer: RocketPlexMaster val outer: HasRocketPlexMaster
val io: RocketPlexMasterBundle
val clock: Clock
val reset: Bool
outer.coreplex.module.io.tcrs.foreach { case tcr => outer.coreplex.module.io.tcrs.foreach { case tcr =>
tcr.clock := clock tcr.clock := clock

View File

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

View File

@ -16,30 +16,13 @@ class TestHarness()(implicit p: Parameters) extends Module {
} }
val dut = Module(LazyModule(new ExampleRocketTop).module) val dut = Module(LazyModule(new ExampleRocketTop).module)
dut.reset := reset | dut.io.ndreset dut.reset := reset | dut.debug.ndreset
dut.tieOffInterrupts()
dut.io.interrupts := UInt(0) dut.connectSimAXIMem()
dut.connectSimAXIMMIO()
val channels = p(coreplex.BankedL2Config).nMemoryChannels dut.tieOffAXI4SlavePort()
if (channels > 0) Module(LazyModule(new SimAXIMem(channels)).module).io.axi4 <> dut.io.mem_axi4 dut.connectDebug(clock, reset, io.success)
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)
} }
class SimAXIMem(channels: Int, forceSize: BigInt = 0)(implicit p: Parameters) extends LazyModule { class SimAXIMem(channels: Int, forceSize: BigInt = 0)(implicit p: Parameters) extends LazyModule {