commit
19485a9861
@ -30,6 +30,7 @@ addons:
|
|||||||
- bison
|
- bison
|
||||||
- flex
|
- flex
|
||||||
- texinfo
|
- texinfo
|
||||||
|
- device-tree-compiler
|
||||||
|
|
||||||
env:
|
env:
|
||||||
matrix:
|
matrix:
|
||||||
|
@ -5,8 +5,11 @@ OBJCOPY=riscv64-unknown-elf-objcopy
|
|||||||
|
|
||||||
all: $(bootrom_img)
|
all: $(bootrom_img)
|
||||||
|
|
||||||
%.img: %.elf
|
%.img: %.bin
|
||||||
$(OBJCOPY) -O binary --change-addresses=-0x1000 --only-section .text $< $@
|
dd if=$< of=$@ bs=128 count=1
|
||||||
|
|
||||||
|
%.bin: %.elf
|
||||||
|
$(OBJCOPY) -O binary $< $@
|
||||||
|
|
||||||
%.elf: %.S linker.ld
|
%.elf: %.S linker.ld
|
||||||
$(GCC) -Tlinker.ld $< -nostdlib -static -o $@
|
$(GCC) -Tlinker.ld $< -nostdlib -static -Wl,--no-gc-sections -o $@
|
||||||
|
@ -1,13 +1,19 @@
|
|||||||
.text
|
.section .text.start, "ax", @progbits
|
||||||
.global _start
|
.globl _start
|
||||||
_start:
|
_start:
|
||||||
// This boot ROM doesn't know about any boot devices, so it just spins,
|
la s0, DRAM_BASE
|
||||||
// waiting for the debugger to load a program and change the PC.
|
csrr a0, mhartid
|
||||||
j _start // reset vector
|
la a1, _dtb
|
||||||
.word 0 // reserved
|
jr s0
|
||||||
.word 0 // reserved
|
|
||||||
.word 0 // pointer to config string
|
.section .text.hang, "ax", @progbits
|
||||||
.word 0 // default trap vector
|
.globl _hang
|
||||||
.word 0
|
_hang:
|
||||||
.word 0
|
wfi
|
||||||
.word 0
|
j _hang
|
||||||
|
|
||||||
|
.section .rodata.dtb, "a", @progbits
|
||||||
|
.globl _dtb
|
||||||
|
.align 5, 0
|
||||||
|
_dtb:
|
||||||
|
.ascii "DTB goes here"
|
||||||
|
BIN
bootrom/bootrom.img
Executable file → Normal file
BIN
bootrom/bootrom.img
Executable file → Normal file
Binary file not shown.
@ -1,5 +1,12 @@
|
|||||||
SECTIONS
|
SECTIONS
|
||||||
{
|
{
|
||||||
. = 0x1000;
|
DRAM_BASE = 0x80000000;
|
||||||
.text : { *(.text) }
|
ROM_BASE = 0x10000;
|
||||||
|
|
||||||
|
. = ROM_BASE;
|
||||||
|
.text.start : { *(.text.start) }
|
||||||
|
. = ROM_BASE + 0x40;
|
||||||
|
.text.hang : { *(.text.hang) }
|
||||||
|
. = ROM_BASE + 0x80;
|
||||||
|
.rodata.dtb : { *(.rodata.dtb) }
|
||||||
}
|
}
|
||||||
|
@ -25,6 +25,7 @@ trait CoreplexRISCVPlatform extends CoreplexNetwork {
|
|||||||
plic.intnode := intBar.intnode
|
plic.intnode := intBar.intnode
|
||||||
|
|
||||||
lazy val dts = DTS(bindingTree)
|
lazy val dts = DTS(bindingTree)
|
||||||
|
lazy val dtb = DTB(dts)
|
||||||
lazy val json = JSON(bindingTree)
|
lazy val json = JSON(bindingTree)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,6 +4,8 @@ package diplomacy
|
|||||||
|
|
||||||
import Chisel._
|
import Chisel._
|
||||||
import config._
|
import config._
|
||||||
|
import sys.process._
|
||||||
|
import java.io.{ByteArrayInputStream, ByteArrayOutputStream}
|
||||||
|
|
||||||
case object DTSModel extends Field[String]
|
case object DTSModel extends Field[String]
|
||||||
case object DTSCompat extends Field[Seq[String]] // -dev, -soc
|
case object DTSCompat extends Field[Seq[String]] // -dev, -soc
|
||||||
@ -115,3 +117,17 @@ object DTS
|
|||||||
case x: ResourceMap => fmtMap(x, indent, cells)
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -305,9 +305,9 @@ trait PeripheryBootROM {
|
|||||||
this: HasTopLevelNetworks =>
|
this: HasTopLevelNetworks =>
|
||||||
val coreplex: CoreplexRISCVPlatform
|
val coreplex: CoreplexRISCVPlatform
|
||||||
|
|
||||||
private val bootrom_address = 0x1000
|
private val bootrom_address = 0x10000
|
||||||
private val bootrom_size = 0x1000
|
private val bootrom_size = 0x10000
|
||||||
private lazy val bootrom_contents = GenerateBootROM(p, bootrom_address, coreplex.dts)
|
private lazy val bootrom_contents = GenerateBootROM(coreplex.dtb)
|
||||||
val bootrom = LazyModule(new TLROM(bootrom_address, bootrom_size, bootrom_contents, true, peripheryBusConfig.beatBytes))
|
val bootrom = LazyModule(new TLROM(bootrom_address, bootrom_size, bootrom_contents, true, peripheryBusConfig.beatBytes))
|
||||||
bootrom.node := TLFragmenter(peripheryBusConfig.beatBytes, cacheBlockBytes)(peripheryBus.node)
|
bootrom.node := TLFragmenter(peripheryBusConfig.beatBytes, cacheBlockBytes)(peripheryBus.node)
|
||||||
}
|
}
|
||||||
|
@ -124,5 +124,5 @@ trait HardwiredResetVectorModule extends HasTopLevelNetworksModule {
|
|||||||
val outer: HardwiredResetVector
|
val outer: HardwiredResetVector
|
||||||
val io: HardwiredResetVectorBundle
|
val io: HardwiredResetVectorBundle
|
||||||
|
|
||||||
outer.coreplex.module.io.resetVector := UInt(0x1000) // boot ROM
|
outer.coreplex.module.io.resetVector := UInt(0x10040) // boot ROM: hang
|
||||||
}
|
}
|
||||||
|
@ -53,17 +53,9 @@ class GlobalVariable[T] {
|
|||||||
}
|
}
|
||||||
|
|
||||||
object GenerateBootROM {
|
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 romdata = Files.readAllBytes(Paths.get(p(BootROMFile)))
|
||||||
val rom = ByteBuffer.wrap(romdata)
|
val rom = ByteBuffer.wrap(romdata)
|
||||||
|
rom.array() ++ dtb.contents
|
||||||
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)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -30,20 +30,22 @@ class TLROM(val base: BigInt, val size: Int, contentsDelayed: => Seq[Byte], exec
|
|||||||
}
|
}
|
||||||
|
|
||||||
val contents = contentsDelayed
|
val contents = contentsDelayed
|
||||||
require (contents.size <= size)
|
val wrapSize = 1 << log2Ceil(contents.size)
|
||||||
|
require (wrapSize <= size)
|
||||||
|
|
||||||
val in = io.in(0)
|
val in = io.in(0)
|
||||||
val edge = node.edgesIn(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 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)))
|
val rom = Vec(bigs.map(x => UInt(x, width = 8*beatBytes)))
|
||||||
|
|
||||||
in.d.valid := in.a.valid
|
in.d.valid := in.a.valid
|
||||||
in.a.ready := in.d.ready
|
in.a.ready := in.d.ready
|
||||||
|
|
||||||
val index = in.a.bits.address(log2Ceil(size)-1,log2Ceil(beatBytes))
|
val index = in.a.bits.address(log2Ceil(wrapSize)-1,log2Ceil(beatBytes))
|
||||||
in.d.bits := edge.AccessAck(in.a.bits, UInt(0), rom(index))
|
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
|
// Tie off unused channels
|
||||||
in.b.valid := Bool(false)
|
in.b.valid := Bool(false)
|
||||||
|
Loading…
Reference in New Issue
Block a user