diff --git a/src/main/scala/rocketchip/Configs.scala b/src/main/scala/rocketchip/Configs.scala index 30aef92e..29437d44 100644 --- a/src/main/scala/rocketchip/Configs.scala +++ b/src/main/scala/rocketchip/Configs.scala @@ -12,6 +12,7 @@ import uncore.converters._ import coreplex._ import scala.math.max import scala.collection.mutable.{LinkedHashSet, ListBuffer} +import scala.collection.immutable.HashMap import DefaultTestSuites._ import cde.{Parameters, Config, Dump, Knob, CDEMatchError} @@ -93,13 +94,7 @@ class BasePlatformConfig extends Config ( res append " };\n" } res append "};\n" - for (device <- site(ExtraDevices)) { - if (device.hasMMIOPort) { - val deviceName = device.addrMapEntry.name - val deviceRegion = addrMap("io:ext:" + deviceName) - res.append(device.makeConfigString(deviceRegion)) - } - } + res append (site(ExtraDevices).makeConfigString(addrMap)) res append '\u0000' res.toString.getBytes } @@ -124,22 +119,19 @@ class BasePlatformConfig extends Config ( case AsyncDebugBus => false case IncludeJtagDTM => false case AsyncMMIOChannels => false - case ExtraDevices => Nil + case ExtraDevices => new EmptyDeviceBlock case ExtraTopPorts => (p: Parameters) => new Bundle case ExtMMIOPorts => Nil case ExtIOAddrMapEntries => - site(ExtraDevices) - .filter(_.hasMMIOPort) - .map(_.addrMapEntry) ++ - site(ExtMMIOPorts) + site(ExtraDevices).addrMapEntries ++ site(ExtMMIOPorts) case NExtMMIOAXIChannels => 0 case NExtMMIOAHBChannels => 0 case NExtMMIOTLChannels => 0 - case ExportMMIOPort => (site(ExtraDevices).filter(_.hasMMIOPort).size + site(ExtMMIOPorts).size) > 0 + case ExportMMIOPort => site(ExtraDevices).addrMapEntries.size > 0 case AsyncBusChannels => false case NExtBusAXIChannels => 0 - case NExternalClients => (if (site(NExtBusAXIChannels) > 1) 1 else 0) + - site(ExtraDevices).filter(_.hasClientPort).size + case NExternalClients => (if (site(NExtBusAXIChannels) > 0) 1 else 0) + + site(ExtraDevices).nClientPorts case ConnectExtraPorts => (out: Bundle, in: Bundle, p: Parameters) => out <> in @@ -262,21 +254,20 @@ class TinyConfig extends Config( class WithTestRAM extends Config( (pname, site, here) => pname match { case ExtraDevices => { - class TestRAMDevice extends Device { + class TestRAMDevice extends DeviceBlock { val ramSize = 0x1000 - def hasClientPort = false - def hasMMIOPort = true + def nClientPorts = 0 + def addrMapEntries = Seq( + AddrMapEntry("testram", MemSize(ramSize, MemAttr(AddrMapProt.RW)))) def builder( - mmioPort: Option[ClientUncachedTileLinkIO], - clientPort: Option[ClientUncachedTileLinkIO], + mmioPorts: HashMap[String, ClientUncachedTileLinkIO], + clientPorts: Seq[ClientUncachedTileLinkIO], extra: Bundle, p: Parameters) { val testram = Module(new TileLinkTestRAM(ramSize)(p)) - testram.io <> mmioPort.get + testram.io <> mmioPorts("testram") } - override def addrMapEntry = - AddrMapEntry("testram", MemSize(ramSize, MemAttr(AddrMapProt.RW))) } - Seq(new TestRAMDevice) + new TestRAMDevice } } ) diff --git a/src/main/scala/rocketchip/Devices.scala b/src/main/scala/rocketchip/Devices.scala index 7a27d198..d79b4ac4 100644 --- a/src/main/scala/rocketchip/Devices.scala +++ b/src/main/scala/rocketchip/Devices.scala @@ -3,45 +3,57 @@ package rocketchip import Chisel._ import junctions._ import uncore.tilelink._ +import scala.collection.immutable.HashMap import cde.{Parameters, Field} case object ExtraTopPorts extends Field[Parameters => Bundle] -case object ExtraDevices extends Field[Seq[Device]] +case object ExtraDevices extends Field[DeviceBlock] + +abstract class DeviceBlock { + /** How many client ports will the devices use */ + def nClientPorts: Int + /** Address map entries for all of the devices */ + def addrMapEntries: Seq[AddrMapEntry] -abstract class Device { - /** Does this device have an MMIO port? */ - def hasMMIOPort: Boolean - /** Does this device have a client port? */ - def hasClientPort: Boolean /** - * This function elaborates the hardware for the device and connects - * it to the mmio port, client port, and extra top-level ports. + * The function that elaborates all the extra devices and connects them + * to the TileLink ports and extra top-level ports. * - * @param mmioPort The port from the MMIO network that goes to this device. - * If hasMMIOPort is false, this will be None - * - * @param clientPort The client port provided for this device to make - * requests to the memory system. If hasClientPort is false, this will be None + * @param mmioPorts A hashmap for the mmio ports. + * Use the names specified in addrMapEntries to get + * the mmio port for each device. + * @param clientPorts All the client ports available for the devices + * @param extra The extra top-level IO bundle + * @param p The CDE parameters for the devices */ def builder( - mmioPort: Option[ClientUncachedTileLinkIO], - clientPort: Option[ClientUncachedTileLinkIO], + mmioPorts: HashMap[String, ClientUncachedTileLinkIO], + clientPorts: Seq[ClientUncachedTileLinkIO], extra: Bundle, p: Parameters): Unit - /** - * The entry that will be placed into the address map for this device. - * If hasMMIOPort is false, you do not need to override this - */ - def addrMapEntry: AddrMapEntry = - throw new UnsupportedOperationException("no addrMapEntry defined") /** * Create the config string entry for this device that goes into the * Boot ROM. You generally won't need to override this + * + * @param fullAddrMap The full global address map */ - def makeConfigString(region: MemRegion): String = { - s"${addrMapEntry.name} {\n" + - s" addr 0x${region.start.toString(16)};\n" + - s" size 0x${region.size.toString(16)}; \n" + - "}\n" + def makeConfigString(fullAddrMap: AddrMap): String = { + addrMapEntries.map { entry => + val region = fullAddrMap("io:ext:" + entry.name) + s"${entry.name} {\n" + + s" addr 0x${region.start.toString(16)};\n" + + s" size 0x${region.size.toString(16)}; \n" + + "}\n" + }.mkString } } + +class EmptyDeviceBlock extends DeviceBlock { + def nClientPorts = 0 + def addrMapEntries = Seq.empty + + def builder( + mmioPorts: HashMap[String, ClientUncachedTileLinkIO], + clientPorts: Seq[ClientUncachedTileLinkIO], + extra: Bundle, p: Parameters) {} +} diff --git a/src/main/scala/rocketchip/RocketChip.scala b/src/main/scala/rocketchip/RocketChip.scala index d22e1609..2ddabbbf 100644 --- a/src/main/scala/rocketchip/RocketChip.scala +++ b/src/main/scala/rocketchip/RocketChip.scala @@ -12,6 +12,7 @@ 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 */ @@ -202,15 +203,12 @@ class Periphery(implicit val p: Parameters) extends Module val extra = p(ExtraTopPorts)(p) } - var client_ind = 0 - 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 <> conv.io.tl + conv.io.nasti <> arb.io.slave io.clients_out.head <> conv.io.tl - client_ind += 1 } def connectExternalMMIO(ports: Seq[ClientUncachedTileLinkIO])(implicit p: Parameters) { @@ -243,22 +241,21 @@ class Periphery(implicit val p: Parameters) extends Module val mmioNetwork = Module(new TileLinkRecursiveInterconnect(1, extAddrMap)) mmioNetwork.io.in.head <> io.mmio_in.get - for (device <- p(ExtraDevices)) { - val mmioPort = if (device.hasMMIOPort) - Some(mmioNetwork.port(device.addrMapEntry.name)) else None + val extraDevices = p(ExtraDevices) - val clientPort = if (device.hasClientPort) { - client_ind += 1 - Some(io.clients_out(client_ind - 1)) - } else None + val deviceMMIO = HashMap.newBuilder[String, ClientUncachedTileLinkIO] + for ((entry, i) <- extraDevices.addrMapEntries.zipWithIndex) + deviceMMIO += (entry.name -> mmioNetwork.port(entry.name)) - val buildParams = p.alterPartial({ - case InnerTLId => "L2toMMIO" // Device MMIO port - case OuterTLId => "L1toL2" // Device client port - }) + val deviceClients = if (io.bus_axi.size > 0) io.clients_out.tail else io.clients_out + require(deviceClients.size == extraDevices.nClientPorts) - device.builder(mmioPort, clientPort, io.extra, buildParams) - } + val buildParams = p.alterPartial({ + case InnerTLId => "L2toMMIO" // Device MMIO port + case OuterTLId => "L1toL2" // Device client port + }) + + extraDevices.builder(deviceMMIO.result(), deviceClients, io.extra, buildParams) val ext = p(ExtMMIOPorts).map( port => TileLinkWidthAdapter(mmioNetwork.port(port.name), "MMIO_Outermost")) diff --git a/src/main/scala/rocketchip/TestConfigs.scala b/src/main/scala/rocketchip/TestConfigs.scala index 34995897..359d9628 100644 --- a/src/main/scala/rocketchip/TestConfigs.scala +++ b/src/main/scala/rocketchip/TestConfigs.scala @@ -11,6 +11,7 @@ import uncore.unittests._ import junctions._ import junctions.unittests._ import scala.collection.mutable.LinkedHashSet +import scala.collection.immutable.HashMap import cde.{Parameters, Config, Dump, Knob, CDEMatchError} import scala.math.max import coreplex._ @@ -183,21 +184,20 @@ class WithBusMasterTest extends Config( case BuildGroundTest => (p: Parameters) => Module(new BusMasterTest()(p)) case ExtraDevices => { - class BusMasterDevice extends Device { - def hasClientPort = true - def hasMMIOPort = true + class BusMasterDevice extends DeviceBlock { + def nClientPorts = 1 + def addrMapEntries = Seq( + AddrMapEntry("busmaster", MemSize(4096, MemAttr(AddrMapProt.RW)))) def builder( - mmioPort: Option[ClientUncachedTileLinkIO], - clientPort: Option[ClientUncachedTileLinkIO], + mmioPorts: HashMap[String, ClientUncachedTileLinkIO], + clientPorts: Seq[ClientUncachedTileLinkIO], extra: Bundle, p: Parameters) { val busmaster = Module(new ExampleBusMaster()(p)) - busmaster.io.mmio <> mmioPort.get - clientPort.get <> busmaster.io.mem + busmaster.io.mmio <> mmioPorts("busmaster") + clientPorts.head <> busmaster.io.mem } - override def addrMapEntry = - AddrMapEntry("busmaster", MemSize(4096, MemAttr(AddrMapProt.RW))) } - Seq(new BusMasterDevice) + new BusMasterDevice } case _ => throw new CDEMatchError }) diff --git a/src/main/scala/rocketchip/TestHarness.scala b/src/main/scala/rocketchip/TestHarness.scala index e51fa03e..6a6bb9b7 100644 --- a/src/main/scala/rocketchip/TestHarness.scala +++ b/src/main/scala/rocketchip/TestHarness.scala @@ -20,10 +20,8 @@ class TestHarness(implicit p: Parameters) extends Module { require(dut.io.mem_tl.isEmpty) require(dut.io.bus_clk.isEmpty) require(dut.io.bus_rst.isEmpty) - require(dut.io.bus_axi.isEmpty) require(dut.io.mmio_clk.isEmpty) require(dut.io.mmio_rst.isEmpty) - require(dut.io.mmio_axi.isEmpty) require(dut.io.mmio_ahb.isEmpty) require(dut.io.mmio_tl.isEmpty) require(dut.io.extra.elements.isEmpty) @@ -79,6 +77,21 @@ class TestHarness(implicit p: Parameters) extends Module { stop(1) } } + + for (bus_axi <- dut.io.bus_axi) { + bus_axi.ar.valid := Bool(false) + bus_axi.aw.valid := Bool(false) + bus_axi.w.valid := Bool(false) + bus_axi.r.ready := Bool(false) + bus_axi.b.ready := Bool(false) + } + + for (mmio_axi <- dut.io.mmio_axi) { + val slave = Module(new NastiErrorSlave) + slave.io <> mmio_axi + } + + } } class SimAXIMem(size: BigInt)(implicit p: Parameters) extends Module {