From f2fe437fa466870cd34499005bb78f368e20d653 Mon Sep 17 00:00:00 2001 From: Jack Koenig Date: Thu, 15 Sep 2016 19:47:18 -0700 Subject: [PATCH 01/26] Use CDEMatchError for improved performance (#304) --- src/main/scala/coreplex/TestConfigs.scala | 1 + src/main/scala/rocketchip/Configs.scala | 7 +++++-- src/main/scala/uncore/Builder.scala | 15 +++++++++------ 3 files changed, 15 insertions(+), 8 deletions(-) diff --git a/src/main/scala/coreplex/TestConfigs.scala b/src/main/scala/coreplex/TestConfigs.scala index b2e7e05c..7b44868e 100644 --- a/src/main/scala/coreplex/TestConfigs.scala +++ b/src/main/scala/coreplex/TestConfigs.scala @@ -146,6 +146,7 @@ class WithTraceGen extends Config( knobValues = { case "L1D_SETS" => 16 case "L1D_WAYS" => 1 + case _ => throw new CDEMatchError }) class WithPCIeMockupTest extends Config( diff --git a/src/main/scala/rocketchip/Configs.scala b/src/main/scala/rocketchip/Configs.scala index 37ad9047..c7c0deb9 100644 --- a/src/main/scala/rocketchip/Configs.scala +++ b/src/main/scala/rocketchip/Configs.scala @@ -152,6 +152,7 @@ class RoccExampleConfig extends Config(new WithRoccExample ++ new BaseConfig) class WithMIFDataBits(n: Int) extends Config( (pname, site, here) => pname match { case MIFDataBits => Dump("MIF_DATA_BITS", n) + case _ => throw new CDEMatchError }) class MIF128BitConfig extends Config( @@ -182,12 +183,14 @@ class TinyConfig extends Config( class WithAsyncDebug extends Config ( (pname, site, here) => pname match { - case AsyncDebugBus => true + case AsyncDebugBus => true + case _ => throw new CDEMatchError } ) class WithJtagDTM extends Config ( (pname, site, here) => pname match { - case IncludeJtagDTM => true + case IncludeJtagDTM => true + case _ => throw new CDEMatchError } ) diff --git a/src/main/scala/uncore/Builder.scala b/src/main/scala/uncore/Builder.scala index b5605082..a75f5688 100644 --- a/src/main/scala/uncore/Builder.scala +++ b/src/main/scala/uncore/Builder.scala @@ -1,7 +1,7 @@ package uncore import Chisel._ -import cde.{Config, Parameters, ParameterDump, Knob, Dump} +import cde.{Config, Parameters, ParameterDump, Knob, Dump, CDEMatchError} import junctions.PAddrBits import uncore.tilelink._ import uncore.agents._ @@ -85,6 +85,7 @@ class DefaultL2Config extends Config ( case ECCCode => None case AmoAluOperandBits => 64 case SplitMetadata => false + case _ => throw new CDEMatchError // case XLen => 128 }}, knobValues = { @@ -93,22 +94,24 @@ class DefaultL2Config extends Config ( case "NTILES" => 2 case "N_CACHED_TILES" => 2 case "L2_CAPACITY_IN_KB" => 256 + case _ => throw new CDEMatchError } ) class WithPLRU extends Config( (pname, site, here) => pname match { case L2Replacer => () => new SeqPLRU(site(NSets), site(NWays)) + case _ => throw new CDEMatchError }) class PLRUL2Config extends Config(new WithPLRU ++ new DefaultL2Config) -class With1L2Ways extends Config(knobValues = { case "L2_WAYS" => 1 }) -class With2L2Ways extends Config(knobValues = { case "L2_WAYS" => 2 }) -class With4L2Ways extends Config(knobValues = { case "L2_WAYS" => 4 }) +class With1L2Ways extends Config(knobValues = { case "L2_WAYS" => 1; case _ => throw new CDEMatchError }) +class With2L2Ways extends Config(knobValues = { case "L2_WAYS" => 2; case _ => throw new CDEMatchError }) +class With4L2Ways extends Config(knobValues = { case "L2_WAYS" => 4; case _ => throw new CDEMatchError }) -class With1Cached extends Config(knobValues = { case "N_CACHED_TILES" => 1 }) -class With2Cached extends Config(knobValues = { case "N_CACHED_TILES" => 2 }) +class With1Cached extends Config(knobValues = { case "N_CACHED_TILES" => 1; case _ => throw new CDEMatchError }) +class With2Cached extends Config(knobValues = { case "N_CACHED_TILES" => 2; case _ => throw new CDEMatchError }) class W1Cached1WaysConfig extends Config(new With1L2Ways ++ new With1Cached ++ new DefaultL2Config) From 9442958d6707856fc18a317eb3b8c9508bd924a5 Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Wed, 14 Sep 2016 18:08:18 -0700 Subject: [PATCH 02/26] tilelink2: allow := on nodes outside the tilelink2 package --- src/main/scala/uncore/tilelink2/Nodes.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/scala/uncore/tilelink2/Nodes.scala b/src/main/scala/uncore/tilelink2/Nodes.scala index 025d137b..a0de1a84 100644 --- a/src/main/scala/uncore/tilelink2/Nodes.scala +++ b/src/main/scala/uncore/tilelink2/Nodes.scala @@ -76,7 +76,7 @@ class BaseNode[PO, PI, EO, EI, B <: Data](imp: NodeImp[PO, PI, EO, EI, B])( def connectOut = bundleOut def connectIn = bundleIn - protected[tilelink2] def := (y: BaseNode[PO, PI, EO, EI, B])(implicit sourceInfo: SourceInfo) = { + def := (y: BaseNode[PO, PI, EO, EI, B])(implicit sourceInfo: SourceInfo) = { val x = this // x := y val info = sourceLine(sourceInfo, " at ", "") require (!LazyModule.stack.isEmpty, s"${y.name} cannot be connected to ${x.name} outside of LazyModule scope" + info) From ddd93871d8042394be9c8deca6502ef9b9602382 Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Wed, 14 Sep 2016 18:08:49 -0700 Subject: [PATCH 03/26] tilelink2: add an executable manager parameter --- src/main/scala/uncore/tilelink2/Parameters.scala | 11 +++++++---- src/main/scala/uncore/tilelink2/SRAM.scala | 1 + 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/main/scala/uncore/tilelink2/Parameters.scala b/src/main/scala/uncore/tilelink2/Parameters.scala index a6891af5..3c93e96b 100644 --- a/src/main/scala/uncore/tilelink2/Parameters.scala +++ b/src/main/scala/uncore/tilelink2/Parameters.scala @@ -63,7 +63,7 @@ case class TransferSizes(min: Int, max: Int) def contains(x: TransferSizes) = x.none || (min <= x.min && x.max <= max) def intersect(x: TransferSizes) = - if (x.max < min || min < x.max) TransferSizes.none + if (x.max < min || max < x.min) TransferSizes.none else TransferSizes(scala.math.max(min, x.min), scala.math.min(max, x.max)) } @@ -101,8 +101,10 @@ case class AddressSet(base: BigInt, mask: BigInt) case class TLManagerParameters( address: Seq[AddressSet], - sinkId: IdRange = IdRange(0, 1), - regionType: RegionType.T = RegionType.GET_EFFECTS, + sinkId: IdRange = IdRange(0, 1), + regionType: RegionType.T = RegionType.GET_EFFECTS, + executable: Boolean = false, // processor can execute from this memory + nodePath: Seq[TLBaseNode] = Seq(), // Supports both Acquire+Release+Finish of these sizes supportsAcquire: TransferSizes = TransferSizes.none, supportsArithmetic: TransferSizes = TransferSizes.none, @@ -207,7 +209,8 @@ case class TLManagerPortParameters(managers: Seq[TLManagerParameters], beatBytes } case class TLClientParameters( - sourceId: IdRange = IdRange(0,1), + sourceId: IdRange = IdRange(0,1), + nodePath: Seq[TLBaseNode] = Seq(), // Supports both Probe+Grant of these sizes supportsProbe: TransferSizes = TransferSizes.none, supportsArithmetic: TransferSizes = TransferSizes.none, diff --git a/src/main/scala/uncore/tilelink2/SRAM.scala b/src/main/scala/uncore/tilelink2/SRAM.scala index 03e7385d..2970eb78 100644 --- a/src/main/scala/uncore/tilelink2/SRAM.scala +++ b/src/main/scala/uncore/tilelink2/SRAM.scala @@ -9,6 +9,7 @@ class TLRAM(address: AddressSet, beatBytes: Int = 4) extends LazyModule val node = TLManagerNode(beatBytes, TLManagerParameters( address = List(address), regionType = RegionType.UNCACHED, + executable = true, supportsGet = TransferSizes(1, beatBytes), supportsPutPartial = TransferSizes(1, beatBytes), supportsPutFull = TransferSizes(1, beatBytes), From 3f30e11f16424ba8e5901ce39e63c41a931935a8 Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Wed, 14 Sep 2016 19:52:03 -0700 Subject: [PATCH 04/26] tilelink2: Legacy, manager_xact_id does not matter for uncached --- src/main/scala/uncore/tilelink2/Legacy.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/scala/uncore/tilelink2/Legacy.scala b/src/main/scala/uncore/tilelink2/Legacy.scala index 99ccc2fe..91bb74b6 100644 --- a/src/main/scala/uncore/tilelink2/Legacy.scala +++ b/src/main/scala/uncore/tilelink2/Legacy.scala @@ -49,7 +49,7 @@ class TLLegacy(implicit val p: Parameters) extends LazyModule with HasTileLinkPa // During conversion from TL Legacy, we won't support Acquire // Must be able to fit TL2 sink_id into TL legacy - require ((1 << tlManagerXactIdBits) >= edge.manager.endSinkId) + require ((1 << tlManagerXactIdBits) >= edge.manager.endSinkId || !edge.manager.anySupportAcquire) val out = io.out(0) out.a.valid := io.legacy.acquire.valid From 5c8e52ca32c4e1afbbd643d776c2a0baf050afc9 Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Wed, 14 Sep 2016 20:40:00 -0700 Subject: [PATCH 05/26] devices: TL2 version of ROM --- src/main/scala/uncore/devices/Rom.scala | 37 +++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/src/main/scala/uncore/devices/Rom.scala b/src/main/scala/uncore/devices/Rom.scala index d30812f4..8e31cbe5 100644 --- a/src/main/scala/uncore/devices/Rom.scala +++ b/src/main/scala/uncore/devices/Rom.scala @@ -4,9 +4,46 @@ import Chisel._ import unittest.UnitTest import junctions._ import uncore.tilelink._ +import uncore.tilelink2._ import uncore.util._ import cde.{Parameters, Field} +class TLROM(val base: BigInt, val size: Int, contentsDelayed: => Seq[Byte], beatBytes: Int = 4) extends LazyModule +{ + val node = TLManagerNode(beatBytes, TLManagerParameters( + address = List(AddressSet(base, size-1)), + regionType = RegionType.UNCACHED, + supportsGet = TransferSizes(1, beatBytes), + fifoId = Some(0))) + + lazy val module = new LazyModuleImp(this) { + val io = new Bundle { + val in = node.bundleIn + } + + val contents = contentsDelayed + require (contents.size <= size) + + val in = io.in(0) + val edge = node.edgesIn(0) + + val words = (contents ++ Seq.fill(size-contents.size)(0.toByte)).grouped(beatBytes).toSeq + val bigs = words.map(_.foldRight(BigInt(0)){ case (x,y) => (x.toInt & 0xff) | y << 8}) + val rom = Vec(bigs.map(x => UInt(x, width = 8*beatBytes))) + + in.d.valid := in.a.valid + in.a.ready := in.d.ready + + val index = in.a.bits.addr_hi(log2Ceil(size/beatBytes)-1,0) + in.d.bits := edge.AccessAck(in.a.bits, UInt(0), rom(index)) + + // Tie off unused channels + in.b.valid := Bool(false) + in.c.ready := Bool(true) + in.e.ready := Bool(true) + } +} + class ROMSlave(contents: Seq[Byte])(implicit val p: Parameters) extends Module with HasTileLinkParameters with HasAddrMapParameters { From 3875e11b26b95a880641a4d60810df3d72058f05 Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Wed, 14 Sep 2016 23:06:49 -0700 Subject: [PATCH 06/26] tilelink2: RegField splits up big registers --- src/main/scala/uncore/tilelink2/RegField.scala | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/main/scala/uncore/tilelink2/RegField.scala b/src/main/scala/uncore/tilelink2/RegField.scala index fa258b5c..3a49659f 100644 --- a/src/main/scala/uncore/tilelink2/RegField.scala +++ b/src/main/scala/uncore/tilelink2/RegField.scala @@ -105,6 +105,23 @@ object RegField bb.d := data Bool(true) })) + + // Split a large register into a sequence of byte fields + // The bytes can be individually written, as they are one byte per field + def bytes(x: UInt, base: Int = 0, beatBytes: Int = 4): Seq[RegField.Map] = { + require (x.getWidth % 8 == 0) + Seq.tabulate(x.getWidth/8) { i => + RegField(8, x(8*(i+1)-1, 8*i), RegWriteFn { (valid, data) => + when (valid) { + val mask = ~UInt(BigInt(0xff) << 8*i, width = x.getWidth) + x := (x & mask) | (data & UInt(0xff)) << 8*i + } + Bool(true) + }) + }.grouped(beatBytes).toSeq.zipWithIndex.map { case (reg, i) => + (i+base, reg) + } + } } trait HasRegMap From 91e7da4de32db84d7596634ebaa016832c7db1b6 Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Wed, 14 Sep 2016 23:19:03 -0700 Subject: [PATCH 07/26] tilelink2: make RegisterRouter constructor args public --- src/main/scala/uncore/tilelink2/RegisterRouter.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/scala/uncore/tilelink2/RegisterRouter.scala b/src/main/scala/uncore/tilelink2/RegisterRouter.scala index ce46fc11..c20f0c49 100644 --- a/src/main/scala/uncore/tilelink2/RegisterRouter.scala +++ b/src/main/scala/uncore/tilelink2/RegisterRouter.scala @@ -100,7 +100,7 @@ class TLRegModule[P, B <: TLRegBundleBase](val params: P, bundleBuilder: => B, r } class TLRegisterRouter[B <: TLRegBundleBase, M <: LazyModuleImp] - (base: BigInt, interrupts: Int = 0, size: BigInt = 4096, concurrency: Option[Int] = None, beatBytes: Int = 4) + (val base: BigInt, val interrupts: Int = 0, val size: BigInt = 4096, val concurrency: Option[Int] = None, val beatBytes: Int = 4) (bundleBuilder: TLRegBundleArg => B) (moduleBuilder: (=> B, TLRegisterRouterBase) => M) extends TLRegisterRouterBase(AddressSet(base, size-1), interrupts, concurrency, beatBytes) From 644f8fe974d8bf8d86192eeea6de23c4450e5cb5 Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Wed, 14 Sep 2016 18:09:27 -0700 Subject: [PATCH 08/26] rocketchip: switch to TL2 mmio + port PRCI --- src/main/scala/coreplex/Configs.scala | 2 +- src/main/scala/rocketchip/Periphery.scala | 70 ++++++-------- src/main/scala/rocketchip/Top.scala | 15 ++- src/main/scala/rocketchip/Utils.scala | 10 +- src/main/scala/uncore/devices/Prci.scala | 113 ++++++++-------------- 5 files changed, 87 insertions(+), 123 deletions(-) diff --git a/src/main/scala/coreplex/Configs.scala b/src/main/scala/coreplex/Configs.scala index 8d8d87ad..79e4652b 100644 --- a/src/main/scala/coreplex/Configs.scala +++ b/src/main/scala/coreplex/Configs.scala @@ -177,7 +177,7 @@ class BaseCoreplexConfig extends Config ( TileLinkParameters( coherencePolicy = new MICoherence( new NullRepresentation(site(NBanksPerMemoryChannel))), - nManagers = site(GlobalAddrMap).get.subMap("io").numSlaves, + nManagers = 1, nCachingClients = 0, nCachelessClients = 1, maxClientXacts = 4, diff --git a/src/main/scala/rocketchip/Periphery.scala b/src/main/scala/rocketchip/Periphery.scala index 5fd15e97..cdc0275e 100644 --- a/src/main/scala/rocketchip/Periphery.scala +++ b/src/main/scala/rocketchip/Periphery.scala @@ -7,7 +7,7 @@ import cde.{Parameters, Field} import junctions._ import junctions.NastiConstants._ import uncore.tilelink._ -import uncore.tilelink2.{LazyModule, LazyModuleImp} +import uncore.tilelink2._ import uncore.converters._ import uncore.devices._ import uncore.util._ @@ -202,10 +202,10 @@ trait PeripheryMasterMMIOModule extends HasPeripheryParameters { implicit val p: Parameters val outer: PeripheryMasterMMIO val io: PeripheryMasterMMIOBundle - val mmioNetwork: Option[TileLinkRecursiveInterconnect] + val mmioNetwork: TileLinkRecursiveInterconnect val mmio_ports = p(ExtMMIOPorts) map { port => - TileLinkWidthAdapter(mmioNetwork.get.port(port.name), "MMIO_Outermost") + TileLinkWidthAdapter(mmioNetwork.port(port.name), "MMIO_Outermost") } val mmio_axi_start = 0 @@ -278,11 +278,16 @@ trait PeripherySlaveModule extends HasPeripheryParameters { ///// /** Always-ON block */ -trait PeripheryAON extends LazyModule { +trait PeripheryAON extends LazyModule with HasPeripheryParameters { implicit val p: Parameters - val pDevices: ResourceManager[AddrMapEntry] + val peripheryBus: TLXbar - pDevices.add(AddrMapEntry("prci", MemSize(0x4000000, MemAttr(AddrMapProt.RW)))) + val prci = LazyModule(new PRCI()(innerMMIOParams)) + prci.node := TLFragmenter(peripheryBus.node, 4, 256) + + // TL1 legacy + val pDevices: ResourceManager[AddrMapEntry] + pDevices.add(AddrMapEntry("prci", MemRange(prci.base, prci.size, MemAttr(AddrMapProt.RW)))) } trait PeripheryAONBundle { @@ -293,21 +298,23 @@ trait PeripheryAONModule extends HasPeripheryParameters { implicit val p: Parameters val outer: PeripheryAON val io: PeripheryAONBundle - val mmioNetwork: Option[TileLinkRecursiveInterconnect] val coreplex: Coreplex - val prci = Module(new PRCI()(innerMMIOParams)) - prci.io.rtcTick := Counter(p(RTCPeriod)).inc() - prci.io.tl <> mmioNetwork.get.port("prci") - coreplex.io.prci <> prci.io.tiles + outer.prci.module.io.rtcTick := Counter(p(RTCPeriod)).inc() + coreplex.io.prci <> outer.prci.module.io.tiles } ///// trait PeripheryBootROM extends LazyModule { implicit val p: Parameters - val pDevices: ResourceManager[AddrMapEntry] + val peripheryBus: TLXbar + val rom = LazyModule(new TLROM(0x1000, 0x1000, GenerateBootROM(p))) + rom.node := TLFragmenter(peripheryBus.node, 4, 256) + + // TL1 legacy address map + val pDevices: ResourceManager[AddrMapEntry] pDevices.add(AddrMapEntry("bootrom", MemRange(0x1000, 4096, MemAttr(AddrMapProt.RX)))) } @@ -319,20 +326,23 @@ trait PeripheryBootROMModule extends HasPeripheryParameters { implicit val p: Parameters val outer: PeripheryBootROM val io: PeripheryBootROMBundle - val mmioNetwork: Option[TileLinkRecursiveInterconnect] - - val bootROM = Module(new ROMSlave(GenerateBootROM(p))(innerMMIOParams)) - bootROM.io <> mmioNetwork.get.port("bootrom") } ///// trait PeripheryTestRAM extends LazyModule { implicit val p: Parameters - val pDevices: ResourceManager[AddrMapEntry] + val peripheryBus: TLXbar + val ramBase = 0x52000000 val ramSize = 0x1000 - pDevices.add(AddrMapEntry("testram", MemSize(ramSize, MemAttr(AddrMapProt.RW)))) + + val sram = LazyModule(new TLRAM(AddressSet(ramBase, ramSize-1))) + sram.node := TLFragmenter(peripheryBus.node, 4, 256) + + // TL1 legacy address map + val pDevices: ResourceManager[AddrMapEntry] + pDevices.add(AddrMapEntry("testram", MemRange(ramBase, ramSize, MemAttr(AddrMapProt.RW)))) } trait PeripheryTestRAMBundle { @@ -342,22 +352,16 @@ trait PeripheryTestRAMBundle { trait PeripheryTestRAMModule extends HasPeripheryParameters { implicit val p: Parameters val outer: PeripheryTestRAM - val io: PeripheryTestRAMBundle - val mmioNetwork: Option[TileLinkRecursiveInterconnect] - - val testram = Module(new TileLinkTestRAM(outer.ramSize)(innerMMIOParams)) - testram.io <> mmioNetwork.get.port("testram") } ///// trait PeripheryTestBusMaster extends LazyModule { implicit val p: Parameters - val pBusMasters: RangeManager - val pDevices: ResourceManager[AddrMapEntry] + val peripheryBus: TLXbar - pBusMasters.add("busmaster", 1) - pDevices.add(AddrMapEntry("busmaster", MemSize(4096, MemAttr(AddrMapProt.RW)))) + val fuzzer = LazyModule(new TLFuzzer(5000)) + peripheryBus.node := fuzzer.node } trait PeripheryTestBusMasterBundle { @@ -367,16 +371,4 @@ trait PeripheryTestBusMasterBundle { trait PeripheryTestBusMasterModule { implicit val p: Parameters val outer: PeripheryTestBusMaster - val io: PeripheryTestBusMasterBundle - val mmioNetwork: Option[TileLinkRecursiveInterconnect] - val coreplex: Coreplex - - val busmaster = Module(new groundtest.ExampleBusMaster()(p)) - busmaster.io.mmio <> mmioNetwork.get.port("busmaster") - - { - val r = outer.pBusMasters.range("busmaster") - require(r._2 - r._1 == 1, "RangeManager should return 1 slot") - coreplex.io.slave(r._1) <> busmaster.io.mem - } } diff --git a/src/main/scala/rocketchip/Top.scala b/src/main/scala/rocketchip/Top.scala index c56ffc46..8e723d97 100644 --- a/src/main/scala/rocketchip/Top.scala +++ b/src/main/scala/rocketchip/Top.scala @@ -6,7 +6,7 @@ import Chisel._ import cde.{Parameters, Field} import junctions._ import uncore.tilelink._ -import uncore.tilelink2.{LazyModule, LazyModuleImp} +import uncore.tilelink2._ import uncore.devices._ import util.ParameterizedBundle import rocket._ @@ -26,6 +26,10 @@ abstract class BaseTop(val p: Parameters) extends LazyModule { val pInterrupts = new RangeManager val pBusMasters = new RangeManager val pDevices = new ResourceManager[AddrMapEntry] + val peripheryBus = LazyModule(new TLXbar) + val legacy = LazyModule(new TLLegacy()(p.alterPartial({ case TLId => "L2toMMIO" }))) + + peripheryBus.node := TLBuffer(TLWidthWidget(TLHintHandler(legacy.node), legacy.tlDataBytes)) } class BaseTopBundle(val p: Parameters, val c: Coreplex) extends ParameterizedBundle()(p) { @@ -41,7 +45,7 @@ class BaseTopModule[+L <: BaseTop, +B <: BaseTopBundle](val p: Parameters, l: L, nSlaves = outer.pBusMasters.sum, nMemChannels = p(NMemoryChannels), hasSupervisor = p(UseVM), - hasExtMMIOPort = !(outer.pDevices.get.isEmpty && p(ExtMMIOPorts).isEmpty) + hasExtMMIOPort = true ) def genGlobalAddrMap = GenerateGlobalAddrMap(p, outer.pDevices.get) @@ -67,10 +71,11 @@ class BaseTopModule[+L <: BaseTop, +B <: BaseTopBundle](val p: Parameters, l: L, io.success zip coreplex.io.success map { case (x, y) => x := y } - val mmioNetwork = c.hasExtMMIOPort.option( + val mmioNetwork = Module(new TileLinkRecursiveInterconnect(1, p(GlobalAddrMap).get.subMap("io:ext"))( - p.alterPartial({ case TLId => "L2toMMIO" })))) - mmioNetwork.foreach { _.io.in.head <> coreplex.io.master.mmio.get } + p.alterPartial({ case TLId => "L2toMMIO" }))) + mmioNetwork.io.in.head <> coreplex.io.master.mmio.get + outer.legacy.module.io.legacy <> mmioNetwork.port("TL2") } /** Example Top with Periphery */ diff --git a/src/main/scala/rocketchip/Utils.scala b/src/main/scala/rocketchip/Utils.scala index fb0d8676..1813713c 100644 --- a/src/main/scala/rocketchip/Utils.scala +++ b/src/main/scala/rocketchip/Utils.scala @@ -64,10 +64,8 @@ object GenerateGlobalAddrMap { new AddrMap(entries) } - lazy val extIOAddrMap = new AddrMap( - pDevicesEntries ++ p(ExtMMIOPorts), - start = BigInt("50000000", 16), - collapse = true) + lazy val tl2AddrMap = new AddrMap(pDevicesEntries, collapse = true) + lazy val extIOAddrMap = new AddrMap(AddrMapEntry("TL2", tl2AddrMap) +: p(ExtMMIOPorts), collapse = true) val memBase = 0x80000000L val memSize = p(ExtMemSize) @@ -85,7 +83,7 @@ object GenerateConfigString { def apply(p: Parameters, c: CoreplexConfig, pDevicesEntries: Seq[AddrMapEntry]) = { val addrMap = p(GlobalAddrMap).get val plicAddr = addrMap("io:int:plic").start - val prciAddr = addrMap("io:ext:prci").start + val prciAddr = addrMap("io:ext:TL2:prci").start val xLen = p(XLen) val res = new StringBuilder res append "plic {\n" @@ -138,7 +136,7 @@ object GenerateConfigString { } res append "};\n" pDevicesEntries foreach { entry => - val region = addrMap("io:ext:" + entry.name) + val region = addrMap("io:ext:TL2:" + entry.name) res append s"${entry.name} {\n" res append s" addr 0x${region.start.toString(16)};\n" res append s" size 0x${region.size.toString(16)}; \n" diff --git a/src/main/scala/uncore/devices/Prci.scala b/src/main/scala/uncore/devices/Prci.scala index d607be91..22b45425 100644 --- a/src/main/scala/uncore/devices/Prci.scala +++ b/src/main/scala/uncore/devices/Prci.scala @@ -6,7 +6,7 @@ import Chisel._ import rocket.Util._ import junctions._ import junctions.NastiConstants._ -import uncore.tilelink._ +import uncore.tilelink2._ import uncore.util._ import cde.{Parameters, Field} @@ -32,45 +32,28 @@ object PRCI { def size = 0xc000 } -/** Power, Reset, Clock, Interrupt */ -class PRCI(implicit val p: Parameters) extends Module - with HasTileLinkParameters - with HasAddrMapParameters { - val io = new Bundle { - val tl = new ClientUncachedTileLinkIO().flip - val tiles = Vec(p(NTiles), new PRCITileIO) - val rtcTick = Bool(INPUT) - } +case class PRCIConfig(address: BigInt = 0x44000000, beatBytes: Int = 4) + +trait MixPRCIParameters { + val params: (PRCIConfig, Parameters) + val c = params._1 + implicit val p = params._2 +} + +trait PRCIBundle extends Bundle with MixPRCIParameters { + val tiles = Vec(p(NTiles), new PRCITileIO) + val rtcTick = Bool(INPUT) +} + +trait PRCIModule extends Module with HasRegMap with MixPRCIParameters { + val io: PRCIBundle val timeWidth = 64 - val timecmp = Reg(Vec(p(NTiles), UInt(width = timeWidth))) val time = Reg(init=UInt(0, timeWidth)) when (io.rtcTick) { time := time + UInt(1) } - val ipi = Reg(init=Vec.fill(p(NTiles))(UInt(0, 32))) - - val acq = Queue(io.tl.acquire, 1) - val addr = acq.bits.full_addr()(log2Ceil(PRCI.size)-1,0) - val read = acq.bits.isBuiltInType(Acquire.getType) - val rdata = Wire(init=UInt(0)) - io.tl.grant.valid := acq.valid - acq.ready := io.tl.grant.ready - io.tl.grant.bits := Grant( - is_builtin_type = Bool(true), - g_type = acq.bits.getBuiltInGrantType(), - client_xact_id = acq.bits.client_xact_id, - manager_xact_id = UInt(0), - addr_beat = UInt(0), - data = rdata) - - when (addr(log2Floor(PRCI.time))) { - require(log2Floor(PRCI.timecmp(p(NTiles)-1)) < log2Floor(PRCI.time)) - rdata := store(Seq(time), acq.bits, io.tl.grant.fire()) - }.elsewhen (addr >= PRCI.timecmp(0)) { - rdata := store(timecmp, acq.bits, io.tl.grant.fire()) - }.otherwise { - rdata := store(ipi, acq.bits, io.tl.grant.fire()) & Fill(tlDataBits/32, UInt(1, 32)) - } + val timecmp = Seq.fill(p(NTiles)) { Reg(UInt(width = timeWidth)) } + val ipi = Seq.fill(p(NTiles)) { RegInit(UInt(0, width = 1)) } for ((tile, i) <- io.tiles zipWithIndex) { tile.interrupts.msip := ipi(i)(0) @@ -78,42 +61,28 @@ class PRCI(implicit val p: Parameters) extends Module tile.reset := reset } - // TODO generalize these to help other TL slaves - def load(v: Seq[UInt], acq: Acquire): UInt = { - val w = v.head.getWidth - val a = acq.full_addr() - require(isPow2(w) && w >= 8) - if (w > tlDataBits) { - (v(a.extract(log2Ceil(w/8*v.size)-1,log2Ceil(w/8))) >> a.extract(log2Ceil(w/8)-1,log2Ceil(tlDataBytes)))(tlDataBits-1,0) - } else { - val row: Seq[UInt] = for (i <- 0 until v.size by tlDataBits/w) - yield Cat(v.slice(i, i + tlDataBits/w).reverse) - if (row.size == 1) row.head - else row(a(log2Ceil(w/8*v.size)-1,log2Ceil(tlDataBytes))) - } - } + /* 0000 msip hart 0 + * 0004 msip hart 1 + * 4000 mtimecmp hart 0 lo + * 4004 mtimecmp hart 0 hi + * 4008 mtimecmp hart 1 lo + * 400c mtimecmp hart 1 hi + * bff8 mtime lo + * bffc mtime hi + */ - def store(v: Seq[UInt], acq: Acquire, en: Bool): UInt = { - val w = v.head.getWidth - require(isPow2(w) && w >= 8) - val a = acq.full_addr() - val rdata = load(v, acq) - val wdata = (acq.data & acq.full_wmask()) | (rdata & ~acq.full_wmask()) - when (en && acq.isBuiltInType(Acquire.putType)) { - if (w <= tlDataBits) { - val word = - if (tlDataBits/w >= v.size) UInt(0) - else a(log2Up(w/8*v.size)-1,log2Up(tlDataBytes)) - for (i <- 0 until v.size) when (word === i/(tlDataBits/w)) { - val base = i % (tlDataBits/w) - v(i) := wdata >> (w * (i % (tlDataBits/w))) - } - } else { - val i = a.extract(log2Ceil(w/8*v.size)-1,log2Ceil(w/8)) - val mask = FillInterleaved(tlDataBits, UIntToOH(a.extract(log2Ceil(w/8)-1,log2Ceil(tlDataBytes)))) - v(i) := (wdata & mask) | (v(i) & ~mask) - } - } - rdata - } + val timecmp_regs = timecmp.zipWithIndex.map { case (reg, i) => + RegField.bytes(reg, PRCI.timecmp(i)/c.beatBytes, c.beatBytes) + }.flatten + val time_reg = RegField.bytes(time, PRCI.time/c.beatBytes, c.beatBytes) + val ipi_regs = ipi.zipWithIndex.map { case (reg, i) => (i -> Seq(RegField(1, reg))) } + + regmap((timecmp_regs ++ time_reg ++ ipi_regs):_*) } + +/** Power, Reset, Clock, Interrupt */ +// Magic TL2 Incantation to create a TL2 Slave +class PRCI(c: PRCIConfig = PRCIConfig())(implicit val p: Parameters) + extends TLRegisterRouter(c.address, 0, 0x10000, None, c.beatBytes)( + new TLRegBundle((c, p), _) with PRCIBundle)( + new TLRegModule((c, p), _, _) with PRCIModule) From fb24e847fd13b6a1c9aa467fb0b4f9d783b5f5f2 Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Thu, 15 Sep 2016 00:38:46 -0700 Subject: [PATCH 09/26] rocketchip: globals are for sissies --- src/main/scala/coreplex/Configs.scala | 2 +- src/main/scala/coreplex/Coreplex.scala | 2 +- src/main/scala/coreplex/TestConfigs.scala | 10 +-- src/main/scala/junctions/addrmap.scala | 2 +- src/main/scala/rocketchip/Configs.scala | 6 -- src/main/scala/rocketchip/Generator.scala | 25 +++++--- src/main/scala/rocketchip/TestConfigs.scala | 2 +- src/main/scala/rocketchip/TestHarness.scala | 7 ++- src/main/scala/rocketchip/Top.scala | 68 +++++++++++---------- src/main/scala/rocketchip/UnitTest.scala | 8 +-- src/main/scala/rocketchip/Utils.scala | 8 +-- 11 files changed, 74 insertions(+), 66 deletions(-) diff --git a/src/main/scala/coreplex/Configs.scala b/src/main/scala/coreplex/Configs.scala index 79e4652b..2e124a9c 100644 --- a/src/main/scala/coreplex/Configs.scala +++ b/src/main/scala/coreplex/Configs.scala @@ -146,7 +146,7 @@ class BaseCoreplexConfig extends Config ( else new MESICoherence(site(L2DirectoryRepresentation))), nManagers = site(NBanksPerMemoryChannel)*site(NMemoryChannels) + 1 /* MMIO */, nCachingClients = site(NCachedTileLinkPorts), - nCachelessClients = site(NCoreplexExtClients).get + site(NUncachedTileLinkPorts), + nCachelessClients = site(NCoreplexExtClients) + site(NUncachedTileLinkPorts), maxClientXacts = max_int( // L1 cache site(DCacheKey).nMSHRs + 1 /* IOMSHR */, diff --git a/src/main/scala/coreplex/Coreplex.scala b/src/main/scala/coreplex/Coreplex.scala index 2da93f9f..b28b8e5a 100644 --- a/src/main/scala/coreplex/Coreplex.scala +++ b/src/main/scala/coreplex/Coreplex.scala @@ -32,7 +32,7 @@ trait HasCoreplexParameters { 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 globalAddrMap = p(rocketchip.GlobalAddrMap).get + lazy val globalAddrMap = p(rocketchip.GlobalAddrMap) } case class CoreplexConfig( diff --git a/src/main/scala/coreplex/TestConfigs.scala b/src/main/scala/coreplex/TestConfigs.scala index 7b44868e..e2e2fd03 100644 --- a/src/main/scala/coreplex/TestConfigs.scala +++ b/src/main/scala/coreplex/TestConfigs.scala @@ -24,7 +24,7 @@ class WithComparator extends Config( (p: Parameters) => Module(new ComparatorCore()(p)) case ComparatorKey => ComparatorParameters( targets = Seq("mem", "io:ext:testram").map(name => - site(GlobalAddrMap).get(name).start.longValue), + site(GlobalAddrMap)(name).start.longValue), width = 8, operations = 1000, atomics = site(UseAtomics), @@ -54,7 +54,7 @@ class WithMemtest extends Config( } case GeneratorKey => GeneratorParameters( maxRequests = 128, - startAddress = site(GlobalAddrMap).get("mem").start) + startAddress = site(GlobalAddrMap)("mem").start) case BuildGroundTest => (p: Parameters) => Module(new GeneratorTest()(p)) case _ => throw new CDEMatchError @@ -114,7 +114,7 @@ class WithNastiConverterTest extends Config( } case GeneratorKey => GeneratorParameters( maxRequests = 128, - startAddress = site(GlobalAddrMap).get("mem").start) + startAddress = site(GlobalAddrMap)("mem").start) case BuildGroundTest => (p: Parameters) => Module(new NastiConverterTest()(p)) case _ => throw new CDEMatchError @@ -134,7 +134,7 @@ class WithTraceGen extends Config( val nSets = 32 // L2 NSets val nWays = 1 val blockOffset = site(CacheBlockOffsetBits) - val baseAddr = site(GlobalAddrMap).get("mem").start + val baseAddr = site(GlobalAddrMap)("mem").start val nBeats = site(MIFDataBeats) List.tabulate(4 * nWays) { i => Seq.tabulate(nBeats) { j => (j * 8) + ((i * nSets) << blockOffset) } @@ -157,7 +157,7 @@ class WithPCIeMockupTest extends Config( GroundTestTileSettings(1)) case GeneratorKey => GeneratorParameters( maxRequests = 128, - startAddress = site(GlobalAddrMap).get("mem").start) + startAddress = site(GlobalAddrMap)("mem").start) case BuildGroundTest => (p: Parameters) => p(TileId) match { case 0 => Module(new GeneratorTest()(p)) diff --git a/src/main/scala/junctions/addrmap.scala b/src/main/scala/junctions/addrmap.scala index b3f1722a..19613ae7 100644 --- a/src/main/scala/junctions/addrmap.scala +++ b/src/main/scala/junctions/addrmap.scala @@ -12,7 +12,7 @@ trait HasAddrMapParameters { implicit val p: Parameters val paddrBits = p(PAddrBits) - def addrMap = p(rocketchip.GlobalAddrMap).get + def addrMap = p(rocketchip.GlobalAddrMap) } case class MemAttr(prot: Int, cacheable: Boolean = false) diff --git a/src/main/scala/rocketchip/Configs.scala b/src/main/scala/rocketchip/Configs.scala index c7c0deb9..7003df30 100644 --- a/src/main/scala/rocketchip/Configs.scala +++ b/src/main/scala/rocketchip/Configs.scala @@ -20,9 +20,6 @@ import cde.{Parameters, Config, Dump, Knob, CDEMatchError} class BasePlatformConfig extends Config( topDefinitions = { - val configString = new GlobalVariable[String] - val globalAddrMap = new GlobalVariable[AddrMap] - val nCoreplexExtClients = new GlobalVariable[Int] (pname,site,here) => { type PF = PartialFunction[Any,Any] def findBy(sname:Any):Any = here[PF](site[Any](sname))(pname) @@ -55,7 +52,6 @@ class BasePlatformConfig extends Config( case NExtMMIOTLChannels => 0 case AsyncBusChannels => false case NExtBusAXIChannels => 0 - case NCoreplexExtClients => nCoreplexExtClients case HastiId => "Ext" case HastiKey("TL") => HastiParameters( @@ -69,8 +65,6 @@ class BasePlatformConfig extends Config( case NMemoryChannels => Dump("N_MEM_CHANNELS", 1) case TMemoryChannels => BusType.AXI case ExtMemSize => Dump("MEM_SIZE", 0x10000000L) - case ConfigString => configString - case GlobalAddrMap => globalAddrMap case RTCPeriod => 100 // gives 10 MHz RTC assuming 1 GHz uncore clock case BuildExampleTop => (p: Parameters) => uncore.tilelink2.LazyModule(new ExampleTop(p)) diff --git a/src/main/scala/rocketchip/Generator.scala b/src/main/scala/rocketchip/Generator.scala index ec0d6a39..f4f24247 100644 --- a/src/main/scala/rocketchip/Generator.scala +++ b/src/main/scala/rocketchip/Generator.scala @@ -56,6 +56,10 @@ trait HasGeneratorUtilities { } } +object ConfigStringOutput { + var contents: Option[String] = None +} + trait Generator extends App with HasGeneratorUtilities { lazy val names = { require(args.size == 5, "Usage: sbt> " + @@ -67,20 +71,25 @@ trait Generator extends App with HasGeneratorUtilities { configProject = args(3), configs = args(4)) } + + lazy val td = names.targetDir lazy val config = getConfig(names) lazy val world = config.toInstance lazy val params = Parameters.root(world) lazy val circuit = elaborate(names, params) + lazy val longName = names.topModuleClass + "." + names.configs + + def writeOutputFiles() { + TestGeneration.addSuite(new RegressionTestSuite(params(RegressionTestNames))) + writeOutputFile(td, s"$longName.d", TestGeneration.generateMakefrag) // Coreplex-specific test suites + writeOutputFile(td, s"$longName.prm", ParameterDump.getDump) // Parameters flagged with Dump() + writeOutputFile(td, s"${names.configs}.knb", world.getKnobs) // Knobs for DSE + writeOutputFile(td, s"${names.configs}.cst", world.getConstraints) // Constraints for DSE + ConfigStringOutput.contents.foreach(c => writeOutputFile(td, s"${names.configs}.cfg", c)) // String for software + } } object RocketChipGenerator extends Generator { - val longName = names.topModuleClass + "." + names.configs - val td = names.targetDir Driver.dumpFirrtl(circuit, Some(new File(td, s"$longName.fir"))) // FIRRTL - TestGeneration.addSuite(new RegressionTestSuite(params(RegressionTestNames))) - writeOutputFile(td, s"$longName.d", TestGeneration.generateMakefrag) // Coreplex-specific test suites - writeOutputFile(td, s"$longName.prm", ParameterDump.getDump) // Parameters flagged with Dump() - writeOutputFile(td, s"${names.configs}.knb", world.getKnobs) // Knobs for DSE - writeOutputFile(td, s"${names.configs}.cst", world.getConstraints) // Constraints for DSE - writeOutputFile(td, s"${names.configs}.cfg", params(ConfigString).get) // String for software + writeOutputFiles() } diff --git a/src/main/scala/rocketchip/TestConfigs.scala b/src/main/scala/rocketchip/TestConfigs.scala index 96127f16..ff13902c 100644 --- a/src/main/scala/rocketchip/TestConfigs.scala +++ b/src/main/scala/rocketchip/TestConfigs.scala @@ -27,7 +27,7 @@ class WithGroundTest extends Config( else new MESICoherence(site(L2DirectoryRepresentation))), nManagers = site(NBanksPerMemoryChannel)*site(NMemoryChannels) + 1, nCachingClients = site(NCachedTileLinkPorts), - nCachelessClients = site(NCoreplexExtClients).get + site(NUncachedTileLinkPorts), + nCachelessClients = site(NCoreplexExtClients) + site(NUncachedTileLinkPorts), maxClientXacts = ((site(DCacheKey).nMSHRs + 1) +: site(GroundTestKey).map(_.maxXacts)) .reduce(max(_, _)), diff --git a/src/main/scala/rocketchip/TestHarness.scala b/src/main/scala/rocketchip/TestHarness.scala index 9e073499..8612e539 100644 --- a/src/main/scala/rocketchip/TestHarness.scala +++ b/src/main/scala/rocketchip/TestHarness.scala @@ -11,11 +11,12 @@ import junctions.NastiConstants._ case object BuildExampleTop extends Field[Parameters => ExampleTop] case object SimMemLatency extends Field[Int] -class TestHarness(implicit val p: Parameters) extends Module with HasAddrMapParameters { +class TestHarness(q: Parameters) extends Module { val io = new Bundle { val success = Bool(OUTPUT) } - val dut = p(BuildExampleTop)(p).module + val dut = q(BuildExampleTop)(q).module + implicit val p = dut.p // This test harness isn't especially flexible yet require(dut.io.mem_clk.isEmpty) @@ -33,7 +34,7 @@ class TestHarness(implicit val p: Parameters) extends Module with HasAddrMapPara int := false if (dut.io.mem_axi.nonEmpty) { - val memSize = addrMap("mem").size + val memSize = p(GlobalAddrMap)("mem").size require(memSize % dut.io.mem_axi.size == 0) for (axi <- dut.io.mem_axi) { val mem = Module(new SimAXIMem(memSize / dut.io.mem_axi.size)) diff --git a/src/main/scala/rocketchip/Top.scala b/src/main/scala/rocketchip/Top.scala index 8e723d97..bbf89c1a 100644 --- a/src/main/scala/rocketchip/Top.scala +++ b/src/main/scala/rocketchip/Top.scala @@ -14,18 +14,37 @@ import rocket.Util._ import coreplex._ // the following parameters will be refactored properly with TL2 -case object GlobalAddrMap extends Field[GlobalVariable[AddrMap]] -case object ConfigString extends Field[GlobalVariable[String]] -case object NCoreplexExtClients extends Field[GlobalVariable[Int]] +case object GlobalAddrMap extends Field[AddrMap] +case object ConfigString extends Field[String] +case object NCoreplexExtClients extends Field[Int] /** Function for building Coreplex */ case object BuildCoreplex extends Field[(Parameters, CoreplexConfig) => Coreplex] /** Base Top with no Periphery */ -abstract class BaseTop(val p: Parameters) extends LazyModule { +abstract class BaseTop(q: Parameters) extends LazyModule { // the following variables will be refactored properly with TL2 val pInterrupts = new RangeManager val pBusMasters = new RangeManager val pDevices = new ResourceManager[AddrMapEntry] + + lazy val c = CoreplexConfig( + nTiles = q(NTiles), + nExtInterrupts = pInterrupts.sum, + nSlaves = pBusMasters.sum, + nMemChannels = q(NMemoryChannels), + hasSupervisor = q(UseVM), + hasExtMMIOPort = true + ) + + lazy val genGlobalAddrMap = GenerateGlobalAddrMap(q, pDevices.get) + private val qWithMap = q.alterPartial({case GlobalAddrMap => genGlobalAddrMap}) + + lazy val genConfigString = GenerateConfigString(qWithMap, c, pDevices.get) + implicit val p = qWithMap.alterPartial({ + case ConfigString => genConfigString + case NCoreplexExtClients => pBusMasters.sum}) + + // Add a peripheral bus val peripheryBus = LazyModule(new TLXbar) val legacy = LazyModule(new TLLegacy()(p.alterPartial({ case TLId => "L2toMMIO" }))) @@ -39,24 +58,19 @@ class BaseTopBundle(val p: Parameters, val c: Coreplex) extends ParameterizedBun class BaseTopModule[+L <: BaseTop, +B <: BaseTopBundle](val p: Parameters, l: L, b: Coreplex => B) extends LazyModuleImp(l) { val outer: L = l - val c = CoreplexConfig( - nTiles = p(NTiles), - nExtInterrupts = outer.pInterrupts.sum, - nSlaves = outer.pBusMasters.sum, - nMemChannels = p(NMemoryChannels), - hasSupervisor = p(UseVM), - hasExtMMIOPort = true - ) + val coreplex = p(BuildCoreplex)(p, outer.c) + val io: B = b(coreplex) - def genGlobalAddrMap = GenerateGlobalAddrMap(p, outer.pDevices.get) - def genConfigString = GenerateConfigString(p, c, outer.pDevices.get) + io.success zip coreplex.io.success map { case (x, y) => x := y } - p(NCoreplexExtClients).assign(outer.pBusMasters.sum) - p(GlobalAddrMap).assign(genGlobalAddrMap) - p(ConfigString).assign(genConfigString) + val mmioNetwork = + Module(new TileLinkRecursiveInterconnect(1, p(GlobalAddrMap).subMap("io:ext"))( + p.alterPartial({ case TLId => "L2toMMIO" }))) + mmioNetwork.io.in.head <> coreplex.io.master.mmio.get + outer.legacy.module.io.legacy <> mmioNetwork.port("TL2") println("Generated Address Map") - for (entry <- p(GlobalAddrMap).get.flatten) { + for (entry <- p(GlobalAddrMap).flatten) { val name = entry.name val start = entry.region.start val end = entry.region.start + entry.region.size - 1 @@ -64,22 +78,12 @@ class BaseTopModule[+L <: BaseTop, +B <: BaseTopBundle](val p: Parameters, l: L, } println("Generated Configuration String") - println(p(ConfigString).get) - - val coreplex = p(BuildCoreplex)(p, c) - val io: B = b(coreplex) - - io.success zip coreplex.io.success map { case (x, y) => x := y } - - val mmioNetwork = - Module(new TileLinkRecursiveInterconnect(1, p(GlobalAddrMap).get.subMap("io:ext"))( - p.alterPartial({ case TLId => "L2toMMIO" }))) - mmioNetwork.io.in.head <> coreplex.io.master.mmio.get - outer.legacy.module.io.legacy <> mmioNetwork.port("TL2") + println(p(ConfigString)) + ConfigStringOutput.contents = Some(p(ConfigString)) } /** Example Top with Periphery */ -class ExampleTop(p: Parameters) extends BaseTop(p) +class ExampleTop(q: Parameters) extends BaseTop(q) with PeripheryBootROM with PeripheryDebug with PeripheryExtInterrupts with PeripheryAON with PeripheryMasterMem with PeripheryMasterMMIO with PeripherySlave { override lazy val module = Module(new ExampleTopModule(p, this, new ExampleTopBundle(p, _))) @@ -94,7 +98,7 @@ class ExampleTopModule[+L <: ExampleTop, +B <: ExampleTopBundle](p: Parameters, with PeripheryMasterMemModule with PeripheryMasterMMIOModule with PeripherySlaveModule /** Example Top with TestRAM */ -class ExampleTopWithTestRAM(p: Parameters) extends ExampleTop(p) +class ExampleTopWithTestRAM(q: Parameters) extends ExampleTop(q) with PeripheryTestRAM { override lazy val module = Module(new ExampleTopWithTestRAMModule(p, this, new ExampleTopWithTestRAMBundle(p, _))) } diff --git a/src/main/scala/rocketchip/UnitTest.scala b/src/main/scala/rocketchip/UnitTest.scala index 1d23e3c7..4ec1db6c 100644 --- a/src/main/scala/rocketchip/UnitTest.scala +++ b/src/main/scala/rocketchip/UnitTest.scala @@ -36,10 +36,10 @@ class UnitTestHarness(implicit val p: Parameters) extends Module { val success = Bool(OUTPUT) } - p(NCoreplexExtClients).assign(0) - p(ConfigString).assign("") - - val l1params = p.alterPartial({ case TLId => "L1toL2" }) + val l1params = p.alterPartial({ + case NCoreplexExtClients => 0 + case ConfigString => "" + case TLId => "L1toL2" }) val tests = Module(new UnitTestSuite()(l1params)) io.success := tests.io.finished diff --git a/src/main/scala/rocketchip/Utils.scala b/src/main/scala/rocketchip/Utils.scala index 1813713c..9b696983 100644 --- a/src/main/scala/rocketchip/Utils.scala +++ b/src/main/scala/rocketchip/Utils.scala @@ -81,7 +81,7 @@ object GenerateGlobalAddrMap { object GenerateConfigString { def apply(p: Parameters, c: CoreplexConfig, pDevicesEntries: Seq[AddrMapEntry]) = { - val addrMap = p(GlobalAddrMap).get + val addrMap = p(GlobalAddrMap) val plicAddr = addrMap("io:int:plic").start val prciAddr = addrMap("io:ext:TL2:prci").start val xLen = p(XLen) @@ -156,8 +156,8 @@ object GenerateBootROM { // for now, have the reset vector jump straight to memory val memBase = ( - if (p(GlobalAddrMap).get contains "mem") p(GlobalAddrMap).get("mem") - else p(GlobalAddrMap).get("io:int:dmem0") + if (p(GlobalAddrMap) contains "mem") p(GlobalAddrMap)("mem") + else p(GlobalAddrMap)("io:int:dmem0") ).start val resetToMemDist = memBase - p(ResetVector) require(resetToMemDist == (resetToMemDist.toInt >> 12 << 12)) @@ -166,6 +166,6 @@ object GenerateBootROM { require(rom.getInt(12) == 0, "Config string address position should not be occupied by code") rom.putInt(12, configStringAddr) - rom.array() ++ (p(ConfigString).get.getBytes.toSeq) + rom.array() ++ (p(ConfigString).getBytes.toSeq) } } From 6b1c57aedc46c288ad021d3e08e5454fa7955905 Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Thu, 15 Sep 2016 14:47:44 -0700 Subject: [PATCH 10/26] tilelink2: compute minimal decisive mask --- .../uncore/tilelink2/AddressDecoder.scala | 118 ++++++++++++++++++ .../scala/uncore/tilelink2/Parameters.scala | 13 +- 2 files changed, 130 insertions(+), 1 deletion(-) create mode 100644 src/main/scala/uncore/tilelink2/AddressDecoder.scala diff --git a/src/main/scala/uncore/tilelink2/AddressDecoder.scala b/src/main/scala/uncore/tilelink2/AddressDecoder.scala new file mode 100644 index 00000000..e937d60d --- /dev/null +++ b/src/main/scala/uncore/tilelink2/AddressDecoder.scala @@ -0,0 +1,118 @@ +// See LICENSE for license details. + +package uncore.tilelink2 + +import Chisel._ +import scala.math.{max,min} + +object AddressDecoder +{ + type Port = Seq[AddressSet] + type Ports = Seq[Port] + type Partition = Ports + type Partitions = Seq[Partition] + + val addressOrder = Ordering.ordered[AddressSet] + val portOrder = Ordering.Iterable(addressOrder) + val partitionOrder = Ordering.Iterable(portOrder) + + // Find the minimum subset of bits needed to disambiguate port addresses. + // ie: inspecting only the bits in the output, you can look at an address + // and decide to which port (outer Seq) the address belongs. + def apply(ports: Ports): BigInt = if (ports.size <= 1) 0 else { + // Every port must have at least one address! + ports.foreach { p => require (!p.isEmpty) } + // Verify the user did not give us an impossible problem + ports.combinations(2).foreach { case Seq(x, y) => + x.foreach { a => y.foreach { b => + require (!a.overlaps(b)) // it must be possible to disambiguate addresses! + } } + } + val maxBits = log2Ceil(ports.map(_.map(_.max).max).max + 1) + val bits = (0 until maxBits).map(BigInt(1) << _).toSeq + val selected = recurse(Seq(ports.map(_.sorted).sorted(portOrder)), bits) + selected.reduceLeft(_ | _) + } + + // A simpler version that works for a Seq[Int] + def apply(keys: Seq[Int]): Int = { + val ports = keys.map(b => Seq(AddressSet(b, 0))) + apply(ports).toInt + } + + // The algorithm has a set of partitions, discriminated by the selected bits. + // Each partion has a set of ports, listing all addresses that lead to that port. + // Seq[Seq[Seq[AddressSet]]] + // ^^^^^^^^^^^^^^^ set of addresses that are routed out this port + // ^^^ the list of ports + // ^^^ cases already distinguished by the selected bits thus far + // + // Solving this problem is NP-hard, so we use a simple greedy heuristic: + // pick the bit which minimizes the number of ports in each partition + // as a secondary goal, reduce the number of AddressSets within a partition + + val bigValue = 100000 + def bitScore(partitions: Partitions): Int = { + val maxPortsPerPartition = partitions.map(_.size).max + val maxSetsPerPartition = partitions.map(_.map(_.size).sum).max + maxPortsPerPartition * bigValue + maxSetsPerPartition + } + + def partitionPort(port: Port, bit: BigInt): (Port, Port) = { + val addr_a = AddressSet(0, ~bit) + val addr_b = AddressSet(bit, ~bit) + // The addresses were sorted, so the filtered addresses are still sorted + val subset_a = port.filter(_.overlaps(addr_a)) + val subset_b = port.filter(_.overlaps(addr_b)) + (subset_a, subset_b) + } + + def partitionPorts(ports: Ports, bit: BigInt): (Ports, Ports) = { + val partitioned_ports = ports.map(p => partitionPort(p, bit)) + // because partitionPort dropped AddresSets, the ports might no longer be sorted + val case_a_ports = partitioned_ports.map(_._1).filter(!_.isEmpty).sorted(portOrder) + val case_b_ports = partitioned_ports.map(_._2).filter(!_.isEmpty).sorted(portOrder) + (case_a_ports, case_b_ports) + } + + def partitionPartitions(partitions: Partitions, bit: BigInt): Partitions = { + val partitioned_partitions = partitions.map(p => partitionPorts(p, bit)) + val case_a_partitions = partitioned_partitions.map(_._1) + val case_b_partitions = partitioned_partitions.map(_._2) + val new_partitions = (case_a_partitions ++ case_b_partitions).sorted(partitionOrder) + // Prevent combinational memory explosion; if two partitions are equal, keep only one + // Note: AddressSets in a port are sorted, and ports in a partition are sorted. + // This makes it easy to structurally compare two partitions for equality + val keep = (new_partitions.init zip new_partitions.tail) filter { case (a,b) => partitionOrder.compare(a,b) != 0 } map { _._2 } + new_partitions.head +: keep + } + + // requirement: ports have sorted addresses and are sorted lexicographically + val debug = false + def recurse(partitions: Partitions, bits: Seq[BigInt]): Seq[BigInt] = { + if (debug) { + println("Partitioning:") + partitions.foreach { partition => + println(" Partition:") + partition.foreach { port => + print(" ") + port.foreach { a => print(s" ${a}") } + println("") + } + } + } + val candidates = bits.map { bit => + val result = partitionPartitions(partitions, bit) + val score = bitScore(result) + (score, bit, result) + } + val (bestScore, bestBit, bestPartitions) = candidates.min(Ordering.by[(Int, BigInt, Partitions), Int](_._1)) + if (debug) println("=> Selected bit 0x%x".format(bestBit)) + if (bestScore < 2*bigValue) { + if (debug) println("---") + Seq(bestBit) + } else { + bestBit +: recurse(bestPartitions, bits.filter(_ != bestBit)) + } + } +} diff --git a/src/main/scala/uncore/tilelink2/Parameters.scala b/src/main/scala/uncore/tilelink2/Parameters.scala index 3c93e96b..6423db3c 100644 --- a/src/main/scala/uncore/tilelink2/Parameters.scala +++ b/src/main/scala/uncore/tilelink2/Parameters.scala @@ -78,7 +78,7 @@ object TransferSizes { // Base is the base address, and mask are the bits consumed by the manager // e.g: base=0x200, mask=0xff describes a device managing 0x200-0x2ff // e.g: base=0x1000, mask=0xf0f decribes a device managing 0x1000-0x100f, 0x1100-0x110f, ... -case class AddressSet(base: BigInt, mask: BigInt) +case class AddressSet(base: BigInt, mask: BigInt) extends Ordered[AddressSet] { // Forbid misaligned base address (and empty sets) require ((base & mask) == 0) @@ -97,6 +97,16 @@ case class AddressSet(base: BigInt, mask: BigInt) // A strided slave serves discontiguous ranges def strided = alignment1 != mask + + // AddressSets have one natural Ordering (the containment order) + def compare(x: AddressSet) = { + val primary = (this.base - x.base).signum // smallest address first + val secondary = (x.mask - this.mask).signum // largest mask first + if (primary != 0) primary else secondary + } + + // We always want to see things in hex + override def toString() = "AddressSet(0x%x, 0x%x)".format(base, mask) } case class TLManagerParameters( @@ -185,6 +195,7 @@ case class TLManagerPortParameters(managers: Seq[TLManagerParameters], beatBytes def findFifoId(address: UInt) = Mux1H(find(address), managers.map(m => UInt(m.fifoId.map(_+1).getOrElse(0)))) def hasFifoId(address: UInt) = Mux1H(find(address), managers.map(m => Bool(m.fifoId.isDefined))) + lazy val addressMask = AddressDecoder(managers.map(_.address)) // !!! need a cheaper version of find, where we assume a valid address match exists // Does this Port manage this ID/address? From 30fa4ea95684a7c53c2dc7c7067a82717adbe2bc Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Thu, 15 Sep 2016 15:52:50 -0700 Subject: [PATCH 11/26] RegisterRouter: compress register mapping for sparse devices --- .../scala/uncore/tilelink2/RegMapper.scala | 56 ++++++++++++------- .../uncore/tilelink2/RegisterRouter.scala | 16 +++--- 2 files changed, 45 insertions(+), 27 deletions(-) diff --git a/src/main/scala/uncore/tilelink2/RegMapper.scala b/src/main/scala/uncore/tilelink2/RegMapper.scala index 88882737..b20937f8 100644 --- a/src/main/scala/uncore/tilelink2/RegMapper.scala +++ b/src/main/scala/uncore/tilelink2/RegMapper.scala @@ -28,8 +28,8 @@ class RegMapperOutput(params: RegMapperParams) extends GenericParameterizedBundl object RegMapper { // Create a generic register-based device - def apply(bytes: Int, concurrency: Option[Int], in: DecoupledIO[RegMapperInput], mapping: RegField.Map*) = { - val regmap = mapping.toList + def apply(bytes: Int, concurrency: Option[Int], undefZero: Boolean, in: DecoupledIO[RegMapperInput], mapping: RegField.Map*) = { + val regmap = mapping.toList.filter(!_._2.isEmpty) require (!regmap.isEmpty) // Ensure no register appears twice @@ -37,15 +37,31 @@ object RegMapper require (reg1 != reg2) } - // Flatten the regmap into (Reg:Int, Offset:Int, field:RegField) - val flat = regmap.map { case (reg, fields) => - val offsets = fields.scanLeft(0)(_ + _.width).init - (offsets zip fields) map { case (o, f) => (reg, o, f) } - }.flatten - require (!flat.isEmpty) + // Convert to and from Bits + def toBits(x: Int, tail: List[Boolean] = List.empty): List[Boolean] = + if (x == 0) tail.reverse else toBits(x >> 1, ((x & 1) == 1) :: tail) + def ofBits(bits: List[Boolean]) = bits.foldRight(0){ case (x,y) => (if (x) 1 else 0) | y << 1 } + // Find the minimal mask that can decide the register map + val mask = AddressDecoder(regmap.map(_._1)) + val maskFilter = toBits(mask) + val maskBits = maskFilter.filter(x => x).size + + // Calculate size and indexes into the register map val endIndex = 1 << log2Ceil(regmap.map(_._1).max+1) val params = RegMapperParams(log2Up(endIndex), bytes, in.bits.params.extraBits) + val regSize = 1 << maskBits + def regIndexI(x: Int) = ofBits((maskFilter zip toBits(x)).filter(_._1).map(_._2)) + def regIndexU(x: UInt) = if (maskBits == 0) UInt(0) else + Cat((maskFilter zip x.toBools).filter(_._1).map(_._2).reverse) + + // Flatten the regmap into (RegIndex:Int, Offset:Int, field:RegField) + val flat = regmap.map { case (reg, fields) => + val offsets = fields.scanLeft(0)(_ + _.width).init + val index = regIndexI(reg) + // println("mapping 0x%x -> 0x%x for 0x%x/%d".format(reg, index, mask, maskBits)) + (offsets zip fields) map { case (o, f) => (index, o, f) } + }.flatten val out = Wire(Irrevocable(new RegMapperOutput(params))) val front = Wire(Irrevocable(new RegMapperInput(params))) @@ -69,13 +85,13 @@ object RegMapper val woready = Wire(Vec(flat.size, Bool())) // Per-register list of all control signals needed for data to flow - val rifire = Array.tabulate(endIndex) { i => Seq(Bool(true)) } - val wifire = Array.tabulate(endIndex) { i => Seq(Bool(true)) } - val rofire = Array.tabulate(endIndex) { i => Seq(Bool(true)) } - val wofire = Array.tabulate(endIndex) { i => Seq(Bool(true)) } + val rifire = Array.tabulate(regSize) { i => Seq(Bool(true)) } + val wifire = Array.tabulate(regSize) { i => Seq(Bool(true)) } + val rofire = Array.tabulate(regSize) { i => Seq(Bool(true)) } + val wofire = Array.tabulate(regSize) { i => Seq(Bool(true)) } // The output values for each register - val dataOut = Array.tabulate(endIndex) { _ => UInt(0) } + val dataOut = Array.tabulate(regSize) { _ => UInt(0) } // Which bits are touched? val frontMask = FillInterleaved(8, front.bits.mask) @@ -110,8 +126,10 @@ object RegMapper val wifireMux = Vec(wifire.map(_.reduce(_ && _))) val rofireMux = Vec(rofire.map(_.reduce(_ && _))) val wofireMux = Vec(wofire.map(_.reduce(_ && _))) - val iready = Mux(front.bits.read, rifireMux(front.bits.index), wifireMux(front.bits.index)) - val oready = Mux(back .bits.read, rofireMux(back .bits.index), wofireMux(back .bits.index)) + val iindex = regIndexU(front.bits.index) + val oindex = regIndexU(back .bits.index) + val iready = Mux(front.bits.read, rifireMux(iindex), wifireMux(iindex)) + val oready = Mux(back .bits.read, rofireMux(oindex), wofireMux(oindex)) // Connect the pipeline in.ready := front.ready && iready @@ -120,11 +138,11 @@ object RegMapper out.valid := back.valid && oready // Which register is touched? - val frontSel = UIntToOH(front.bits.index) - val backSel = UIntToOH(back.bits.index) + val frontSel = UIntToOH(iindex) + val backSel = UIntToOH(oindex) // Include the per-register one-hot selected criteria - for (reg <- 0 until endIndex) { + for (reg <- 0 until regSize) { rifire(reg) = (in.valid && front.ready && front.bits.read && frontSel(reg)) +: rifire(reg) wifire(reg) = (in.valid && front.ready && !front.bits.read && frontSel(reg)) +: wifire(reg) rofire(reg) = (back.valid && out.ready && back .bits.read && backSel (reg)) +: rofire(reg) @@ -141,7 +159,7 @@ object RegMapper } out.bits.read := back.bits.read - out.bits.data := Vec(dataOut)(back.bits.index) + out.bits.data := Vec(dataOut)(oindex) out.bits.extra := back.bits.extra (endIndex, out) diff --git a/src/main/scala/uncore/tilelink2/RegisterRouter.scala b/src/main/scala/uncore/tilelink2/RegisterRouter.scala index c20f0c49..58e9f8c6 100644 --- a/src/main/scala/uncore/tilelink2/RegisterRouter.scala +++ b/src/main/scala/uncore/tilelink2/RegisterRouter.scala @@ -4,7 +4,7 @@ package uncore.tilelink2 import Chisel._ -class TLRegisterNode(address: AddressSet, concurrency: Option[Int] = None, beatBytes: Int = 4) +class TLRegisterNode(address: AddressSet, concurrency: Option[Int] = None, beatBytes: Int = 4, undefZero: Boolean = true) extends TLManagerNode(beatBytes, TLManagerParameters( address = Seq(address), supportsGet = TransferSizes(1, beatBytes), @@ -36,7 +36,7 @@ class TLRegisterNode(address: AddressSet, concurrency: Option[Int] = None, beatB in.bits.extra := Cat(edge.addr_lo(a.bits), a.bits.source, a.bits.size) // Invoke the register map builder - val (endIndex, out) = RegMapper(beatBytes, concurrency, in, mapping:_*) + val (endIndex, out) = RegMapper(beatBytes, concurrency, undefZero, in, mapping:_*) // All registers must fit inside the device address space require (address.mask >= (endIndex-1)*beatBytes) @@ -67,17 +67,17 @@ class TLRegisterNode(address: AddressSet, concurrency: Option[Int] = None, beatB object TLRegisterNode { - def apply(address: AddressSet, concurrency: Option[Int] = None, beatBytes: Int = 4) = - new TLRegisterNode(address, concurrency, beatBytes) + def apply(address: AddressSet, concurrency: Option[Int] = None, beatBytes: Int = 4, undefZero: Boolean = true) = + new TLRegisterNode(address, concurrency, beatBytes, undefZero) } // These convenience methods below combine to make it possible to create a TL2 // register mapped device from a totally abstract register mapped device. // See GPIO.scala in this directory for an example -abstract class TLRegisterRouterBase(address: AddressSet, interrupts: Int, concurrency: Option[Int], beatBytes: Int) extends LazyModule +abstract class TLRegisterRouterBase(address: AddressSet, interrupts: Int, concurrency: Option[Int], beatBytes: Int, undefZero: Boolean) extends LazyModule { - val node = TLRegisterNode(address, concurrency, beatBytes) + val node = TLRegisterNode(address, concurrency, beatBytes, undefZero) val intnode = IntSourceNode(name + s" @ ${address.base}", interrupts) } @@ -100,10 +100,10 @@ class TLRegModule[P, B <: TLRegBundleBase](val params: P, bundleBuilder: => B, r } class TLRegisterRouter[B <: TLRegBundleBase, M <: LazyModuleImp] - (val base: BigInt, val interrupts: Int = 0, val size: BigInt = 4096, val concurrency: Option[Int] = None, val beatBytes: Int = 4) + (val base: BigInt, val interrupts: Int = 0, val size: BigInt = 4096, val concurrency: Option[Int] = None, val beatBytes: Int = 4, undefZero: Boolean = true) (bundleBuilder: TLRegBundleArg => B) (moduleBuilder: (=> B, TLRegisterRouterBase) => M) - extends TLRegisterRouterBase(AddressSet(base, size-1), interrupts, concurrency, beatBytes) + extends TLRegisterRouterBase(AddressSet(base, size-1), interrupts, concurrency, beatBytes, undefZero) { require (isPow2(size)) // require (size >= 4096) ... not absolutely required, but highly recommended From 669e3b0d96a24486a3c34263ac7a996770827999 Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Thu, 15 Sep 2016 16:16:36 -0700 Subject: [PATCH 12/26] Regression: fix-up address lookup --- src/main/scala/coreplex/TestConfigs.scala | 2 +- src/main/scala/groundtest/Regression.scala | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/scala/coreplex/TestConfigs.scala b/src/main/scala/coreplex/TestConfigs.scala index e2e2fd03..2a4f4f6d 100644 --- a/src/main/scala/coreplex/TestConfigs.scala +++ b/src/main/scala/coreplex/TestConfigs.scala @@ -23,7 +23,7 @@ class WithComparator extends Config( case BuildGroundTest => (p: Parameters) => Module(new ComparatorCore()(p)) case ComparatorKey => ComparatorParameters( - targets = Seq("mem", "io:ext:testram").map(name => + targets = Seq("mem", "io:ext:TL2:testram").map(name => site(GlobalAddrMap)(name).start.longValue), width = 8, operations = 1000, diff --git a/src/main/scala/groundtest/Regression.scala b/src/main/scala/groundtest/Regression.scala index ef9eb576..3eb37eed 100644 --- a/src/main/scala/groundtest/Regression.scala +++ b/src/main/scala/groundtest/Regression.scala @@ -72,7 +72,7 @@ class IOGetAfterPutBlockRegression(implicit p: Parameters) extends Regression()( io.mem.grant.ready := Bool(true) io.cache.req.valid := !get_sent && started - io.cache.req.bits.addr := UInt(addrMap("io:ext:bootrom").start) + io.cache.req.bits.addr := UInt(addrMap("io:ext:TL2:bootrom").start) io.cache.req.bits.typ := UInt(log2Ceil(32 / 8)) io.cache.req.bits.cmd := M_XRD io.cache.req.bits.tag := UInt(0) From 38a9421c75d155c608ff0894b684bab8a264352e Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Thu, 15 Sep 2016 18:55:58 -0700 Subject: [PATCH 13/26] Comparator: don't compare addr_beat when it's irrelevant --- src/main/scala/groundtest/Comparator.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/scala/groundtest/Comparator.scala b/src/main/scala/groundtest/Comparator.scala index 67cffb9e..8c5c8213 100644 --- a/src/main/scala/groundtest/Comparator.scala +++ b/src/main/scala/groundtest/Comparator.scala @@ -338,7 +338,7 @@ class ComparatorSink(implicit val p: Parameters) extends Module assert (g.is_builtin_type, "grant not builtin") assert (base.g_type === g.g_type, "g_type mismatch") - assert (base.addr_beat === g.addr_beat || !g.hasData(), "addr_beat mismatch") + assert (base.addr_beat === g.addr_beat || !g.hasMultibeatData(), "addr_beat mismatch") assert (base.data === g.data || !g.hasData(), "data mismatch") assert_conds.zipWithIndex.foreach { case (cond, i) => From f05222a0724d3784fe50cf98e8d2875a3da77f78 Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Thu, 15 Sep 2016 21:15:30 -0700 Subject: [PATCH 14/26] testconfigs: disable atomics until AtomicAbsorber finished --- src/main/scala/coreplex/TestConfigs.scala | 4 ++-- src/main/scala/uncore/tilelink2/Legacy.scala | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/scala/coreplex/TestConfigs.scala b/src/main/scala/coreplex/TestConfigs.scala index 2a4f4f6d..0e7ecace 100644 --- a/src/main/scala/coreplex/TestConfigs.scala +++ b/src/main/scala/coreplex/TestConfigs.scala @@ -27,7 +27,7 @@ class WithComparator extends Config( site(GlobalAddrMap)(name).start.longValue), width = 8, operations = 1000, - atomics = site(UseAtomics), + atomics = false, // !!! re-enable soon: site(UseAtomics), prefetches = site("COMPARATOR_PREFETCHES")) case FPUConfig => None case UseAtomics => false @@ -191,7 +191,7 @@ class WithDirectComparator extends Config( targets = Seq(0L, 0x100L), width = 8, operations = 1000, - atomics = site(UseAtomics), + atomics = false, // !!! re-enable soon: site(UseAtomics), prefetches = site("COMPARATOR_PREFETCHES")) case FPUConfig => None case UseAtomics => false diff --git a/src/main/scala/uncore/tilelink2/Legacy.scala b/src/main/scala/uncore/tilelink2/Legacy.scala index 91bb74b6..e55f8c05 100644 --- a/src/main/scala/uncore/tilelink2/Legacy.scala +++ b/src/main/scala/uncore/tilelink2/Legacy.scala @@ -78,6 +78,8 @@ class TLLegacy(implicit val p: Parameters) extends LazyModule with HasTileLinkPa MemoryOpConstants.M_XA_MINU -> edge.Arithmetic(source, address, beat, data, TLAtomics.MINU)._2, MemoryOpConstants.M_XA_MAXU -> edge.Arithmetic(source, address, beat, data, TLAtomics.MAXU)._2)) } else { + // If no managers support atomics, assert fail if TL1 asks for them + assert (!io.legacy.acquire.valid || io.legacy.acquire.bits.a_type =/= Acquire.putAtomicType) Wire(new TLBundleA(edge.bundle)) } From 0e80f7fd0fc846963a22956caf3815019eb896d6 Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Thu, 15 Sep 2016 21:27:49 -0700 Subject: [PATCH 15/26] HintHandler: don't violate Irrevocable rules --- .../scala/uncore/tilelink2/HintHandler.scala | 68 +++++++++++++------ 1 file changed, 48 insertions(+), 20 deletions(-) diff --git a/src/main/scala/uncore/tilelink2/HintHandler.scala b/src/main/scala/uncore/tilelink2/HintHandler.scala index 3d57f03c..4e1bd12d 100644 --- a/src/main/scala/uncore/tilelink2/HintHandler.scala +++ b/src/main/scala/uncore/tilelink2/HintHandler.scala @@ -32,22 +32,36 @@ class TLHintHandler(supportManagers: Boolean = true, supportClients: Boolean = f val smartManagers = edgeOut.manager.managers.map(_.supportsHint.max == edgeOut.manager.maxTransfer).reduce(_&&_) if (supportManagers && !smartManagers) { + // State of the Hint bypass + val counter = RegInit(UInt(0, width = log2Up(edgeOut.manager.maxTransfer/edgeOut.manager.beatBytes))) + val hintHoldsD = RegInit(Bool(false)) + val outerHoldsD = counter =/= UInt(0) + // Only one of them can hold it + assert (!hintHoldsD || !outerHoldsD) + + // Count outer D beats + val beats1 = edgeOut.numBeats1(out.d.bits) + when (out.d.fire()) { counter := Mux(outerHoldsD, counter - UInt(1), beats1) } + + // Who wants what? val address = edgeIn.address(in.a.bits) val handleA = if (passthrough) !edgeOut.manager.supportsHint(address, edgeIn.size(in.a.bits)) else Bool(true) - val bypassD = handleA && in.a.bits.opcode === TLMessages.Hint + val hintBitsAtA = handleA && in.a.bits.opcode === TLMessages.Hint + val hintWantsD = in.a.valid && hintBitsAtA + val outerWantsD = out.d.valid // Prioritize existing D traffic over HintAck (and finish multibeat xfers) - val beats1 = edgeOut.numBeats1(out.d.bits) - val counter = RegInit(UInt(0, width = log2Up(edgeOut.manager.maxTransfer/edgeOut.manager.beatBytes))) - val first = counter === UInt(0) - when (out.d.fire()) { counter := Mux(first, beats1, counter - UInt(1)) } + val hintWinsD = hintHoldsD || (!outerHoldsD && !outerWantsD) + hintHoldsD := hintWantsD && hintWinsD && !in.d.ready + // Hint can only hold D b/c it still wants it from last cycle + assert (!hintHoldsD || hintWantsD) - in.d.valid := out.d.valid || (bypassD && in.a.valid && first) - out.d.ready := in.d.ready - in.d.bits := Mux(out.d.valid, out.d.bits, edgeIn.HintAck(in.a.bits, edgeOut.manager.findId(address))) + in.d.valid := Mux(hintWinsD, hintWantsD, outerWantsD) + in.d.bits := Mux(hintWinsD, edgeIn.HintAck(in.a.bits, edgeOut.manager.findId(address)), out.d.bits) + out.d.ready := in.d.ready && !hintHoldsD - in.a.ready := Mux(bypassD, in.d.ready && first && !out.d.valid, out.a.ready) - out.a.valid := in.a.valid && !bypassD + in.a.ready := Mux(hintBitsAtA, hintWinsD && in.d.ready, out.a.ready) + out.a.valid := in.a.valid && !hintBitsAtA out.a.bits := in.a.bits } else { out.a.valid := in.a.valid @@ -60,21 +74,35 @@ class TLHintHandler(supportManagers: Boolean = true, supportClients: Boolean = f } if (supportClients && !smartClients) { + // State of the Hint bypass + val counter = RegInit(UInt(0, width = log2Up(edgeIn.client.maxTransfer/edgeIn.manager.beatBytes))) + val hintHoldsC = RegInit(Bool(false)) + val innerHoldsC = counter =/= UInt(0) + // Only one of them can hold it + assert (!hintHoldsC || !innerHoldsC) + + // Count inner C beats + val beats1 = edgeIn.numBeats1(in.c.bits) + when (in.c.fire()) { counter := Mux(innerHoldsC, counter - UInt(1), beats1) } + + // Who wants what? val handleB = if (passthrough) !edgeIn.client.supportsHint(out.b.bits.source, edgeOut.size(out.b.bits)) else Bool(true) - val bypassC = handleB && out.b.bits.opcode === TLMessages.Hint + val hintBitsAtB = handleB && out.b.bits.opcode === TLMessages.Hint + val hintWantsC = out.b.valid && hintBitsAtB + val innerWantsC = in.c.valid // Prioritize existing C traffic over HintAck (and finish multibeat xfers) - val beats1 = edgeIn.numBeats1(in.c.bits) - val counter = RegInit(UInt(0, width = log2Up(edgeIn.client.maxTransfer/edgeIn.manager.beatBytes))) - val first = counter === UInt(0) - when (in.c.fire()) { counter := Mux(first, beats1, counter - UInt(1)) } + val hintWinsC = hintHoldsC || (!innerHoldsC && !innerWantsC) + hintHoldsC := hintWantsC && hintWinsC && !out.c.ready + // Hint can only hold C b/c it still wants it from last cycle + assert (!hintHoldsC || hintWantsC) - out.c.valid := in.c.valid || (bypassC && in.b.valid && first) - in.c.ready := out.c.ready - out.c.bits := Mux(in.c.valid, in.c.bits, edgeOut.HintAck(out.b.bits)) + out.c.valid := Mux(hintWinsC, hintWantsC, innerWantsC) + out.c.bits := Mux(hintWinsC, edgeOut.HintAck(out.b.bits), in.c.bits) + in.c.ready := out.c.ready && !hintHoldsC - out.b.ready := Mux(bypassC, out.c.ready && first && !in.c.valid, in.b.ready) - in.b.valid := out.b.valid && !bypassC + out.b.ready := Mux(hintBitsAtB, hintWinsC && out.c.ready, in.b.ready) + in.b.valid := out.b.valid && !hintBitsAtB in.b.bits := out.b.bits } else if (bce) { in.b.valid := out.b.valid From 2c53620275f62d3c4ac2b00df7e1dc5b9fadb392 Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Thu, 15 Sep 2016 21:28:16 -0700 Subject: [PATCH 16/26] chisel3: bump for Irrevocable(Decoupled) constructor --- chisel3 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/chisel3 b/chisel3 index 2ff229da..dda64c1d 160000 --- a/chisel3 +++ b/chisel3 @@ -1 +1 @@ -Subproject commit 2ff229dac5f915e7f583cbf9cc8118674a4e52a5 +Subproject commit dda64c1dee16b5da15ac690bd3cd6759c3d5c032 From e1d7f6d7df40bc8909fb1df3ee19cf31bd92585c Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Thu, 15 Sep 2016 22:06:39 -0700 Subject: [PATCH 17/26] PRCI: always use bus width >= XLen --- src/main/scala/rocketchip/Periphery.scala | 9 +++++++-- src/main/scala/uncore/devices/Prci.scala | 23 ++++++++++++++++++----- 2 files changed, 25 insertions(+), 7 deletions(-) diff --git a/src/main/scala/rocketchip/Periphery.scala b/src/main/scala/rocketchip/Periphery.scala index cdc0275e..7559187c 100644 --- a/src/main/scala/rocketchip/Periphery.scala +++ b/src/main/scala/rocketchip/Periphery.scala @@ -12,6 +12,8 @@ import uncore.converters._ import uncore.devices._ import uncore.util._ import rocket.Util._ +import rocket.XLen +import scala.math.max import coreplex._ /** Options for memory bus interface */ @@ -282,8 +284,11 @@ trait PeripheryAON extends LazyModule with HasPeripheryParameters { implicit val p: Parameters val peripheryBus: TLXbar - val prci = LazyModule(new PRCI()(innerMMIOParams)) - prci.node := TLFragmenter(peripheryBus.node, 4, 256) + // PRCI must be at least XLen in size for atomicity + val beatBytes = max(innerMMIOParams(XLen)/8, 4) + val prci = LazyModule(new PRCI(PRCIConfig(beatBytes))(innerMMIOParams)) + // The periphery bus is 32-bit, so we may need to adapt PRCI's width + prci.node := TLFragmenter(TLWidthWidget(peripheryBus.node, 4), beatBytes, 256) // TL1 legacy val pDevices: ResourceManager[AddrMapEntry] diff --git a/src/main/scala/uncore/devices/Prci.scala b/src/main/scala/uncore/devices/Prci.scala index 22b45425..334072b5 100644 --- a/src/main/scala/uncore/devices/Prci.scala +++ b/src/main/scala/uncore/devices/Prci.scala @@ -8,6 +8,7 @@ import junctions._ import junctions.NastiConstants._ import uncore.tilelink2._ import uncore.util._ +import scala.math.{min,max} import cde.{Parameters, Field} /** Number of tiles */ @@ -32,7 +33,7 @@ object PRCI { def size = 0xc000 } -case class PRCIConfig(address: BigInt = 0x44000000, beatBytes: Int = 4) +case class PRCIConfig(beatBytes: Int, address: BigInt = 0x44000000) trait MixPRCIParameters { val params: (PRCIConfig, Parameters) @@ -49,7 +50,7 @@ trait PRCIModule extends Module with HasRegMap with MixPRCIParameters { val io: PRCIBundle val timeWidth = 64 - val time = Reg(init=UInt(0, timeWidth)) + val time = Reg(init=UInt(0, width = timeWidth)) when (io.rtcTick) { time := time + UInt(1) } val timecmp = Seq.fill(p(NTiles)) { Reg(UInt(width = timeWidth)) } @@ -71,18 +72,30 @@ trait PRCIModule extends Module with HasRegMap with MixPRCIParameters { * bffc mtime hi */ + // laying out IPI fields suck... + // bytes=1 -> pad to 7, step 4, group 1 + // bytes=2 -> pad to 15, step 2, group 1 + // bytes=4 -> pad to 31, step 1, group 1 + // bytes=8 -> pad to 31, step 1, group 2 + // bytes=16-> pad to 31, step 1, group 4 + val pad = min(c.beatBytes*8,32) - 1 + val step = max(1, 4/c.beatBytes) + val group = max(1, c.beatBytes/4) + val ipi_regs = ipi.map { reg => Seq(RegField(1, reg), RegField(pad)) }.flatten.grouped(group*2). + zipWithIndex.map { case (fields, i) => (i*step -> fields) } + + // Just split up time fields by bytes val timecmp_regs = timecmp.zipWithIndex.map { case (reg, i) => RegField.bytes(reg, PRCI.timecmp(i)/c.beatBytes, c.beatBytes) }.flatten val time_reg = RegField.bytes(time, PRCI.time/c.beatBytes, c.beatBytes) - val ipi_regs = ipi.zipWithIndex.map { case (reg, i) => (i -> Seq(RegField(1, reg))) } regmap((timecmp_regs ++ time_reg ++ ipi_regs):_*) } /** Power, Reset, Clock, Interrupt */ // Magic TL2 Incantation to create a TL2 Slave -class PRCI(c: PRCIConfig = PRCIConfig())(implicit val p: Parameters) - extends TLRegisterRouter(c.address, 0, 0x10000, None, c.beatBytes)( +class PRCI(c: PRCIConfig)(implicit val p: Parameters) + extends TLRegisterRouter(c.address, 0, 0x10000, None, c.beatBytes, false)( new TLRegBundle((c, p), _) with PRCIBundle)( new TLRegModule((c, p), _, _) with PRCIModule) From dd19e0911e4114e52b2bce3af7658075220f1c45 Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Thu, 15 Sep 2016 22:13:08 -0700 Subject: [PATCH 18/26] tilelink2: handle bus width=1 --- src/main/scala/uncore/tilelink2/Fragmenter.scala | 4 ++-- src/main/scala/uncore/tilelink2/RegisterRouter.scala | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/scala/uncore/tilelink2/Fragmenter.scala b/src/main/scala/uncore/tilelink2/Fragmenter.scala index 32fd539b..30775583 100644 --- a/src/main/scala/uncore/tilelink2/Fragmenter.scala +++ b/src/main/scala/uncore/tilelink2/Fragmenter.scala @@ -146,7 +146,7 @@ class TLFragmenter(minSize: Int, maxSize: Int, alwaysMin: Boolean = false) exten val dFragnum = out.d.bits.source(fragmentBits-1, 0) val dFirst = acknum === UInt(0) val dsizeOH = UIntToOH (out.d.bits.size, log2Ceil(maxDownSize)+1) - val dsizeOH1 = UIntToOH1(out.d.bits.size, log2Ceil(maxDownSize)) + val dsizeOH1 = UIntToOH1(out.d.bits.size, log2Up(maxDownSize)) val dHasData = edgeOut.hasData(out.d.bits) // calculate new acknum @@ -209,7 +209,7 @@ class TLFragmenter(minSize: Int, maxSize: Int, alwaysMin: Boolean = false) exten val aOrig = in.a.bits.size val aFrag = Mux(aOrig > limit, limit, aOrig) val aOrigOH1 = UIntToOH1(aOrig, log2Ceil(maxSize)) - val aFragOH1 = UIntToOH1(aFrag, log2Ceil(maxDownSize)) + val aFragOH1 = UIntToOH1(aFrag, log2Up(maxDownSize)) val aHasData = node.edgesIn(0).hasData(in.a.bits) val aMask = Mux(aHasData, UInt(0), aFragOH1) diff --git a/src/main/scala/uncore/tilelink2/RegisterRouter.scala b/src/main/scala/uncore/tilelink2/RegisterRouter.scala index 58e9f8c6..7cf6184d 100644 --- a/src/main/scala/uncore/tilelink2/RegisterRouter.scala +++ b/src/main/scala/uncore/tilelink2/RegisterRouter.scala @@ -25,7 +25,7 @@ class TLRegisterNode(address: AddressSet, concurrency: Option[Int] = None, beatB val baseEnd = 0 val (sizeEnd, sizeOff) = (edge.bundle.sizeBits + baseEnd, baseEnd) val (sourceEnd, sourceOff) = (edge.bundle.sourceBits + sizeEnd, sizeEnd) - val (addrLoEnd, addrLoOff) = (log2Ceil(beatBytes) + sourceEnd, sourceEnd) + val (addrLoEnd, addrLoOff) = (log2Up(beatBytes) + sourceEnd, sourceEnd) val params = RegMapperParams(log2Up(address.mask+1), beatBytes, addrLoEnd) val in = Wire(Decoupled(new RegMapperInput(params))) From a94b4af92d745244c72c70c33ac969e975c7d5c2 Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Thu, 15 Sep 2016 14:45:47 -0700 Subject: [PATCH 19/26] Simplify AsyncResetRegVec and make AsyncResetReg companion object --- src/main/scala/uncore/util/BlackBoxRegs.scala | 44 +++++++++++++------ 1 file changed, 31 insertions(+), 13 deletions(-) diff --git a/src/main/scala/uncore/util/BlackBoxRegs.scala b/src/main/scala/uncore/util/BlackBoxRegs.scala index 23271f9b..51af290f 100644 --- a/src/main/scala/uncore/util/BlackBoxRegs.scala +++ b/src/main/scala/uncore/util/BlackBoxRegs.scala @@ -45,7 +45,6 @@ class AsyncResetReg extends BlackBox { } - class SimpleRegIO(val w: Int) extends Bundle{ val d = UInt(INPUT, width = w) @@ -55,29 +54,48 @@ class SimpleRegIO(val w: Int) extends Bundle{ } -class AsyncResetRegVec(val w: Int, val init: Int) extends Module { +class AsyncResetRegVec(val w: Int, val init: BigInt) extends Module { val io = new SimpleRegIO(w) - val bb_q = Wire(UInt(width = w)) - val bb_d = Wire(UInt(width = w)) - - val init_val = Wire(UInt(width = w)) - init_val := UInt(init, width = w) + val bb_d = Mux(io.en, io.d, io.q) val async_regs = List.fill(w)(Module (new AsyncResetReg)) - bb_q := (async_regs.map(_.io.q)).asUInt() - bb_d := Mux(io.en , io.d , bb_q) + io.q := async_regs.map(_.io.q).asUInt - io.q := bb_q - - for ((reg, idx) <- async_regs.zipWithIndex) { reg.io.clk := clock reg.io.rst := reset - reg.io.init := init_val(idx) + reg.io.init := Bool(((init >> idx) & 1) == 1) reg.io.d := bb_d(idx) } } + +object AsyncResetReg { + def apply(d: Bool, clk: Clock, rst: Bool, init: Bool): Bool = { + val reg = Module(new AsyncResetReg) + reg.io.d := d + reg.io.clk := clk + reg.io.rst := rst + reg.io.init := init + reg.io.q + } + + def apply(d: Bool, clk: Clock, rst: Bool): Bool = apply(d, clk, rst, Bool(false)) + + def apply(updateData: UInt, resetData: BigInt, enable: Bool): UInt = { + val w = updateData.getWidth max resetData.bitLength + val reg = Module(new AsyncResetRegVec(w, resetData)) + reg.io.d := updateData + reg.io.en := enable + reg.io.q + } + + def apply(updateData: UInt, resetData: BigInt): UInt = apply(updateData, resetData, Bool(true)) + + def apply(updateData: UInt, enable: Bool): UInt = apply(updateData, BigInt(0), enable) + + def apply(updateData: UInt): UInt = apply(updateData, BigInt(0), Bool(true)) +} From a031686763982de66a11cf61884a116262419cee Mon Sep 17 00:00:00 2001 From: mwachs5 Date: Fri, 16 Sep 2016 13:50:09 -0700 Subject: [PATCH 20/26] util: Do BlackBox Async Set/Reset Registers more properly (#305) * util: Do Set/Reset Async Registers more properly The way BlackBox "init" registers were coded before was not really kosher verilog for most synthesis tools. Also, the enable logic wasn't really pushed down into the flop. This change is more explicit about set/reset flops, again this is only a 'temporary' problem that would go away with parameterizable blackboxes (or general async reset support). * Tabs, not spaces, in Makefiles * util: Fix typos in Async BB Reg Comments --- src/main/scala/uncore/util/BlackBoxRegs.scala | 49 +++++++++++-------- vsim/Makefrag | 7 +-- vsrc/AsyncResetReg.v | 21 +++----- vsrc/AsyncSetReg.v | 47 ++++++++++++++++++ 4 files changed, 88 insertions(+), 36 deletions(-) create mode 100644 vsrc/AsyncSetReg.v diff --git a/src/main/scala/uncore/util/BlackBoxRegs.scala b/src/main/scala/uncore/util/BlackBoxRegs.scala index 51af290f..439adab0 100644 --- a/src/main/scala/uncore/util/BlackBoxRegs.scala +++ b/src/main/scala/uncore/util/BlackBoxRegs.scala @@ -5,13 +5,17 @@ import Chisel._ import cde.{Parameters} /** This black-boxes an Async Reset - * Reg. + * (or Set) + * Register. * * Because Chisel doesn't support * parameterized black boxes, * we unfortunately have to * instantiate a number of these. * + * We also have to hard-code the set/ + * reset behavior. + * * Do not confuse an asynchronous * reset signal with an asynchronously * reset reg. You should still @@ -22,29 +26,26 @@ import cde.{Parameters} * @param q Data Output * @param clk Clock Input * @param rst Reset Input + * @param en Write Enable Input * - * @param init Value to write at Reset. - * This is a constant, - * but this construction - * will likely make backend flows - * and lint tools unhappy. - * */ -class AsyncResetReg extends BlackBox { +abstract class AbstractBBReg extends BlackBox { val io = new Bundle { val d = Bool(INPUT) val q = Bool(OUTPUT) + val en = Bool(INPUT) val clk = Clock(INPUT) val rst = Bool(INPUT) - - val init = Bool(INPUT) } } +class AsyncResetReg extends AbstractBBReg +class AsyncSetReg extends AbstractBBReg + class SimpleRegIO(val w: Int) extends Bundle{ val d = UInt(INPUT, width = w) @@ -60,30 +61,38 @@ class AsyncResetRegVec(val w: Int, val init: BigInt) extends Module { val bb_d = Mux(io.en, io.d, io.q) - val async_regs = List.fill(w)(Module (new AsyncResetReg)) + val async_regs: List[AbstractBBReg] = List.tabulate(w)( + i => Module ( + if (((init >> i) % 2) > 0) + new AsyncSetReg + else + new AsyncResetReg) + ) io.q := async_regs.map(_.io.q).asUInt for ((reg, idx) <- async_regs.zipWithIndex) { reg.io.clk := clock reg.io.rst := reset - reg.io.init := Bool(((init >> idx) & 1) == 1) - reg.io.d := bb_d(idx) + reg.io.d := bb_d(idx) + reg.io.en := io.en } } object AsyncResetReg { - def apply(d: Bool, clk: Clock, rst: Bool, init: Bool): Bool = { - val reg = Module(new AsyncResetReg) + def apply(d: Bool, clk: Clock, rst: Bool, init: Boolean): Bool = { + val reg: AbstractBBReg = + if (init) Module (new AsyncSetReg) + else Module(new AsyncResetReg) reg.io.d := d reg.io.clk := clk reg.io.rst := rst - reg.io.init := init + reg.io.en := Bool(true) reg.io.q } - def apply(d: Bool, clk: Clock, rst: Bool): Bool = apply(d, clk, rst, Bool(false)) + def apply(d: Bool, clk: Clock, rst: Bool): Bool = apply(d, clk, rst, false) def apply(updateData: UInt, resetData: BigInt, enable: Bool): UInt = { val w = updateData.getWidth max resetData.bitLength @@ -93,9 +102,9 @@ object AsyncResetReg { reg.io.q } - def apply(updateData: UInt, resetData: BigInt): UInt = apply(updateData, resetData, Bool(true)) + def apply(updateData: UInt, resetData: BigInt): UInt = apply(updateData, resetData, enable=Bool(true)) - def apply(updateData: UInt, enable: Bool): UInt = apply(updateData, BigInt(0), enable) + def apply(updateData: UInt, enable: Bool): UInt = apply(updateData, resetData=BigInt(0), enable) - def apply(updateData: UInt): UInt = apply(updateData, BigInt(0), Bool(true)) + def apply(updateData: UInt): UInt = apply(updateData, resetData=BigInt(0), enable=Bool(true)) } diff --git a/vsim/Makefrag b/vsim/Makefrag index ba537d85..ed8e3bbf 100644 --- a/vsim/Makefrag +++ b/vsim/Makefrag @@ -8,10 +8,11 @@ bb_vsrcs = $(base_dir)/vsrc/DebugTransportModuleJtag.v \ $(base_dir)/vsrc/jtag_vpi.v \ $(base_dir)/vsrc/AsyncMailbox.v \ $(base_dir)/vsrc/AsyncResetReg.v \ + $(base_dir)/vsrc/AsyncSetReg.v \ $(base_dir)/vsrc/ClockDivider.v \ - $(base_dir)/vsrc/ClockToSignal.v \ - $(base_dir)/vsrc/SignalToClock.v \ - + $(base_dir)/vsrc/ClockToSignal.v \ + $(base_dir)/vsrc/SignalToClock.v \ + sim_vsrcs = \ $(generated_dir)/$(MODEL).$(CONFIG).v \ diff --git a/vsrc/AsyncResetReg.v b/vsrc/AsyncResetReg.v index 3adf16b1..4775f6c6 100644 --- a/vsrc/AsyncResetReg.v +++ b/vsrc/AsyncResetReg.v @@ -8,6 +8,8 @@ * we unfortunately have to * instantiate a number of these. * + * We also have to hard-code the set/reset. + * * Do not confuse an asynchronous * reset signal with an asynchronously * reset reg. You should still @@ -18,32 +20,25 @@ * @param q Data Output * @param clk Clock Input * @param rst Reset Input + * @param en Write Enable Input * - * @param init Value to write at Reset. - * This is a constant, - * but this construction - * will likely make backend flows - * and lint tools unhappy. - * */ module AsyncResetReg ( input d, output reg q, + input en, input clk, - input rst, - - input init); - + input rst); + always @(posedge clk or posedge rst) begin if (rst) begin - q <= init; - end else begin + q <= 1'b0; + end else if (en) begin q <= d; end - end diff --git a/vsrc/AsyncSetReg.v b/vsrc/AsyncSetReg.v new file mode 100644 index 00000000..ffafdab3 --- /dev/null +++ b/vsrc/AsyncSetReg.v @@ -0,0 +1,47 @@ + + +/** This black-boxes an Async Set + * Reg. + * + * Because Chisel doesn't support + * parameterized black boxes, + * we unfortunately have to + * instantiate a number of these. + * + * We also have to hard-code the set/reset. + * + * Do not confuse an asynchronous + * reset signal with an asynchronously + * reset reg. You should still + * properly synchronize your reset + * deassertion. + * + * @param d Data input + * @param q Data Output + * @param clk Clock Input + * @param rst Reset Input + * @param en Write Enable Input + * + */ + +module AsyncSetReg ( + input d, + output reg q, + input en, + + input clk, + input rst); + + always @(posedge clk or posedge rst) begin + + if (rst) begin + q <= 1'b1; + end else if (en) begin + q <= d; + end + + end + + +endmodule // AsyncSetReg + From 6134384da4549c35396b4ad54b947ed8b1df1f42 Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Fri, 16 Sep 2016 12:43:36 -0700 Subject: [PATCH 21/26] Fix deprecation warnings --- src/main/scala/uncore/tilelink2/Monitor.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/scala/uncore/tilelink2/Monitor.scala b/src/main/scala/uncore/tilelink2/Monitor.scala index ffd4c5f6..9ab63c9c 100644 --- a/src/main/scala/uncore/tilelink2/Monitor.scala +++ b/src/main/scala/uncore/tilelink2/Monitor.scala @@ -406,7 +406,7 @@ object TLMonitor val last_v = RegNext(irr.valid, Bool(false)) val last_r = RegNext(irr.ready, Bool(false)) val last_b = RegNext(irr.bits) - val bits_changed = irr.bits.toBits === last_b.toBits + val bits_changed = irr.bits.asUInt === last_b.asUInt when (last_v && !last_r) { assert(irr.valid, s"${irr.bits.channelName} had contents that were revoked by the supplier (valid lowered)" + extra) From 943c36954d676c9f4f3b4ad64b7ce5933d19bc21 Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Fri, 16 Sep 2016 13:45:05 -0700 Subject: [PATCH 22/26] tilelink2 RegField: .bytes should update more than one byte! --- src/main/scala/uncore/tilelink2/RegField.scala | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/scala/uncore/tilelink2/RegField.scala b/src/main/scala/uncore/tilelink2/RegField.scala index 3a49659f..7a51cb1f 100644 --- a/src/main/scala/uncore/tilelink2/RegField.scala +++ b/src/main/scala/uncore/tilelink2/RegField.scala @@ -110,12 +110,12 @@ object RegField // The bytes can be individually written, as they are one byte per field def bytes(x: UInt, base: Int = 0, beatBytes: Int = 4): Seq[RegField.Map] = { require (x.getWidth % 8 == 0) + val bytes = Seq.tabulate(x.getWidth/8) { i => x(8*(i+1)-1, 8*i) } + val wires = bytes.map { b => Wire(init = b) } + x := Cat(wires.reverse) Seq.tabulate(x.getWidth/8) { i => - RegField(8, x(8*(i+1)-1, 8*i), RegWriteFn { (valid, data) => - when (valid) { - val mask = ~UInt(BigInt(0xff) << 8*i, width = x.getWidth) - x := (x & mask) | (data & UInt(0xff)) << 8*i - } + RegField(8, bytes(i), RegWriteFn { (valid, data) => + when (valid) { wires(i) := data } Bool(true) }) }.grouped(beatBytes).toSeq.zipWithIndex.map { case (reg, i) => From 4b1de82c1db7c0cc3c758648a5b579d6424356b0 Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Fri, 16 Sep 2016 14:19:42 -0700 Subject: [PATCH 23/26] RegField: separate UInt=>bytes and bytes=>regs --- src/main/scala/uncore/devices/Prci.scala | 31 +++++++------------ .../scala/uncore/tilelink2/RegField.scala | 11 +++++-- 2 files changed, 20 insertions(+), 22 deletions(-) diff --git a/src/main/scala/uncore/devices/Prci.scala b/src/main/scala/uncore/devices/Prci.scala index 334072b5..d43beea3 100644 --- a/src/main/scala/uncore/devices/Prci.scala +++ b/src/main/scala/uncore/devices/Prci.scala @@ -62,6 +62,11 @@ trait PRCIModule extends Module with HasRegMap with MixPRCIParameters { tile.reset := reset } + def pad = RegField(8) // each use is a new field + val ipi_fields = ipi.map(r => Seq(RegField(1, r), RegField(7), pad, pad, pad)).flatten + val timecmp_fields = timecmp.map(RegField.bytes(_)).flatten + val time_fields = Seq.fill(PRCI.time%c.beatBytes)(pad) ++ RegField.bytes(time) + /* 0000 msip hart 0 * 0004 msip hart 1 * 4000 mtimecmp hart 0 lo @@ -71,26 +76,14 @@ trait PRCIModule extends Module with HasRegMap with MixPRCIParameters { * bff8 mtime lo * bffc mtime hi */ + val ipi_base = 0 + val timecmp_base = PRCI.timecmp(0) / c.beatBytes + val time_base = PRCI.time / c.beatBytes - // laying out IPI fields suck... - // bytes=1 -> pad to 7, step 4, group 1 - // bytes=2 -> pad to 15, step 2, group 1 - // bytes=4 -> pad to 31, step 1, group 1 - // bytes=8 -> pad to 31, step 1, group 2 - // bytes=16-> pad to 31, step 1, group 4 - val pad = min(c.beatBytes*8,32) - 1 - val step = max(1, 4/c.beatBytes) - val group = max(1, c.beatBytes/4) - val ipi_regs = ipi.map { reg => Seq(RegField(1, reg), RegField(pad)) }.flatten.grouped(group*2). - zipWithIndex.map { case (fields, i) => (i*step -> fields) } - - // Just split up time fields by bytes - val timecmp_regs = timecmp.zipWithIndex.map { case (reg, i) => - RegField.bytes(reg, PRCI.timecmp(i)/c.beatBytes, c.beatBytes) - }.flatten - val time_reg = RegField.bytes(time, PRCI.time/c.beatBytes, c.beatBytes) - - regmap((timecmp_regs ++ time_reg ++ ipi_regs):_*) + regmap(( + RegField.split(ipi_fields, ipi_base, c.beatBytes) ++ + RegField.split(timecmp_fields, timecmp_base, c.beatBytes) ++ + RegField.split(time_fields, time_base, c.beatBytes)):_*) } /** Power, Reset, Clock, Interrupt */ diff --git a/src/main/scala/uncore/tilelink2/RegField.scala b/src/main/scala/uncore/tilelink2/RegField.scala index 7a51cb1f..2b372208 100644 --- a/src/main/scala/uncore/tilelink2/RegField.scala +++ b/src/main/scala/uncore/tilelink2/RegField.scala @@ -108,7 +108,7 @@ object RegField // Split a large register into a sequence of byte fields // The bytes can be individually written, as they are one byte per field - def bytes(x: UInt, base: Int = 0, beatBytes: Int = 4): Seq[RegField.Map] = { + def bytes(x: UInt): Seq[RegField] = { require (x.getWidth % 8 == 0) val bytes = Seq.tabulate(x.getWidth/8) { i => x(8*(i+1)-1, 8*i) } val wires = bytes.map { b => Wire(init = b) } @@ -118,10 +118,15 @@ object RegField when (valid) { wires(i) := data } Bool(true) }) - }.grouped(beatBytes).toSeq.zipWithIndex.map { case (reg, i) => - (i+base, reg) } } + + // Divide a long sequence of RegFields into a maximum sized registers + // Your input RegFields may not cross a beatBytes boundary! + def split(fields: Seq[RegField], base: Int, beatBytes: Int = 4): Seq[RegField.Map] = { + val offsets = fields.map(_.width).scanLeft(0)(_ + _).init + (offsets zip fields).groupBy(_._1 / (beatBytes*8)).toList.map(r => (r._1 + base, r._2.map(_._2))) + } } trait HasRegMap From 86b70c8c599ca22d127761767a2447452406c7cf Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Fri, 16 Sep 2016 14:26:34 -0700 Subject: [PATCH 24/26] Rename PRCI to CoreplexLocalInterrupter That's all it's doing (there wasn't much PRC). --- src/main/scala/coreplex/Coreplex.scala | 6 +-- src/main/scala/rocketchip/Periphery.scala | 28 +++++------ src/main/scala/rocketchip/Top.scala | 6 +-- src/main/scala/rocketchip/Utils.scala | 8 ++-- src/main/scala/uncore/devices/Prci.scala | 57 +++++++++++------------ 5 files changed, 50 insertions(+), 55 deletions(-) diff --git a/src/main/scala/coreplex/Coreplex.scala b/src/main/scala/coreplex/Coreplex.scala index b28b8e5a..fe1d5bf0 100644 --- a/src/main/scala/coreplex/Coreplex.scala +++ b/src/main/scala/coreplex/Coreplex.scala @@ -56,7 +56,7 @@ abstract class Coreplex(implicit val p: Parameters, implicit val c: CoreplexConf val slave = Vec(c.nSlaves, new ClientUncachedTileLinkIO()(innerParams)).flip val interrupts = Vec(c.nExtInterrupts, Bool()).asInput val debug = new DebugBusIO()(p).flip - val prci = Vec(c.nTiles, new PRCITileIO).flip + val clint = Vec(c.nTiles, new CoreplexLocalInterrupts).asInput val success: Option[Bool] = hasSuccessFlag.option(Bool(OUTPUT)) } @@ -147,8 +147,8 @@ class DefaultCoreplex(tp: Parameters, tc: CoreplexConfig) extends Coreplex()(tp, // connect coreplex-internal interrupts to tiles for (((tile, tileReset), i) <- (tileList zip tileResets) zipWithIndex) { - tileReset := io.prci(i).reset - tile.io.interrupts := io.prci(i).interrupts + tileReset := reset // TODO should tiles be reset separately from coreplex? + tile.io.interrupts := io.clint(i) tile.io.interrupts.meip := plic.io.harts(plic.cfg.context(i, 'M')) tile.io.interrupts.seip.foreach(_ := plic.io.harts(plic.cfg.context(i, 'S'))) tile.io.interrupts.debug := debugModule.io.debugInterrupts(i) diff --git a/src/main/scala/rocketchip/Periphery.scala b/src/main/scala/rocketchip/Periphery.scala index 7559187c..f2d867cc 100644 --- a/src/main/scala/rocketchip/Periphery.scala +++ b/src/main/scala/rocketchip/Periphery.scala @@ -279,34 +279,34 @@ trait PeripherySlaveModule extends HasPeripheryParameters { ///// -/** Always-ON block */ -trait PeripheryAON extends LazyModule with HasPeripheryParameters { +trait PeripheryCoreplexLocalInterrupter extends LazyModule with HasPeripheryParameters { implicit val p: Parameters val peripheryBus: TLXbar - // PRCI must be at least XLen in size for atomicity - val beatBytes = max(innerMMIOParams(XLen)/8, 4) - val prci = LazyModule(new PRCI(PRCIConfig(beatBytes))(innerMMIOParams)) - // The periphery bus is 32-bit, so we may need to adapt PRCI's width - prci.node := TLFragmenter(TLWidthWidget(peripheryBus.node, 4), beatBytes, 256) + // CoreplexLocalInterrupter must be at least 64b if XLen >= 64 + val beatBytes = (innerMMIOParams(XLen) min 64) / 8 + val clintConfig = CoreplexLocalInterrupterConfig(beatBytes) + val clint = LazyModule(new CoreplexLocalInterrupter(clintConfig)(innerMMIOParams)) + // The periphery bus is 32-bit, so we may need to adapt its width to XLen + clint.node := TLFragmenter(TLWidthWidget(peripheryBus.node, 4), beatBytes, 256) // TL1 legacy val pDevices: ResourceManager[AddrMapEntry] - pDevices.add(AddrMapEntry("prci", MemRange(prci.base, prci.size, MemAttr(AddrMapProt.RW)))) + pDevices.add(AddrMapEntry("clint", MemRange(clintConfig.address, clintConfig.size, MemAttr(AddrMapProt.RW)))) } -trait PeripheryAONBundle { +trait PeripheryCoreplexLocalInterrupterBundle { implicit val p: Parameters } -trait PeripheryAONModule extends HasPeripheryParameters { +trait PeripheryCoreplexLocalInterrupterModule extends HasPeripheryParameters { implicit val p: Parameters - val outer: PeripheryAON - val io: PeripheryAONBundle + val outer: PeripheryCoreplexLocalInterrupter + val io: PeripheryCoreplexLocalInterrupterBundle val coreplex: Coreplex - outer.prci.module.io.rtcTick := Counter(p(RTCPeriod)).inc() - coreplex.io.prci <> outer.prci.module.io.tiles + outer.clint.module.io.rtcTick := Counter(p(RTCPeriod)).inc() + coreplex.io.clint <> outer.clint.module.io.tiles } ///// diff --git a/src/main/scala/rocketchip/Top.scala b/src/main/scala/rocketchip/Top.scala index bbf89c1a..30bddc3c 100644 --- a/src/main/scala/rocketchip/Top.scala +++ b/src/main/scala/rocketchip/Top.scala @@ -84,17 +84,17 @@ class BaseTopModule[+L <: BaseTop, +B <: BaseTopBundle](val p: Parameters, l: L, /** Example Top with Periphery */ class ExampleTop(q: Parameters) extends BaseTop(q) - with PeripheryBootROM with PeripheryDebug with PeripheryExtInterrupts with PeripheryAON + with PeripheryBootROM with PeripheryDebug with PeripheryExtInterrupts with PeripheryCoreplexLocalInterrupter with PeripheryMasterMem with PeripheryMasterMMIO with PeripherySlave { override lazy val module = Module(new ExampleTopModule(p, this, new ExampleTopBundle(p, _))) } class ExampleTopBundle(p: Parameters, c: Coreplex) extends BaseTopBundle(p, c) - with PeripheryBootROMBundle with PeripheryDebugBundle with PeripheryExtInterruptsBundle with PeripheryAONBundle + with PeripheryBootROMBundle with PeripheryDebugBundle with PeripheryExtInterruptsBundle with PeripheryCoreplexLocalInterrupterBundle 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 PeripheryBootROMModule with PeripheryDebugModule with PeripheryExtInterruptsModule with PeripheryAONModule + with PeripheryBootROMModule with PeripheryDebugModule with PeripheryExtInterruptsModule with PeripheryCoreplexLocalInterrupterModule with PeripheryMasterMemModule with PeripheryMasterMMIOModule with PeripherySlaveModule /** Example Top with TestRAM */ diff --git a/src/main/scala/rocketchip/Utils.scala b/src/main/scala/rocketchip/Utils.scala index 9b696983..bb32006b 100644 --- a/src/main/scala/rocketchip/Utils.scala +++ b/src/main/scala/rocketchip/Utils.scala @@ -83,7 +83,7 @@ object GenerateConfigString { def apply(p: Parameters, c: CoreplexConfig, pDevicesEntries: Seq[AddrMapEntry]) = { val addrMap = p(GlobalAddrMap) val plicAddr = addrMap("io:int:plic").start - val prciAddr = addrMap("io:ext:TL2:prci").start + val clint = CoreplexLocalInterrupterConfig(0, addrMap("io:ext:TL2:clint").start) val xLen = p(XLen) val res = new StringBuilder res append "plic {\n" @@ -92,7 +92,7 @@ object GenerateConfigString { res append s" ndevs ${c.plicKey.nDevices};\n" res append "};\n" res append "rtc {\n" - res append s" addr 0x${(prciAddr + PRCI.time).toString(16)};\n" + res append s" addr 0x${clint.timeAddress.toString(16)};\n" res append "};\n" if (addrMap contains "mem") { res append "ram {\n" @@ -115,8 +115,8 @@ object GenerateConfigString { res append s" $i {\n" res append " 0 {\n" res append s" isa $isa;\n" - res append s" timecmp 0x${(prciAddr + PRCI.timecmp(i)).toString(16)};\n" - res append s" ipi 0x${(prciAddr + PRCI.msip(i)).toString(16)};\n" + res append s" timecmp 0x${clint.timecmpAddress(i).toString(16)};\n" + res append s" ipi 0x${clint.msipAddress(i).toString(16)};\n" res append s" plic {\n" res append s" m {\n" res append s" ie 0x${(plicAddr + c.plicKey.enableAddr(i, 'M')).toString(16)};\n" diff --git a/src/main/scala/uncore/devices/Prci.scala b/src/main/scala/uncore/devices/Prci.scala index d43beea3..ff9800dc 100644 --- a/src/main/scala/uncore/devices/Prci.scala +++ b/src/main/scala/uncore/devices/Prci.scala @@ -14,40 +14,36 @@ import cde.{Parameters, Field} /** Number of tiles */ case object NTiles extends Field[Int] -class PRCITileIO(implicit p: Parameters) extends Bundle { - val reset = Bool(OUTPUT) - val interrupts = new Bundle { - val mtip = Bool() - val msip = Bool() - } - - override def cloneType: this.type = new PRCITileIO().asInstanceOf[this.type] +class CoreplexLocalInterrupts extends Bundle { + val mtip = Bool() + val msip = Bool() } -object PRCI { - def msip(hart: Int) = hart * msipBytes - def timecmp(hart: Int) = 0x4000 + hart * timecmpBytes - def time = 0xbff8 +case class CoreplexLocalInterrupterConfig(beatBytes: Int, address: BigInt = 0x44000000) { + def msipOffset(hart: Int) = hart * msipBytes + def msipAddress(hart: Int) = address + msipOffset(hart) + def timecmpOffset(hart: Int) = 0x4000 + hart * timecmpBytes + def timecmpAddress(hart: Int) = address + timecmpOffset(hart) + def timeOffset = 0xbff8 + def timeAddress = address + timeOffset def msipBytes = 4 def timecmpBytes = 8 - def size = 0xc000 + def size = 0x10000 } -case class PRCIConfig(beatBytes: Int, address: BigInt = 0x44000000) - -trait MixPRCIParameters { - val params: (PRCIConfig, Parameters) +trait MixCoreplexLocalInterrupterParameters { + val params: (CoreplexLocalInterrupterConfig, Parameters) val c = params._1 implicit val p = params._2 } -trait PRCIBundle extends Bundle with MixPRCIParameters { - val tiles = Vec(p(NTiles), new PRCITileIO) +trait CoreplexLocalInterrupterBundle extends Bundle with MixCoreplexLocalInterrupterParameters { + val tiles = Vec(p(NTiles), new CoreplexLocalInterrupts).asOutput val rtcTick = Bool(INPUT) } -trait PRCIModule extends Module with HasRegMap with MixPRCIParameters { - val io: PRCIBundle +trait CoreplexLocalInterrupterModule extends Module with HasRegMap with MixCoreplexLocalInterrupterParameters { + val io: CoreplexLocalInterrupterBundle val timeWidth = 64 val time = Reg(init=UInt(0, width = timeWidth)) @@ -57,15 +53,14 @@ trait PRCIModule extends Module with HasRegMap with MixPRCIParameters { val ipi = Seq.fill(p(NTiles)) { RegInit(UInt(0, width = 1)) } for ((tile, i) <- io.tiles zipWithIndex) { - tile.interrupts.msip := ipi(i)(0) - tile.interrupts.mtip := time >= timecmp(i) - tile.reset := reset + tile.msip := ipi(i)(0) + tile.mtip := time >= timecmp(i) } def pad = RegField(8) // each use is a new field val ipi_fields = ipi.map(r => Seq(RegField(1, r), RegField(7), pad, pad, pad)).flatten val timecmp_fields = timecmp.map(RegField.bytes(_)).flatten - val time_fields = Seq.fill(PRCI.time%c.beatBytes)(pad) ++ RegField.bytes(time) + val time_fields = Seq.fill(c.timeOffset % c.beatBytes)(pad) ++ RegField.bytes(time) /* 0000 msip hart 0 * 0004 msip hart 1 @@ -77,8 +72,8 @@ trait PRCIModule extends Module with HasRegMap with MixPRCIParameters { * bffc mtime hi */ val ipi_base = 0 - val timecmp_base = PRCI.timecmp(0) / c.beatBytes - val time_base = PRCI.time / c.beatBytes + val timecmp_base = c.timecmpOffset(0) / c.beatBytes + val time_base = c.timeOffset / c.beatBytes regmap(( RegField.split(ipi_fields, ipi_base, c.beatBytes) ++ @@ -88,7 +83,7 @@ trait PRCIModule extends Module with HasRegMap with MixPRCIParameters { /** Power, Reset, Clock, Interrupt */ // Magic TL2 Incantation to create a TL2 Slave -class PRCI(c: PRCIConfig)(implicit val p: Parameters) - extends TLRegisterRouter(c.address, 0, 0x10000, None, c.beatBytes, false)( - new TLRegBundle((c, p), _) with PRCIBundle)( - new TLRegModule((c, p), _, _) with PRCIModule) +class CoreplexLocalInterrupter(c: CoreplexLocalInterrupterConfig)(implicit val p: Parameters) + extends TLRegisterRouter(c.address, 0, c.size, None, c.beatBytes, false)( + new TLRegBundle((c, p), _) with CoreplexLocalInterrupterBundle)( + new TLRegModule((c, p), _, _) with CoreplexLocalInterrupterModule) From 4abba87b619f33acb708c8c3f1136f2e7067cc3e Mon Sep 17 00:00:00 2001 From: Yunsup Lee Date: Fri, 16 Sep 2016 15:53:53 -0700 Subject: [PATCH 25/26] bump firrtl to include empty module fix for vivado (#306) --- firrtl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/firrtl b/firrtl index 7c38199c..726c8083 160000 --- a/firrtl +++ b/firrtl @@ -1 +1 @@ -Subproject commit 7c38199ce7a5d9dd7e27ffbb9b2b2770b972ed94 +Subproject commit 726c808375fe513c70376bf05e76dd938e578bf9 From 3fdf40c088805b0a7bce0bfac4a77e065a4ee5f9 Mon Sep 17 00:00:00 2001 From: Richard Xia Date: Fri, 16 Sep 2016 17:47:31 -0700 Subject: [PATCH 26/26] Change implicit argument to explicit. --- src/main/scala/groundtest/TestHarness.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/scala/groundtest/TestHarness.scala b/src/main/scala/groundtest/TestHarness.scala index 8853c513..dbabf0da 100644 --- a/src/main/scala/groundtest/TestHarness.scala +++ b/src/main/scala/groundtest/TestHarness.scala @@ -4,4 +4,4 @@ import Chisel._ import cde.Parameters // !!! TODO: Replace with a groundtest-specific test harness -class TestHarness(implicit p: Parameters) extends rocketchip.TestHarness()(p) +class TestHarness(implicit p: Parameters) extends rocketchip.TestHarness(p)