diff --git a/.travis.yml b/.travis.yml index 37a4eb52..aadb05c6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -30,6 +30,7 @@ addons: - bison - flex - texinfo + - device-tree-compiler env: matrix: diff --git a/bootrom/Makefile b/bootrom/Makefile index 3ea5f831..0580ba5a 100644 --- a/bootrom/Makefile +++ b/bootrom/Makefile @@ -5,8 +5,11 @@ OBJCOPY=riscv64-unknown-elf-objcopy all: $(bootrom_img) -%.img: %.elf - $(OBJCOPY) -O binary --change-addresses=-0x1000 --only-section .text $< $@ +%.img: %.bin + dd if=$< of=$@ bs=128 count=1 + +%.bin: %.elf + $(OBJCOPY) -O binary $< $@ %.elf: %.S linker.ld - $(GCC) -Tlinker.ld $< -nostdlib -static -o $@ + $(GCC) -Tlinker.ld $< -nostdlib -static -Wl,--no-gc-sections -o $@ diff --git a/bootrom/bootrom.S b/bootrom/bootrom.S index b35ee02a..384a4a37 100644 --- a/bootrom/bootrom.S +++ b/bootrom/bootrom.S @@ -1,13 +1,19 @@ -.text -.global _start +.section .text.start, "ax", @progbits +.globl _start _start: - // This boot ROM doesn't know about any boot devices, so it just spins, - // waiting for the debugger to load a program and change the PC. - j _start // reset vector - .word 0 // reserved - .word 0 // reserved - .word 0 // pointer to config string - .word 0 // default trap vector - .word 0 - .word 0 - .word 0 + la s0, DRAM_BASE + csrr a0, mhartid + la a1, _dtb + jr s0 + +.section .text.hang, "ax", @progbits +.globl _hang +_hang: + wfi + j _hang + +.section .rodata.dtb, "a", @progbits +.globl _dtb +.align 5, 0 +_dtb: +.ascii "DTB goes here" diff --git a/bootrom/bootrom.img b/bootrom/bootrom.img old mode 100755 new mode 100644 index 6d852f38..bee192cf Binary files a/bootrom/bootrom.img and b/bootrom/bootrom.img differ diff --git a/bootrom/linker.ld b/bootrom/linker.ld index 1b6ff96d..f871bf4c 100644 --- a/bootrom/linker.ld +++ b/bootrom/linker.ld @@ -1,5 +1,12 @@ SECTIONS { - . = 0x1000; - .text : { *(.text) } + DRAM_BASE = 0x80000000; + ROM_BASE = 0x10000; + + . = ROM_BASE; + .text.start : { *(.text.start) } + . = ROM_BASE + 0x40; + .text.hang : { *(.text.hang) } + . = ROM_BASE + 0x80; + .rodata.dtb : { *(.rodata.dtb) } } diff --git a/src/main/scala/coreplex/RISCVPlatform.scala b/src/main/scala/coreplex/RISCVPlatform.scala index 4744ea85..e2e6d079 100644 --- a/src/main/scala/coreplex/RISCVPlatform.scala +++ b/src/main/scala/coreplex/RISCVPlatform.scala @@ -25,6 +25,7 @@ trait CoreplexRISCVPlatform extends CoreplexNetwork { plic.intnode := intBar.intnode lazy val dts = DTS(bindingTree) + lazy val dtb = DTB(dts) lazy val json = JSON(bindingTree) } diff --git a/src/main/scala/diplomacy/DeviceTree.scala b/src/main/scala/diplomacy/DeviceTree.scala index 8a26991a..04c468f2 100644 --- a/src/main/scala/diplomacy/DeviceTree.scala +++ b/src/main/scala/diplomacy/DeviceTree.scala @@ -4,6 +4,8 @@ package diplomacy import Chisel._ import config._ +import sys.process._ +import java.io.{ByteArrayInputStream, ByteArrayOutputStream} case object DTSModel extends Field[String] case object DTSCompat extends Field[Seq[String]] // -dev, -soc @@ -115,3 +117,17 @@ object DTS case x: ResourceMap => fmtMap(x, indent, cells) } } + +case class DTB(contents: Seq[Byte]) +object DTB +{ + def apply(dts: String): DTB = { + val instream = new ByteArrayInputStream(dts.getBytes("UTF-8")) + val outstream = new ByteArrayOutputStream + val proc = "dtc -O dtb" #< instream #> outstream + require (proc.! == 0, "Failed to run dtc; is it in your path?") + instream.close + outstream.close + DTB(outstream.toByteArray) + } +} diff --git a/src/main/scala/rocketchip/Periphery.scala b/src/main/scala/rocketchip/Periphery.scala index 65b59033..4b1776ea 100644 --- a/src/main/scala/rocketchip/Periphery.scala +++ b/src/main/scala/rocketchip/Periphery.scala @@ -305,9 +305,9 @@ trait PeripheryBootROM { this: HasTopLevelNetworks => val coreplex: CoreplexRISCVPlatform - private val bootrom_address = 0x1000 - private val bootrom_size = 0x1000 - private lazy val bootrom_contents = GenerateBootROM(p, bootrom_address, coreplex.dts) + private val bootrom_address = 0x10000 + private val bootrom_size = 0x10000 + private lazy val bootrom_contents = GenerateBootROM(coreplex.dtb) 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/RISCVPlatform.scala b/src/main/scala/rocketchip/RISCVPlatform.scala index 7bc9779a..b3cc4071 100644 --- a/src/main/scala/rocketchip/RISCVPlatform.scala +++ b/src/main/scala/rocketchip/RISCVPlatform.scala @@ -124,5 +124,5 @@ trait HardwiredResetVectorModule extends HasTopLevelNetworksModule { val outer: HardwiredResetVector val io: HardwiredResetVectorBundle - outer.coreplex.module.io.resetVector := UInt(0x1000) // boot ROM + outer.coreplex.module.io.resetVector := UInt(0x10040) // boot ROM: hang } diff --git a/src/main/scala/rocketchip/Utils.scala b/src/main/scala/rocketchip/Utils.scala index 31632741..f6d039d8 100644 --- a/src/main/scala/rocketchip/Utils.scala +++ b/src/main/scala/rocketchip/Utils.scala @@ -53,17 +53,9 @@ class GlobalVariable[T] { } object GenerateBootROM { - def apply(p: Parameters, address: BigInt, dts: String) = { + def apply(dtb: DTB)(implicit p: Parameters) = { val romdata = Files.readAllBytes(Paths.get(p(BootROMFile))) val rom = ByteBuffer.wrap(romdata) - - rom.order(ByteOrder.LITTLE_ENDIAN) - - require(address == address.toInt) - val dtsAddr = address.toInt + rom.capacity - require(rom.getInt(12) == 0, - "DTS address position should not be occupied by code") - rom.putInt(12, dtsAddr) - rom.array() ++ (dts.getBytes.toSeq) + rom.array() ++ dtb.contents } } diff --git a/src/main/scala/uncore/devices/Rom.scala b/src/main/scala/uncore/devices/Rom.scala index 8f5edc5a..2e686480 100644 --- a/src/main/scala/uncore/devices/Rom.scala +++ b/src/main/scala/uncore/devices/Rom.scala @@ -30,20 +30,22 @@ class TLROM(val base: BigInt, val size: Int, contentsDelayed: => Seq[Byte], exec } val contents = contentsDelayed - require (contents.size <= size) + val wrapSize = 1 << log2Ceil(contents.size) + require (wrapSize <= size) val in = io.in(0) val edge = node.edgesIn(0) - val words = (contents ++ Seq.fill(size-contents.size)(0.toByte)).grouped(beatBytes).toSeq + val words = (contents ++ Seq.fill(wrapSize-contents.size)(0.toByte)).grouped(beatBytes).toSeq val bigs = words.map(_.foldRight(BigInt(0)){ case (x,y) => (x.toInt & 0xff) | y << 8}) val rom = Vec(bigs.map(x => UInt(x, width = 8*beatBytes))) in.d.valid := in.a.valid in.a.ready := in.d.ready - val index = in.a.bits.address(log2Ceil(size)-1,log2Ceil(beatBytes)) - in.d.bits := edge.AccessAck(in.a.bits, UInt(0), rom(index)) + val index = in.a.bits.address(log2Ceil(wrapSize)-1,log2Ceil(beatBytes)) + val high = if (wrapSize == size) UInt(0) else in.a.bits.address(log2Ceil(size)-1, log2Ceil(wrapSize)) + in.d.bits := edge.AccessAck(in.a.bits, UInt(0), Mux(high.orR, UInt(0), rom(index))) // Tie off unused channels in.b.valid := Bool(false)