From 915a929af1a1db77bcafe393cd60476aa2c1abab Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Fri, 16 Sep 2016 17:25:00 -0700 Subject: [PATCH 1/7] tilelink2: Nodes can now mix context into parameters --- src/main/scala/uncore/tilelink2/Nodes.scala | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/main/scala/uncore/tilelink2/Nodes.scala b/src/main/scala/uncore/tilelink2/Nodes.scala index a0de1a84..c9482e69 100644 --- a/src/main/scala/uncore/tilelink2/Nodes.scala +++ b/src/main/scala/uncore/tilelink2/Nodes.scala @@ -17,6 +17,9 @@ abstract class NodeImp[PO, PI, EO, EI, B <: Data] def bundleO(eo: Seq[EO]): Vec[B] def bundleI(ei: Seq[EI]): Vec[B] def connect(bo: B, eo: EO, bi: B, ei: EI)(implicit sourceInfo: SourceInfo): Unit + // If you want to track parameters as they flow through nodes, overload these: + def mixO(po: PO, node: BaseNode[PO, PI, EO, EI, B]): PO = po + def mixI(pi: PI, node: BaseNode[PO, PI, EO, EI, B]): PI = pi } class RootNode @@ -59,12 +62,12 @@ class BaseNode[PO, PI, EO, EI, B <: Data](imp: NodeImp[PO, PI, EO, EI, B])( private lazy val oParams : Seq[PO] = { val o = oFn(oPorts.size, iPorts.map{ case (i, n) => n.oParams(i) }) reqE(oPorts.size, o.size) - o + o.map(imp.mixO(_, this)) } private lazy val iParams : Seq[PI] = { val i = iFn(iPorts.size, oPorts.map{ case (o, n) => n.iParams(o) }) reqE(i.size, iPorts.size) - i + i.map(imp.mixI(_, this)) } lazy val edgesOut = (oPorts zip oParams).map { case ((i, n), o) => imp.edgeO(o, n.iParams(i)) } From 258723483864fe8f2faab6715f1e7df59eb98c75 Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Fri, 16 Sep 2016 17:25:22 -0700 Subject: [PATCH 2/7] tilelink2 TLNodes: capture nodePath in {Client,Manager}Parameters --- src/main/scala/uncore/tilelink2/TLNodes.scala | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/main/scala/uncore/tilelink2/TLNodes.scala b/src/main/scala/uncore/tilelink2/TLNodes.scala index ea0d2c77..7e1c79b5 100644 --- a/src/main/scala/uncore/tilelink2/TLNodes.scala +++ b/src/main/scala/uncore/tilelink2/TLNodes.scala @@ -24,6 +24,11 @@ object TLImp extends NodeImp[TLClientPortParameters, TLManagerPortParameters, TL TLMonitor.legalize(bo, eo) bi <> bo } + + override def mixO(po: TLClientPortParameters, node: TLBaseNode): TLClientPortParameters = + po.copy(clients = po.clients.map { c => c.copy (nodePath = node +: c.nodePath) }) + override def mixI(pi: TLManagerPortParameters, node: TLBaseNode): TLManagerPortParameters = + pi.copy(managers = pi.managers.map { m => m.copy (nodePath = node +: m.nodePath) }) } case class TLIdentityNode() extends IdentityNode(TLImp) From a357c1d42e655753ea23aec00db3a4f77fdaf7fa Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Fri, 16 Sep 2016 17:26:14 -0700 Subject: [PATCH 3/7] tilelink2: create DTS for devices automagically --- src/main/scala/uncore/tilelink2/Parameters.scala | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/main/scala/uncore/tilelink2/Parameters.scala b/src/main/scala/uncore/tilelink2/Parameters.scala index 7c49e792..61bdad72 100644 --- a/src/main/scala/uncore/tilelink2/Parameters.scala +++ b/src/main/scala/uncore/tilelink2/Parameters.scala @@ -127,7 +127,8 @@ case class TLManagerParameters( supportsPutPartial: TransferSizes = TransferSizes.none, supportsHint: TransferSizes = TransferSizes.none, // If fifoId=Some, all accesses sent to the same fifoId are executed and ACK'd in FIFO order - fifoId: Option[Int] = None) + fifoId: Option[Int] = None, + customDTS: Option[String]= None) { address.combinations(2).foreach({ case Seq(x,y) => require (!x.overlaps(y)) @@ -143,6 +144,18 @@ case class TLManagerParameters( supportsPutFull.max, supportsPutPartial.max).max + // Generate the config string (in future device tree) + lazy val name = nodePath.lastOption.map(_.lazyModule.name).getOrElse("disconnected") + lazy val dts = customDTS.getOrElse { + val header = s"${name} {\n" + val middle = address.map { a => + require (!a.strided) // Config String does not support this + " addr 0x%x;\n size 0x%x;\n".format(a.base, a.mask+1) + } + val footer = "}\n" + header + middle.reduce(_ + _) + footer + } + // The device had better not support a transfer larger than it's alignment address.foreach({ case a => require (a.alignment1 >= maxTransfer-1) From 8876d83640cb28857528da83460285bc94113962 Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Fri, 16 Sep 2016 17:26:50 -0700 Subject: [PATCH 4/7] Prci: preserve Andrew's preferred clint name --- src/main/scala/uncore/devices/Prci.scala | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/scala/uncore/devices/Prci.scala b/src/main/scala/uncore/devices/Prci.scala index ff9800dc..1d324005 100644 --- a/src/main/scala/uncore/devices/Prci.scala +++ b/src/main/scala/uncore/devices/Prci.scala @@ -87,3 +87,6 @@ class CoreplexLocalInterrupter(c: CoreplexLocalInterrupterConfig)(implicit val p extends TLRegisterRouter(c.address, 0, c.size, None, c.beatBytes, false)( new TLRegBundle((c, p), _) with CoreplexLocalInterrupterBundle)( new TLRegModule((c, p), _, _) with CoreplexLocalInterrupterModule) +{ + override def name = "clint" // defaul is "CoreplexLocalInterrupter" +} From b5ce6150c7e73004c2d6e3bb8d683f2e16303834 Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Fri, 16 Sep 2016 17:27:49 -0700 Subject: [PATCH 5/7] Periphery: dynamically create address map + config string for TL2 --- src/main/scala/rocketchip/Periphery.scala | 14 +------------ src/main/scala/rocketchip/Top.scala | 10 ++++++---- src/main/scala/rocketchip/Utils.scala | 24 ++++++++++++++++++----- 3 files changed, 26 insertions(+), 22 deletions(-) diff --git a/src/main/scala/rocketchip/Periphery.scala b/src/main/scala/rocketchip/Periphery.scala index f2d867cc..0b2ae458 100644 --- a/src/main/scala/rocketchip/Periphery.scala +++ b/src/main/scala/rocketchip/Periphery.scala @@ -289,10 +289,6 @@ trait PeripheryCoreplexLocalInterrupter extends LazyModule with HasPeripheryPara 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("clint", MemRange(clintConfig.address, clintConfig.size, MemAttr(AddrMapProt.RW)))) } trait PeripheryCoreplexLocalInterrupterBundle { @@ -315,12 +311,8 @@ trait PeripheryBootROM extends LazyModule { implicit val p: Parameters val peripheryBus: TLXbar - val rom = LazyModule(new TLROM(0x1000, 0x1000, GenerateBootROM(p))) + val rom = LazyModule(new TLROM(0x1000, 0x1000, GenerateBootROM(p)) { override def name = "bootrom" }) 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)))) } trait PeripheryBootROMBundle { @@ -344,10 +336,6 @@ trait PeripheryTestRAM extends LazyModule { 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 { diff --git a/src/main/scala/rocketchip/Top.scala b/src/main/scala/rocketchip/Top.scala index 30bddc3c..6ea9069c 100644 --- a/src/main/scala/rocketchip/Top.scala +++ b/src/main/scala/rocketchip/Top.scala @@ -27,6 +27,10 @@ abstract class BaseTop(q: Parameters) extends LazyModule { val pBusMasters = new RangeManager val pDevices = new ResourceManager[AddrMapEntry] + // Add a peripheral bus + val peripheryBus = LazyModule(new TLXbar) + lazy val peripheryManagers = peripheryBus.node.edgesIn(0).manager.managers + lazy val c = CoreplexConfig( nTiles = q(NTiles), nExtInterrupts = pInterrupts.sum, @@ -36,16 +40,14 @@ abstract class BaseTop(q: Parameters) extends LazyModule { hasExtMMIOPort = true ) - lazy val genGlobalAddrMap = GenerateGlobalAddrMap(q, pDevices.get) + lazy val genGlobalAddrMap = GenerateGlobalAddrMap(q, pDevices.get, peripheryManagers) private val qWithMap = q.alterPartial({case GlobalAddrMap => genGlobalAddrMap}) - lazy val genConfigString = GenerateConfigString(qWithMap, c, pDevices.get) + lazy val genConfigString = GenerateConfigString(qWithMap, c, pDevices.get, peripheryManagers) 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" }))) peripheryBus.node := TLBuffer(TLWidthWidget(TLHintHandler(legacy.node), legacy.tlDataBytes)) diff --git a/src/main/scala/rocketchip/Utils.scala b/src/main/scala/rocketchip/Utils.scala index bb32006b..b045e8c7 100644 --- a/src/main/scala/rocketchip/Utils.scala +++ b/src/main/scala/rocketchip/Utils.scala @@ -8,6 +8,7 @@ import uncore.devices._ import rocket._ import rocket.Util._ import coreplex._ +import uncore.tilelink2._ import java.nio.file.{Files, Paths} import java.nio.{ByteBuffer, ByteOrder} @@ -51,7 +52,7 @@ class GlobalVariable[T] { } object GenerateGlobalAddrMap { - def apply(p: Parameters, pDevicesEntries: Seq[AddrMapEntry]) = { + def apply(p: Parameters, pDevicesEntries: Seq[AddrMapEntry], peripheryManagers: Seq[TLManagerParameters]) = { lazy val intIOAddrMap: AddrMap = { val entries = collection.mutable.ArrayBuffer[AddrMapEntry]() entries += AddrMapEntry("debug", MemSize(4096, MemAttr(AddrMapProt.RWX))) @@ -64,8 +65,20 @@ object GenerateGlobalAddrMap { new AddrMap(entries) } - lazy val tl2AddrMap = new AddrMap(pDevicesEntries, collapse = true) - lazy val extIOAddrMap = new AddrMap(AddrMapEntry("TL2", tl2AddrMap) +: p(ExtMMIOPorts), collapse = true) + lazy val tl2Devices = peripheryManagers.map { manager => + val attr = MemAttr( + (if (manager.supportsGet) AddrMapProt.R else 0) | + (if (manager.supportsPutFull) AddrMapProt.W else 0) | + (if (manager.executable) AddrMapProt.X else 0)) + val name = manager.nodePath.last.lazyModule.name // !!! + manager.address.zipWithIndex.map { case (address, i) => + require (!address.strided) // TL1 can't do this + AddrMapEntry(s"${name}", MemRange(address.base, address.mask+1, attr)) + } + }.flatten + + lazy val tl2AddrMap = new AddrMap(tl2Devices, collapse = true) + lazy val extIOAddrMap = new AddrMap(AddrMapEntry("TL2", tl2AddrMap) +: (p(ExtMMIOPorts) ++ pDevicesEntries), collapse = true) val memBase = 0x80000000L val memSize = p(ExtMemSize) @@ -80,7 +93,7 @@ object GenerateGlobalAddrMap { } object GenerateConfigString { - def apply(p: Parameters, c: CoreplexConfig, pDevicesEntries: Seq[AddrMapEntry]) = { + def apply(p: Parameters, c: CoreplexConfig, pDevicesEntries: Seq[AddrMapEntry], peripheryManagers: Seq[TLManagerParameters]) = { val addrMap = p(GlobalAddrMap) val plicAddr = addrMap("io:int:plic").start val clint = CoreplexLocalInterrupterConfig(0, addrMap("io:ext:TL2:clint").start) @@ -136,12 +149,13 @@ object GenerateConfigString { } res append "};\n" pDevicesEntries foreach { entry => - val region = addrMap("io:ext:TL2:" + entry.name) + val region = addrMap("io:ext:" + 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" res append "}\n" } + peripheryManagers.foreach { manager => res append manager.dts } res append '\u0000' res.toString } From a9382b3116c44158fa2b9f9f39f4687e39bd13c5 Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Fri, 16 Sep 2016 17:47:20 -0700 Subject: [PATCH 6/7] Periphery: test bench looks for "testram" --- src/main/scala/rocketchip/Periphery.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/scala/rocketchip/Periphery.scala b/src/main/scala/rocketchip/Periphery.scala index 0b2ae458..c69ef131 100644 --- a/src/main/scala/rocketchip/Periphery.scala +++ b/src/main/scala/rocketchip/Periphery.scala @@ -334,7 +334,7 @@ trait PeripheryTestRAM extends LazyModule { val ramBase = 0x52000000 val ramSize = 0x1000 - val sram = LazyModule(new TLRAM(AddressSet(ramBase, ramSize-1))) + val sram = LazyModule(new TLRAM(AddressSet(ramBase, ramSize-1)) { override def name = "testram" }) sram.node := TLFragmenter(peripheryBus.node, 4, 256) } From 5c858685aa1701a1cbb65174521090316bb00047 Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Fri, 16 Sep 2016 18:03:49 -0700 Subject: [PATCH 7/7] Utils: support managers with multiple addresses --- src/main/scala/rocketchip/Utils.scala | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/scala/rocketchip/Utils.scala b/src/main/scala/rocketchip/Utils.scala index b045e8c7..8f27cc1b 100644 --- a/src/main/scala/rocketchip/Utils.scala +++ b/src/main/scala/rocketchip/Utils.scala @@ -70,10 +70,11 @@ object GenerateGlobalAddrMap { (if (manager.supportsGet) AddrMapProt.R else 0) | (if (manager.supportsPutFull) AddrMapProt.W else 0) | (if (manager.executable) AddrMapProt.X else 0)) - val name = manager.nodePath.last.lazyModule.name // !!! + val multi = manager.address.size > 1 manager.address.zipWithIndex.map { case (address, i) => require (!address.strided) // TL1 can't do this - AddrMapEntry(s"${name}", MemRange(address.base, address.mask+1, attr)) + val name = manager.name + (if (multi) ".%d".format(i) else "") + AddrMapEntry(name, MemRange(address.base, address.mask+1, attr)) } }.flatten