diff --git a/riscv-tools b/riscv-tools index 84a47e0b..3fba5b66 160000 --- a/riscv-tools +++ b/riscv-tools @@ -1 +1 @@ -Subproject commit 84a47e0b4ef322daf0ade05510bf4d30d9d9a0fa +Subproject commit 3fba5b66223eb92413baa555cd2792b31fe135e3 diff --git a/src/main/scala/Configs.scala b/src/main/scala/Configs.scala index 1ec37c6d..5b39d745 100644 --- a/src/main/scala/Configs.scala +++ b/src/main/scala/Configs.scala @@ -18,13 +18,41 @@ class DefaultConfig extends Config ( type PF = PartialFunction[Any,Any] def findBy(sname:Any):Any = here[PF](site[Any](sname))(pname) def genCsrAddrMap: AddrMap = { + val deviceTree = AddrMapEntry("devicetree", None, MemSize(1 << 15, AddrMapConsts.R)) val csrSize = (1 << 12) * (site(XLen) / 8) val csrs = (0 until site(NTiles)).map{ i => AddrMapEntry(s"csr$i", None, MemSize(csrSize, AddrMapConsts.RW)) } val scrSize = site(HtifKey).nSCR * (site(XLen) / 8) val scr = AddrMapEntry("scr", None, MemSize(scrSize, AddrMapConsts.RW)) - new AddrMap(csrs :+ scr) + new AddrMap(deviceTree +: csrs :+ scr) + } + def makeDeviceTree() = { + val addrMap = new AddrHashMap(site(GlobalAddrMap)) + val dt = new DeviceTreeGenerator + dt.beginNode("") + dt.addProp("#address-cells", 2) + dt.addProp("#size-cells", 2) + dt.addProp("model", "Rocket-Chip") + dt.beginNode("memory@0") + dt.addProp("device_type", "memory") + dt.addReg(0, site(MMIOBase).toLong) + dt.endNode() + dt.beginNode("cpus") + dt.addProp("#address-cells", 2) + dt.addProp("#size-cells", 2) + for (i <- 0 until site(NTiles)) { + val csrs = addrMap(s"conf:csr$i") + dt.beginNode(s"cpu@${csrs.start.toLong.toHexString}") + dt.addProp("device_type", "cpu") + dt.addProp("compatible", "riscv") + dt.addProp("isa", s"rv${site(XLen)}") + dt.addReg(csrs.start.toLong) + dt.endNode() + } + dt.endNode() + dt.endNode() + dt.toArray() } pname match { case HtifKey => HtifParameters( @@ -165,6 +193,7 @@ class DefaultConfig extends Config ( case UseBackupMemoryPort => true case MMIOBase => Dump("MEM_SIZE", BigInt(1 << 30)) // 1 GB case ExternalIOStart => 2 * site(MMIOBase) + case DeviceTree => makeDeviceTree() case GlobalAddrMap => AddrMap( AddrMapEntry("mem", None, MemChannels(site(MMIOBase), site(NMemoryChannels), AddrMapConsts.RWX)), AddrMapEntry("conf", None, MemSubmap(site(ExternalIOStart) - site(MMIOBase), genCsrAddrMap)), diff --git a/src/main/scala/DeviceTree.scala b/src/main/scala/DeviceTree.scala new file mode 100644 index 00000000..7d98a238 --- /dev/null +++ b/src/main/scala/DeviceTree.scala @@ -0,0 +1,80 @@ +package rocketchip + +case object DeviceTree extends cde.Field[Array[Byte]] + +private class StringTable { + private val strings = collection.mutable.HashMap[String, Int]() + private val data = collection.mutable.ArrayBuffer[Byte]() + + def add(x: String) = { + if (!strings.contains(x)) { + strings(x) = data.length + data ++= x.getBytes + data += 0 + } + strings(x) + } + + def toArray = data.toArray +} + +class DeviceTreeGenerator { + def beginNode(name: String): Unit = { + append(pack(1)) + append(pack(name)) + } + def endNode(): Unit = append(pack(2)) + def addProp(name: String, data: Int): Unit = addProp(name, pack(data), 4) + def addProp(name: String, data: String): Unit = + addProp(name, pack(data), data.getBytes.length+1) + def addReg(values: Long*): Unit = { + val seq = values.toSeq + val buf = java.nio.ByteBuffer.allocate(seq.length*8) + seq foreach buf.putLong + addProp("reg", buf.array, buf.array.length) + } + def toArray(): Array[Byte] = { + append(pack(9)) + val structArray = os.toByteArray + val stringArray = strings.toArray + + val headerSize = 40 + val rsvMap = Array.fill[Byte](16)(0) + val rsvMapOffset = headerSize + val structOffset = headerSize + rsvMap.length + val stringOffset = structOffset + structArray.length + val totalSize = stringOffset + stringArray.length + + os.reset() + append(pack(0xd00dfeed)) // magic + append(pack(totalSize)) + append(pack(structOffset)) + append(pack(stringOffset)) + append(pack(rsvMapOffset)) + append(pack(17)) // version + append(pack(16)) // compatible version + append(pack(0)) // boot cpuid + append(pack(stringArray.length)) + append(pack(structArray.length)) + append(rsvMap) + append(structArray) + append(stringArray) + + val res = os.toByteArray + os.reset + res + } + + private val os = new java.io.ByteArrayOutputStream + private val strings = new StringTable + private def pack(x: String) = x.getBytes.padTo((x.getBytes.length+4)/4*4, 0.toByte) + private def pack(x: Int) = java.nio.ByteBuffer.allocate(4).putInt(x).array + private def append(x: Array[Byte]) = os.write(x, 0, x.length) + private def addProp(name: String, data: Array[Byte], length: Int) = { + require(data.length % 4 == 0) + append(pack(3)) + append(pack(length)) + append(pack(strings.add(name))) + append(data) + } +} diff --git a/src/main/scala/RocketChip.scala b/src/main/scala/RocketChip.scala index bb5af14d..1f053ec7 100644 --- a/src/main/scala/RocketChip.scala +++ b/src/main/scala/RocketChip.scala @@ -165,6 +165,9 @@ class Uncore(implicit val p: Parameters) extends Module scrFile.io.smi <> scrArb.io.out // scrFile.io.scr <> (... your SCR connections ...) + val deviceTree = Module(new NastiROM(p(DeviceTree).toSeq)) + deviceTree.io <> outmemsys.io.deviceTree + // Wire the htif to the memory port(s) and host interface io.host.debug_stats_csr := htif.io.host.debug_stats_csr io.mem <> outmemsys.io.mem @@ -194,6 +197,7 @@ class OuterMemorySystem(implicit val p: Parameters) extends Module with HasTopLe val csr = Vec(new SMIIO(xLen, csrAddrBits), nTiles) val scr = new SMIIO(xLen, scrAddrBits) val mmio = new NastiIO + val deviceTree = new NastiIO } // Create a simple L1toL2 NoC between the tiles+htif and the banks of outer memory @@ -266,6 +270,7 @@ class OuterMemorySystem(implicit val p: Parameters) extends Module with HasTopLe io.scr <> conv.io.smi io.mmio <> interconnect.io.slaves(addrHashMap("io").port) + io.deviceTree <> interconnect.io.slaves(addrHashMap("conf:devicetree").port) val mem_channels = interconnect.io.slaves.take(nMemChannels) diff --git a/src/main/scala/Testing.scala b/src/main/scala/Testing.scala index 96550383..a010975b 100644 --- a/src/main/scala/Testing.scala +++ b/src/main/scala/Testing.scala @@ -165,6 +165,9 @@ object TestGenerator extends App with FileSystemUtilities { val v = createOutputFile(configClassName + ".knb") v.write(world.getKnobs) v.close + val d = new java.io.FileOutputStream(Driver.targetDir + configClassName + ".dtb") + d.write(paramsFromConfig(DeviceTree)) + d.close val w = createOutputFile(configClassName + ".cst") w.write(world.getConstraints) w.close diff --git a/uncore b/uncore index 4380fe85..67724914 160000 --- a/uncore +++ b/uncore @@ -1 +1 @@ -Subproject commit 4380fe85a367da1aabd845fa105fa7d2d198a119 +Subproject commit 677249148f87cc2735ce88c0892ca02ebd767a94