2017-07-23 17:31:04 +02:00
|
|
|
// See LICENSE.SiFive for license details.
|
|
|
|
|
|
|
|
package freechips.rocketchip.devices.tilelink
|
|
|
|
|
|
|
|
import Chisel._
|
|
|
|
import freechips.rocketchip.config.{Field, Parameters}
|
|
|
|
import freechips.rocketchip.coreplex._
|
|
|
|
import freechips.rocketchip.diplomacy._
|
2017-08-01 06:12:45 +02:00
|
|
|
import freechips.rocketchip.tilelink._
|
|
|
|
import freechips.rocketchip.util._
|
|
|
|
|
2017-07-23 17:31:04 +02:00
|
|
|
import java.nio.{ByteBuffer, ByteOrder}
|
|
|
|
import java.nio.file.{Files, Paths}
|
|
|
|
|
|
|
|
/** Size, location and contents of the boot rom. */
|
|
|
|
case class BootROMParams(
|
|
|
|
address: BigInt = 0x10000,
|
|
|
|
size: Int = 0x10000,
|
|
|
|
hang: BigInt = 0x10040,
|
|
|
|
contentFileName: String)
|
|
|
|
case object BootROMParams extends Field[BootROMParams]
|
|
|
|
|
2017-08-01 06:12:45 +02:00
|
|
|
class TLROM(val base: BigInt, val size: Int, contentsDelayed: => Seq[Byte], executable: Boolean = true, beatBytes: Int = 4,
|
|
|
|
resources: Seq[Resource] = new SimpleDevice("rom", Seq("sifive,rom0")).reg("mem"))(implicit p: Parameters) extends LazyModule
|
|
|
|
{
|
|
|
|
val node = TLManagerNode(beatBytes, TLManagerParameters (
|
|
|
|
address = List(AddressSet(base, size-1)),
|
|
|
|
resources = resources,
|
|
|
|
regionType = RegionType.UNCACHED,
|
|
|
|
executable = executable,
|
|
|
|
supportsGet = TransferSizes(1, beatBytes),
|
|
|
|
fifoId = Some(0)))
|
|
|
|
|
|
|
|
lazy val module = new LazyModuleImp(this) {
|
|
|
|
val io = new Bundle {
|
|
|
|
val in = node.bundleIn
|
|
|
|
}
|
|
|
|
|
|
|
|
val contents = contentsDelayed
|
|
|
|
val wrapSize = 1 << log2Ceil(contents.size)
|
|
|
|
require (wrapSize <= size)
|
|
|
|
|
|
|
|
val in = io.in(0)
|
|
|
|
val edge = node.edgesIn(0)
|
|
|
|
|
|
|
|
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(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, Mux(high.orR, UInt(0), rom(index)))
|
|
|
|
|
|
|
|
// Tie off unused channels
|
|
|
|
in.b.valid := Bool(false)
|
|
|
|
in.c.ready := Bool(true)
|
|
|
|
in.e.ready := Bool(true)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-07-23 17:31:04 +02:00
|
|
|
/** Adds a boot ROM that contains the DTB describing the system's coreplex. */
|
|
|
|
trait HasPeripheryBootROM extends HasPeripheryBus {
|
|
|
|
val dtb: DTB
|
|
|
|
private val params = p(BootROMParams)
|
|
|
|
private lazy val contents = {
|
|
|
|
val romdata = Files.readAllBytes(Paths.get(params.contentFileName))
|
|
|
|
val rom = ByteBuffer.wrap(romdata)
|
|
|
|
rom.array() ++ dtb.contents
|
|
|
|
}
|
|
|
|
def resetVector: BigInt = params.hang
|
|
|
|
|
|
|
|
val bootrom = LazyModule(new TLROM(params.address, params.size, contents, true, pbus.beatBytes))
|
|
|
|
|
|
|
|
bootrom.node := pbus.toVariableWidthSlaves
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Coreplex will power-on running at 0x10040 (BootROM) */
|
|
|
|
trait HasPeripheryBootROMModuleImp extends LazyMultiIOModuleImp
|
|
|
|
with HasResetVectorWire {
|
|
|
|
val outer: HasPeripheryBootROM
|
2017-09-02 02:50:54 +02:00
|
|
|
global_reset_vector := outer.resetVector.U
|
2017-07-23 17:31:04 +02:00
|
|
|
}
|