diff --git a/src/main/scala/uncore/devices/Debug.scala b/src/main/scala/uncore/devices/Debug.scala index 9f62a9f8..11fd21fb 100644 --- a/src/main/scala/uncore/devices/Debug.scala +++ b/src/main/scala/uncore/devices/Debug.scala @@ -849,7 +849,7 @@ trait DebugModule extends Module with HasDebugModuleParameters with HasRegMap { */ class TLDebugModule(address: BigInt = 0)(implicit p: Parameters) - extends TLRegisterRouter(address, beatBytes=p(XLen)/8, executable=true)( + extends TLRegisterRouter(address, "debug", Nil, beatBytes=p(XLen)/8, executable=true)( new TLRegBundle((), _ ) with DebugModuleBundle)( new TLRegModule((), _, _) with DebugModule) diff --git a/src/main/scala/uncore/devices/Plic.scala b/src/main/scala/uncore/devices/Plic.scala index ed2c8a21..e11647f3 100644 --- a/src/main/scala/uncore/devices/Plic.scala +++ b/src/main/scala/uncore/devices/Plic.scala @@ -58,19 +58,34 @@ class TLPLIC(supervisor: Boolean, maxPriorities: Int, address: BigInt = 0xC00000 val contextsPerHart = if (supervisor) 2 else 1 require (maxPriorities >= 0) + // plic0 => max devices 1023 + val device = new SimpleDevice("interrupt-controller", Seq("riscv,plic0")) { + override val alwaysExtended = true + override def describe(resources: ResourceBindings): Description = { + val Description(name, mapping) = super.describe(resources) + val extra = Map( + "interrupt-controller" -> Nil, + "riscv,ndev" -> Seq(ResourceInt(nDevices)), + "#interrupt-cells" -> Seq(ResourceInt(1)), + "#address-cells" -> Seq(ResourceInt(0))) + Description(name, mapping ++ extra) + } + } + val node = TLRegisterNode( address = AddressSet(address, PLICConsts.size-1), + device = device, beatBytes = p(XLen)/8, undefZero = false) val intnode = IntNexusNode( numSourcePorts = 0 to 1024, numSinkPorts = 0 to 1024, - sourceFn = { _ => IntSourcePortParameters(Seq(IntSourceParameters(contextsPerHart))) }, + sourceFn = { _ => IntSourcePortParameters(Seq(IntSourceParameters(contextsPerHart, Seq(Resource(device, "int"))))) }, sinkFn = { _ => IntSinkPortParameters(Seq(IntSinkParameters())) }) /* Negotiated sizes */ - def nDevices = intnode.edgesIn.map(_.source.num).sum + def nDevices: Int = intnode.edgesIn.map(_.source.num).sum def nPriorities = min(maxPriorities, nDevices) def nHarts = intnode.edgesOut.map(_.source.num).sum @@ -106,6 +121,19 @@ class TLPLIC(supervisor: Boolean, maxPriorities: Int, address: BigInt = 0xC00000 s" };\n")).mkString } + // Assign all the devices unique ranges + lazy val sources = intnode.edgesIn.map(_.source) + lazy val flatSources = (sources zip sources.map(_.num).scanLeft(0)(_+_).init).map { + case (s, o) => s.sources.map(z => z.copy(range = z.range.offset(o))) + }.flatten + + ResourceBinding { + flatSources.foreach { s => s.resources.foreach { r => + // +1 because interrupt 0 is reserved + (s.range.start until s.range.end).foreach { i => r.bind(device, ResourceInt(i+1)) } + } } + } + lazy val module = new LazyModuleImp(this) { val io = new Bundle { val tl_in = node.bundleIn @@ -113,11 +141,6 @@ class TLPLIC(supervisor: Boolean, maxPriorities: Int, address: BigInt = 0xC00000 val harts = intnode.bundleOut } - // Assign all the devices unique ranges - val sources = intnode.edgesIn.map(_.source) - val flatSources = (sources zip sources.map(_.num).scanLeft(0)(_+_).init).map { - case (s, o) => s.sources.map(z => z.copy(range = z.range.offset(o))) - }.flatten // Compact the interrupt vector the same way val interrupts = (intnode.edgesIn zip io.devices).map { case (e, i) => i.take(e.source.num) }.flatten // This flattens the harts into an MSMSMSMSMS... or MMMMM.... sequence diff --git a/src/main/scala/uncore/devices/Prci.scala b/src/main/scala/uncore/devices/Prci.scala index 4362b59e..f61b773c 100644 --- a/src/main/scala/uncore/devices/Prci.scala +++ b/src/main/scala/uncore/devices/Prci.scala @@ -83,8 +83,9 @@ trait CoreplexLocalInterrupterModule extends Module with HasRegMap with MixCorep /** Power, Reset, Clock, Interrupt */ // Magic TL2 Incantation to create a TL2 Slave +// prci0 => at most 4095 devices class CoreplexLocalInterrupter(address: BigInt = 0x02000000)(implicit p: Parameters) - extends TLRegisterRouter(address, size = ClintConsts.size, beatBytes = p(XLen)/8, undefZero = true)( + extends TLRegisterRouter(address, "clint", Seq("riscv,clint0"), size = ClintConsts.size, beatBytes = p(XLen)/8, undefZero = true)( new TLRegBundle((), _) with CoreplexLocalInterrupterBundle)( new TLRegModule((), _, _) with CoreplexLocalInterrupterModule) { diff --git a/src/main/scala/uncore/devices/Rom.scala b/src/main/scala/uncore/devices/Rom.scala index 4d39b75f..8f5edc5a 100644 --- a/src/main/scala/uncore/devices/Rom.scala +++ b/src/main/scala/uncore/devices/Rom.scala @@ -14,8 +14,11 @@ import config._ class TLROM(val base: BigInt, val size: Int, contentsDelayed: => Seq[Byte], executable: Boolean = true, beatBytes: Int = 4)(implicit p: Parameters) extends LazyModule { + val device = new SimpleDevice("rom", Nil) + val node = TLManagerNode(beatBytes, TLManagerParameters( address = List(AddressSet(base, size-1)), + resources = device.reg, regionType = RegionType.UNCACHED, executable = executable, supportsGet = TransferSizes(1, beatBytes), diff --git a/src/main/scala/uncore/tilelink2/Example.scala b/src/main/scala/uncore/tilelink2/Example.scala index db102fc0..2cb9ce19 100644 --- a/src/main/scala/uncore/tilelink2/Example.scala +++ b/src/main/scala/uncore/tilelink2/Example.scala @@ -34,6 +34,7 @@ trait ExampleModule extends HasRegMap } // Create a concrete TL2 version of the abstract Example slave -class TLExample(params: ExampleParams)(implicit p: Parameters) extends TLRegisterRouter(params.address, 4)( +class TLExample(params: ExampleParams)(implicit p: Parameters) + extends TLRegisterRouter(params.address, "somedev", Seq("ucbbar,random-interface"), 4)( new TLRegBundle(params, _) with ExampleBundle)( new TLRegModule(params, _, _) with ExampleModule) diff --git a/src/main/scala/uncore/tilelink2/RegisterRouter.scala b/src/main/scala/uncore/tilelink2/RegisterRouter.scala index fc834c6d..28ea03ac 100644 --- a/src/main/scala/uncore/tilelink2/RegisterRouter.scala +++ b/src/main/scala/uncore/tilelink2/RegisterRouter.scala @@ -8,10 +8,18 @@ import diplomacy._ import regmapper._ import scala.math.{min,max} -class TLRegisterNode(address: AddressSet, concurrency: Int = 0, beatBytes: Int = 4, undefZero: Boolean = true, executable: Boolean = false) +class TLRegisterNode( + address: AddressSet, + device: Device, + deviceKey: String = "reg", + concurrency: Int = 0, + beatBytes: Int = 4, + undefZero: Boolean = true, + executable: Boolean = false) extends TLManagerNode(Seq(TLManagerPortParameters( Seq(TLManagerParameters( address = Seq(address), + resources = Seq(Resource(device, deviceKey)), executable = executable, supportsGet = TransferSizes(1, beatBytes), supportsPutPartial = TransferSizes(1, beatBytes), @@ -72,18 +80,26 @@ class TLRegisterNode(address: AddressSet, concurrency: Int = 0, beatBytes: Int = object TLRegisterNode { - def apply(address: AddressSet, concurrency: Int = 0, beatBytes: Int = 4, undefZero: Boolean = true, executable: Boolean = false) = - new TLRegisterNode(address, concurrency, beatBytes, undefZero, executable) + def apply( + address: AddressSet, + device: Device, + deviceKey: String = "reg", + concurrency: Int = 0, + beatBytes: Int = 4, + undefZero: Boolean = true, + executable: Boolean = false) = + new TLRegisterNode(address, device, deviceKey, concurrency, beatBytes, undefZero, executable) } // 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(val address: AddressSet, interrupts: Int, concurrency: Int, beatBytes: Int, undefZero: Boolean, executable: Boolean)(implicit p: Parameters) extends LazyModule +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 node = TLRegisterNode(address, concurrency, beatBytes, undefZero, executable) - val intnode = IntSourceNode(interrupts) + val device = new SimpleDevice(devname, devcompat) + val node = TLRegisterNode(address, device, "reg", concurrency, beatBytes, undefZero, executable) + val intnode = IntSourceNode(interrupts, Seq(Resource(device, "int"))) } case class TLRegBundleArg(interrupts: util.HeterogeneousBag[Vec[Bool]], in: util.HeterogeneousBag[TLBundle])(implicit val p: Parameters) @@ -106,11 +122,19 @@ class TLRegModule[P, B <: TLRegBundleBase](val params: P, bundleBuilder: => B, r def regmap(mapping: RegField.Map*) = router.node.regmap(mapping:_*) } -class TLRegisterRouter[B <: TLRegBundleBase, M <: LazyModuleImp] - (val base: BigInt, val interrupts: Int = 0, val size: BigInt = 4096, val concurrency: Int = 0, val beatBytes: Int = 4, undefZero: Boolean = true, executable: Boolean = false) +class TLRegisterRouter[B <: TLRegBundleBase, M <: LazyModuleImp]( + val base: BigInt, + val devname: String, + val devcompat: Seq[String], + val interrupts: Int = 0, + val size: BigInt = 4096, + val concurrency: Int = 0, + val beatBytes: Int = 4, + val undefZero: Boolean = true, + val executable: Boolean = false) (bundleBuilder: TLRegBundleArg => B) (moduleBuilder: (=> B, TLRegisterRouterBase) => M)(implicit p: Parameters) - extends TLRegisterRouterBase(AddressSet(base, size-1), interrupts, concurrency, beatBytes, undefZero, executable) + extends TLRegisterRouterBase(devname, devcompat, AddressSet(base, size-1), interrupts, concurrency, beatBytes, undefZero, executable) { require (isPow2(size)) // require (size >= 4096) ... not absolutely required, but highly recommended diff --git a/src/main/scala/uncore/tilelink2/RegisterRouterTest.scala b/src/main/scala/uncore/tilelink2/RegisterRouterTest.scala index 2564c0a7..5bef9428 100644 --- a/src/main/scala/uncore/tilelink2/RegisterRouterTest.scala +++ b/src/main/scala/uncore/tilelink2/RegisterRouterTest.scala @@ -214,7 +214,7 @@ trait RRTest0Module extends HasRegMap regmap(RRTest0Map.map:_*) } -class RRTest0(address: BigInt)(implicit p: Parameters) extends TLRegisterRouter(address, 0, 32, 0, 4)( +class RRTest0(address: BigInt)(implicit p: Parameters) extends TLRegisterRouter(address, "test0", Nil, 0, 32, 0, 4)( new TLRegBundle((), _) with RRTest0Bundle)( new TLRegModule((), _, _) with RRTest0Module) @@ -251,7 +251,7 @@ trait RRTest1Module extends Module with HasRegMap regmap(map:_*) } -class RRTest1(address: BigInt)(implicit p: Parameters) extends TLRegisterRouter(address, 0, 32, 6, 4)( +class RRTest1(address: BigInt)(implicit p: Parameters) extends TLRegisterRouter(address, "test1", Nil, 0, 32, 6, 4)( new TLRegBundle((), _) with RRTest1Bundle)( new TLRegModule((), _, _) with RRTest1Module) diff --git a/src/main/scala/uncore/tilelink2/SRAM.scala b/src/main/scala/uncore/tilelink2/SRAM.scala index e7c1c26e..fcf611d4 100644 --- a/src/main/scala/uncore/tilelink2/SRAM.scala +++ b/src/main/scala/uncore/tilelink2/SRAM.scala @@ -9,9 +9,12 @@ import util._ class TLRAM(address: AddressSet, executable: Boolean = true, beatBytes: Int = 4)(implicit p: Parameters) extends LazyModule { + val device = new MemoryDevice + val node = TLManagerNode(Seq(TLManagerPortParameters( Seq(TLManagerParameters( address = List(address), + resources = device.reg, 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 2da7f940..fa952f13 100644 --- a/src/main/scala/uncore/tilelink2/Zero.scala +++ b/src/main/scala/uncore/tilelink2/Zero.scala @@ -8,9 +8,12 @@ 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 node = TLManagerNode(Seq(TLManagerPortParameters( Seq(TLManagerParameters( address = List(address), + resources = device.reg, regionType = RegionType.UNCACHED, executable = executable, supportsGet = TransferSizes(1, beatBytes),