From bb70b1a3c33939b8db342339152a7362fdc81ebc Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Tue, 28 Feb 2017 14:41:49 -0800 Subject: [PATCH 01/14] diplomacy: add resource tracking --- src/main/scala/diplomacy/Resources.scala | 189 +++++++++++++++++++++++ 1 file changed, 189 insertions(+) create mode 100644 src/main/scala/diplomacy/Resources.scala diff --git a/src/main/scala/diplomacy/Resources.scala b/src/main/scala/diplomacy/Resources.scala new file mode 100644 index 00000000..04a454df --- /dev/null +++ b/src/main/scala/diplomacy/Resources.scala @@ -0,0 +1,189 @@ +// See LICENSE.SiFive for license details. + +package diplomacy + +import Chisel._ +import config._ +import scala.collection.immutable.{ListMap,SortedMap} + +sealed trait ResourceValue +final case class ResourceAddress(address: Seq[AddressSet], r: Boolean, w: Boolean, x: Boolean) extends ResourceValue +final case class ResourceMapping(address: Seq[AddressSet], offset: BigInt) 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 +final case class ResourceMap(value: Map[String, Seq[ResourceValue]], labels: Seq[String] = Nil) extends ResourceValue + +/* If device is None, the value is global */ +case class Binding(device: Option[Device], value: ResourceValue) +case class ResourceBindings(map: Map[String, Seq[Binding]]) +{ + def apply(key: String): Seq[Binding] = map.getOrElse(key, Nil) +} + +case class Description(name: String, mapping: Map[String, Seq[ResourceValue]]) + +abstract class Device +{ + def describe(resources: ResourceBindings): Description + + val label = "L" + Device.index.toString + Device.index = Device.index + 1 +} + +object Device +{ + private var index: Int = 0 +} + +trait DeviceInterrupts +{ + this: Device => + val alwaysExtended = false + def describeInterrupts(resources: ResourceBindings): Map[String, Seq[ResourceValue]] = { + val int = resources("int") + + int.foreach { b => require (b.device.isDefined, "Device ${devname} property 'int' is missing user device") } + val parents = int.map(_.device.get).distinct + val simple = parents.size == 1 && !alwaysExtended + + val parent = + if (!simple) None else + Some("interrupt-parent" -> Seq(ResourceReference(parents.head.label))) + val interrupts = + if (!simple) None else + Some("interrupts" -> int.map(_.value)) + + val interrupts_extended = + if (simple || parents.isEmpty) None else + Some("interrupts-extended" -> int.flatMap(b => Seq(ResourceReference(b.device.get.label), b.value))) + + ListMap() ++ parent ++ interrupts ++ interrupts_extended + } + + def int = Seq(Resource(this, "int")) +} + +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 { + 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")) +} + +class SimpleDevice(devname: String, devcompat: Seq[String]) extends Device with DeviceInterrupts with DeviceRegName +{ + 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(_))) + + Description(name, + ListMap("reg" -> resources("reg").map(_.value)) + ++ compat ++ int) + } +} + +class MemoryDevice extends Device with DeviceRegName +{ + override val prefix = "" + def describe(resources: ResourceBindings): Description = { + Description(describeName("memory", resources), ListMap( + "reg" -> resources("reg").map(_.value), + "device_type" -> Seq(ResourceString("memory")))) + } +} + +case class Resource(owner: Device, key: String) +{ + def bind(user: Device, value: ResourceValue) { + val scope = BindingScope.active.get + scope.resourceBindings = (this, Some(user), value) +: scope.resourceBindings + } + def bind(value: ResourceValue) { + val scope = BindingScope.active.get + scope.resourceBindings = (this, None, value) +: scope.resourceBindings + } +} + +trait BindingScope +{ + this: LazyModule => + + private val parentScope = BindingScope.find(parent) + protected[diplomacy] var resourceBindingFns: Seq[() => Unit] = Nil + protected[diplomacy] var resourceBindings: Seq[(Resource, Option[Device], ResourceValue)] = Nil + + private case class ExpandedValue(path: Seq[String], labels: Seq[String], value: Seq[ResourceValue]) + private def eval() { + require (LazyModule.stack.isEmpty, "May not evaluate binding while still constructing LazyModules") + parentScope.foreach { _.eval() } + resourceBindings = parentScope.map(_.resourceBindings).getOrElse(Nil) + BindingScope.active = Some(this) + resourceBindingFns.reverse.foreach { _() } + BindingScope.active = None + resourceBindingFns = Nil + } + + private def makeTree(list: Seq[ExpandedValue]): Seq[ResourceValue] = { + val (values_p, keys_p) = list.partition(_.path.isEmpty) + val values = values_p.flatMap(_.value) + val labels = values_p.flatMap(_.labels) + val keys = keys_p.groupBy(_.path.head).toList.map { case (key, seq) => + (key -> makeTree(seq.map { x => x.copy(path = x.path.tail) })) + // case ExpandedValue(keys, values) => ExpandedValue(keys.tail, values) })) + } + if (keys.isEmpty) values else ResourceMap(SortedMap(keys:_*), labels) +: values + } + + private def expand(path: Seq[String], values: Seq[ResourceValue]): Seq[ExpandedValue] = { + ExpandedValue(path, Nil, Nil) +: + values.flatMap { + case ResourceMap(map, labels) => + ExpandedValue(path, labels, Nil) +: + map.toList.flatMap { case (key, values) => expand(path :+ key, values) } + case z => Seq(ExpandedValue(path, Nil, Seq(z))) + } + } + + def bindingTree: ResourceMap = { + eval() + val map: Map[Device, ResourceBindings] = + resourceBindings.reverse.groupBy(_._1.owner).mapValues(seq => ResourceBindings( + seq.groupBy(_._1.key).mapValues(_.map(z => Binding(z._2, z._3))))) + val tree = makeTree(map.toList.flatMap { case (d, m) => + val Description(name, mapping) = d.describe(m) + val tokens = name.split("/").toList + expand(tokens, Seq(ResourceMap(mapping, Seq(d.label)))) }) + ResourceMap(SortedMap("/" -> tree)) + } +} + +object BindingScope +{ + protected[diplomacy] var active: Option[BindingScope] = None + protected[diplomacy] def find(m: Option[LazyModule] = LazyModule.stack.headOption): Option[BindingScope] = m.flatMap { + case s: BindingScope => Some(s) + case x => find(x.parent) + } +} + +object ResourceBinding +{ + def apply(block: => Unit) { + val scope = BindingScope.find() + require (scope.isDefined, "ResourceBinding must be called from within a BindingScope") + scope.get.resourceBindingFns = { () => block } +: scope.get.resourceBindingFns + } +} From c01a74f4a0370153ff7cbb86af1fa810e822696d Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Tue, 28 Feb 2017 17:50:54 -0800 Subject: [PATCH 02/14] diplomacy: add AddressRange conversion to/from AddressSet --- src/main/scala/diplomacy/Parameters.scala | 52 +++++++++++++++++++++++ src/main/scala/diplomacy/package.scala | 10 +++++ 2 files changed, 62 insertions(+) diff --git a/src/main/scala/diplomacy/Parameters.scala b/src/main/scala/diplomacy/Parameters.scala index fd9d9f0b..ccad3fbb 100644 --- a/src/main/scala/diplomacy/Parameters.scala +++ b/src/main/scala/diplomacy/Parameters.scala @@ -76,6 +76,32 @@ object TransferSizes { implicit def asBool(x: TransferSizes) = !x.none } +// Use AddressSet instead -- this is just for pretty printing +case class AddressRange(base: BigInt, size: BigInt) extends Ordered[AddressRange] +{ + val end = base + size + + require (base >= 0) + require (size > 0) + + def compare(x: AddressRange) = { + val primary = (this.base - x.base).signum + val secondary = (x.size - this.size).signum + if (primary != 0) primary else secondary + } + + def contains(x: AddressRange) = base <= x.base && x.end <= end + def union(x: AddressRange): Option[AddressRange] = { + if (base > x.end || x.base > end) { + None + } else { + val obase = if (base < x.base) base else x.base + val oend = if (end > x.end) end else x.end + Some(AddressRange(obase, oend-obase)) + } + } +} + // AddressSets specify the address space managed by the manager // 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 @@ -132,6 +158,32 @@ case class AddressSet(base: BigInt, mask: BigInt) extends Ordered[AddressSet] "AddressSet(0x%x, ~0x%x)".format(base, ~mask) } } + + def toRanges = { + require (finite) + val size = alignment + val fragments = mask & ~(size-1) + val bits = bitIndexes(fragments) + (BigInt(0) until (BigInt(1) << bits.size)).map { i => + val off = bitIndexes(i).foldLeft(base) { case (a, b) => a.setBit(bits(b)) } + AddressRange(off, size) + } + } +} + +object AddressRange +{ + def fromSets(seq: Seq[AddressSet]): Seq[AddressRange] = unify(seq.flatMap(_.toRanges)) + def unify(seq: Seq[AddressRange]): Seq[AddressRange] = { + if (seq.isEmpty) return Nil + val ranges = seq.sorted + ranges.tail.foldLeft(Seq(ranges.head)) { case (head :: tail, x) => + head.union(x) match { + case Some(z) => z :: tail + case None => x :: head :: tail + } + }.reverse + } } object AddressSet diff --git a/src/main/scala/diplomacy/package.scala b/src/main/scala/diplomacy/package.scala index 12fd0bfd..5b9d4944 100644 --- a/src/main/scala/diplomacy/package.scala +++ b/src/main/scala/diplomacy/package.scala @@ -9,4 +9,14 @@ package object diplomacy case SourceLine(filename, line, col) => s"$prefix$filename:$line:$col$suffix" case _ => "" } + + def bitIndexes(x: BigInt, tail: Seq[Int] = Nil): Seq[Int] = { + require (x >= 0) + if (x == 0) { + tail.reverse + } else { + val lowest = x.lowestSetBit + bitIndexes(x.clearBit(lowest), lowest +: tail) + } + } } From e322692d164162f80b70fbc696703216cb072a12 Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Tue, 28 Feb 2017 19:48:24 -0800 Subject: [PATCH 03/14] diplomacy: add DeviceTree renderer --- src/main/scala/diplomacy/DeviceTree.scala | 117 ++++++++++++++++++++++ src/main/scala/rocketchip/Configs.scala | 9 ++ 2 files changed, 126 insertions(+) create mode 100644 src/main/scala/diplomacy/DeviceTree.scala diff --git a/src/main/scala/diplomacy/DeviceTree.scala b/src/main/scala/diplomacy/DeviceTree.scala new file mode 100644 index 00000000..8a26991a --- /dev/null +++ b/src/main/scala/diplomacy/DeviceTree.scala @@ -0,0 +1,117 @@ +// See LICENSE.SiFive for license details. + +package diplomacy + +import Chisel._ +import config._ + +case object DTSModel extends Field[String] +case object DTSCompat extends Field[Seq[String]] // -dev, -soc +case object DTSTimebase extends Field[BigInt] // Clock frequency of clint RTC (use 0 if you don't know it) + +object DTS +{ + def apply(res: ResourceValue): String = "/dts-v1/;\n\n" + helper(res, "", defaultCells).mkString("") + + private val nodeStartChars = (('a' to 'z') ++ ('A' to 'Z')).toSet + private val nodeChars = (('a' to 'z') ++ ('A' to 'Z') ++ ('0' to '9') ++ Seq(',', '.', '_', '+', '-', '@')).toSet + def legalNode(x: String): Boolean = + x == "/" || (!x.isEmpty && x.size < 32 && nodeStartChars.contains(x(0)) && x.forall(nodeChars.contains(_))) + + // the DTS spec does not list '-', but uses it everywhere ... + private val propChars = (('a' to 'z') ++ ('A' to 'Z') ++ ('0' to '9') ++ Seq(',', '.', '_', '+', '?', '#', '-')).toSet + def legalProperty(x: String): Boolean = + x == "/" || (!x.isEmpty && x.size < 32 && x.forall(propChars.contains(_))) + + // The DTS spec doesn't say what is allowed in a string, so just use our own judgement + private val strChars = (('#' to '[') ++ (']' to '~') ++ Seq(' ', '!')).toSet + def legalString(x: String): Boolean = x.forall(strChars.contains(_)) + + private case class Cells( + parentAddress: Int, + parentSize: Int, + selfAddress: Int, + selfSize: Int) + private val defaultCells = Cells(2, 1, 2, 1) + + private def fmtCell(x: BigInt, cells: Int): Seq[String] = { + val cellbits = 32 + val mask = (BigInt(1) << cellbits) - 1 + (0 until cells).reverse map { case i => "0x%x".format((x >> (i*cellbits)) & mask) } + } + + private def fmtAddress(x: ResourceAddress, cells: Cells): Seq[String] = { + val ranges = AddressRange.fromSets(x.address) + ranges.flatMap { case AddressRange(base, size) => + fmtCell(base, cells.parentAddress) ++ fmtCell(size, cells.parentSize) + } + } + + private def fmtMapping(x: ResourceMapping, cells: Cells): Seq[String] = { + val ranges = AddressRange.fromSets(x.address) + ranges.flatMap { case AddressRange(base, size) => + fmtCell(base+x.offset, cells.selfAddress) ++ fmtCell(base, cells.parentAddress) ++ fmtCell(size, cells.selfSize) + } + } + + private def fmtString(x: ResourceString): Seq[String] = { + require (legalString(x.value), s"The string '${x.value}' contains chars probably unwise for use in a DTS string") + Seq("\"" + x.value + "\"") + } + + private def fmtMap(x: ResourceMap, indent: String, cells: Cells): Seq[String] = { + val (nodes, props) = x.value.partition(_ match { + case (_, Seq(ResourceMap(_, _))) => true + case _ => false + }) + + def getInt(x: ResourceValue) = x match { + case ResourceInt(value) => Some(value.toInt) + case _ => None + } + val selfAddress = x.value.getOrElse("#address-cells", Nil).headOption.flatMap(getInt) + val selfSize = x.value.getOrElse("#size-cells", Nil).headOption.flatMap(getInt) + + val myCells = Cells( + parentAddress = cells.selfAddress, + parentSize = cells.selfSize, + selfAddress = selfAddress.getOrElse(defaultCells.selfAddress), + selfSize = selfSize .getOrElse(defaultCells.selfSize)) + + props.flatMap { case (k, seq) => + require (legalProperty(k), s"The string '${k}' is not a legal DTS property name") + seq.headOption match { + case None => Seq(indent, k, ";\n") + case Some(ResourceString(_)) => { + seq.foreach { r => r match { + case ResourceString(_) => Unit + case _ => require(false, s"The property '${k}' has values of conflicting type: ${seq}") + } } + Seq(indent, k, " = ", seq.flatMap(z => helper(z, "", myCells)).mkString(", "), ";\n") + } + case Some(_) => { + seq.foreach { r => r match { + case ResourceMap(_, _) => require(false, s"The property '${k}' has values of conflicting type: ${seq}") + case ResourceString(_) => require(false, s"The property '${k}' has values of conflicting type: ${seq}") + case _ => Unit + } } + Seq(indent, k, " = <", seq.flatMap(z => helper(z, "", myCells)).mkString(" "), ">;\n") + } + } + }.toList ++ + nodes.flatMap { case (k, Seq(s: ResourceMap)) => + require (legalNode(k), s"The string '${k}' is not a legal DTS node name") + Seq(indent) ++ s.labels.map(_ + ": ").filter(_ => !indent.isEmpty) ++ // labels on root not allowed + Seq(k, " {\n") ++ helper(s, indent + "\t", myCells) ++ Seq(indent, "};\n") + } + } + + private def helper(res: ResourceValue, indent: String, cells: Cells): Seq[String] = res match { + case x: ResourceAddress => fmtAddress(x, cells) + case x: ResourceMapping => fmtMapping(x, cells) + case x: ResourceInt => Seq(x.value.toString) + case x: ResourceString => fmtString(x) + case x: ResourceReference => Seq("&" + x.value) + case x: ResourceMap => fmtMap(x, indent, cells) + } +} diff --git a/src/main/scala/rocketchip/Configs.scala b/src/main/scala/rocketchip/Configs.scala index acd483bc..f69f0d9b 100644 --- a/src/main/scala/rocketchip/Configs.scala +++ b/src/main/scala/rocketchip/Configs.scala @@ -20,6 +20,10 @@ import DefaultTestSuites._ import config._ class BasePlatformConfig extends Config((site, here, up) => { + // DTS descriptive parameters + case DTSModel => "ucbbar,rocketchip-unknown" + case DTSCompat => Nil + case DTSTimebase => BigInt(0) // TileLink connection parameters case TLMonitorBuilder => (args: TLMonitorArgs) => Some(LazyModule(new TLMonitor(args))) case TLFuzzReadyValid => false @@ -139,6 +143,11 @@ class WithExtMemSize(n: Long) extends Config((site, here, up) => { case ExtMem => up(ExtMem, site).copy(size = n) }) +class WithDTS(model: String, compat: Seq[String]) extends Config((site, here, up) => { + case DTSModel => model + case DTSCompat => compat +}) + class WithScratchpad extends Config(new WithNMemoryChannels(0) ++ new WithDataScratchpad(16384)) class DefaultFPGASmallConfig extends Config(new WithNSmallCores(1) ++ new DefaultFPGAConfig) From 7f6a250dbf59d56573bef593a89fbeb10211fa06 Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Tue, 28 Feb 2017 19:49:39 -0800 Subject: [PATCH 04/14] tilelink2: add hooks for Resources --- src/main/scala/uncore/tilelink2/IntNodes.scala | 18 +++++++++++------- .../scala/uncore/tilelink2/Parameters.scala | 8 ++++++++ 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/src/main/scala/uncore/tilelink2/IntNodes.scala b/src/main/scala/uncore/tilelink2/IntNodes.scala index dab03d4e..110d89ef 100644 --- a/src/main/scala/uncore/tilelink2/IntNodes.scala +++ b/src/main/scala/uncore/tilelink2/IntNodes.scala @@ -18,20 +18,22 @@ case class IntRange(start: Int, end: Int) def overlaps(x: IntRange) = start < x.end && x.start < end def offset(x: Int) = IntRange(x+start, x+end) } + object IntRange { implicit def apply(end: Int): IntRange = apply(0, end) } case class IntSourceParameters( - range: IntRange, - nodePath: Seq[BaseNode] = Seq()) + range: IntRange, + resources: Seq[Resource] = Seq(), + nodePath: Seq[BaseNode] = Seq()) { val name = nodePath.lastOption.map(_.lazyModule.name).getOrElse("disconnected") } case class IntSinkParameters( - nodePath: Seq[BaseNode] = Seq()) + nodePath: Seq[BaseNode] = Seq()) { val name = nodePath.lastOption.map(_.lazyModule.name).getOrElse("disconnected") } @@ -74,8 +76,8 @@ object IntImp extends NodeImp[IntSourcePortParameters, IntSinkPortParameters, In } case class IntIdentityNode() extends IdentityNode(IntImp) -case class IntSourceNode(num: Int) extends SourceNode(IntImp)( - if (num == 0) Seq() else Seq(IntSourcePortParameters(Seq(IntSourceParameters(num))))) +case class IntSourceNode(num: Int, resources: Seq[Resource] = Nil) extends SourceNode(IntImp)( + if (num == 0) Seq() else Seq(IntSourcePortParameters(Seq(IntSourceParameters(num, resources))))) case class IntSinkNode() extends SinkNode(IntImp)( Seq(IntSinkPortParameters(Seq(IntSinkParameters())))) @@ -90,10 +92,12 @@ case class IntOutputNode() extends OutputNode(IntImp) case class IntInputNode() extends InputNode(IntImp) case class IntBlindOutputNode() extends BlindOutputNode(IntImp)(Seq(IntSinkPortParameters(Seq(IntSinkParameters())))) -case class IntBlindInputNode(num: Int) extends BlindInputNode(IntImp)(Seq(IntSourcePortParameters(Seq(IntSourceParameters(num))))) +case class IntBlindInputNode(num: Int, resources: Seq[Resource] = Nil) extends BlindInputNode(IntImp)( + Seq(IntSourcePortParameters(Seq(IntSourceParameters(num, resources))))) case class IntInternalOutputNode() extends InternalOutputNode(IntImp)(Seq(IntSinkPortParameters(Seq(IntSinkParameters())))) -case class IntInternalInputNode(num: Int) extends InternalInputNode(IntImp)(Seq(IntSourcePortParameters(Seq(IntSourceParameters(num))))) +case class IntInternalInputNode(num: Int, resources: Seq[Resource] = Nil) extends InternalInputNode(IntImp)( + Seq(IntSourcePortParameters(Seq(IntSourceParameters(num, resources))))) class IntXbar()(implicit p: Parameters) extends LazyModule { diff --git a/src/main/scala/uncore/tilelink2/Parameters.scala b/src/main/scala/uncore/tilelink2/Parameters.scala index 3462e559..cdfad24b 100644 --- a/src/main/scala/uncore/tilelink2/Parameters.scala +++ b/src/main/scala/uncore/tilelink2/Parameters.scala @@ -9,6 +9,7 @@ import util.RationalDirection case class TLManagerParameters( address: Seq[AddressSet], + resources: Seq[Resource] = Seq(), regionType: RegionType.T = RegionType.GET_EFFECTS, executable: Boolean = false, // processor can execute from this memory nodePath: Seq[BaseNode] = Seq(), @@ -67,6 +68,13 @@ case class TLManagerParameters( // The device had better not support a transfer larger than it's alignment val minAlignment = address.map(_.alignment).min require (minAlignment >= maxTransfer) + + def toResource: ResourceAddress = { + ResourceAddress(address, + r = supportsAcquireB || supportsGet, + w = supportsAcquireT || supportsPutFull, + x = executable) + } } case class TLManagerPortParameters( From 0b950b5938bb9e0443f5d6973db8e1e0a131dd93 Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Tue, 28 Feb 2017 22:34:24 -0800 Subject: [PATCH 05/14] coreplex: bind assigned resources --- src/main/scala/coreplex/BaseCoreplex.scala | 2 +- src/main/scala/coreplex/CoreplexNetwork.scala | 48 +++++++++++++++++++ src/main/scala/coreplex/RISCVPlatform.scala | 5 ++ 3 files changed, 54 insertions(+), 1 deletion(-) diff --git a/src/main/scala/coreplex/BaseCoreplex.scala b/src/main/scala/coreplex/BaseCoreplex.scala index 3188e15b..e0333128 100644 --- a/src/main/scala/coreplex/BaseCoreplex.scala +++ b/src/main/scala/coreplex/BaseCoreplex.scala @@ -55,7 +55,7 @@ trait HasCoreplexParameters { case class CoreplexParameters(implicit val p: Parameters) extends HasCoreplexParameters -abstract class BareCoreplex(implicit p: Parameters) extends LazyModule +abstract class BareCoreplex(implicit p: Parameters) extends LazyModule with BindingScope abstract class BareCoreplexBundle[+L <: BareCoreplex](_outer: L) extends GenericParameterizedBundle(_outer) { val outer = _outer diff --git a/src/main/scala/coreplex/CoreplexNetwork.scala b/src/main/scala/coreplex/CoreplexNetwork.scala index d4b700aa..0171a939 100644 --- a/src/main/scala/coreplex/CoreplexNetwork.scala +++ b/src/main/scala/coreplex/CoreplexNetwork.scala @@ -11,6 +11,7 @@ import util._ trait CoreplexNetwork extends HasCoreplexParameters { val module: CoreplexNetworkModule + def bindingTree: ResourceMap val l1tol2 = LazyModule(new TLXbar) val l1tol2_beatBytes = l1tol2Config.beatBytes @@ -40,6 +41,53 @@ trait CoreplexNetwork extends HasCoreplexParameters { mmio := TLWidthWidget(l1tol2_beatBytes)( l1tol2.node) + + val root = new Device { + def describe(resources: ResourceBindings): Description = { + val width = resources("width").map(_.value) + Description("/", Map( + "#address-cells" -> width, + "#size-cells" -> width, + "model" -> Seq(ResourceString(p(DTSModel))), + "compatible" -> (p(DTSModel) +: p(DTSCompat)).map(s => ResourceString(s + "-dev")))) + } + } + + val soc = new Device { + def describe(resources: ResourceBindings): Description = { + val width = resources("width").map(_.value) + Description("soc", Map( + "#address-cells" -> width, + "#size-cells" -> width, + "compatible" -> (p(DTSModel) +: p(DTSCompat)).map(s => ResourceString(s + "-soc")), + "ranges" -> Nil)) + } + } + + val cpus = new Device { + def describe(resources: ResourceBindings): Description = { + Description("cpus", Map( + "#address-cells" -> Seq(ResourceInt(1)), + "#size-cells" -> Seq(ResourceInt(0)), + "timebase-frequency" -> Seq(ResourceInt(p(DTSTimebase))))) + } + } + + ResourceBinding { + val managers = l1tol2.node.edgesIn.headOption.map(_.manager.managers).getOrElse(Nil) + val max = managers.flatMap(_.address).map(_.max).max + val width = ResourceInt((log2Ceil(max)+31) / 32) + Resource(root, "width").bind(width) + Resource(soc, "width").bind(width) + Resource(cpus, "null").bind(ResourceString("")) + + managers.foreach { case manager => + val value = manager.toResource + manager.resources.foreach { case resource => + resource.bind(value) + } + } + } } trait CoreplexNetworkBundle extends HasCoreplexParameters { diff --git a/src/main/scala/coreplex/RISCVPlatform.scala b/src/main/scala/coreplex/RISCVPlatform.scala index bbba0bd0..e375ab14 100644 --- a/src/main/scala/coreplex/RISCVPlatform.scala +++ b/src/main/scala/coreplex/RISCVPlatform.scala @@ -28,6 +28,8 @@ trait CoreplexRISCVPlatform extends CoreplexNetwork { val managers = l1tol2.node.edgesIn(0).manager.managers rocketchip.GenerateConfigString(p, clint, plic, managers) } + + lazy val dts = DTS(bindingTree) } trait CoreplexRISCVPlatformBundle extends CoreplexNetworkBundle { @@ -52,4 +54,7 @@ trait CoreplexRISCVPlatformModule extends CoreplexNetworkModule { println(s"\nGenerated Configuration String\n${outer.configString}") ElaborationArtefacts.add("cfg", outer.configString) + + println(outer.dts) + ElaborationArtefacts.add("dts", outer.dts) } From 9a5e2e038ba921e3f66414b7f907047b44821986 Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Tue, 28 Feb 2017 23:12:36 -0800 Subject: [PATCH 06/14] uncore: add DTS meta-data for devices --- src/main/scala/uncore/devices/Debug.scala | 2 +- src/main/scala/uncore/devices/Plic.scala | 37 ++++++++++++---- src/main/scala/uncore/devices/Prci.scala | 3 +- src/main/scala/uncore/devices/Rom.scala | 3 ++ src/main/scala/uncore/tilelink2/Example.scala | 3 +- .../uncore/tilelink2/RegisterRouter.scala | 42 +++++++++++++++---- .../uncore/tilelink2/RegisterRouterTest.scala | 4 +- src/main/scala/uncore/tilelink2/SRAM.scala | 3 ++ src/main/scala/uncore/tilelink2/Zero.scala | 3 ++ 9 files changed, 79 insertions(+), 21 deletions(-) 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), From cfd367248f69a5162a6106cfbce6fa85a3c34625 Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Wed, 1 Mar 2017 00:03:01 -0800 Subject: [PATCH 07/14] rocketchip: add blind ports to DTS --- src/main/scala/rocketchip/Periphery.scala | 15 ++++++++++++++- src/main/scala/uncore/ahb/Parameters.scala | 1 + src/main/scala/uncore/apb/Parameters.scala | 1 + src/main/scala/uncore/axi4/Parameters.scala | 1 + src/main/scala/uncore/axi4/ToTL.scala | 1 + src/main/scala/uncore/tilelink2/ToAHB.scala | 1 + src/main/scala/uncore/tilelink2/ToAPB.scala | 1 + src/main/scala/uncore/tilelink2/ToAXI4.scala | 1 + 8 files changed, 21 insertions(+), 1 deletion(-) diff --git a/src/main/scala/rocketchip/Periphery.scala b/src/main/scala/rocketchip/Periphery.scala index d8d4aae5..b72ae9e3 100644 --- a/src/main/scala/rocketchip/Periphery.scala +++ b/src/main/scala/rocketchip/Periphery.scala @@ -51,8 +51,14 @@ trait HasPeripheryParameters { trait PeripheryExtInterrupts { this: HasTopLevelNetworks => + private val device = new Device with DeviceInterrupts { + def describe(resources: ResourceBindings): Description = { + Description("soc/offchip-interrupts", describeInterrupts(resources)) + } + } + val nExtInterrupts = p(NExtTopInterrupts) - val extInterrupts = IntInternalInputNode(nExtInterrupts) + val extInterrupts = IntInternalInputNode(nExtInterrupts, device.int) val extInterruptXing = LazyModule(new IntXing) intBus.intnode := extInterruptXing.intnode @@ -84,6 +90,8 @@ trait PeripheryMasterAXI4Mem { private val channels = p(BankedL2Config).nMemoryChannels private val lineBytes = p(CacheBlockBytes) + private val device = new MemoryDevice + val mem_axi4 = AXI4BlindOutputNode(Seq.tabulate(channels) { channel => val base = AddressSet(config.base, config.size-1) val filter = AddressSet(channel * lineBytes, ~((channels-1) * lineBytes)) @@ -91,6 +99,7 @@ trait PeripheryMasterAXI4Mem { AXI4SlavePortParameters( slaves = Seq(AXI4SlaveParameters( address = base.intersect(filter).toList, + resources = device.reg, regionType = RegionType.UNCACHED, // cacheable executable = true, supportsWrite = TransferSizes(1, 256), // The slave supports 1-256 byte transfers @@ -160,9 +169,11 @@ trait PeripheryMasterAXI4MMIO { this: HasTopLevelNetworks => private val config = p(ExtBus) + private val device = new SimpleDevice("mmio", Nil) val mmio_axi4 = AXI4BlindOutputNode(Seq(AXI4SlavePortParameters( slaves = Seq(AXI4SlaveParameters( address = List(AddressSet(BigInt(config.base), config.size-1)), + resources = device.reg, executable = true, // Can we run programs on this memory? supportsWrite = TransferSizes(1, 256), // The slave supports 1-256 byte transfers supportsRead = TransferSizes(1, 256), @@ -227,9 +238,11 @@ trait PeripheryMasterTLMMIO { this: HasTopLevelNetworks => private val config = p(ExtBus) + private val device = new SimpleDevice("mmio", Nil) val mmio_tl = TLBlindOutputNode(Seq(TLManagerPortParameters( managers = Seq(TLManagerParameters( address = List(AddressSet(BigInt(config.base), config.size-1)), + resources = device.reg, executable = true, supportsGet = TransferSizes(1, cacheBlockBytes), supportsPutFull = TransferSizes(1, cacheBlockBytes), diff --git a/src/main/scala/uncore/ahb/Parameters.scala b/src/main/scala/uncore/ahb/Parameters.scala index ce85c0cd..f8b0b85a 100644 --- a/src/main/scala/uncore/ahb/Parameters.scala +++ b/src/main/scala/uncore/ahb/Parameters.scala @@ -9,6 +9,7 @@ import scala.math.max case class AHBSlaveParameters( address: Seq[AddressSet], + resources: Seq[Resource] = Nil, regionType: RegionType.T = RegionType.GET_EFFECTS, executable: Boolean = false, // processor can execute from this memory nodePath: Seq[BaseNode] = Seq(), diff --git a/src/main/scala/uncore/apb/Parameters.scala b/src/main/scala/uncore/apb/Parameters.scala index 3f47c96e..a3cb4d72 100644 --- a/src/main/scala/uncore/apb/Parameters.scala +++ b/src/main/scala/uncore/apb/Parameters.scala @@ -9,6 +9,7 @@ import scala.math.max case class APBSlaveParameters( address: Seq[AddressSet], + resources: Seq[Resource] = Nil, regionType: RegionType.T = RegionType.GET_EFFECTS, executable: Boolean = false, // processor can execute from this memory nodePath: Seq[BaseNode] = Seq(), diff --git a/src/main/scala/uncore/axi4/Parameters.scala b/src/main/scala/uncore/axi4/Parameters.scala index 8d151645..23844be7 100644 --- a/src/main/scala/uncore/axi4/Parameters.scala +++ b/src/main/scala/uncore/axi4/Parameters.scala @@ -9,6 +9,7 @@ import scala.math.max case class AXI4SlaveParameters( address: Seq[AddressSet], + resources: Seq[Resource] = Nil, regionType: RegionType.T = RegionType.GET_EFFECTS, executable: Boolean = false, // processor can execute from this memory nodePath: Seq[BaseNode] = Seq(), diff --git a/src/main/scala/uncore/axi4/ToTL.scala b/src/main/scala/uncore/axi4/ToTL.scala index 6561d1fd..a7612b36 100644 --- a/src/main/scala/uncore/axi4/ToTL.scala +++ b/src/main/scala/uncore/axi4/ToTL.scala @@ -20,6 +20,7 @@ case class AXI4ToTLNode() extends MixedAdapterNode(AXI4Imp, TLImp)( slaves = mp.managers.map { m => AXI4SlaveParameters( address = m.address, + resources = m.resources, regionType = m.regionType, executable = m.executable, nodePath = m.nodePath, diff --git a/src/main/scala/uncore/tilelink2/ToAHB.scala b/src/main/scala/uncore/tilelink2/ToAHB.scala index 4d7f8c81..7757c012 100644 --- a/src/main/scala/uncore/tilelink2/ToAHB.scala +++ b/src/main/scala/uncore/tilelink2/ToAHB.scala @@ -19,6 +19,7 @@ case class TLToAHBNode() extends MixedAdapterNode(TLImp, AHBImp)( val managers = slaves.map { case s => TLManagerParameters( address = s.address, + resources = s.resources, regionType = s.regionType, executable = s.executable, nodePath = s.nodePath, diff --git a/src/main/scala/uncore/tilelink2/ToAPB.scala b/src/main/scala/uncore/tilelink2/ToAPB.scala index c2966751..48ee119e 100644 --- a/src/main/scala/uncore/tilelink2/ToAPB.scala +++ b/src/main/scala/uncore/tilelink2/ToAPB.scala @@ -19,6 +19,7 @@ case class TLToAPBNode() extends MixedAdapterNode(TLImp, APBImp)( val managers = slaves.map { case s => TLManagerParameters( address = s.address, + resources = s.resources, regionType = s.regionType, executable = s.executable, nodePath = s.nodePath, diff --git a/src/main/scala/uncore/tilelink2/ToAXI4.scala b/src/main/scala/uncore/tilelink2/ToAXI4.scala index c0b7a6c8..566013d9 100644 --- a/src/main/scala/uncore/tilelink2/ToAXI4.scala +++ b/src/main/scala/uncore/tilelink2/ToAXI4.scala @@ -23,6 +23,7 @@ case class TLToAXI4Node(idBits: Int) extends MixedAdapterNode(TLImp, AXI4Imp)( managers = p.slaves.map { case s => TLManagerParameters( address = s.address, + resources = s.resources, regionType = s.regionType, executable = s.executable, nodePath = s.nodePath, From 5bd9f18e5b581c4caf80dabc06634624df4b56a9 Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Wed, 1 Mar 2017 16:47:10 -0800 Subject: [PATCH 08/14] rocket: add dts cpu description --- src/main/scala/coreplex/RocketTiles.scala | 6 +- src/main/scala/rocket/Rocket.scala | 1 + src/main/scala/rocket/Tile.scala | 70 +++++++++++++++++++++-- 3 files changed, 69 insertions(+), 8 deletions(-) diff --git a/src/main/scala/coreplex/RocketTiles.scala b/src/main/scala/coreplex/RocketTiles.scala index 31f39ba6..5beed003 100644 --- a/src/main/scala/coreplex/RocketTiles.scala +++ b/src/main/scala/coreplex/RocketTiles.scala @@ -43,7 +43,7 @@ trait HasRocketTiles extends CoreplexRISCVPlatform { crossing match { case Synchronous => { - val tile = LazyModule(new RocketTile(c)(pWithExtra)) + val tile = LazyModule(new RocketTile(c, i)(pWithExtra)) val buffer = LazyModule(new TLBuffer) buffer.node :=* tile.masterNode l1tol2.node :=* buffer.node @@ -56,7 +56,7 @@ trait HasRocketTiles extends CoreplexRISCVPlatform { } } case Asynchronous(depth, sync) => { - val wrapper = LazyModule(new AsyncRocketTile(c)(pWithExtra)) + val wrapper = LazyModule(new AsyncRocketTile(c, i)(pWithExtra)) val sink = LazyModule(new TLAsyncCrossingSink(depth, sync)) val source = LazyModule(new TLAsyncCrossingSource(sync)) sink.node :=* wrapper.masterNode @@ -72,7 +72,7 @@ trait HasRocketTiles extends CoreplexRISCVPlatform { } } case Rational => { - val wrapper = LazyModule(new RationalRocketTile(c)(pWithExtra)) + val wrapper = LazyModule(new RationalRocketTile(c, i)(pWithExtra)) val sink = LazyModule(new TLRationalCrossingSink(util.FastToSlow)) val source = LazyModule(new TLRationalCrossingSource) sink.node :=* wrapper.masterNode diff --git a/src/main/scala/rocket/Rocket.scala b/src/main/scala/rocket/Rocket.scala index 345b5d79..5c17c5f4 100644 --- a/src/main/scala/rocket/Rocket.scala +++ b/src/main/scala/rocket/Rocket.scala @@ -11,6 +11,7 @@ import util._ import Chisel.ImplicitConversions._ case class RocketCoreParams( + bootFreqHz: BigInt = 0, useVM: Boolean = true, useUser: Boolean = false, useDebug: Boolean = true, diff --git a/src/main/scala/rocket/Tile.scala b/src/main/scala/rocket/Tile.scala index 23f726ff..737536c1 100644 --- a/src/main/scala/rocket/Tile.scala +++ b/src/main/scala/rocket/Tile.scala @@ -23,12 +23,72 @@ case class RocketTileParams( require(dcache.isDefined) } -class RocketTile(val rocketParams: RocketTileParams)(implicit p: Parameters) extends BaseTile(rocketParams)(p) +class RocketTile(val rocketParams: RocketTileParams, val hartid: Int)(implicit p: Parameters) extends BaseTile(rocketParams)(p) with CanHaveLegacyRoccs // implies CanHaveSharedFPU with CanHavePTW with HasHellaCache with CanHaveScratchpad { // implies CanHavePTW with HasHellaCache with HasICacheFrontend nDCachePorts += 1 // core TODO dcachePorts += () => module.core.io.dmem ?? + val device = new Device { + def ofInt(x: Int) = Seq(ResourceInt(BigInt(x))) + def ofStr(x: String) = Seq(ResourceString(x)) + def describe(resources: ResourceBindings): Description = { + val block = p(CacheBlockBytes) + val m = if (rocketParams.core.mulDiv.nonEmpty) "m" else "" + val a = if (rocketParams.core.useAtomics) "a" else "" + val f = if (rocketParams.core.fpu.nonEmpty) "f" else "" + val d = if (rocketParams.core.fpu.nonEmpty && p(XLen) > 32) "d" else "" + val c = if (rocketParams.core.useCompressed) "c" else "" + val s = if (rocketParams.core.useVM) "s" else "" + val isa = s"rv${p(XLen)}i$m$a$f$d$c$s" + + val dcache = rocketParams.dcache.map(d => Map( + "d-tlb-size" -> ofInt(d.nTLBEntries), + "d-tlb-sets" -> ofInt(1), + "d-cache-block-size" -> ofInt(block), + "d-cache-sets" -> ofInt(d.nSets), + "d-cache-size" -> ofInt(d.nSets * d.nWays * block))).getOrElse(Map()) + + val icache = rocketParams.icache.map(i => Map( + "i-tlb-size" -> ofInt(i.nTLBEntries), + "i-tlb-sets" -> ofInt(1), + "i-cache-block-size" -> ofInt(block), + "i-cache-sets" -> ofInt(i.nSets), + "i-cache-size" -> ofInt(i.nSets * i.nWays * block))).getOrElse(Map()) + + // Find all the caches + val outer = masterNode.edgesOut + .flatMap(_.manager.managers) + .filter(_.supportsAcquireB) + .flatMap(_.resources.headOption) + .map(_.owner.label) + .distinct + val nextlevel: Option[(String, Seq[ResourceValue])] = + if (outer.isEmpty) None else + Some("next-level-cache" -> outer.map(l => ResourceReference(l)).toList) + + Description(s"cpus/cpu@${hartid}", Map( + "reg" -> resources("reg").map(_.value), + "device_type" -> ofStr("cpu"), + "compatible" -> ofStr("riscv"), + "status" -> ofStr("okay"), + "clock-frequency" -> Seq(ResourceInt(rocketParams.core.bootFreqHz)), + "riscv,isa" -> ofStr(isa), + "mmu-type" -> ofStr(p(PgLevels) match { + case 2 => "riscv,sv32" + case 3 => "riscv,sv39" + case 4 => "riscv,sv48" }), + "tlb-split" -> Nil, + "interrupt-controller" -> Nil, + "#interrupt-cells" -> ofInt(1)) + ++ dcache ++ icache ++ nextlevel) + } + } + + ResourceBinding { + Resource(device, "reg").bind(ResourceInt(BigInt(hartid))) + } + override lazy val module = new RocketTileModule(this) } @@ -66,8 +126,8 @@ class RocketTileModule(outer: RocketTile) extends BaseTileModule(outer, () => ne ptwOpt foreach { ptw => ptw.io.requestor <> ptwPorts } } -class AsyncRocketTile(rtp: RocketTileParams)(implicit p: Parameters) extends LazyModule { - val rocket = LazyModule(new RocketTile(rtp)) +class AsyncRocketTile(rtp: RocketTileParams, hartid: Int)(implicit p: Parameters) extends LazyModule { + val rocket = LazyModule(new RocketTile(rtp, hartid)) val masterNode = TLAsyncOutputNode() val source = LazyModule(new TLAsyncCrossingSource) @@ -94,8 +154,8 @@ class AsyncRocketTile(rtp: RocketTileParams)(implicit p: Parameters) extends Laz } } -class RationalRocketTile(rtp: RocketTileParams)(implicit p: Parameters) extends LazyModule { - val rocket = LazyModule(new RocketTile(rtp)) +class RationalRocketTile(rtp: RocketTileParams, hartid: Int)(implicit p: Parameters) extends LazyModule { + val rocket = LazyModule(new RocketTile(rtp, hartid)) val masterNode = TLRationalOutputNode() val source = LazyModule(new TLRationalCrossingSource) From 38489ad9b0ed8d4dc404921ce90e52115fb740d6 Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Wed, 1 Mar 2017 18:23:28 -0800 Subject: [PATCH 09/14] tilelink2: bring IntNode parameters up to the current standard --- src/main/scala/coreplex/RocketTiles.scala | 2 +- src/main/scala/rocketchip/Periphery.scala | 2 +- .../scala/uncore/ahb/RegisterRouter.scala | 2 +- .../scala/uncore/apb/RegisterRouter.scala | 2 +- .../scala/uncore/axi4/RegisterRouter.scala | 2 +- .../scala/uncore/tilelink2/IntNodes.scala | 27 ++++++++++++------- .../uncore/tilelink2/RegisterRouter.scala | 2 +- 7 files changed, 23 insertions(+), 16 deletions(-) diff --git a/src/main/scala/coreplex/RocketTiles.scala b/src/main/scala/coreplex/RocketTiles.scala index 5beed003..3202f128 100644 --- a/src/main/scala/coreplex/RocketTiles.scala +++ b/src/main/scala/coreplex/RocketTiles.scala @@ -23,7 +23,7 @@ trait HasRocketTiles extends CoreplexRISCVPlatform { private val crossing = p(RocketCrossing) private val configs = p(RocketTilesKey) - private val rocketTileIntNodes = configs.map { _ => IntInternalOutputNode() } + private val rocketTileIntNodes = configs.map { _ => IntInternalOutputNode(IntSinkPortSimple()) } rocketTileIntNodes.foreach { _ := plic.intnode } private def wireInterrupts(x: TileInterrupts, i: Int) { diff --git a/src/main/scala/rocketchip/Periphery.scala b/src/main/scala/rocketchip/Periphery.scala index b72ae9e3..ce91fbdb 100644 --- a/src/main/scala/rocketchip/Periphery.scala +++ b/src/main/scala/rocketchip/Periphery.scala @@ -58,7 +58,7 @@ trait PeripheryExtInterrupts { } val nExtInterrupts = p(NExtTopInterrupts) - val extInterrupts = IntInternalInputNode(nExtInterrupts, device.int) + val extInterrupts = IntInternalInputNode(IntSourcePortSimple(num = nExtInterrupts, resources = device.int)) val extInterruptXing = LazyModule(new IntXing) intBus.intnode := extInterruptXing.intnode diff --git a/src/main/scala/uncore/ahb/RegisterRouter.scala b/src/main/scala/uncore/ahb/RegisterRouter.scala index e514292e..2621e41f 100644 --- a/src/main/scala/uncore/ahb/RegisterRouter.scala +++ b/src/main/scala/uncore/ahb/RegisterRouter.scala @@ -77,7 +77,7 @@ object AHBRegisterNode abstract class AHBRegisterRouterBase(address: AddressSet, interrupts: Int, concurrency: Int, beatBytes: Int, undefZero: Boolean, executable: Boolean)(implicit p: Parameters) extends LazyModule { val node = AHBRegisterNode(address, concurrency, beatBytes, undefZero, executable) - val intnode = uncore.tilelink2.IntSourceNode(interrupts) + val intnode = uncore.tilelink2.IntSourceNode(uncore.tilelink2.IntSourcePortSimple(num = interrupts)) } case class AHBRegBundleArg(interrupts: util.HeterogeneousBag[Vec[Bool]], in: util.HeterogeneousBag[AHBBundle])(implicit val p: Parameters) diff --git a/src/main/scala/uncore/apb/RegisterRouter.scala b/src/main/scala/uncore/apb/RegisterRouter.scala index 62585d0e..b8e3a9ae 100644 --- a/src/main/scala/uncore/apb/RegisterRouter.scala +++ b/src/main/scala/uncore/apb/RegisterRouter.scala @@ -61,7 +61,7 @@ object APBRegisterNode abstract class APBRegisterRouterBase(address: AddressSet, interrupts: Int, concurrency: Int, beatBytes: Int, undefZero: Boolean, executable: Boolean)(implicit p: Parameters) extends LazyModule { val node = APBRegisterNode(address, concurrency, beatBytes, undefZero, executable) - val intnode = uncore.tilelink2.IntSourceNode(interrupts) + val intnode = uncore.tilelink2.IntSourceNode(uncore.tilelink2.IntSourcePortSimple(num = interrupts)) } case class APBRegBundleArg(interrupts: util.HeterogeneousBag[Vec[Bool]], in: util.HeterogeneousBag[APBBundle])(implicit val p: Parameters) diff --git a/src/main/scala/uncore/axi4/RegisterRouter.scala b/src/main/scala/uncore/axi4/RegisterRouter.scala index 2da706bf..b7d51611 100644 --- a/src/main/scala/uncore/axi4/RegisterRouter.scala +++ b/src/main/scala/uncore/axi4/RegisterRouter.scala @@ -82,7 +82,7 @@ object AXI4RegisterNode abstract class AXI4RegisterRouterBase(address: AddressSet, interrupts: Int, concurrency: Int, beatBytes: Int, undefZero: Boolean, executable: Boolean)(implicit p: Parameters) extends LazyModule { val node = AXI4RegisterNode(address, concurrency, beatBytes, undefZero, executable) - val intnode = uncore.tilelink2.IntSourceNode(interrupts) + val intnode = uncore.tilelink2.IntSourceNode(uncore.tilelink2.IntSourcePortSimple(num = interrupts)) } case class AXI4RegBundleArg(interrupts: util.HeterogeneousBag[Vec[Bool]], in: util.HeterogeneousBag[AXI4Bundle])(implicit val p: Parameters) diff --git a/src/main/scala/uncore/tilelink2/IntNodes.scala b/src/main/scala/uncore/tilelink2/IntNodes.scala index 110d89ef..eb241918 100644 --- a/src/main/scala/uncore/tilelink2/IntNodes.scala +++ b/src/main/scala/uncore/tilelink2/IntNodes.scala @@ -46,8 +46,19 @@ case class IntSourcePortParameters(sources: Seq[IntSourceParameters]) // The interrupts must perfectly cover the range require (sources.isEmpty || sources.map(_.range.end).max == num) } +object IntSourcePortSimple +{ + def apply(num: Int = 1, ports: Int = 1, sources: Int = 1, resources: Seq[Resource] = Nil) = + if (num == 0) Nil else + Seq.fill(ports)(IntSourcePortParameters(Seq.fill(sources)(IntSourceParameters(range = IntRange(0, num), resources = resources)))) +} case class IntSinkPortParameters(sinks: Seq[IntSinkParameters]) +object IntSinkPortSimple +{ + def apply(ports: Int = 1, sinks: Int = 1) = + Seq.fill(ports)(IntSinkPortParameters(Seq.fill(sinks)(IntSinkParameters()))) +} case class IntEdge(source: IntSourcePortParameters, sink: IntSinkPortParameters) @@ -76,10 +87,8 @@ object IntImp extends NodeImp[IntSourcePortParameters, IntSinkPortParameters, In } case class IntIdentityNode() extends IdentityNode(IntImp) -case class IntSourceNode(num: Int, resources: Seq[Resource] = Nil) extends SourceNode(IntImp)( - if (num == 0) Seq() else Seq(IntSourcePortParameters(Seq(IntSourceParameters(num, resources))))) -case class IntSinkNode() extends SinkNode(IntImp)( - Seq(IntSinkPortParameters(Seq(IntSinkParameters())))) +case class IntSourceNode(portParams: Seq[IntSourcePortParameters]) extends SourceNode(IntImp)(portParams) +case class IntSinkNode(portParams: Seq[IntSinkPortParameters]) extends SinkNode(IntImp)(portParams) case class IntNexusNode( sourceFn: Seq[IntSourcePortParameters] => IntSourcePortParameters, @@ -91,13 +100,11 @@ case class IntNexusNode( case class IntOutputNode() extends OutputNode(IntImp) case class IntInputNode() extends InputNode(IntImp) -case class IntBlindOutputNode() extends BlindOutputNode(IntImp)(Seq(IntSinkPortParameters(Seq(IntSinkParameters())))) -case class IntBlindInputNode(num: Int, resources: Seq[Resource] = Nil) extends BlindInputNode(IntImp)( - Seq(IntSourcePortParameters(Seq(IntSourceParameters(num, resources))))) +case class IntBlindOutputNode(portParams: Seq[IntSinkPortParameters]) extends BlindOutputNode(IntImp)(portParams) +case class IntBlindInputNode(portParams: Seq[IntSourcePortParameters]) extends BlindInputNode(IntImp)(portParams) -case class IntInternalOutputNode() extends InternalOutputNode(IntImp)(Seq(IntSinkPortParameters(Seq(IntSinkParameters())))) -case class IntInternalInputNode(num: Int, resources: Seq[Resource] = Nil) extends InternalInputNode(IntImp)( - Seq(IntSourcePortParameters(Seq(IntSourceParameters(num, resources))))) +case class IntInternalOutputNode(portParams: Seq[IntSinkPortParameters]) extends InternalOutputNode(IntImp)(portParams) +case class IntInternalInputNode(portParams: Seq[IntSourcePortParameters]) extends InternalInputNode(IntImp)(portParams) class IntXbar()(implicit p: Parameters) extends LazyModule { diff --git a/src/main/scala/uncore/tilelink2/RegisterRouter.scala b/src/main/scala/uncore/tilelink2/RegisterRouter.scala index 28ea03ac..e46c2a56 100644 --- a/src/main/scala/uncore/tilelink2/RegisterRouter.scala +++ b/src/main/scala/uncore/tilelink2/RegisterRouter.scala @@ -99,7 +99,7 @@ abstract class TLRegisterRouterBase(devname: String, devcompat: Seq[String], val { val device = new SimpleDevice(devname, devcompat) val node = TLRegisterNode(address, device, "reg", concurrency, beatBytes, undefZero, executable) - val intnode = IntSourceNode(interrupts, Seq(Resource(device, "int"))) + val intnode = IntSourceNode(IntSourcePortSimple(num = interrupts, resources = Seq(Resource(device, "int")))) } case class TLRegBundleArg(interrupts: util.HeterogeneousBag[Vec[Bool]], in: util.HeterogeneousBag[TLBundle])(implicit val p: Parameters) From 7ff9f88ad7972ba81c492ce992aced116ff82b9b Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Wed, 1 Mar 2017 21:57:00 -0800 Subject: [PATCH 10/14] rocket: connect interrupt map for Plic+Clint --- src/main/scala/coreplex/RocketTiles.scala | 42 ++++++- src/main/scala/diplomacy/Nodes.scala | 4 +- src/main/scala/uncore/devices/Prci.scala | 130 +++++++++++----------- 3 files changed, 106 insertions(+), 70 deletions(-) diff --git a/src/main/scala/coreplex/RocketTiles.scala b/src/main/scala/coreplex/RocketTiles.scala index 3202f128..206098f0 100644 --- a/src/main/scala/coreplex/RocketTiles.scala +++ b/src/main/scala/coreplex/RocketTiles.scala @@ -23,14 +23,18 @@ trait HasRocketTiles extends CoreplexRISCVPlatform { private val crossing = p(RocketCrossing) private val configs = p(RocketTilesKey) - private val rocketTileIntNodes = configs.map { _ => IntInternalOutputNode(IntSinkPortSimple()) } - rocketTileIntNodes.foreach { _ := plic.intnode } + private val rocketTileIntNodes = configs.map { _ => IntInternalOutputNode(IntSinkPortSimple(ports = 2)) } + rocketTileIntNodes.foreach { n => + n := plic.intnode + n := clint.intnode + } private def wireInterrupts(x: TileInterrupts, i: Int) { - x := clint.module.io.tiles(i) x.debug := debug.module.io.debugInterrupts(i) x.meip := rocketTileIntNodes(i).bundleOut(0)(0) - x.seip.foreach { _ := rocketTileIntNodes(i).bundleOut(0)(1) } + x.seip.foreach { _ := rocketTileIntNodes(i).bundleOut(0)(1) } // optional + x.msip := rocketTileIntNodes(i).bundleOut(1)(0) + x.mtip := rocketTileIntNodes(i).bundleOut(1)(1) } val rocketWires: Seq[HasRocketTilesBundle => Unit] = configs.zipWithIndex.map { case (c, i) => @@ -48,6 +52,16 @@ trait HasRocketTiles extends CoreplexRISCVPlatform { buffer.node :=* tile.masterNode l1tol2.node :=* buffer.node tile.slaveNode :*= cbus.node + ResourceBinding { + rocketTileIntNodes(i).edgesIn(0).source.sources.flatMap(_.resources).foreach { r => + r.bind(tile.device, ResourceInt(11)) // meip + if (c.core.useVM) r.bind(tile.device, ResourceInt(9)) // seip + } + rocketTileIntNodes(i).edgesIn(1).source.sources.flatMap(_.resources).foreach { r => + r.bind(tile.device, ResourceInt(3)) // msip + r.bind(tile.device, ResourceInt(7)) // mtip + } + } (io: HasRocketTilesBundle) => { // leave clock as default (simpler for hierarchical PnR) tile.module.io.hartid := UInt(i) @@ -63,6 +77,16 @@ trait HasRocketTiles extends CoreplexRISCVPlatform { l1tol2.node :=* sink.node wrapper.slaveNode :*= source.node source.node :*= cbus.node + ResourceBinding { + rocketTileIntNodes(i).edgesIn(0).source.sources.flatMap(_.resources).foreach { r => + r.bind(wrapper.rocket.device, ResourceInt(11)) // meip + if (c.core.useVM) r.bind(wrapper.rocket.device, ResourceInt(9)) // seip + } + rocketTileIntNodes(i).edgesIn(1).source.sources.flatMap(_.resources).foreach { r => + r.bind(wrapper.rocket.device, ResourceInt(3)) // msip + r.bind(wrapper.rocket.device, ResourceInt(7)) // mtip + } + } (io: HasRocketTilesBundle) => { wrapper.module.clock := io.tcrs(i).clock wrapper.module.reset := io.tcrs(i).reset @@ -79,6 +103,16 @@ trait HasRocketTiles extends CoreplexRISCVPlatform { l1tol2.node :=* sink.node wrapper.slaveNode :*= source.node source.node :*= cbus.node + ResourceBinding { + rocketTileIntNodes(i).edgesIn(0).source.sources.flatMap(_.resources).foreach { r => + r.bind(wrapper.rocket.device, ResourceInt(11)) // meip + if (c.core.useVM) r.bind(wrapper.rocket.device, ResourceInt(9)) // seip + } + rocketTileIntNodes(i).edgesIn(1).source.sources.flatMap(_.resources).foreach { r => + r.bind(wrapper.rocket.device, ResourceInt(3)) // msip + r.bind(wrapper.rocket.device, ResourceInt(7)) // mtip + } + } (io: HasRocketTilesBundle) => { wrapper.module.clock := io.tcrs(i).clock wrapper.module.reset := io.tcrs(i).reset diff --git a/src/main/scala/diplomacy/Nodes.scala b/src/main/scala/diplomacy/Nodes.scala index 312e9997..2080e8c0 100644 --- a/src/main/scala/diplomacy/Nodes.scala +++ b/src/main/scala/diplomacy/Nodes.scala @@ -302,8 +302,8 @@ class MixedNexusNode[DI, UI, EI, BI <: Data, DO, UO, EO, BO <: Data]( numPI: Range.Inclusive = 1 to 999) extends MixedNode(inner, outer)(numPO, numPI) { - require (numPO.end >= 1, s"${name} does not accept outputs${lazyModule.line}") - require (numPI.end >= 1, s"${name} does not accept inputs${lazyModule.line}") +// require (numPO.end >= 1, s"${name} does not accept outputs${lazyModule.line}") +// require (numPI.end >= 1, s"${name} does not accept inputs${lazyModule.line}") val externalIn: Boolean = true val externalOut: Boolean = true diff --git a/src/main/scala/uncore/devices/Prci.scala b/src/main/scala/uncore/devices/Prci.scala index f61b773c..fa05b29e 100644 --- a/src/main/scala/uncore/devices/Prci.scala +++ b/src/main/scala/uncore/devices/Prci.scala @@ -17,11 +17,6 @@ import tile.XLen /** Number of tiles */ case object NTiles extends Field[Int] -class CoreplexLocalInterrupts extends Bundle { - val mtip = Bool() - val msip = Bool() -} - object ClintConsts { def msipOffset(hart: Int) = hart * msipBytes @@ -30,71 +25,78 @@ object ClintConsts def msipBytes = 4 def timecmpBytes = 8 def size = 0x10000 + def timeWidth = 64 + def regWidth = 32 + def ints = 2 } -trait MixCoreplexLocalInterrupterParameters { - implicit val p: Parameters -} - -trait CoreplexLocalInterrupterBundle extends Bundle with MixCoreplexLocalInterrupterParameters { - val tiles = Vec(p(NTiles), new CoreplexLocalInterrupts).asOutput - val rtcTick = Bool(INPUT) -} - -trait CoreplexLocalInterrupterModule extends Module with HasRegMap with MixCoreplexLocalInterrupterParameters { - val io: CoreplexLocalInterrupterBundle - val address: AddressSet - - val timeWidth = 64 - val regWidth = 32 - - val time = Seq.fill(timeWidth/regWidth)(Reg(init=UInt(0, width = regWidth))) - when (io.rtcTick) { - val newTime = time.asUInt + UInt(1) - for ((reg, i) <- time zip (0 until timeWidth by regWidth)) - reg := newTime >> i - } - - val timecmp = Seq.fill(p(NTiles)) { Seq.fill(timeWidth/regWidth)(Reg(UInt(width = regWidth))) } - val ipi = Seq.fill(p(NTiles)) { RegInit(UInt(0, width = 1)) } - - for ((tile, i) <- io.tiles zipWithIndex) { - tile.msip := ipi(i)(0) - tile.mtip := time.asUInt >= timecmp(i).asUInt - } - - /* 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 - */ - - regmap( - 0 -> makeRegFields(ipi), - ClintConsts.timecmpOffset(0) -> makeRegFields(timecmp.flatten), - ClintConsts.timeOffset -> makeRegFields(time)) - - def makeRegFields(s: Seq[UInt]) = s.map(r => RegField(regWidth, r)) -} - -/** 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, "clint", Seq("riscv,clint0"), size = ClintConsts.size, beatBytes = p(XLen)/8, undefZero = true)( - new TLRegBundle((), _) with CoreplexLocalInterrupterBundle)( - new TLRegModule((), _, _) with CoreplexLocalInterrupterModule) +class CoreplexLocalInterrupter(address: BigInt = 0x02000000)(implicit p: Parameters) extends LazyModule { + import ClintConsts._ + + // clint0 => at most 4095 devices + val device = new SimpleDevice("clint", Seq("riscv,clint0")) { + override val alwaysExtended = true + } + + val node = TLRegisterNode( + address = AddressSet(address, size-1), + device = device, + beatBytes = p(XLen)/8) + + val intnode = IntNexusNode( + numSourcePorts = 0 to 1024, + numSinkPorts = 0 to 0, + sourceFn = { _ => IntSourcePortParameters(Seq(IntSourceParameters(ints, Seq(Resource(device, "int"))))) }, + sinkFn = { _ => IntSinkPortParameters(Seq(IntSinkParameters())) }) + + // Legacy stuff: val globalConfigString = Seq( s"rtc {\n", - s" addr 0x${(address + ClintConsts.timeOffset).toString(16)};\n", + s" addr 0x${(address + timeOffset).toString(16)};\n", s"};\n").mkString val hartConfigStrings = (0 until p(NTiles)).map { i => Seq( - s" timecmp 0x${(address + ClintConsts.timecmpOffset(i)).toString(16)};\n", - s" ipi 0x${(address + ClintConsts.msipOffset(i)).toString(16)};\n").mkString + s" timecmp 0x${(address + timecmpOffset(i)).toString(16)};\n", + s" ipi 0x${(address + msipOffset(i)).toString(16)};\n").mkString + } + + lazy val module = new LazyModuleImp(this) { + val io = new Bundle { + val rtcTick = Bool(INPUT) + val int = intnode.bundleOut + val in = node.bundleIn + } + + val time = Seq.fill(timeWidth/regWidth)(Reg(init=UInt(0, width = regWidth))) + when (io.rtcTick) { + val newTime = time.asUInt + UInt(1) + for ((reg, i) <- time zip (0 until timeWidth by regWidth)) + reg := newTime >> i + } + + val timecmp = Seq.fill(p(NTiles)) { Seq.fill(timeWidth/regWidth)(Reg(UInt(width = regWidth))) } + val ipi = Seq.fill(p(NTiles)) { RegInit(UInt(0, width = 1)) } + + io.int.zipWithIndex.foreach { case (int, i) => + int(0) := ipi(i)(0) // msip + int(1) := time.asUInt >= timecmp(i).asUInt // mtip + } + + /* 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 makeRegFields(s: Seq[UInt]) = s.map(r => RegField(regWidth, r)) + + node.regmap( + 0 -> makeRegFields(ipi), + timecmpOffset(0) -> makeRegFields(timecmp.flatten), + timeOffset -> makeRegFields(time)) } } From 637bc6c3a71d13dcb5e98e18d5ea903df54e514d Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Thu, 2 Mar 2017 13:32:42 -0800 Subject: [PATCH 11/14] coreplex: pretty print discontiguous ranges properly --- src/main/scala/coreplex/CoreplexNetwork.scala | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/main/scala/coreplex/CoreplexNetwork.scala b/src/main/scala/coreplex/CoreplexNetwork.scala index 0171a939..1eef5555 100644 --- a/src/main/scala/coreplex/CoreplexNetwork.scala +++ b/src/main/scala/coreplex/CoreplexNetwork.scala @@ -102,16 +102,17 @@ trait CoreplexNetworkModule extends HasCoreplexParameters { val outer: CoreplexNetwork val io: CoreplexNetworkBundle - println("\nGenerated Address Map") + println("Generated Address Map") for (manager <- outer.l1tol2.node.edgesIn(0).manager.managers) { val prot = (if (manager.supportsGet) "R" else "") + (if (manager.supportsPutFull) "W" else "") + (if (manager.executable) "X" else "") + (if (manager.supportsAcquireB) " [C]" else "") - manager.address.foreach { a => - println(f"\t${manager.name}%s ${a.base}%x - ${a.base+a.mask+1}%x, $prot") + AddressRange.fromSets(manager.address).foreach { r => + println(f"\t${manager.name}%s ${r.base}%x - ${r.base+r.size}%x, $prot") } } + println("") } ///// From 93ca555c20f86660d667bebd1a45dd45583b1d3b Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Thu, 2 Mar 2017 13:33:05 -0800 Subject: [PATCH 12/14] IntXing: support configurable sync depth --- src/main/scala/uncore/tilelink2/IntNodes.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/scala/uncore/tilelink2/IntNodes.scala b/src/main/scala/uncore/tilelink2/IntNodes.scala index eb241918..77aa2e3b 100644 --- a/src/main/scala/uncore/tilelink2/IntNodes.scala +++ b/src/main/scala/uncore/tilelink2/IntNodes.scala @@ -127,7 +127,7 @@ class IntXbar()(implicit p: Parameters) extends LazyModule } } -class IntXing()(implicit p: Parameters) extends LazyModule +class IntXing(sync: Int = 3)(implicit p: Parameters) extends LazyModule { val intnode = IntIdentityNode() @@ -138,7 +138,7 @@ class IntXing()(implicit p: Parameters) extends LazyModule } (io.in zip io.out) foreach { case (in, out) => - out := RegNext(RegNext(RegNext(in))) + out := (0 to sync).foldLeft(in) { case (a, _) => RegNext(a) } } } } From d3c5318714fa5ee5084afe17dcad12291694002c Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Thu, 2 Mar 2017 11:02:35 -0800 Subject: [PATCH 13/14] build: remove the now obsolete config string --- src/main/scala/coreplex/RISCVPlatform.scala | 8 ---- src/main/scala/rocketchip/Periphery.scala | 2 +- src/main/scala/rocketchip/Utils.scala | 42 +++---------------- src/main/scala/uncore/devices/Plic.scala | 35 +--------------- src/main/scala/uncore/devices/Prci.scala | 10 ----- .../scala/uncore/tilelink2/Parameters.scala | 14 +------ 6 files changed, 9 insertions(+), 102 deletions(-) diff --git a/src/main/scala/coreplex/RISCVPlatform.scala b/src/main/scala/coreplex/RISCVPlatform.scala index e375ab14..87afaaa0 100644 --- a/src/main/scala/coreplex/RISCVPlatform.scala +++ b/src/main/scala/coreplex/RISCVPlatform.scala @@ -24,11 +24,6 @@ trait CoreplexRISCVPlatform extends CoreplexNetwork { plic.intnode := intBar.intnode - lazy val configString = { - val managers = l1tol2.node.edgesIn(0).manager.managers - rocketchip.GenerateConfigString(p, clint, plic, managers) - } - lazy val dts = DTS(bindingTree) } @@ -52,9 +47,6 @@ trait CoreplexRISCVPlatformModule extends CoreplexNetworkModule { val rtcLast = Reg(init = Bool(false), next=rtcSync) outer.clint.module.io.rtcTick := Reg(init = Bool(false), next=(rtcSync & (~rtcLast))) - println(s"\nGenerated Configuration String\n${outer.configString}") - ElaborationArtefacts.add("cfg", outer.configString) - println(outer.dts) ElaborationArtefacts.add("dts", outer.dts) } diff --git a/src/main/scala/rocketchip/Periphery.scala b/src/main/scala/rocketchip/Periphery.scala index ce91fbdb..3fdc8a41 100644 --- a/src/main/scala/rocketchip/Periphery.scala +++ b/src/main/scala/rocketchip/Periphery.scala @@ -305,7 +305,7 @@ trait PeripheryBootROM { private val bootrom_address = 0x1000 private val bootrom_size = 0x1000 - private lazy val bootrom_contents = GenerateBootROM(p, bootrom_address, coreplex.configString) + private lazy val bootrom_contents = GenerateBootROM(p, bootrom_address, coreplex.dts) val bootrom = LazyModule(new TLROM(bootrom_address, bootrom_size, bootrom_contents, true, peripheryBusConfig.beatBytes)) bootrom.node := TLFragmenter(peripheryBusConfig.beatBytes, cacheBlockBytes)(peripheryBus.node) } diff --git a/src/main/scala/rocketchip/Utils.scala b/src/main/scala/rocketchip/Utils.scala index 78f4bb9c..31632741 100644 --- a/src/main/scala/rocketchip/Utils.scala +++ b/src/main/scala/rocketchip/Utils.scala @@ -52,50 +52,18 @@ class GlobalVariable[T] { def get: T = { require(assigned); variable } } -object GenerateConfigString { - def apply(p: Parameters, clint: CoreplexLocalInterrupter, plic: TLPLIC, peripheryManagers: Seq[TLManagerParameters]) = { - val c = CoreplexParameters()(p) - val res = new StringBuilder - res append plic.globalConfigString - res append clint.globalConfigString - res append "core {\n" - c.tilesParams.zipWithIndex.map { case(t, i) => - val isa = { - val m = if (t.core.mulDiv.nonEmpty) "m" else "" - val a = if (t.core.useAtomics) "a" else "" - val f = if (t.core.fpu.nonEmpty) "f" else "" - val d = if (t.core.fpu.nonEmpty && p(XLen) > 32) "d" else "" - val c = if (t.core.useCompressed) "c" else "" - val s = if (t.core.useVM) "s" else "" - s"rv${p(XLen)}i$m$a$f$d$c$s" - } - res append s" $i {\n" - res append " 0 {\n" - res append s" isa $isa;\n" - res append clint.hartConfigStrings(i) - res append plic.hartConfigStrings(i) - res append " };\n" - res append " };\n" - } - res append "};\n" - peripheryManagers.foreach { manager => res append manager.dts } - res append '\u0000' - res.toString - } -} - object GenerateBootROM { - def apply(p: Parameters, address: BigInt, configString: String) = { + def apply(p: Parameters, address: BigInt, dts: String) = { val romdata = Files.readAllBytes(Paths.get(p(BootROMFile))) val rom = ByteBuffer.wrap(romdata) rom.order(ByteOrder.LITTLE_ENDIAN) require(address == address.toInt) - val configStringAddr = address.toInt + rom.capacity + val dtsAddr = address.toInt + rom.capacity require(rom.getInt(12) == 0, - "Config string address position should not be occupied by code") - rom.putInt(12, configStringAddr) - rom.array() ++ (configString.getBytes.toSeq) + "DTS address position should not be occupied by code") + rom.putInt(12, dtsAddr) + rom.array() ++ (dts.getBytes.toSeq) } } diff --git a/src/main/scala/uncore/devices/Plic.scala b/src/main/scala/uncore/devices/Plic.scala index e11647f3..adfc38ea 100644 --- a/src/main/scala/uncore/devices/Plic.scala +++ b/src/main/scala/uncore/devices/Plic.scala @@ -89,38 +89,6 @@ class TLPLIC(supervisor: Boolean, maxPriorities: Int, address: BigInt = 0xC00000 def nPriorities = min(maxPriorities, nDevices) def nHarts = intnode.edgesOut.map(_.source.num).sum - def context(i: Int, mode: Char) = mode match { - case 'M' => i * contextsPerHart - case 'S' => require(supervisor); i * contextsPerHart + 1 - } - def claimAddr(i: Int, mode: Char) = address + PLICConsts.hartBase(context(i, mode)) + PLICConsts.claimOffset - def threshAddr(i: Int, mode: Char) = address + PLICConsts.hartBase(context(i, mode)) - def enableAddr(i: Int, mode: Char) = address + PLICConsts.enableBase(context(i, mode)) - - // Create the global PLIC config string - lazy val globalConfigString = Seq( - s"plic {\n", - s" priority 0x${address.toString(16)};\n", - s" pending 0x${(address + PLICConsts.pendingBase).toString(16)};\n", - s" ndevs ${nDevices};\n", - s"};\n").mkString - - // Create the per-Hart config string - lazy val hartConfigStrings = Seq.tabulate(intnode.edgesOut.size) { i => (Seq( - s" plic {\n", - s" m {\n", - s" ie 0x${enableAddr(i, 'M').toString(16)};\n", - s" thresh 0x${threshAddr(i, 'M').toString(16)};\n", - s" claim 0x${claimAddr(i, 'M').toString(16)};\n", - s" };\n") ++ (if (!supervisor) Seq() else Seq( - s" s {\n", - s" ie 0x${enableAddr(i, 'S').toString(16)};\n", - s" thresh 0x${threshAddr(i, 'S').toString(16)};\n", - s" claim 0x${claimAddr(i, 'S').toString(16)};\n", - s" };\n")) ++ Seq( - 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 { @@ -146,11 +114,12 @@ class TLPLIC(supervisor: Boolean, maxPriorities: Int, address: BigInt = 0xC00000 // This flattens the harts into an MSMSMSMSMS... or MMMMM.... sequence val harts = io.harts.flatten - println("\nInterrupt map:") + println(s"Interrupt map (${nHarts} harts ${nDevices} interrupts):") flatSources.foreach { s => // +1 because 0 is reserved, +1-1 because the range is half-open println(s" [${s.range.start+1}, ${s.range.end}] => ${s.name}") } + println("") require (nDevices == interrupts.size) require (nHarts == harts.size) diff --git a/src/main/scala/uncore/devices/Prci.scala b/src/main/scala/uncore/devices/Prci.scala index fa05b29e..8e9427f8 100644 --- a/src/main/scala/uncore/devices/Prci.scala +++ b/src/main/scala/uncore/devices/Prci.scala @@ -50,16 +50,6 @@ class CoreplexLocalInterrupter(address: BigInt = 0x02000000)(implicit p: Paramet sourceFn = { _ => IntSourcePortParameters(Seq(IntSourceParameters(ints, Seq(Resource(device, "int"))))) }, sinkFn = { _ => IntSinkPortParameters(Seq(IntSinkParameters())) }) - // Legacy stuff: - val globalConfigString = Seq( - s"rtc {\n", - s" addr 0x${(address + timeOffset).toString(16)};\n", - s"};\n").mkString - val hartConfigStrings = (0 until p(NTiles)).map { i => Seq( - s" timecmp 0x${(address + timecmpOffset(i)).toString(16)};\n", - s" ipi 0x${(address + msipOffset(i)).toString(16)};\n").mkString - } - lazy val module = new LazyModuleImp(this) { val io = new Bundle { val rtcTick = Bool(INPUT) diff --git a/src/main/scala/uncore/tilelink2/Parameters.scala b/src/main/scala/uncore/tilelink2/Parameters.scala index cdfad24b..0a8ffd17 100644 --- a/src/main/scala/uncore/tilelink2/Parameters.scala +++ b/src/main/scala/uncore/tilelink2/Parameters.scala @@ -23,8 +23,7 @@ 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, - customDTS: Option[String]= None) + fifoId: Option[Int] = None) { require (!address.isEmpty) address.foreach { a => require (a.finite) } @@ -54,17 +53,6 @@ case class TLManagerParameters( val name = nodePath.lastOption.map(_.lazyModule.name).getOrElse("disconnected") - // Generate the config string (in future device tree) - lazy val dts = customDTS.getOrElse { - val header = s"${name} {\n" - val middle = address.map { a => - require (a.contiguous) // Config String is not so flexible - " 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 val minAlignment = address.map(_.alignment).min require (minAlignment >= maxTransfer) From 4535de2669369affd4e8b076346a12be8d56f16f Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Thu, 2 Mar 2017 13:37:25 -0800 Subject: [PATCH 14/14] rocket: use diplomatic interrupts This makes it possible for the PLIC to work with heterogenous cores. --- src/main/scala/coreplex/BaseCoreplex.scala | 1 - src/main/scala/coreplex/RISCVPlatform.scala | 2 +- src/main/scala/coreplex/RocketTiles.scala | 62 +++++---------------- src/main/scala/rocket/Tile.scala | 37 ++++++++++-- src/main/scala/tile/BaseTile.scala | 3 +- src/main/scala/uncore/devices/Plic.scala | 5 +- 6 files changed, 52 insertions(+), 58 deletions(-) diff --git a/src/main/scala/coreplex/BaseCoreplex.scala b/src/main/scala/coreplex/BaseCoreplex.scala index e0333128..4d2f0b59 100644 --- a/src/main/scala/coreplex/BaseCoreplex.scala +++ b/src/main/scala/coreplex/BaseCoreplex.scala @@ -49,7 +49,6 @@ trait HasCoreplexParameters { lazy val cbusConfig = p(CBusConfig) lazy val l1tol2Config = p(L1toL2Config) lazy val nTiles = tilesParams.size - lazy val hasSupervisor = tilesParams.exists(_.core.useVM) // TODO ask andrew about this lazy val l2Config = p(BankedL2Config) } diff --git a/src/main/scala/coreplex/RISCVPlatform.scala b/src/main/scala/coreplex/RISCVPlatform.scala index 87afaaa0..79a306e2 100644 --- a/src/main/scala/coreplex/RISCVPlatform.scala +++ b/src/main/scala/coreplex/RISCVPlatform.scala @@ -15,7 +15,7 @@ trait CoreplexRISCVPlatform extends CoreplexNetwork { val module: CoreplexRISCVPlatformModule val debug = LazyModule(new TLDebugModule()) - val plic = LazyModule(new TLPLIC(hasSupervisor, maxPriorities = 7)) + val plic = LazyModule(new TLPLIC(maxPriorities = 7)) val clint = LazyModule(new CoreplexLocalInterrupter) debug.node := TLFragmenter(cbus_beatBytes, cbus_lineBytes)(cbus.node) diff --git a/src/main/scala/coreplex/RocketTiles.scala b/src/main/scala/coreplex/RocketTiles.scala index 206098f0..d9d2e3bb 100644 --- a/src/main/scala/coreplex/RocketTiles.scala +++ b/src/main/scala/coreplex/RocketTiles.scala @@ -23,20 +23,6 @@ trait HasRocketTiles extends CoreplexRISCVPlatform { private val crossing = p(RocketCrossing) private val configs = p(RocketTilesKey) - private val rocketTileIntNodes = configs.map { _ => IntInternalOutputNode(IntSinkPortSimple(ports = 2)) } - rocketTileIntNodes.foreach { n => - n := plic.intnode - n := clint.intnode - } - - private def wireInterrupts(x: TileInterrupts, i: Int) { - x.debug := debug.module.io.debugInterrupts(i) - x.meip := rocketTileIntNodes(i).bundleOut(0)(0) - x.seip.foreach { _ := rocketTileIntNodes(i).bundleOut(0)(1) } // optional - x.msip := rocketTileIntNodes(i).bundleOut(1)(0) - x.mtip := rocketTileIntNodes(i).bundleOut(1)(1) - } - val rocketWires: Seq[HasRocketTilesBundle => Unit] = configs.zipWithIndex.map { case (c, i) => val pWithExtra = p.alterPartial { case TileKey => c @@ -45,6 +31,15 @@ trait HasRocketTiles extends CoreplexRISCVPlatform { case PAddrBits => l1tol2.node.edgesIn(0).bundle.addressBits } + // Hack debug interrupt into a node (future debug module should use diplomacy) + val debugNode = IntInternalInputNode(IntSourcePortSimple()) + + val intBar = LazyModule(new IntXbar) + intBar.intnode := debugNode + intBar.intnode := clint.intnode // msip+mtip + intBar.intnode := plic.intnode // meip + if (c.core.useVM) intBar.intnode := plic.intnode // seip + crossing match { case Synchronous => { val tile = LazyModule(new RocketTile(c, i)(pWithExtra)) @@ -52,21 +47,12 @@ trait HasRocketTiles extends CoreplexRISCVPlatform { buffer.node :=* tile.masterNode l1tol2.node :=* buffer.node tile.slaveNode :*= cbus.node - ResourceBinding { - rocketTileIntNodes(i).edgesIn(0).source.sources.flatMap(_.resources).foreach { r => - r.bind(tile.device, ResourceInt(11)) // meip - if (c.core.useVM) r.bind(tile.device, ResourceInt(9)) // seip - } - rocketTileIntNodes(i).edgesIn(1).source.sources.flatMap(_.resources).foreach { r => - r.bind(tile.device, ResourceInt(3)) // msip - r.bind(tile.device, ResourceInt(7)) // mtip - } - } + tile.intNode := intBar.intnode (io: HasRocketTilesBundle) => { // leave clock as default (simpler for hierarchical PnR) tile.module.io.hartid := UInt(i) tile.module.io.resetVector := io.resetVector - wireInterrupts(tile.module.io.interrupts, i) + debugNode.bundleOut(0)(0) := debug.module.io.debugInterrupts(i) } } case Asynchronous(depth, sync) => { @@ -76,23 +62,14 @@ trait HasRocketTiles extends CoreplexRISCVPlatform { sink.node :=* wrapper.masterNode l1tol2.node :=* sink.node wrapper.slaveNode :*= source.node + wrapper.intNode := intBar.intnode source.node :*= cbus.node - ResourceBinding { - rocketTileIntNodes(i).edgesIn(0).source.sources.flatMap(_.resources).foreach { r => - r.bind(wrapper.rocket.device, ResourceInt(11)) // meip - if (c.core.useVM) r.bind(wrapper.rocket.device, ResourceInt(9)) // seip - } - rocketTileIntNodes(i).edgesIn(1).source.sources.flatMap(_.resources).foreach { r => - r.bind(wrapper.rocket.device, ResourceInt(3)) // msip - r.bind(wrapper.rocket.device, ResourceInt(7)) // mtip - } - } (io: HasRocketTilesBundle) => { wrapper.module.clock := io.tcrs(i).clock wrapper.module.reset := io.tcrs(i).reset wrapper.module.io.hartid := UInt(i) wrapper.module.io.resetVector := io.resetVector - wireInterrupts(wrapper.module.io.interrupts, i) + debugNode.bundleOut(0)(0) := debug.module.io.debugInterrupts(i) } } case Rational => { @@ -102,23 +79,14 @@ trait HasRocketTiles extends CoreplexRISCVPlatform { sink.node :=* wrapper.masterNode l1tol2.node :=* sink.node wrapper.slaveNode :*= source.node + wrapper.intNode := intBar.intnode source.node :*= cbus.node - ResourceBinding { - rocketTileIntNodes(i).edgesIn(0).source.sources.flatMap(_.resources).foreach { r => - r.bind(wrapper.rocket.device, ResourceInt(11)) // meip - if (c.core.useVM) r.bind(wrapper.rocket.device, ResourceInt(9)) // seip - } - rocketTileIntNodes(i).edgesIn(1).source.sources.flatMap(_.resources).foreach { r => - r.bind(wrapper.rocket.device, ResourceInt(3)) // msip - r.bind(wrapper.rocket.device, ResourceInt(7)) // mtip - } - } (io: HasRocketTilesBundle) => { wrapper.module.clock := io.tcrs(i).clock wrapper.module.reset := io.tcrs(i).reset wrapper.module.io.hartid := UInt(i) wrapper.module.io.resetVector := io.resetVector - wireInterrupts(wrapper.module.io.interrupts, i) + debugNode.bundleOut(0)(0) := debug.module.io.debugInterrupts(i) } } } diff --git a/src/main/scala/rocket/Tile.scala b/src/main/scala/rocket/Tile.scala index 737536c1..04462028 100644 --- a/src/main/scala/rocket/Tile.scala +++ b/src/main/scala/rocket/Tile.scala @@ -87,6 +87,19 @@ class RocketTile(val rocketParams: RocketTileParams, val hartid: Int)(implicit p ResourceBinding { Resource(device, "reg").bind(ResourceInt(BigInt(hartid))) + + // debug, msip, mtip, meip, seip offsets in CSRs + val intMap = Seq(65535, 3, 7, 11, 9) + + intNode.edgesIn.flatMap(_.source.sources).map { case s => + for (i <- s.range.start until s.range.end) { + intMap.lift(i).foreach { j => + s.resources.foreach { r => + r.bind(device, ResourceInt(j)) + } + } + } + } } override lazy val module = new RocketTileModule(this) @@ -100,7 +113,6 @@ class RocketTileModule(outer: RocketTile) extends BaseTileModule(outer, () => ne with CanHaveScratchpadModule { val core = Module(p(BuildCore)(outer.p)) - core.io.interrupts := io.interrupts core.io.hartid := io.hartid outer.frontend.module.io.cpu <> core.io.imem outer.frontend.module.io.resetVector := io.resetVector @@ -115,6 +127,13 @@ class RocketTileModule(outer: RocketTile) extends BaseTileModule(outer, () => ne core.io.rocc.interrupt := lr.module.io.core.interrupt } + // Decode the interrupt vector + core.io.interrupts.debug := io.interrupts(0)(0) + core.io.interrupts.msip := io.interrupts(0)(1) + core.io.interrupts.mtip := io.interrupts(0)(2) + core.io.interrupts.meip := io.interrupts(0)(3) + core.io.interrupts.seip.foreach { _ := io.interrupts(0)(4) } + // TODO eliminate this redundancy val h = dcachePorts.size val c = core.dcacheArbPorts @@ -139,15 +158,19 @@ class AsyncRocketTile(rtp: RocketTileParams, hartid: Int)(implicit p: Parameters rocket.slaveNode :*= sink.node sink.node :*= slaveNode + val intNode = IntInputNode() + val xing = LazyModule(new IntXing(3)) + rocket.intNode := xing.intnode + xing.intnode := intNode + lazy val module = new LazyModuleImp(this) { val io = new Bundle { val master = masterNode.bundleOut val slave = slaveNode.bundleIn + val interrupts = intNode.bundleIn val hartid = UInt(INPUT, p(XLen)) - val interrupts = new TileInterrupts()(p).asInput val resetVector = UInt(INPUT, p(XLen)) } - rocket.module.io.interrupts := ShiftRegister(io.interrupts, 3) // signals that do not change: rocket.module.io.hartid := io.hartid rocket.module.io.resetVector := io.resetVector @@ -167,15 +190,19 @@ class RationalRocketTile(rtp: RocketTileParams, hartid: Int)(implicit p: Paramet rocket.slaveNode :*= sink.node sink.node :*= slaveNode + val intNode = IntInputNode() + val xing = LazyModule(new IntXing(1)) + rocket.intNode := xing.intnode + xing.intnode := intNode + lazy val module = new LazyModuleImp(this) { val io = new Bundle { val master = masterNode.bundleOut val slave = slaveNode.bundleIn + val interrupts = intNode.bundleIn val hartid = UInt(INPUT, p(XLen)) - val interrupts = new TileInterrupts()(p).asInput val resetVector = UInt(INPUT, p(XLen)) } - rocket.module.io.interrupts := ShiftRegister(io.interrupts, 1) // signals that do not change: rocket.module.io.hartid := io.hartid rocket.module.io.resetVector := io.resetVector diff --git a/src/main/scala/tile/BaseTile.scala b/src/main/scala/tile/BaseTile.scala index 1434697d..f39da677 100644 --- a/src/main/scala/tile/BaseTile.scala +++ b/src/main/scala/tile/BaseTile.scala @@ -53,11 +53,13 @@ trait HasTileLinkMasterPort extends HasTileParameters { implicit val p: Parameters val module: HasTileLinkMasterPortModule val masterNode = TLOutputNode() + val intNode = IntSinkNode(IntSinkPortSimple()) } trait HasTileLinkMasterPortBundle { val outer: HasTileLinkMasterPort val master = outer.masterNode.bundleOut + val interrupts = outer.intNode.bundleIn } trait HasTileLinkMasterPortModule { @@ -73,7 +75,6 @@ abstract class BaseTile(tileParams: TileParams)(implicit p: Parameters) extends class BaseTileBundle[+L <: BaseTile](_outer: L) extends BareTileBundle(_outer) with HasTileLinkMasterPortBundle { val hartid = UInt(INPUT, p(XLen)) - val interrupts = new TileInterrupts()(p).asInput val resetVector = UInt(INPUT, p(XLen)) } diff --git a/src/main/scala/uncore/devices/Plic.scala b/src/main/scala/uncore/devices/Plic.scala index adfc38ea..98e54f0c 100644 --- a/src/main/scala/uncore/devices/Plic.scala +++ b/src/main/scala/uncore/devices/Plic.scala @@ -53,9 +53,8 @@ object PLICConsts } /** Platform-Level Interrupt Controller */ -class TLPLIC(supervisor: Boolean, maxPriorities: Int, address: BigInt = 0xC000000)(implicit p: Parameters) extends LazyModule +class TLPLIC(maxPriorities: Int, address: BigInt = 0xC000000)(implicit p: Parameters) extends LazyModule { - val contextsPerHart = if (supervisor) 2 else 1 require (maxPriorities >= 0) // plic0 => max devices 1023 @@ -81,7 +80,7 @@ class TLPLIC(supervisor: Boolean, maxPriorities: Int, address: BigInt = 0xC00000 val intnode = IntNexusNode( numSourcePorts = 0 to 1024, numSinkPorts = 0 to 1024, - sourceFn = { _ => IntSourcePortParameters(Seq(IntSourceParameters(contextsPerHart, Seq(Resource(device, "int"))))) }, + sourceFn = { _ => IntSourcePortParameters(Seq(IntSourceParameters(1, Seq(Resource(device, "int"))))) }, sinkFn = { _ => IntSinkPortParameters(Seq(IntSinkParameters())) }) /* Negotiated sizes */