From 6c2b7706052725b6e04356dd7b004525103c672c Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Wed, 7 Jun 2017 13:49:51 -0700 Subject: [PATCH 01/13] plic: do not output #address-cells This is only needed for an interrupt-map, not an interrupt-controller. --- src/main/scala/uncore/devices/Plic.scala | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/scala/uncore/devices/Plic.scala b/src/main/scala/uncore/devices/Plic.scala index a71b7d5c..8ccfbeca 100644 --- a/src/main/scala/uncore/devices/Plic.scala +++ b/src/main/scala/uncore/devices/Plic.scala @@ -70,8 +70,7 @@ class TLPLIC(params: PLICParams)(implicit p: Parameters) extends LazyModule val extra = Map( "interrupt-controller" -> Nil, "riscv,ndev" -> Seq(ResourceInt(nDevices)), - "#interrupt-cells" -> Seq(ResourceInt(1)), - "#address-cells" -> Seq(ResourceInt(0))) + "#interrupt-cells" -> Seq(ResourceInt(1))) Description(name, mapping ++ extra) } } From 852f03282f01670fe31154c9f168193c7fe1f764 Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Wed, 28 Jun 2017 12:00:44 -0700 Subject: [PATCH 02/13] rocket: give itim and dtim a compatible field for drivers to match --- src/main/scala/rocket/ICache.scala | 2 +- src/main/scala/rocket/ScratchpadSlavePort.scala | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/scala/rocket/ICache.scala b/src/main/scala/rocket/ICache.scala index cd4bed4d..2a7828cb 100644 --- a/src/main/scala/rocket/ICache.scala +++ b/src/main/scala/rocket/ICache.scala @@ -40,7 +40,7 @@ class ICache(val icacheParams: ICacheParams, val hartid: Int)(implicit p: Parame val masterNode = TLClientNode(TLClientParameters(name = s"Core ${hartid} ICache")) val size = icacheParams.nSets * icacheParams.nWays * icacheParams.blockBytes - val device = new SimpleDevice("itim", Nil) + val device = new SimpleDevice("itim", Seq("sifive,itim0")) val slaveNode = icacheParams.itimAddr.map { itimAddr => val wordBytes = icacheParams.fetchBytes TLManagerNode(Seq(TLManagerPortParameters( diff --git a/src/main/scala/rocket/ScratchpadSlavePort.scala b/src/main/scala/rocket/ScratchpadSlavePort.scala index f2681fb2..545b0d0b 100644 --- a/src/main/scala/rocket/ScratchpadSlavePort.scala +++ b/src/main/scala/rocket/ScratchpadSlavePort.scala @@ -15,7 +15,7 @@ import util._ class ScratchpadSlavePort(address: AddressSet)(implicit p: Parameters) extends LazyModule with HasCoreParameters { - val device = new SimpleDevice("dtim", Nil) + val device = new SimpleDevice("dtim", Seq("sifive,dtim0")) val node = TLManagerNode(Seq(TLManagerPortParameters( Seq(TLManagerParameters( address = List(address), From 0bf46edb6c4cb4fcc81ee3b17c022f23f8dc876e Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Wed, 28 Jun 2017 12:40:43 -0700 Subject: [PATCH 03/13] diplomacy: support reg-names in DTS output --- src/main/scala/diplomacy/Resources.scala | 36 +++++++++++++++++++----- 1 file changed, 29 insertions(+), 7 deletions(-) diff --git a/src/main/scala/diplomacy/Resources.scala b/src/main/scala/diplomacy/Resources.scala index aaaa3723..528d4306 100644 --- a/src/main/scala/diplomacy/Resources.scala +++ b/src/main/scala/diplomacy/Resources.scala @@ -69,15 +69,26 @@ trait DeviceRegName this: Device => val prefix = "soc/" // nearly everything on-chip belongs here def describeName(devname: String, resources: ResourceBindings): String = { - val reg = resources("reg") - require (!reg.isEmpty, "Device is missing the 'reg' property") - reg.head.value match { + val reg = resources.map.filterKeys(regFilter) + require (!reg.isEmpty, "Device $devname is missing the 'reg' property") + val (named, bulk) = reg.partition { case (k, v) => regName(k).isDefined } + val mainreg = reg.find(x => regName(x._1) == "control").getOrElse(reg.head)._2 + require (!mainreg.isEmpty, s"reg binding for $devname is empty!") + mainreg.head.value match { case x: ResourceAddress => s"${prefix}${devname}@${x.address.head.base.toString(16)}" case _ => require(false, "Device has the wrong type of 'reg' property (${reg.head})"); "" } } - def reg = Seq(Resource(this, "reg")) + def reg(name: String): Seq[Resource] = Seq(Resource(this, "reg/" + name)) + def reg: Seq[Resource] = Seq(Resource(this, "reg")) + + def regFilter(name: String): Boolean = name == "reg" || name.take(4) == "reg/" + def regName(name: String): Option[String] = { + val keys = name.split("/") + require (keys.size >= 1 && keys.size <= 2 && keys(0) == "reg", s"Invalid reg name '${name}'") + if (keys.size == 1) None else Some(keys(1)) + } } class SimpleDevice(devname: String, devcompat: Seq[String]) extends Device with DeviceInterrupts with DeviceRegName @@ -89,9 +100,20 @@ class SimpleDevice(devname: String, devcompat: Seq[String]) extends Device with if (devcompat.isEmpty) None else Some("compatible" -> devcompat.map(ResourceString(_))) - Description(name, - ListMap("reg" -> resources("reg").map(_.value)) - ++ compat ++ int) + val reg = resources.map.filterKeys(regFilter) + val (named, bulk) = reg.partition { case (k, v) => regName(k).isDefined } + // We need to be sure that each named reg has exactly one AddressRange associated to it + named.foreach { + case (k, Seq(Binding(_, value: ResourceAddress))) => + val ranges = AddressRange.fromSets(value.address) + require (ranges.size == 1, s"DTS device $name has $k = $ranges, must be a single range!") + case (k, seq) => + require (false, s"DTS device $name has $k = $seq, must be a single ResourceAddress!") + } + val names = named.map(x => ResourceString(regName(x._1).get)).toList + val regs = (named ++ bulk).flatMap(_._2.map(_.value)).toList + Description(name, ListMap() ++ compat ++ int ++ + Seq("reg" -> regs) ++ (if (names.isEmpty) Nil else Seq("reg-names" -> names))) } } From 84dc23c215b8be4988296020ca6b7e9cbcfaf6f4 Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Wed, 28 Jun 2017 13:01:40 -0700 Subject: [PATCH 04/13] devices: add reg-names to most devices --- src/main/scala/rocket/ICache.scala | 2 +- src/main/scala/rocket/ScratchpadSlavePort.scala | 2 +- src/main/scala/uncore/devices/Rom.scala | 2 +- src/main/scala/uncore/devices/debug/Debug.scala | 3 --- src/main/scala/uncore/tilelink2/Error.scala | 2 +- src/main/scala/uncore/tilelink2/RegisterRouter.scala | 6 +++--- src/main/scala/uncore/tilelink2/SRAM.scala | 2 +- src/main/scala/uncore/tilelink2/TestRAM.scala | 2 +- src/main/scala/uncore/tilelink2/Zero.scala | 2 +- 9 files changed, 10 insertions(+), 13 deletions(-) diff --git a/src/main/scala/rocket/ICache.scala b/src/main/scala/rocket/ICache.scala index 2a7828cb..dfb240f4 100644 --- a/src/main/scala/rocket/ICache.scala +++ b/src/main/scala/rocket/ICache.scala @@ -46,7 +46,7 @@ class ICache(val icacheParams: ICacheParams, val hartid: Int)(implicit p: Parame TLManagerNode(Seq(TLManagerPortParameters( Seq(TLManagerParameters( address = Seq(AddressSet(itimAddr, size-1)), - resources = device.reg, + resources = device.reg("mem"), regionType = RegionType.UNCACHED, executable = true, supportsPutFull = TransferSizes(1, wordBytes), diff --git a/src/main/scala/rocket/ScratchpadSlavePort.scala b/src/main/scala/rocket/ScratchpadSlavePort.scala index 545b0d0b..667cc157 100644 --- a/src/main/scala/rocket/ScratchpadSlavePort.scala +++ b/src/main/scala/rocket/ScratchpadSlavePort.scala @@ -19,7 +19,7 @@ class ScratchpadSlavePort(address: AddressSet)(implicit p: Parameters) extends L val node = TLManagerNode(Seq(TLManagerPortParameters( Seq(TLManagerParameters( address = List(address), - resources = device.reg, + resources = device.reg("mem"), regionType = RegionType.UNCACHED, executable = true, supportsArithmetic = if (usingAtomics) TransferSizes(4, coreDataBytes) else TransferSizes.none, diff --git a/src/main/scala/uncore/devices/Rom.scala b/src/main/scala/uncore/devices/Rom.scala index 929e440e..1836af2d 100644 --- a/src/main/scala/uncore/devices/Rom.scala +++ b/src/main/scala/uncore/devices/Rom.scala @@ -13,7 +13,7 @@ import uncore.util._ import config._ class TLROM(val base: BigInt, val size: Int, contentsDelayed: => Seq[Byte], executable: Boolean = true, beatBytes: Int = 4, - resources: Seq[Resource] = new SimpleDevice("rom", Nil).reg)(implicit p: Parameters) extends LazyModule + resources: Seq[Resource] = new SimpleDevice("rom", Nil).reg("mem"))(implicit p: Parameters) extends LazyModule { val node = TLManagerNode(beatBytes, TLManagerParameters ( diff --git a/src/main/scala/uncore/devices/debug/Debug.scala b/src/main/scala/uncore/devices/debug/Debug.scala index a0b8ce46..574ab673 100644 --- a/src/main/scala/uncore/devices/debug/Debug.scala +++ b/src/main/scala/uncore/devices/debug/Debug.scala @@ -283,7 +283,6 @@ class TLDebugModuleOuter(device: Device)(implicit p: Parameters) extends LazyMod val dmiNode = TLRegisterNode ( address = AddressSet.misaligned(DMI_DMCONTROL << 2, 4), device = device, - deviceKey = "reg", beatBytes = 4, executable = false ) @@ -430,7 +429,6 @@ class TLDebugModuleInner(device: Device, getNComponents: () => Int)(implicit p: address = AddressSet.misaligned(0, DMI_RegAddrs.DMI_DMCONTROL << 2) ++ AddressSet.misaligned((DMI_RegAddrs.DMI_DMCONTROL + 1) << 2, (0x200 - ((DMI_RegAddrs.DMI_DMCONTROL + 1) << 2))), device = device, - deviceKey = "reg", beatBytes = 4, executable = false ) @@ -438,7 +436,6 @@ class TLDebugModuleInner(device: Device, getNComponents: () => Int)(implicit p: val tlNode = TLRegisterNode( address=Seq(AddressSet(0, 0xFFF)), // This is required for correct functionality, it's not configurable. device=device, - deviceKey="reg", beatBytes=p(XLen)/8, executable=true ) diff --git a/src/main/scala/uncore/tilelink2/Error.scala b/src/main/scala/uncore/tilelink2/Error.scala index 38ebf646..51a3f791 100644 --- a/src/main/scala/uncore/tilelink2/Error.scala +++ b/src/main/scala/uncore/tilelink2/Error.scala @@ -14,7 +14,7 @@ class TLError(address: Seq[AddressSet], beatBytes: Int = 4)(implicit p: Paramete val node = TLManagerNode(Seq(TLManagerPortParameters( Seq(TLManagerParameters( address = address, - resources = device.reg, + resources = device.reg("mem"), supportsGet = TransferSizes(1, beatBytes), supportsPutPartial = TransferSizes(1, beatBytes), supportsPutFull = TransferSizes(1, beatBytes), diff --git a/src/main/scala/uncore/tilelink2/RegisterRouter.scala b/src/main/scala/uncore/tilelink2/RegisterRouter.scala index fa5da920..d2f255bf 100644 --- a/src/main/scala/uncore/tilelink2/RegisterRouter.scala +++ b/src/main/scala/uncore/tilelink2/RegisterRouter.scala @@ -11,7 +11,7 @@ import scala.math.{min,max} class TLRegisterNode( address: Seq[AddressSet], device: Device, - deviceKey: String = "reg", + deviceKey: String = "reg/control", concurrency: Int = 0, beatBytes: Int = 4, undefZero: Boolean = true, @@ -88,7 +88,7 @@ object TLRegisterNode def apply( address: Seq[AddressSet], device: Device, - deviceKey: String = "reg", + deviceKey: String = "reg/control", concurrency: Int = 0, beatBytes: Int = 4, undefZero: Boolean = true, @@ -103,7 +103,7 @@ object TLRegisterNode abstract class TLRegisterRouterBase(devname: String, devcompat: Seq[String], val address: AddressSet, interrupts: Int, concurrency: Int, beatBytes: Int, undefZero: Boolean, executable: Boolean)(implicit p: Parameters) extends LazyModule { val device = new SimpleDevice(devname, devcompat) - val node = TLRegisterNode(Seq(address), device, "reg", concurrency, beatBytes, undefZero, executable) + val node = TLRegisterNode(Seq(address), device, "reg/control", concurrency, beatBytes, undefZero, executable) val intnode = IntSourceNode(IntSourcePortSimple(num = interrupts, resources = Seq(Resource(device, "int")))) } diff --git a/src/main/scala/uncore/tilelink2/SRAM.scala b/src/main/scala/uncore/tilelink2/SRAM.scala index 05cea3b8..bd59a8f3 100644 --- a/src/main/scala/uncore/tilelink2/SRAM.scala +++ b/src/main/scala/uncore/tilelink2/SRAM.scala @@ -14,7 +14,7 @@ class TLRAM(address: AddressSet, executable: Boolean = true, beatBytes: Int = 4, val node = TLManagerNode(Seq(TLManagerPortParameters( Seq(TLManagerParameters( address = List(address), - resources = device.reg, + resources = device.reg("mem"), regionType = RegionType.UNCACHED, executable = executable, supportsGet = TransferSizes(1, beatBytes), diff --git a/src/main/scala/uncore/tilelink2/TestRAM.scala b/src/main/scala/uncore/tilelink2/TestRAM.scala index c1b28f56..98426201 100644 --- a/src/main/scala/uncore/tilelink2/TestRAM.scala +++ b/src/main/scala/uncore/tilelink2/TestRAM.scala @@ -15,7 +15,7 @@ class TLTestRAM(address: AddressSet, executable: Boolean = true, beatBytes: Int val node = TLManagerNode(Seq(TLManagerPortParameters( Seq(TLManagerParameters( address = List(address), - resources = device.reg, + resources = device.reg("mem"), regionType = RegionType.UNCACHED, executable = executable, supportsGet = TransferSizes(1, beatBytes), diff --git a/src/main/scala/uncore/tilelink2/Zero.scala b/src/main/scala/uncore/tilelink2/Zero.scala index fa952f13..b07f86f8 100644 --- a/src/main/scala/uncore/tilelink2/Zero.scala +++ b/src/main/scala/uncore/tilelink2/Zero.scala @@ -13,7 +13,7 @@ class TLZero(address: AddressSet, executable: Boolean = true, beatBytes: Int = 4 val node = TLManagerNode(Seq(TLManagerPortParameters( Seq(TLManagerParameters( address = List(address), - resources = device.reg, + resources = device.reg("mem"), regionType = RegionType.UNCACHED, executable = executable, supportsGet = TransferSizes(1, beatBytes), From 171e1a4c0591bf07b154ba744fe30d655b846ff1 Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Wed, 28 Jun 2017 13:47:03 -0700 Subject: [PATCH 05/13] diplomacy: add SimpleBus to describe bridges --- src/main/scala/diplomacy/Resources.scala | 58 ++++++++++++++++++------ 1 file changed, 44 insertions(+), 14 deletions(-) diff --git a/src/main/scala/diplomacy/Resources.scala b/src/main/scala/diplomacy/Resources.scala index 528d4306..ffa0ec22 100644 --- a/src/main/scala/diplomacy/Resources.scala +++ b/src/main/scala/diplomacy/Resources.scala @@ -70,13 +70,16 @@ trait DeviceRegName val prefix = "soc/" // nearly everything on-chip belongs here def describeName(devname: String, resources: ResourceBindings): String = { val reg = resources.map.filterKeys(regFilter) - require (!reg.isEmpty, "Device $devname is missing the 'reg' property") - val (named, bulk) = reg.partition { case (k, v) => regName(k).isDefined } - val mainreg = reg.find(x => regName(x._1) == "control").getOrElse(reg.head)._2 - require (!mainreg.isEmpty, s"reg binding for $devname is empty!") - mainreg.head.value match { - case x: ResourceAddress => s"${prefix}${devname}@${x.address.head.base.toString(16)}" - case _ => require(false, "Device has the wrong type of 'reg' property (${reg.head})"); "" + if (reg.isEmpty) { + devname + } else { + val (named, bulk) = reg.partition { case (k, v) => regName(k).isDefined } + val mainreg = reg.find(x => regName(x._1) == "control").getOrElse(reg.head)._2 + require (!mainreg.isEmpty, s"reg binding for $devname is empty!") + mainreg.head.value match { + case x: ResourceAddress => s"${prefix}${devname}@${x.address.head.base.toString(16)}" + case _ => require(false, "Device has the wrong type of 'reg' property (${reg.head})"); "" + } } } @@ -96,9 +99,9 @@ class SimpleDevice(devname: String, devcompat: Seq[String]) extends Device with def describe(resources: ResourceBindings): Description = { val name = describeName(devname, resources) val int = describeInterrupts(resources) - val compat = - if (devcompat.isEmpty) None else - Some("compatible" -> devcompat.map(ResourceString(_))) + + def optDef(x: String, seq: Seq[ResourceValue]) = if (seq.isEmpty) None else Some(x -> seq) + val compat = optDef("compatible", devcompat.map(ResourceString(_))) val reg = resources.map.filterKeys(regFilter) val (named, bulk) = reg.partition { case (k, v) => regName(k).isDefined } @@ -110,13 +113,40 @@ class SimpleDevice(devname: String, devcompat: Seq[String]) extends Device with case (k, seq) => require (false, s"DTS device $name has $k = $seq, must be a single ResourceAddress!") } - val names = named.map(x => ResourceString(regName(x._1).get)).toList - val regs = (named ++ bulk).flatMap(_._2.map(_.value)).toList - Description(name, ListMap() ++ compat ++ int ++ - Seq("reg" -> regs) ++ (if (names.isEmpty) Nil else Seq("reg-names" -> names))) + + val names = optDef("reg-names", named.map(x => ResourceString(regName(x._1).get)).toList) + val regs = optDef("reg", (named ++ bulk).flatMap(_._2.map(_.value)).toList) + + Description(name, ListMap() ++ compat ++ int ++ names ++ regs) } } +class SimpleBus(devname: String, devcompat: Seq[String], offset: BigInt = 0) extends SimpleDevice(devname, devcompat ++ Seq("simple-bus")) +{ + override def describe(resources: ResourceBindings): Description = { + val ranges = resources("ranges").map { + case Binding(_, a: ResourceAddress) => ResourceMapping(a.address, offset) + } + require (!ranges.isEmpty, s"SimpleBus $devname must set ranges") + + val map = AddressRange.fromSets(ranges.flatMap(_.address)) + val minBase = map.map(_.base).min + val maxBase = map.map(_.end).max + val maxSize = map.map(_.size).max + + def ofInt(x: Int) = Seq(ResourceInt(BigInt(x))) + val extra = Map( + "#address-cells" -> ofInt((log2Ceil(maxBase) + 31) / 32), + "#size-cells" -> ofInt((log2Ceil(maxSize) + 31) / 32), + "ranges" -> ranges) + + val Description(_, mapping) = super.describe(resources) + Description(s"${prefix}${devname}@${minBase.toString(16)}", mapping ++ extra) + } + + def ranges = Seq(Resource(this, "ranges")) +} + class MemoryDevice extends Device with DeviceRegName { override val prefix = "" From 5436be54fff646b69c3e3248e937f0df51ad72f8 Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Wed, 28 Jun 2017 13:58:06 -0700 Subject: [PATCH 06/13] periphery: use SimpleBus for mmio ports --- src/main/scala/rocketchip/Periphery.scala | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/scala/rocketchip/Periphery.scala b/src/main/scala/rocketchip/Periphery.scala index fa817d5e..85a34ac4 100644 --- a/src/main/scala/rocketchip/Periphery.scala +++ b/src/main/scala/rocketchip/Periphery.scala @@ -177,11 +177,11 @@ trait HasPeripheryMasterAXI4MemPortModuleImp extends LazyMultiIOModuleImp with H /** Adds a AXI4 port to the system intended to master an MMIO device bus */ trait HasPeripheryMasterAXI4MMIOPort extends HasSystemNetworks { private val config = p(ExtBus) - private val device = new SimpleDevice("mmio", Nil) + private val device = new SimpleBus("mmio", Nil) val mmio_axi4 = AXI4BlindOutputNode(Seq(AXI4SlavePortParameters( slaves = Seq(AXI4SlaveParameters( address = List(AddressSet(BigInt(config.base), config.size-1)), - resources = device.reg, + resources = device.ranges, executable = true, // Can we run programs on this memory? supportsWrite = TransferSizes(1, 256), // The slave supports 1-256 byte transfers supportsRead = TransferSizes(1, 256))), @@ -252,11 +252,11 @@ trait HasPeripherySlaveAXI4PortModuleImp extends LazyMultiIOModuleImp with HasPe /** Adds a TileLink port to the system intended to master an MMIO device bus */ trait HasPeripheryMasterTLMMIOPort extends HasSystemNetworks { private val config = p(ExtBus) - private val device = new SimpleDevice("mmio", Nil) + private val device = new SimpleBus("mmio", Nil) val mmio_tl = TLBlindOutputNode(Seq(TLManagerPortParameters( managers = Seq(TLManagerParameters( address = List(AddressSet(BigInt(config.base), config.size-1)), - resources = device.reg, + resources = device.ranges, executable = true, supportsGet = TransferSizes(1, cacheBlockBytes), supportsPutFull = TransferSizes(1, cacheBlockBytes), From bca3db086637a97a0670c6bad633c8c0417a66cd Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Wed, 28 Jun 2017 14:07:40 -0700 Subject: [PATCH 07/13] diplomacy: add RWXC permissions also to ResourceMappings --- src/main/scala/coreplex/CoreplexNetwork.scala | 5 +++-- src/main/scala/diplomacy/JSON.scala | 6 +++--- src/main/scala/diplomacy/Resources.scala | 7 ++++--- src/main/scala/uncore/tilelink2/Parameters.scala | 4 ++-- 4 files changed, 12 insertions(+), 10 deletions(-) diff --git a/src/main/scala/coreplex/CoreplexNetwork.scala b/src/main/scala/coreplex/CoreplexNetwork.scala index 70eb30e4..afe42ecb 100644 --- a/src/main/scala/coreplex/CoreplexNetwork.scala +++ b/src/main/scala/coreplex/CoreplexNetwork.scala @@ -118,14 +118,15 @@ trait CoreplexNetworkModule extends HasCoreplexParameters { private def collect(path: List[String], value: ResourceValue): List[(String, ResourceAddress)] = { value match { case r: ResourceAddress => List((path(1), r)) + case b: ResourceMapping => List((path(1), ResourceAddress(b.address, b.permissions))) case ResourceMap(value, _) => value.toList.flatMap { case (key, seq) => seq.flatMap(r => collect(key :: path, r)) } case _ => Nil } } private val ranges = collect(Nil, outer.bindingTree).groupBy(_._2).toList.flatMap { case (key, seq) => - AddressRange.fromSets(key.address).map { r => (r, key.r, key.w, key.x, key.c, seq.map(_._1)) } + AddressRange.fromSets(key.address).map { r => (r, key.permissions, seq.map(_._1)) } }.sortBy(_._1) - private val json = ranges.map { case (range, r, w, x, c, names) => + private val json = ranges.map { case (range, ResourcePermissions(r, w, x, c), names) => println(fmt.format( range.base, range.base+range.size, diff --git a/src/main/scala/diplomacy/JSON.scala b/src/main/scala/diplomacy/JSON.scala index e9632878..448e7b42 100644 --- a/src/main/scala/diplomacy/JSON.scala +++ b/src/main/scala/diplomacy/JSON.scala @@ -26,12 +26,12 @@ object JSON } private def helper(res: ResourceValue)(implicit path: Map[String, String]): Seq[String] = res match { - case ResourceAddress(address, r, w, x, c) => + case ResourceAddress(address, ResourcePermissions(r, w, x, c)) => AddressRange.fromSets(address).map { case AddressRange(base, size) => s"""{"base":${base},"size":${size},"r":${r},"w":${w},"x":${x},"c":${c}}"""} - case ResourceMapping(address, offset) => + case ResourceMapping(address, offset, ResourcePermissions(r, w, x, c)) => AddressRange.fromSets(address).map { case AddressRange(base, size) => - s"""{"base":${base},"size":${size},"offset":${offset}}"""} + s"""{"base":${base},"size":${size},"offset":${offset},"r":${r},"w":${w},"x":${x},"c":${c}}"""} case ResourceInt(value) => Seq(value.toString) case ResourceString(value) => Seq("\"" + value + "\"") case ResourceReference(value) => Seq("\"&" + path(value) + "\"") diff --git a/src/main/scala/diplomacy/Resources.scala b/src/main/scala/diplomacy/Resources.scala index ffa0ec22..cbccb1ff 100644 --- a/src/main/scala/diplomacy/Resources.scala +++ b/src/main/scala/diplomacy/Resources.scala @@ -7,8 +7,9 @@ import config._ import scala.collection.immutable.{ListMap,SortedMap} sealed trait ResourceValue -final case class ResourceAddress(address: Seq[AddressSet], r: Boolean, w: Boolean, x: Boolean, c: Boolean) extends ResourceValue -final case class ResourceMapping(address: Seq[AddressSet], offset: BigInt) extends ResourceValue +case class ResourcePermissions(r: Boolean, w: Boolean, x: Boolean, c: Boolean) // Not part of DTS +final case class ResourceAddress(address: Seq[AddressSet], permissions: ResourcePermissions) extends ResourceValue +final case class ResourceMapping(address: Seq[AddressSet], offset: BigInt, permissions: ResourcePermissions) extends ResourceValue final case class ResourceInt(value: BigInt) extends ResourceValue final case class ResourceString(value: String) extends ResourceValue final case class ResourceReference(value: String) extends ResourceValue @@ -125,7 +126,7 @@ class SimpleBus(devname: String, devcompat: Seq[String], offset: BigInt = 0) ext { override def describe(resources: ResourceBindings): Description = { val ranges = resources("ranges").map { - case Binding(_, a: ResourceAddress) => ResourceMapping(a.address, offset) + case Binding(_, a: ResourceAddress) => ResourceMapping(a.address, offset, a.permissions) } require (!ranges.isEmpty, s"SimpleBus $devname must set ranges") diff --git a/src/main/scala/uncore/tilelink2/Parameters.scala b/src/main/scala/uncore/tilelink2/Parameters.scala index 44ef9258..af2e8151 100644 --- a/src/main/scala/uncore/tilelink2/Parameters.scala +++ b/src/main/scala/uncore/tilelink2/Parameters.scala @@ -57,11 +57,11 @@ case class TLManagerParameters( require (minAlignment >= maxTransfer, s"minAlignment ($minAlignment) must be >= maxTransfer ($maxTransfer)") def toResource: ResourceAddress = { - ResourceAddress(address, + ResourceAddress(address, ResourcePermissions( r = supportsAcquireB || supportsGet, w = supportsAcquireT || supportsPutFull, x = executable, - c = supportsAcquireB) + c = supportsAcquireB)) } } From 3f6d5110cd575fded9f4e12a15162f9e39afa103 Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Wed, 28 Jun 2017 14:15:05 -0700 Subject: [PATCH 08/13] rocket: dtim is not a dcache --- src/main/scala/rocket/RocketTiles.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/scala/rocket/RocketTiles.scala b/src/main/scala/rocket/RocketTiles.scala index ab91fab3..a393cb15 100644 --- a/src/main/scala/rocket/RocketTiles.scala +++ b/src/main/scala/rocket/RocketTiles.scala @@ -42,7 +42,7 @@ class RocketTile(val rocketParams: RocketTileParams, val hartid: Int)(implicit p val c = if (rocketParams.core.useCompressed) "c" else "" val isa = s"rv${p(XLen)}i$m$a$f$d$c" - val dcache = rocketParams.dcache.map(d => Map( + val dcache = rocketParams.dcache.filter(!_.scratch.isDefined).map(d => Map( "d-cache-block-size" -> ofInt(block), "d-cache-sets" -> ofInt(d.nSets), "d-cache-size" -> ofInt(d.nSets * d.nWays * block))).getOrElse(Map()) From e6c2d446ccf85a409969e8b298fa5c6baca4ff4a Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Wed, 28 Jun 2017 14:45:46 -0700 Subject: [PATCH 09/13] rocket: link dtim to its cpu --- src/main/scala/rocket/RocketTiles.scala | 3 +++ src/main/scala/rocket/ScratchpadSlavePort.scala | 14 +++++++++++--- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/src/main/scala/rocket/RocketTiles.scala b/src/main/scala/rocket/RocketTiles.scala index a393cb15..4e5fccad 100644 --- a/src/main/scala/rocket/RocketTiles.scala +++ b/src/main/scala/rocket/RocketTiles.scala @@ -89,6 +89,9 @@ class RocketTile(val rocketParams: RocketTileParams, val hartid: Int)(implicit p ++ dcache ++ icache ++ nextlevel ++ mmu ++ itlb ++ dtlb) } } + + override def dtimOwner = Some(cpuDevice) + val intcDevice = new Device { def describe(resources: ResourceBindings): Description = { Description(s"cpus/cpu@${hartid}/interrupt-controller", Map( diff --git a/src/main/scala/rocket/ScratchpadSlavePort.scala b/src/main/scala/rocket/ScratchpadSlavePort.scala index 667cc157..12035ee8 100644 --- a/src/main/scala/rocket/ScratchpadSlavePort.scala +++ b/src/main/scala/rocket/ScratchpadSlavePort.scala @@ -13,9 +13,16 @@ import uncore.tilelink2._ import uncore.util._ import util._ -class ScratchpadSlavePort(address: AddressSet)(implicit p: Parameters) extends LazyModule +class ScratchpadSlavePort(address: AddressSet, owner: => Option[Device] = None)(implicit p: Parameters) extends LazyModule with HasCoreParameters { - val device = new SimpleDevice("dtim", Seq("sifive,dtim0")) + val device = new SimpleDevice("dtim", Seq("sifive,dtim0")) { + override def describe(resources: ResourceBindings): Description = { + val extra = owner.map(x => ("sifive,cpu" -> Seq(ResourceReference(x.label)))) + val Description(name, mapping) = super.describe(resources) + Description(name, mapping ++ extra) + } + } + val node = TLManagerNode(Seq(TLManagerPortParameters( Seq(TLManagerParameters( address = List(address), @@ -102,6 +109,7 @@ trait CanHaveScratchpad extends HasHellaCache with HasICacheFrontend with HasCor val module: CanHaveScratchpadModule val slaveNode = TLInputNode() // Up to two uses for this input node: + def dtimOwner: Option[Device] = None // who owns the Scratchpad? // 1) Frontend always exists, but may or may not have a scratchpad node val fg = LazyModule(new TLFragmenter(fetchWidth*coreInstBytes, p(CacheBlockBytes), earlyAck=true)) @@ -112,7 +120,7 @@ trait CanHaveScratchpad extends HasHellaCache with HasICacheFrontend with HasCor // 2) ScratchpadSlavePort always has a node, but only exists when the HellaCache has a scratchpad val scratch = tileParams.dcache.flatMap(d => d.scratch.map(s => - LazyModule(new ScratchpadSlavePort(AddressSet(s, d.dataScratchpadBytes-1))))) + LazyModule(new ScratchpadSlavePort(AddressSet(s, d.dataScratchpadBytes-1), dtimOwner)))) scratch foreach { lm => lm.node := TLFragmenter(xLen/8, p(CacheBlockBytes), earlyAck=true)(slaveNode) } def findScratchpadFromICache: Option[AddressSet] = scratch.map { s => From 48390ed604e12dbcb1b119cb2d4eb1c645ea8f7e Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Wed, 28 Jun 2017 14:53:09 -0700 Subject: [PATCH 10/13] rocket: link itim to its cpu --- src/main/scala/rocket/Frontend.scala | 7 ++++--- src/main/scala/rocket/ICache.scala | 11 +++++++++-- src/main/scala/rocket/RocketTiles.scala | 1 + 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/src/main/scala/rocket/Frontend.scala b/src/main/scala/rocket/Frontend.scala index 35642a23..0faad869 100644 --- a/src/main/scala/rocket/Frontend.scala +++ b/src/main/scala/rocket/Frontend.scala @@ -53,9 +53,9 @@ class FrontendIO(implicit p: Parameters) extends CoreBundle()(p) { val perf = new FrontendPerfEvents().asInput } -class Frontend(val icacheParams: ICacheParams, hartid: Int)(implicit p: Parameters) extends LazyModule { +class Frontend(val icacheParams: ICacheParams, hartid: Int, owner: => Option[Device] = None)(implicit p: Parameters) extends LazyModule { lazy val module = new FrontendModule(this) - val icache = LazyModule(new ICache(icacheParams, hartid)) + val icache = LazyModule(new ICache(icacheParams, hartid, owner)) val masterNode = TLOutputNode() val slaveNode = TLInputNode() @@ -184,7 +184,8 @@ class FrontendModule(outer: Frontend) extends LazyModuleImp(outer) /** Mix-ins for constructing tiles that have an ICache-based pipeline frontend */ trait HasICacheFrontend extends CanHavePTW with HasTileLinkMasterPort { val module: HasICacheFrontendModule - val frontend = LazyModule(new Frontend(tileParams.icache.get, hartid: Int)) + def itimOwner : Option[Device] = None + val frontend = LazyModule(new Frontend(tileParams.icache.get, hartid: Int, itimOwner)) val hartid: Int tileBus.node := frontend.masterNode nPTWPorts += 1 diff --git a/src/main/scala/rocket/ICache.scala b/src/main/scala/rocket/ICache.scala index dfb240f4..ec093623 100644 --- a/src/main/scala/rocket/ICache.scala +++ b/src/main/scala/rocket/ICache.scala @@ -35,12 +35,19 @@ class ICacheReq(implicit p: Parameters) extends CoreBundle()(p) with HasL1ICache val addr = UInt(width = vaddrBits) } -class ICache(val icacheParams: ICacheParams, val hartid: Int)(implicit p: Parameters) extends LazyModule { +class ICache(val icacheParams: ICacheParams, val hartid: Int, owner: => Option[Device] = None)(implicit p: Parameters) extends LazyModule { lazy val module = new ICacheModule(this) val masterNode = TLClientNode(TLClientParameters(name = s"Core ${hartid} ICache")) + val device = new SimpleDevice("itim", Seq("sifive,itim0")) { + override def describe(resources: ResourceBindings): Description = { + val extra = owner.map(x => ("sifive,cpu" -> Seq(ResourceReference(x.label)))) + val Description(name, mapping) = super.describe(resources) + Description(name, mapping ++ extra) + } + } + val size = icacheParams.nSets * icacheParams.nWays * icacheParams.blockBytes - val device = new SimpleDevice("itim", Seq("sifive,itim0")) val slaveNode = icacheParams.itimAddr.map { itimAddr => val wordBytes = icacheParams.fetchBytes TLManagerNode(Seq(TLManagerPortParameters( diff --git a/src/main/scala/rocket/RocketTiles.scala b/src/main/scala/rocket/RocketTiles.scala index 4e5fccad..ab118915 100644 --- a/src/main/scala/rocket/RocketTiles.scala +++ b/src/main/scala/rocket/RocketTiles.scala @@ -91,6 +91,7 @@ class RocketTile(val rocketParams: RocketTileParams, val hartid: Int)(implicit p } override def dtimOwner = Some(cpuDevice) + override def itimOwner = Some(cpuDevice) val intcDevice = new Device { def describe(resources: ResourceBindings): Description = { From 02aa80a9580d334d8899580ce40521306e1ee4cf Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Wed, 28 Jun 2017 15:12:46 -0700 Subject: [PATCH 11/13] TLZero: include a version number --- src/main/scala/uncore/tilelink2/Zero.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/scala/uncore/tilelink2/Zero.scala b/src/main/scala/uncore/tilelink2/Zero.scala index b07f86f8..aaed3af7 100644 --- a/src/main/scala/uncore/tilelink2/Zero.scala +++ b/src/main/scala/uncore/tilelink2/Zero.scala @@ -8,7 +8,7 @@ import diplomacy._ class TLZero(address: AddressSet, executable: Boolean = true, beatBytes: Int = 4)(implicit p: Parameters) extends LazyModule { - val device = new SimpleDevice("rom", Seq("ucbbar,cacheable-zero")) + val device = new SimpleDevice("rom", Seq("ucbbar,cacheable-zero0")) val node = TLManagerNode(Seq(TLManagerPortParameters( Seq(TLManagerParameters( From ca3030cba3e507f7d065f35f7ec8b5a1cc05af70 Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Wed, 28 Jun 2017 15:38:21 -0700 Subject: [PATCH 12/13] dcache: fix a gender inversion bug introduced in #826 --- src/main/scala/rocket/DCache.scala | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/scala/rocket/DCache.scala b/src/main/scala/rocket/DCache.scala index 1654d6f3..aa1e255e 100644 --- a/src/main/scala/rocket/DCache.scala +++ b/src/main/scala/rocket/DCache.scala @@ -83,7 +83,8 @@ class DCacheModule(outer: DCache) extends HellaCacheModule(outer) { } val q_depth = if (rational) (2 min maxUncachedInFlight-1) else 0 - val tl_out_a = if (q_depth == 0) tl_out.a else Queue(tl_out.a, q_depth, flow = true, pipe = true) + val tl_out_a = Wire(tl_out.a) + tl_out.a <> (if (q_depth == 0) tl_out_a else Queue(tl_out_a, q_depth, flow = true, pipe = true)) val s1_valid = Reg(next=io.cpu.req.fire(), init=Bool(false)) val s1_probe = Reg(next=tl_out.b.fire(), init=Bool(false)) From 66489ffa132512e405dd6b051bae1915a8c3f791 Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Wed, 28 Jun 2017 15:41:20 -0700 Subject: [PATCH 13/13] rom+sram: add a compatible field --- src/main/scala/uncore/devices/Rom.scala | 2 +- src/main/scala/uncore/tilelink2/SRAM.scala | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/scala/uncore/devices/Rom.scala b/src/main/scala/uncore/devices/Rom.scala index 1836af2d..a676a6fe 100644 --- a/src/main/scala/uncore/devices/Rom.scala +++ b/src/main/scala/uncore/devices/Rom.scala @@ -13,7 +13,7 @@ import uncore.util._ import config._ class TLROM(val base: BigInt, val size: Int, contentsDelayed: => Seq[Byte], executable: Boolean = true, beatBytes: Int = 4, - resources: Seq[Resource] = new SimpleDevice("rom", Nil).reg("mem"))(implicit p: Parameters) extends LazyModule + resources: Seq[Resource] = new SimpleDevice("rom", Seq("sifive,rom0")).reg("mem"))(implicit p: Parameters) extends LazyModule { val node = TLManagerNode(beatBytes, TLManagerParameters ( diff --git a/src/main/scala/uncore/tilelink2/SRAM.scala b/src/main/scala/uncore/tilelink2/SRAM.scala index bd59a8f3..136f4047 100644 --- a/src/main/scala/uncore/tilelink2/SRAM.scala +++ b/src/main/scala/uncore/tilelink2/SRAM.scala @@ -10,7 +10,7 @@ import util._ class TLRAM(address: AddressSet, executable: Boolean = true, beatBytes: Int = 4, name: Option[String] = None)(implicit p: Parameters) extends LazyModule { - val device = name.map(new SimpleDevice(_, Nil)).getOrElse(new MemoryDevice) + val device = name.map(new SimpleDevice(_, Seq("sifive,sram0"))).getOrElse(new MemoryDevice) val node = TLManagerNode(Seq(TLManagerPortParameters( Seq(TLManagerParameters( address = List(address),