133 lines
4.6 KiB
Scala
133 lines
4.6 KiB
Scala
// See LICENSE.SiFive for license details.
|
|
// See LICENSE.Berkeley for license details.
|
|
|
|
package uncore.devices
|
|
|
|
import Chisel._
|
|
import unittest.UnitTest
|
|
import junctions._
|
|
import diplomacy._
|
|
import uncore.tilelink._
|
|
import uncore.tilelink2._
|
|
import uncore.util._
|
|
import config._
|
|
|
|
class TLROM(val base: BigInt, val size: Int, contentsDelayed: => Seq[Byte], executable: Boolean = true, beatBytes: Int = 4,
|
|
resources: Seq[Resource] = new SimpleDevice("rom", Nil).reg)(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, UInt(0), 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)
|
|
}
|
|
}
|
|
|
|
class ROMSlave(contents: Seq[Byte])(implicit val p: Parameters) extends Module
|
|
with HasTileLinkParameters {
|
|
val io = new ClientUncachedTileLinkIO().flip
|
|
|
|
val acq = Queue(io.acquire, 1)
|
|
val single_beat = acq.bits.isBuiltInType(Acquire.getType)
|
|
val multi_beat = acq.bits.isBuiltInType(Acquire.getBlockType)
|
|
assert(!acq.valid || single_beat || multi_beat, "unsupported ROMSlave operation")
|
|
|
|
val addr_beat = Reg(UInt())
|
|
when (io.grant.fire()) { addr_beat := addr_beat + UInt(1) }
|
|
when (io.acquire.fire()) { addr_beat := io.acquire.bits.addr_beat }
|
|
|
|
val byteWidth = tlDataBits / 8
|
|
val rows = (contents.size + byteWidth - 1)/byteWidth
|
|
val rom = Vec.tabulate(rows) { i =>
|
|
val slice = contents.slice(i*byteWidth, (i+1)*byteWidth)
|
|
UInt(slice.foldRight(BigInt(0)) { case (x,y) => (y << 8) + (x.toInt & 0xFF) }, byteWidth*8)
|
|
}
|
|
val raddr = Cat(acq.bits.addr_block, addr_beat)
|
|
val rdata = rom(if (rows == 1) UInt(0) else raddr(log2Up(rom.size)-1,0))
|
|
|
|
val last = !multi_beat || addr_beat === UInt(tlDataBeats-1)
|
|
io.grant.valid := acq.valid
|
|
acq.ready := io.grant.ready && last
|
|
io.grant.bits := Grant(
|
|
is_builtin_type = Bool(true),
|
|
g_type = acq.bits.getBuiltInGrantType(),
|
|
client_xact_id = acq.bits.client_xact_id,
|
|
manager_xact_id = UInt(0),
|
|
addr_beat = addr_beat,
|
|
data = rdata)
|
|
}
|
|
|
|
class ROMSlaveTest(implicit p: Parameters) extends UnitTest {
|
|
val romdata = Seq(
|
|
BigInt("01234567deadbeef", 16),
|
|
BigInt("ab32fee8d00dfeed", 16))
|
|
val rombytes = romdata.map(_.toByteArray.reverse).flatten
|
|
val rom = Module(new ROMSlave(rombytes))
|
|
val driver = Module(new DriverSet(
|
|
(driverParams: Parameters) => {
|
|
implicit val p = driverParams
|
|
Seq(
|
|
Module(new GetMultiWidthDriver),
|
|
Module(new GetSweepDriver(romdata)),
|
|
Module(new GetBlockSweepDriver(romdata)))
|
|
}))
|
|
rom.io <> driver.io.mem
|
|
driver.io.start := io.start
|
|
io.finished := driver.io.finished
|
|
}
|
|
|
|
class NastiROM(contents: Seq[Byte])(implicit p: Parameters) extends Module {
|
|
val io = new NastiIO().flip
|
|
val ar = Queue(io.ar, 1)
|
|
|
|
// This assumes ROMs are in read-only parts of the address map.
|
|
// Reuse b_queue code from NastiErrorSlave if this assumption is bad.
|
|
when (ar.valid) { assert(ar.bits.len === UInt(0), "Can't burst-read from NastiROM") }
|
|
assert(!(io.aw.valid || io.w.valid), "Can't write to NastiROM")
|
|
io.aw.ready := Bool(false)
|
|
io.w.ready := Bool(false)
|
|
io.b.valid := Bool(false)
|
|
|
|
val byteWidth = io.r.bits.nastiXDataBits / 8
|
|
val rows = (contents.size + byteWidth - 1)/byteWidth
|
|
val rom = Vec.tabulate(rows) { i =>
|
|
val slice = contents.slice(i*byteWidth, (i+1)*byteWidth)
|
|
UInt(slice.foldRight(BigInt(0)) { case (x,y) => (y << 8) + (x.toInt & 0xFF) }, byteWidth*8)
|
|
}
|
|
val rdata = rom(if (rows == 1) UInt(0) else ar.bits.addr(log2Up(contents.size)-1,log2Up(byteWidth)))
|
|
|
|
io.r <> ar
|
|
io.r.bits := NastiReadDataChannel(ar.bits.id, rdata)
|
|
}
|