From 2c000a99da986759232c63c48188b03f319df81e Mon Sep 17 00:00:00 2001 From: Yunsup Lee Date: Thu, 8 Sep 2016 02:08:57 -0700 Subject: [PATCH] compartmentalize Top into periphery traits --- src/main/scala/rocketchip/Configs.scala | 1 - src/main/scala/rocketchip/Periphery.scala | 276 ++++++++++++++++++ src/main/scala/rocketchip/RocketChip.scala | 307 -------------------- src/main/scala/rocketchip/TestHarness.scala | 3 +- src/main/scala/rocketchip/Top.scala | 51 ++++ 5 files changed, 328 insertions(+), 310 deletions(-) create mode 100644 src/main/scala/rocketchip/Periphery.scala delete mode 100644 src/main/scala/rocketchip/RocketChip.scala create mode 100644 src/main/scala/rocketchip/Top.scala diff --git a/src/main/scala/rocketchip/Configs.scala b/src/main/scala/rocketchip/Configs.scala index 68681874..9d8e83d8 100644 --- a/src/main/scala/rocketchip/Configs.scala +++ b/src/main/scala/rocketchip/Configs.scala @@ -165,7 +165,6 @@ class BasePlatformConfig extends Config ( case ConfigString => makeConfigString() case GlobalAddrMap => globalAddrMap case RTCPeriod => 100 // gives 10 MHz RTC assuming 1 GHz uncore clock - case RTCTick => (p: Parameters, t_io: Bundle, p_io:Bundle) => Counter(p(RTCPeriod)).inc() case _ => throw new CDEMatchError }}) diff --git a/src/main/scala/rocketchip/Periphery.scala b/src/main/scala/rocketchip/Periphery.scala new file mode 100644 index 00000000..3e7eab1d --- /dev/null +++ b/src/main/scala/rocketchip/Periphery.scala @@ -0,0 +1,276 @@ +// See LICENSE for license details. + +package rocketchip + +import Chisel._ +import cde.{Parameters, Field} +import junctions._ +import uncore.tilelink._ +import uncore.tilelink2.{LazyModule, LazyModuleImp} +import uncore.converters._ +import uncore.devices._ +import uncore.util._ +import rocket.Util._ +import coreplex._ + +/** Options for memory bus interface */ +object BusType { + sealed trait EnumVal + case object AXI extends EnumVal + case object AHB extends EnumVal + case object TL extends EnumVal + val busTypes = Seq(AXI, AHB, TL) +} + +/** Memory channel controls */ +case object TMemoryChannels extends Field[BusType.EnumVal] +/** External MMIO controls */ +case object NExtMMIOAXIChannels extends Field[Int] +case object NExtMMIOAHBChannels extends Field[Int] +case object NExtMMIOTLChannels extends Field[Int] +/** External Bus controls */ +case object NExtBusAXIChannels extends Field[Int] +/** Async configurations */ +case object AsyncBusChannels extends Field[Boolean] +case object AsyncDebugBus extends Field[Boolean] +case object AsyncMemChannels extends Field[Boolean] +case object AsyncMMIOChannels extends Field[Boolean] +/** External address map settings */ +case object ExtMMIOPorts extends Field[Seq[AddrMapEntry]] +/** Function for building Coreplex */ +case object BuildCoreplex extends Field[Parameters => Coreplex] +/** Function for connecting coreplex extra ports to top-level extra ports */ +case object ConnectExtraPorts extends Field[(Bundle, Bundle, Parameters) => Unit] +/** Specifies the size of external memory */ +case object ExtMemSize extends Field[Long] +/** Specifies the actual sorce of External Interrupts as Top and Periphery. + * NExtInterrupts = NExtTopInterrupts + NExtPeripheryInterrupts + **/ +case object NExtTopInterrupts extends Field[Int] +case object NExtPeripheryInterrupts extends Field[Int] +/** Source of RTC. First bundle is TopIO.extra, Second bundle is periphery.io.extra **/ +case object RTCPeriod extends Field[Int] + +object PeripheryUtils { + def addQueueAXI(source: NastiIO)(implicit p: Parameters) = { + val sink = Wire(new NastiIO) + sink.ar <> Queue(source.ar, 1) + sink.aw <> Queue(source.aw, 1) + sink.w <> Queue(source.w) + source.r <> Queue(sink.r) + source.b <> Queue(sink.b, 1) + sink + } + def convertTLtoAXI(tl: ClientUncachedTileLinkIO)(implicit p: Parameters) = { + val bridge = Module(new NastiIOTileLinkIOConverter()) + bridge.io.tl <> tl + addQueueAXI(bridge.io.nasti) + } + def convertTLtoAHB(tl: ClientUncachedTileLinkIO, atomics: Boolean)(implicit p: Parameters) = { + val bridge = Module(new AHBBridge(atomics)) + bridge.io.tl <> tl + bridge.io.ahb + } +} + +/** Utility trait for quick access to some relevant parameters */ +trait HasPeripheryParameters { + implicit val p: Parameters + lazy val tMemChannels = p(TMemoryChannels) + lazy val nMemChannels = p(NMemoryChannels) + lazy val nMemAXIChannels = if (tMemChannels == BusType.AXI) nMemChannels else 0 + lazy val nMemAHBChannels = if (tMemChannels == BusType.AHB) nMemChannels else 0 + lazy val nMemTLChannels = if (tMemChannels == BusType.TL) nMemChannels else 0 + lazy val innerParams = p.alterPartial({ case TLId => "L1toL2" }) + lazy val innerMMIOParams = p.alterPartial({ case TLId => "L2toMMIO" }) + lazy val outermostParams = p.alterPartial({ case TLId => "Outermost" }) + lazy val outermostMMIOParams = p.alterPartial({ case TLId => "MMIO_Outermost" }) +} + +///// + +trait PeripheryDebug extends LazyModule { + implicit val p: Parameters +} + +trait PeripheryDebugBundle { + implicit val p: Parameters + val debug_clk = (p(AsyncDebugBus) && !p(IncludeJtagDTM)).option(Clock(INPUT)) + val debug_rst = (p(AsyncDebugBus) && !p(IncludeJtagDTM)).option(Bool(INPUT)) + val debug = (!p(IncludeJtagDTM)).option(new DebugBusIO()(p).flip) + val jtag = p(IncludeJtagDTM).option(new JTAGIO(true).flip) +} + +trait PeripheryDebugModule { + implicit val p: Parameters + val outer: PeripheryDebug + val io: PeripheryDebugBundle + val coreplex: Coreplex + + if (p(IncludeJtagDTM)) { + // JtagDTMWithSync is a wrapper which + // handles the synchronization as well. + val dtm = Module (new JtagDTMWithSync()(p)) + dtm.io.jtag <> io.jtag.get + coreplex.io.debug <> dtm.io.debug + } else { + coreplex.io.debug <> + (if (p(AsyncDebugBus)) AsyncDebugBusFrom(io.debug_clk.get, io.debug_rst.get, io.debug.get) + else io.debug.get) + } +} + +///// + +trait PeripheryInterrupt extends LazyModule { + implicit val p: Parameters +} + +trait PeripheryInterruptBundle { + implicit val p: Parameters + val interrupts = Vec(p(NExtTopInterrupts), Bool()).asInput +} + +trait PeripheryInterruptModule { + implicit val p: Parameters + val outer: PeripheryInterrupt + val io: PeripheryInterruptBundle + val coreplex: Coreplex + + val interrupts_periphery = Vec(p(NExtPeripheryInterrupts), Bool()) + var interrupts_cnt = 0 + + // This places the Periphery Interrupts at Bits [0...] + // External interrupts are at the higher Bits. + // This may have some implications for prioritization of the interrupts, + // but PLIC could do some internal swizzling in the future. + coreplex.io.interrupts <> (interrupts_periphery ++ io.interrupts) +} + +///// + +trait PeripheryMasterMem extends LazyModule { + implicit val p: Parameters +} + +trait PeripheryMasterMemBundle extends HasPeripheryParameters { + implicit val p: Parameters + val mem_clk = p(AsyncMemChannels).option(Vec(nMemChannels, Clock(INPUT))) + val mem_rst = p(AsyncMemChannels).option(Vec(nMemChannels, Bool (INPUT))) + val mem_axi = Vec(nMemAXIChannels, new NastiIO) + val mem_ahb = Vec(nMemAHBChannels, new HastiMasterIO) + val mem_tl = Vec(nMemTLChannels, new ClientUncachedTileLinkIO()(outermostParams)) +} + +trait PeripheryMasterMemModule extends HasPeripheryParameters { + implicit val p: Parameters + val outer: PeripheryMasterMem + val io: PeripheryMasterMemBundle + val coreplex: Coreplex + + // Abuse the fact that zip takes the shorter of the two lists + ((io.mem_axi zip coreplex.io.mem) zipWithIndex) foreach { case ((axi, mem), idx) => + val axi_sync = PeripheryUtils.convertTLtoAXI(mem)(outermostParams) + axi_sync.ar.bits.cache := UInt("b0011") + axi_sync.aw.bits.cache := UInt("b0011") + axi <> ( + if (!p(AsyncMemChannels)) axi_sync + else AsyncNastiTo(io.mem_clk.get(idx), io.mem_rst.get(idx), axi_sync) + ) + } + + (io.mem_ahb zip coreplex.io.mem) foreach { case (ahb, mem) => + ahb <> PeripheryUtils.convertTLtoAHB(mem, atomics = false)(outermostParams) + } + + (io.mem_tl zip coreplex.io.mem) foreach { case (tl, mem) => + tl <> ClientUncachedTileLinkEnqueuer(mem, 2)(outermostParams) + } +} + +///// + +trait PeripheryMasterMMIO extends LazyModule { + implicit val p: Parameters +} + +trait PeripheryMasterMMIOBundle extends HasPeripheryParameters { + implicit val p: Parameters + val mmio_clk = p(AsyncMMIOChannels).option(Vec(p(NExtMMIOAXIChannels), Clock(INPUT))) + val mmio_rst = p(AsyncMMIOChannels).option(Vec(p(NExtMMIOAXIChannels), Bool (INPUT))) + val mmio_axi = Vec(p(NExtMMIOAXIChannels), new NastiIO) + val mmio_ahb = Vec(p(NExtMMIOAHBChannels), new HastiMasterIO) + val mmio_tl = Vec(p(NExtMMIOTLChannels), new ClientUncachedTileLinkIO()(outermostMMIOParams)) +} + +trait PeripheryMasterMMIOModule extends HasPeripheryParameters { + implicit val p: Parameters + val outer: PeripheryMasterMMIO + val io: PeripheryMasterMMIOBundle + val mmioNetwork: Option[TileLinkRecursiveInterconnect] + + val mmio_ports = p(ExtMMIOPorts) map { port => + TileLinkWidthAdapter(mmioNetwork.get.port(port.name), "MMIO_Outermost") + } + + val mmio_axi_start = 0 + val mmio_axi_end = mmio_axi_start + p(NExtMMIOAXIChannels) + val mmio_ahb_start = mmio_axi_end + val mmio_ahb_end = mmio_ahb_start + p(NExtMMIOAHBChannels) + val mmio_tl_start = mmio_ahb_end + val mmio_tl_end = mmio_tl_start + p(NExtMMIOTLChannels) + require (mmio_tl_end == mmio_ports.size) + + for (i <- 0 until mmio_ports.size) { + if (mmio_axi_start <= i && i < mmio_axi_end) { + val idx = i-mmio_axi_start + val axi_sync = PeripheryUtils.convertTLtoAXI(mmio_ports(i))(outermostMMIOParams) + io.mmio_axi(idx) <> ( + if (!p(AsyncMMIOChannels)) axi_sync + else AsyncNastiTo(io.mmio_clk.get(idx), io.mmio_rst.get(idx), axi_sync) + ) + } else if (mmio_ahb_start <= i && i < mmio_ahb_end) { + val idx = i-mmio_ahb_start + io.mmio_ahb(idx) <> PeripheryUtils.convertTLtoAHB(mmio_ports(i), atomics = true)(outermostMMIOParams) + } else if (mmio_tl_start <= i && i < mmio_tl_end) { + val idx = i-mmio_tl_start + io.mmio_tl(idx) <> ClientUncachedTileLinkEnqueuer(mmio_ports(i), 2)(outermostMMIOParams) + } else { + require(false, "Unconnected external MMIO port") + } + } +} + +///// + +trait PeripherySlave extends LazyModule { + implicit val p: Parameters +} + +trait PeripherySlaveBundle extends HasPeripheryParameters { + implicit val p: Parameters + val bus_clk = p(AsyncBusChannels).option(Vec(p(NExtBusAXIChannels), Clock(INPUT))) + val bus_rst = p(AsyncBusChannels).option(Vec(p(NExtBusAXIChannels), Bool (INPUT))) + val bus_axi = Vec(p(NExtBusAXIChannels), new NastiIO).flip +} + +trait PeripherySlaveModule extends HasPeripheryParameters { + implicit val p: Parameters + val outer: PeripherySlave + val io: PeripherySlaveBundle + val coreplex: Coreplex + + if (p(NExtBusAXIChannels) > 0) { + val arb = Module(new NastiArbiter(p(NExtBusAXIChannels))) + ((io.bus_axi zip arb.io.master) zipWithIndex) foreach { case ((bus, port), idx) => + port <> ( + if (!p(AsyncBusChannels)) bus + else AsyncNastiFrom(io.bus_clk.get(idx), io.bus_rst.get(idx), bus) + ) + } + val conv = Module(new TileLinkIONastiIOConverter()(innerParams)) + conv.io.nasti <> arb.io.slave + coreplex.io.ext_clients.head <> conv.io.tl + require(p(NExternalClients) == 1, "external devices can't slave ports. wait for tilelink2!") + } +} diff --git a/src/main/scala/rocketchip/RocketChip.scala b/src/main/scala/rocketchip/RocketChip.scala deleted file mode 100644 index 4efb143f..00000000 --- a/src/main/scala/rocketchip/RocketChip.scala +++ /dev/null @@ -1,307 +0,0 @@ -// See LICENSE for license details. - -package rocketchip - -import Chisel._ -import cde.{Parameters, Field} -import junctions._ -import uncore.tilelink._ -import uncore.devices._ -import uncore.util._ -import rocket.Util._ -import uncore.converters._ -import uncore.coherence.{InnerTLId, OuterTLId} -import rocket._ -import coreplex._ -import scala.collection.immutable.HashMap - -/** Top-level parameters of RocketChip, values set in e.g. PublicConfigs.scala */ - -/** Options for memory bus interface */ -object BusType { - sealed trait EnumVal - case object AXI extends EnumVal - case object AHB extends EnumVal - case object TL extends EnumVal - val busTypes = Seq(AXI, AHB, TL) -} - -/** Memory channel controls */ -case object TMemoryChannels extends Field[BusType.EnumVal] -/** External MMIO controls */ -case object NExtMMIOAXIChannels extends Field[Int] -case object NExtMMIOAHBChannels extends Field[Int] -case object NExtMMIOTLChannels extends Field[Int] -/** External Bus controls */ -case object NExtBusAXIChannels extends Field[Int] -/** Async configurations */ -case object AsyncBusChannels extends Field[Boolean] -case object AsyncDebugBus extends Field[Boolean] -case object AsyncMemChannels extends Field[Boolean] -case object AsyncMMIOChannels extends Field[Boolean] -/** External address map settings */ -case object ExtMMIOPorts extends Field[Seq[AddrMapEntry]] -/** Function for building Coreplex */ -case object BuildCoreplex extends Field[Parameters => Coreplex] -/** Function for connecting coreplex extra ports to top-level extra ports */ -case object ConnectExtraPorts extends Field[(Bundle, Bundle, Parameters) => Unit] -/** Specifies the size of external memory */ -case object ExtMemSize extends Field[Long] -/** Specifies the actual sorce of External Interrupts as Top and Periphery. - * NExtInterrupts = NExtTopInterrupts + NExtPeripheryInterrupts - **/ -case object NExtTopInterrupts extends Field[Int] -case object NExtPeripheryInterrupts extends Field[Int] -/** Source of RTC. First bundle is TopIO.extra, Second bundle is periphery.io.extra **/ -case object RTCTick extends Field[(Parameters, Bundle, Bundle) => Bool] -case object RTCPeriod extends Field[Int] - - -/** Utility trait for quick access to some relevant parameters */ -trait HasTopLevelParameters { - implicit val p: Parameters - lazy val tMemChannels = p(TMemoryChannels) - lazy val nMemChannels = p(NMemoryChannels) - lazy val nMemAXIChannels = if (tMemChannels == BusType.AXI) nMemChannels else 0 - lazy val nMemAHBChannels = if (tMemChannels == BusType.AHB) nMemChannels else 0 - lazy val nMemTLChannels = if (tMemChannels == BusType.TL) nMemChannels else 0 - lazy val innerParams = p.alterPartial({ case TLId => "L1toL2" }) - lazy val outermostParams = p.alterPartial({ case TLId => "Outermost" }) - lazy val outermostMMIOParams = p.alterPartial({ case TLId => "MMIO_Outermost" }) - lazy val exportMMIO = p(ExportMMIOPort) -} - -class MemBackupCtrlIO extends Bundle { - val en = Bool(INPUT) - val in_valid = Bool(INPUT) - val out_ready = Bool(INPUT) - val out_valid = Bool(OUTPUT) -} - -/** Top-level io for the chip */ -class BasicTopIO(implicit val p: Parameters) extends ParameterizedBundle()(p) - with HasTopLevelParameters - -class TopIO(implicit p: Parameters) extends BasicTopIO()(p) { - val mem_clk = p(AsyncMemChannels).option(Vec(nMemChannels, Clock(INPUT))) - val mem_rst = p(AsyncMemChannels).option(Vec(nMemChannels, Bool (INPUT))) - val mem_axi = Vec(nMemAXIChannels, new NastiIO) - val mem_ahb = Vec(nMemAHBChannels, new HastiMasterIO) - val mem_tl = Vec(nMemTLChannels, new ClientUncachedTileLinkIO()(outermostParams)) - val interrupts = Vec(p(NExtTopInterrupts), Bool()).asInput - val bus_clk = p(AsyncBusChannels).option(Vec(p(NExtBusAXIChannels), Clock(INPUT))) - val bus_rst = p(AsyncBusChannels).option(Vec(p(NExtBusAXIChannels), Bool (INPUT))) - val bus_axi = Vec(p(NExtBusAXIChannels), new NastiIO).flip - val mmio_clk = p(AsyncMMIOChannels).option(Vec(p(NExtMMIOAXIChannels), Clock(INPUT))) - val mmio_rst = p(AsyncMMIOChannels).option(Vec(p(NExtMMIOAXIChannels), Bool (INPUT))) - val mmio_axi = Vec(p(NExtMMIOAXIChannels), new NastiIO) - val mmio_ahb = Vec(p(NExtMMIOAHBChannels), new HastiMasterIO) - val mmio_tl = Vec(p(NExtMMIOTLChannels), new ClientUncachedTileLinkIO()(outermostMMIOParams)) - val debug_clk = (p(AsyncDebugBus) && !p(IncludeJtagDTM)).option(Clock(INPUT)) - val debug_rst = (p(AsyncDebugBus) && !p(IncludeJtagDTM)).option(Bool(INPUT)) - val debug = (!p(IncludeJtagDTM)).option(new DebugBusIO()(p).flip) - val jtag = p(IncludeJtagDTM).option(new JTAGIO(true).flip) - val extra = p(ExtraTopPorts)(p) -} - -object TopUtils { - // Connect two Nasti interfaces with queues in-between - def connectNasti(outer: NastiIO, inner: NastiIO)(implicit p: Parameters) { - val mifDataBeats = p(MIFDataBeats) - outer.ar <> Queue(inner.ar, 1) - outer.aw <> Queue(inner.aw, 1) - outer.w <> Queue(inner.w) - inner.r <> Queue(outer.r) - inner.b <> Queue(outer.b, 1) - } - def connectTilelinkNasti(nasti: NastiIO, tl: ClientUncachedTileLinkIO)(implicit p: Parameters) = { - val conv = Module(new NastiIOTileLinkIOConverter()) - conv.io.tl <> tl - TopUtils.connectNasti(nasti, conv.io.nasti) - } - def connectTilelinkAhb(ahb: HastiMasterIO, tl: ClientUncachedTileLinkIO)(implicit p: Parameters) = { - val bridge = Module(new AHBBridge(true)) - bridge.io.tl <> tl - bridge.io.ahb - } - def connectTilelink( - outer: ClientUncachedTileLinkIO, inner: ClientUncachedTileLinkIO)(implicit p: Parameters) = { - outer.acquire <> Queue(inner.acquire) - inner.grant <> Queue(outer.grant) - } -} - -/** Top-level module for the chip */ -//TODO: Remove this wrapper once multichannel DRAM controller is provided -class Top(topParams: Parameters) extends Module with HasTopLevelParameters { - implicit val p = topParams - - val coreplex = p(BuildCoreplex)(p) - val periphery = Module(new Periphery()(innerParams)) - - val io = new TopIO { - val success = coreplex.hasSuccessFlag.option(Bool(OUTPUT)) - } - io.success zip coreplex.io.success map { case (x, y) => x := y } - - if (exportMMIO) { periphery.io.mmio_in.get <> coreplex.io.mmio.get } - periphery.io.mem_in <> coreplex.io.mem - coreplex.io.ext_clients <> periphery.io.clients_out - - if (p(IncludeJtagDTM)) { - // JtagDTMWithSync is a wrapper which - // handles the synchronization as well. - val jtag_dtm = Module (new JtagDTMWithSync()(p)) - jtag_dtm.io.jtag <> io.jtag.get - coreplex.io.debug <> jtag_dtm.io.debug - } else { - coreplex.io.debug <> - (if (p(AsyncDebugBus)) - AsyncDebugBusFrom(io.debug_clk.get, io.debug_rst.get, io.debug.get) - else io.debug.get) - } - - def asyncAxiTo(clocks: Seq[Clock], resets: Seq[Bool], inner_axis: Seq[NastiIO]): Seq[NastiIO] = - (clocks, resets, inner_axis).zipped.map { - case (clk, rst, in_axi) => AsyncNastiTo(clk, rst, in_axi) - } - - def asyncAxiFrom(clocks: Seq[Clock], resets: Seq[Bool], outer_axis: Seq[NastiIO]): Seq[NastiIO] = - (clocks, resets, outer_axis).zipped.map { - case (clk, rst, out_axi) => AsyncNastiFrom(clk, rst, out_axi) - } - - io.mmio_axi <> - (if (p(AsyncMMIOChannels)) - asyncAxiTo(io.mmio_clk.get, io.mmio_rst.get, periphery.io.mmio_axi) - else periphery.io.mmio_axi) - io.mmio_ahb <> periphery.io.mmio_ahb - io.mmio_tl <> periphery.io.mmio_tl - - io.mem_axi <> - (if (p(AsyncMemChannels)) - asyncAxiTo(io.mem_clk.get, io.mem_rst.get, periphery.io.mem_axi) - else periphery.io.mem_axi) - io.mem_ahb <> periphery.io.mem_ahb - io.mem_tl <> periphery.io.mem_tl - - periphery.io.bus_axi <> - (if (p(AsyncBusChannels)) - asyncAxiFrom(io.bus_clk.get, io.bus_rst.get, io.bus_axi) - else io.bus_axi) - - // This places the Periphery Interrupts at Bits [0...] - // Top-level interrupts are at the higher Bits. - // This may have some implications for prioritization of the interrupts, - // but PLIC could do some internal swizzling in the future. - coreplex.io.interrupts <> (periphery.io.interrupts ++ io.interrupts) - - io.extra <> periphery.io.extra - - coreplex.io.rtcTick := p(RTCTick)(p, io.extra, periphery.io.extra) - - p(ConnectExtraPorts)(io.extra, coreplex.io.extra, p) - -} - - -class Periphery(implicit val p: Parameters) extends Module - with HasTopLevelParameters { - val io = new Bundle { - val mem_in = Vec(nMemChannels, new ClientUncachedTileLinkIO()(outermostParams)).flip - val clients_out = Vec(p(NExternalClients), new ClientUncachedTileLinkIO()(innerParams)) - val mmio_in = exportMMIO.option(new ClientUncachedTileLinkIO()(outermostMMIOParams).flip) - val mem_axi = Vec(nMemAXIChannels, new NastiIO) - val mem_ahb = Vec(nMemAHBChannels, new HastiMasterIO) - val mem_tl = Vec(nMemTLChannels, new ClientUncachedTileLinkIO()(outermostParams)) - val bus_axi = Vec(p(NExtBusAXIChannels), new NastiIO).flip - val mmio_axi = Vec(p(NExtMMIOAXIChannels), new NastiIO) - val mmio_ahb = Vec(p(NExtMMIOAHBChannels), new HastiMasterIO) - val mmio_tl = Vec(p(NExtMMIOTLChannels), new ClientUncachedTileLinkIO()(outermostMMIOParams)) - val interrupts = Vec(p(NExtPeripheryInterrupts), Bool()).asOutput - val extra = p(ExtraTopPorts)(p) - } - - if (io.bus_axi.size > 0) { - val conv = Module(new TileLinkIONastiIOConverter) - val arb = Module(new NastiArbiter(io.bus_axi.size)) - arb.io.master <> io.bus_axi - conv.io.nasti <> arb.io.slave - io.clients_out.head <> conv.io.tl - } - - def connectExternalMMIO(ports: Seq[ClientUncachedTileLinkIO])(implicit p: Parameters) { - val mmio_axi_start = 0 - val mmio_axi_end = mmio_axi_start + p(NExtMMIOAXIChannels) - val mmio_ahb_start = mmio_axi_end - val mmio_ahb_end = mmio_ahb_start + p(NExtMMIOAHBChannels) - val mmio_tl_start = mmio_ahb_end - val mmio_tl_end = mmio_tl_start + p(NExtMMIOTLChannels) - require (mmio_tl_end == ports.size) - - for (i <- 0 until ports.size) { - if (mmio_axi_start <= i && i < mmio_axi_end) { - TopUtils.connectTilelinkNasti(io.mmio_axi(i-mmio_axi_start), ports(i)) - } else if (mmio_ahb_start <= i && i < mmio_ahb_end) { - val ahbBridge = Module(new AHBBridge(true)) - io.mmio_ahb(i-mmio_ahb_start) <> ahbBridge.io.ahb - ahbBridge.io.tl <> ports(i) - } else if (mmio_tl_start <= i && i < mmio_tl_end) { - TopUtils.connectTilelink(io.mmio_tl(i-mmio_tl_start), ports(i)) - } else { - require(false, "Unconnected external MMIO port") - } - } - } - - def buildMMIONetwork(implicit p: Parameters) = { - val extAddrMap = p(GlobalAddrMap).subMap("io:ext") - - val mmioNetwork = Module(new TileLinkRecursiveInterconnect(1, extAddrMap)) - mmioNetwork.io.in.head <> io.mmio_in.get - - val extraDevices = p(ExtraDevices) - - val deviceMMIO = HashMap.newBuilder[String, ClientUncachedTileLinkIO] - for ((entry, i) <- extraDevices.addrMapEntries.zipWithIndex) - deviceMMIO += (entry.name -> mmioNetwork.port(entry.name)) - - val deviceClients = if (io.bus_axi.size > 0) io.clients_out.tail else io.clients_out - require(deviceClients.size == extraDevices.nClientPorts) - - val buildParams = p.alterPartial({ - case InnerTLId => "L2toMMIO" // Device MMIO port - case OuterTLId => "L1toL2" // Device client port - }) - - extraDevices.builder(deviceMMIO.result(), deviceClients, - io.interrupts, io.extra, buildParams) - - val ext = p(ExtMMIOPorts).map( - port => TileLinkWidthAdapter(mmioNetwork.port(port.name), "MMIO_Outermost")) - connectExternalMMIO(ext)(outermostMMIOParams) - } - - if (exportMMIO) { - buildMMIONetwork(p.alterPartial({case TLId => "L2toMMIO"})) - } - - for ((nasti, tl) <- io.mem_axi zip io.mem_in) { - TopUtils.connectTilelinkNasti(nasti, tl)(outermostParams) - // Memory cache type should be normal non-cacheable bufferable - // TODO why is this happening here? Would 0000 (device) be OK instead? - nasti.ar.bits.cache := UInt("b0011") - nasti.aw.bits.cache := UInt("b0011") - } - - // Abuse the fact that zip takes the shorter of the two lists - for ((ahb, tl) <- io.mem_ahb zip io.mem_in) { - val bridge = Module(new AHBBridge(false)) // no atomics - ahb <> bridge.io.ahb - bridge.io.tl <> tl - } - - for ((mem_tl, tl) <- io.mem_tl zip io.mem_in) { - TopUtils.connectTilelink(mem_tl, tl) - } -} diff --git a/src/main/scala/rocketchip/TestHarness.scala b/src/main/scala/rocketchip/TestHarness.scala index 7d91c3c6..0d014800 100644 --- a/src/main/scala/rocketchip/TestHarness.scala +++ b/src/main/scala/rocketchip/TestHarness.scala @@ -11,7 +11,7 @@ class TestHarness(implicit p: Parameters) extends Module { val io = new Bundle { val success = Bool(OUTPUT) } - val dut = Module(new Top(p)) + val dut = uncore.tilelink2.LazyModule(new ExampleTop(p)).module // This test harness isn't especially flexible yet require(dut.io.mem_clk.isEmpty) @@ -24,7 +24,6 @@ class TestHarness(implicit p: Parameters) extends Module { require(dut.io.mmio_rst.isEmpty) require(dut.io.mmio_ahb.isEmpty) require(dut.io.mmio_tl.isEmpty) - require(dut.io.extra.elements.isEmpty) for (int <- dut.io.interrupts) int := false diff --git a/src/main/scala/rocketchip/Top.scala b/src/main/scala/rocketchip/Top.scala new file mode 100644 index 00000000..28192a5c --- /dev/null +++ b/src/main/scala/rocketchip/Top.scala @@ -0,0 +1,51 @@ +// See LICENSE for license details. + +package rocketchip + +import Chisel._ +import cde.{Parameters} +import junctions._ +import uncore.tilelink._ +import uncore.tilelink2.{LazyModule, LazyModuleImp} +import rocket.Util._ +import coreplex._ + + +/** Base Top with no Periphery */ + +abstract class BaseTop(val p: Parameters) extends LazyModule + +class BaseTopBundle(val p: Parameters, val c: Coreplex) extends ParameterizedBundle()(p) { + val success = c.hasSuccessFlag.option(Bool(OUTPUT)) +} + +class BaseTopModule[L <: BaseTop, B <: BaseTopBundle](val p: Parameters, l: L, b: Coreplex => B) extends LazyModuleImp(l) { + val coreplex = p(BuildCoreplex)(p) + val outer: L = l + val io: B = b(coreplex) + + io.success zip coreplex.io.success map { case (x, y) => x := y } + coreplex.io.rtcTick := Counter(p(RTCPeriod)).inc() + + val mmioNetwork = p(ExportMMIOPort).option( + Module(new TileLinkRecursiveInterconnect(1, p(GlobalAddrMap).subMap("io:ext"))( + p.alterPartial({ case TLId => "L2toMMIO" })))) + mmioNetwork.foreach { _.io.in.head <> coreplex.io.mmio.get } +} + + +/** Example Top with Periphery */ + +class ExampleTop(p: Parameters) extends BaseTop(p) + with PeripheryDebug with PeripheryInterrupt + with PeripheryMasterMem with PeripheryMasterMMIO with PeripherySlave { + lazy val module = Module(new ExampleTopModule(p, this, new ExampleTopBundle(p, _))) +} + +class ExampleTopBundle(p: Parameters, c: Coreplex) extends BaseTopBundle(p, c) + with PeripheryDebugBundle with PeripheryInterruptBundle + with PeripheryMasterMemBundle with PeripheryMasterMMIOBundle with PeripherySlaveBundle + +class ExampleTopModule[L <: ExampleTop, B <: ExampleTopBundle](p: Parameters, l: L, b: Coreplex => B) extends BaseTopModule(p, l, b) + with PeripheryDebugModule with PeripheryInterruptModule + with PeripheryMasterMemModule with PeripheryMasterMMIOModule with PeripherySlaveModule