tilelink: add mask rom
This commit is contained in:
@ -1,4 +1,4 @@
|
||||
// See LICENSE for license details.
|
||||
// See LICENSE.SiFive for license details.
|
||||
|
||||
package freechips.rocketchip.coreplex
|
||||
|
||||
|
@ -6,6 +6,9 @@ import Chisel._
|
||||
import freechips.rocketchip.config.{Field, Parameters}
|
||||
import freechips.rocketchip.coreplex._
|
||||
import freechips.rocketchip.diplomacy._
|
||||
import freechips.rocketchip.tilelink._
|
||||
import freechips.rocketchip.util._
|
||||
|
||||
import java.nio.{ByteBuffer, ByteOrder}
|
||||
import java.nio.file.{Files, Paths}
|
||||
|
||||
@ -17,6 +20,47 @@ case class BootROMParams(
|
||||
contentFileName: String)
|
||||
case object BootROMParams extends Field[BootROMParams]
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
/** Adds a boot ROM that contains the DTB describing the system's coreplex. */
|
||||
trait HasPeripheryBootROM extends HasPeripheryBus {
|
||||
val dtb: DTB
|
||||
|
71
src/main/scala/devices/tilelink/MaskROM.scala
Normal file
71
src/main/scala/devices/tilelink/MaskROM.scala
Normal file
@ -0,0 +1,71 @@
|
||||
// See LICENSE.SiFive for license details.
|
||||
|
||||
package freechips.rocketchip.devices.tilelink
|
||||
|
||||
import Chisel._
|
||||
import freechips.rocketchip.coreplex.{HasPeripheryBus}
|
||||
import freechips.rocketchip.config.{Field, Parameters}
|
||||
import freechips.rocketchip.diplomacy._
|
||||
import freechips.rocketchip.tilelink._
|
||||
import freechips.rocketchip.util._
|
||||
|
||||
case class MaskROMParams(address: BigInt, name: String, depth: Int = 2048, width: Int = 32)
|
||||
|
||||
case object PeripheryMaskROMKey extends Field[Seq[MaskROMParams]]
|
||||
|
||||
trait HasPeripheryMaskROMSlave extends HasPeripheryBus {
|
||||
val maskROMParams = p(PeripheryMaskROMKey)
|
||||
val maskROMs = maskROMParams map { params =>
|
||||
val maskROM = LazyModule(new TLMaskROM(params))
|
||||
maskROM.node := pbus.toFixedWidthSingleBeatSlave(maskROM.beatBytes)
|
||||
maskROM
|
||||
}
|
||||
}
|
||||
|
||||
class TLMaskROM(c: MaskROMParams)(implicit p: Parameters) extends LazyModule {
|
||||
val beatBytes = c.width/8
|
||||
val node = TLManagerNode(beatBytes, TLManagerParameters(
|
||||
address = AddressSet.misaligned(c.address, c.depth*beatBytes),
|
||||
resources = new SimpleDevice("rom", Seq("sifive,maskrom0")).reg("mem"),
|
||||
regionType = RegionType.UNCACHED,
|
||||
executable = true,
|
||||
supportsGet = TransferSizes(1, beatBytes),
|
||||
fifoId = Some(0))) // requests are handled in order
|
||||
|
||||
lazy val module = new LazyModuleImp(this) {
|
||||
val io = new Bundle {
|
||||
val in = node.bundleIn
|
||||
}
|
||||
|
||||
val in = io.in(0)
|
||||
val edge = node.edgesIn(0)
|
||||
|
||||
val rom = ROMGenerator(ROMConfig(c.name, c.depth, c.width))
|
||||
rom.io.clock := clock
|
||||
rom.io.address := edge.addr_hi(in.a.bits.address - UInt(c.address))(log2Ceil(c.depth)-1, 0)
|
||||
rom.io.oe := Bool(true) // active high tri state enable
|
||||
rom.io.me := in.a.fire()
|
||||
|
||||
val d_full = RegInit(Bool(false))
|
||||
val d_size = Reg(UInt())
|
||||
val d_source = Reg(UInt())
|
||||
|
||||
// Flow control
|
||||
when (in.d.fire()) { d_full := Bool(false) }
|
||||
when (in.a.fire()) { d_full := Bool(true) }
|
||||
in.d.valid := d_full
|
||||
in.a.ready := in.d.ready || !d_full
|
||||
|
||||
when (in.a.fire()) {
|
||||
d_size := in.a.bits.size
|
||||
d_source := in.a.bits.source
|
||||
}
|
||||
|
||||
in.d.bits := edge.AccessAck(d_source, d_size, rom.io.q)
|
||||
|
||||
// Tie off unused channels
|
||||
in.b.valid := Bool(false)
|
||||
in.c.ready := Bool(true)
|
||||
in.e.ready := Bool(true)
|
||||
}
|
||||
}
|
@ -1,52 +0,0 @@
|
||||
// See LICENSE.SiFive for license details.
|
||||
// See LICENSE.Berkeley for license details.
|
||||
|
||||
package freechips.rocketchip.devices.tilelink
|
||||
|
||||
import Chisel._
|
||||
import freechips.rocketchip.config.Parameters
|
||||
import freechips.rocketchip.diplomacy._
|
||||
import freechips.rocketchip.tilelink._
|
||||
import freechips.rocketchip.util._
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
@ -88,5 +88,6 @@ object Generator extends GeneratorApp {
|
||||
val longName = names.topModuleProject + "." + names.configs
|
||||
generateFirrtl
|
||||
generateTestSuiteMakefrags
|
||||
generateROMs
|
||||
generateArtefacts
|
||||
}
|
||||
|
@ -53,6 +53,21 @@ trait HasGeneratorUtilities {
|
||||
Driver.elaborate(gen)
|
||||
}
|
||||
|
||||
def enumerateROMs(circuit: Circuit): String = {
|
||||
val res = new StringBuilder
|
||||
val configs =
|
||||
circuit.components flatMap { m =>
|
||||
m.id match {
|
||||
case rom: BlackBoxedROM => Some((rom.name, ROMGenerator.lookup(rom)))
|
||||
case _ => None
|
||||
}
|
||||
}
|
||||
configs foreach { case (name, c) =>
|
||||
res append s"name ${name} depth ${c.depth} width ${c.width}\n"
|
||||
}
|
||||
res.toString
|
||||
}
|
||||
|
||||
def writeOutputFile(targetDir: String, fname: String, contents: String): File = {
|
||||
val f = new File(targetDir, fname)
|
||||
val fw = new FileWriter(f)
|
||||
@ -103,6 +118,10 @@ trait GeneratorApp extends App with HasGeneratorUtilities {
|
||||
TestGeneration.addSuite(DefaultTestSuites.singleRegression)
|
||||
}
|
||||
|
||||
def generateROMs {
|
||||
writeOutputFile(td, s"$longName.rom.conf", enumerateROMs(circuit))
|
||||
}
|
||||
|
||||
/** Output files created as a side-effect of elaboration */
|
||||
def generateArtefacts {
|
||||
ElaborationArtefacts.files.foreach { case (extension, contents) =>
|
||||
|
35
src/main/scala/util/ROMGenerator.scala
Normal file
35
src/main/scala/util/ROMGenerator.scala
Normal file
@ -0,0 +1,35 @@
|
||||
// See LICENSE.SiFive for license details.
|
||||
|
||||
package freechips.rocketchip.util
|
||||
|
||||
import Chisel._
|
||||
import scala.collection.mutable.{HashMap}
|
||||
|
||||
case class ROMConfig(name: String, depth: Int, width: Int)
|
||||
|
||||
class BlackBoxedROM(c: ROMConfig) extends BlackBox {
|
||||
val io = new Bundle {
|
||||
val clock = Clock(INPUT)
|
||||
val address = UInt(INPUT, log2Ceil(c.depth))
|
||||
val oe = Bool(INPUT)
|
||||
val me = Bool(INPUT)
|
||||
val q = UInt(OUTPUT, c.width)
|
||||
}
|
||||
|
||||
override def desiredName: String = c.name
|
||||
}
|
||||
|
||||
object ROMGenerator {
|
||||
private var finalized = false
|
||||
private val roms = HashMap[BlackBoxedROM, ROMConfig]()
|
||||
def apply(c: ROMConfig): BlackBoxedROM = {
|
||||
require(!finalized)
|
||||
val m = Module(new BlackBoxedROM(c))
|
||||
roms(m) = c
|
||||
m
|
||||
}
|
||||
def lookup(m: BlackBoxedROM): ROMConfig = {
|
||||
finalized = true
|
||||
roms(m)
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user