reorganize moving non-submodule packages into src/main/scala
This commit is contained in:
161
src/main/scala/uncore/devices/Bram.scala
Normal file
161
src/main/scala/uncore/devices/Bram.scala
Normal file
@ -0,0 +1,161 @@
|
||||
package uncore.devices
|
||||
|
||||
import Chisel._
|
||||
import cde.{Parameters, Field}
|
||||
import junctions._
|
||||
import uncore.tilelink._
|
||||
import uncore.util._
|
||||
import HastiConstants._
|
||||
|
||||
class BRAMSlave(depth: Int)(implicit val p: Parameters) extends Module
|
||||
with HasTileLinkParameters {
|
||||
val io = new ClientUncachedTileLinkIO().flip
|
||||
|
||||
// For TL2:
|
||||
// supportsAcquire = false
|
||||
// supportsMultibeat = false
|
||||
// supportsHint = false
|
||||
// supportsAtomic = false
|
||||
|
||||
// Timing-wise, we assume the input is coming out of registers
|
||||
// since you probably needed a TileLinkFragmenter infront of us
|
||||
|
||||
// Thus, only one pipeline stage: the grant result
|
||||
val g_valid = RegInit(Bool(false))
|
||||
val g_bits = Reg(new Grant)
|
||||
|
||||
// Just pass the pipeline straight through
|
||||
io.grant.valid := g_valid
|
||||
io.grant.bits := g_bits
|
||||
io.acquire.ready := !g_valid || io.grant.ready
|
||||
|
||||
val acq_get = io.acquire.bits.isBuiltInType(Acquire.getType)
|
||||
val acq_put = io.acquire.bits.isBuiltInType(Acquire.putType)
|
||||
val acq_addr = Cat(io.acquire.bits.addr_block, io.acquire.bits.addr_beat)
|
||||
|
||||
val bram = Mem(depth, Bits(width = tlDataBits))
|
||||
|
||||
val ren = acq_get && io.acquire.fire()
|
||||
val wen = acq_put && io.acquire.fire()
|
||||
|
||||
when (io.grant.fire()) {
|
||||
g_valid := Bool(false)
|
||||
}
|
||||
|
||||
when (io.acquire.fire()) {
|
||||
g_valid := Bool(true)
|
||||
g_bits := Grant(
|
||||
is_builtin_type = Bool(true),
|
||||
g_type = io.acquire.bits.getBuiltInGrantType(),
|
||||
client_xact_id = io.acquire.bits.client_xact_id,
|
||||
manager_xact_id = UInt(0),
|
||||
addr_beat = io.acquire.bits.addr_beat,
|
||||
data = UInt(0))
|
||||
}
|
||||
|
||||
when (wen) {
|
||||
bram.write(acq_addr, io.acquire.bits.data)
|
||||
assert(io.acquire.bits.wmask().andR, "BRAMSlave: partial write masks not supported")
|
||||
}
|
||||
io.grant.bits.data := RegEnable(bram.read(acq_addr), ren)
|
||||
}
|
||||
|
||||
class HastiRAM(depth: Int)(implicit p: Parameters) extends HastiModule()(p) {
|
||||
val io = new HastiSlaveIO
|
||||
|
||||
val wdata = Vec.tabulate(hastiDataBytes)(i => io.hwdata(8*(i+1)-1,8*i))
|
||||
val waddr = Reg(UInt(width = hastiAddrBits))
|
||||
val wvalid = Reg(init = Bool(false))
|
||||
val wsize = Reg(UInt(width = SZ_HSIZE))
|
||||
val ram = SeqMem(depth, Vec(hastiDataBytes, Bits(width = 8)))
|
||||
|
||||
val max_size = log2Ceil(hastiDataBytes)
|
||||
val wmask_lut = MuxLookup(wsize, SInt(-1, hastiDataBytes).asUInt,
|
||||
(0 until max_size).map(sz => (UInt(sz) -> UInt((1 << (1 << sz)) - 1))))
|
||||
val wmask = (wmask_lut << waddr(max_size - 1, 0))(hastiDataBytes - 1, 0)
|
||||
|
||||
val is_trans = io.hsel && io.htrans.isOneOf(HTRANS_NONSEQ, HTRANS_SEQ)
|
||||
val raddr = io.haddr >> UInt(max_size)
|
||||
val ren = is_trans && !io.hwrite
|
||||
val bypass = Reg(init = Bool(false))
|
||||
|
||||
when (is_trans && io.hwrite) {
|
||||
waddr := io.haddr
|
||||
wsize := io.hsize
|
||||
wvalid := Bool(true)
|
||||
} .otherwise { wvalid := Bool(false) }
|
||||
|
||||
when (ren) { bypass := wvalid && (waddr >> UInt(max_size)) === raddr }
|
||||
|
||||
when (wvalid) {
|
||||
ram.write(waddr >> UInt(max_size), wdata, wmask.toBools)
|
||||
}
|
||||
|
||||
val rdata = ram.read(raddr, ren)
|
||||
io.hrdata := Cat(rdata.zip(wmask.toBools).zip(wdata).map {
|
||||
case ((rbyte, wsel), wbyte) => Mux(wsel && bypass, wbyte, rbyte)
|
||||
}.reverse)
|
||||
|
||||
io.hready := Bool(true)
|
||||
io.hresp := HRESP_OKAY
|
||||
}
|
||||
|
||||
/**
|
||||
* This RAM is not meant to be particularly performant.
|
||||
* It just supports the entire range of uncached TileLink operations in the
|
||||
* simplest way possible.
|
||||
*/
|
||||
class TileLinkTestRAM(depth: Int)(implicit val p: Parameters) extends Module
|
||||
with HasTileLinkParameters {
|
||||
val io = new ClientUncachedTileLinkIO().flip
|
||||
|
||||
val ram = Mem(depth, UInt(width = tlDataBits))
|
||||
|
||||
val responding = Reg(init = Bool(false))
|
||||
val acq = io.acquire.bits
|
||||
val r_acq = Reg(io.acquire.bits)
|
||||
val acq_addr = Cat(acq.addr_block, acq.addr_beat)
|
||||
val r_acq_addr = Cat(r_acq.addr_block, r_acq.addr_beat)
|
||||
|
||||
when (io.acquire.fire() && io.acquire.bits.last()) {
|
||||
r_acq := io.acquire.bits
|
||||
responding := Bool(true)
|
||||
}
|
||||
|
||||
when (io.grant.fire()) {
|
||||
val is_getblk = r_acq.isBuiltInType(Acquire.getBlockType)
|
||||
val last_beat = r_acq.addr_beat === UInt(tlDataBeats - 1)
|
||||
when (is_getblk && !last_beat) {
|
||||
r_acq.addr_beat := r_acq.addr_beat + UInt(1)
|
||||
} .otherwise { responding := Bool(false) }
|
||||
}
|
||||
|
||||
val old_data = ram(acq_addr)
|
||||
val new_data = acq.data
|
||||
val r_old_data = RegEnable(old_data, io.acquire.fire())
|
||||
|
||||
io.acquire.ready := !responding
|
||||
io.grant.valid := responding
|
||||
io.grant.bits := Grant(
|
||||
is_builtin_type = Bool(true),
|
||||
g_type = r_acq.getBuiltInGrantType(),
|
||||
client_xact_id = r_acq.client_xact_id,
|
||||
manager_xact_id = UInt(0),
|
||||
addr_beat = r_acq.addr_beat,
|
||||
data = Mux(r_acq.isAtomic(), r_old_data, ram(r_acq_addr)))
|
||||
|
||||
val amo_shift_bits = acq.amo_shift_bytes() << UInt(3)
|
||||
val amoalu = Module(new AMOALU(amoAluOperandBits, rhsIsAligned = true))
|
||||
amoalu.io.addr := Cat(acq.addr_block, acq.addr_beat, acq.addr_byte())
|
||||
amoalu.io.cmd := acq.op_code()
|
||||
amoalu.io.typ := acq.op_size()
|
||||
amoalu.io.lhs := old_data >> amo_shift_bits
|
||||
amoalu.io.rhs := new_data >> amo_shift_bits
|
||||
|
||||
val result = Mux(acq.isAtomic(), amoalu.io.out << amo_shift_bits, new_data)
|
||||
val wmask = FillInterleaved(8, acq.wmask())
|
||||
|
||||
when (io.acquire.fire() && acq.hasData()) {
|
||||
ram(acq_addr) := (old_data & ~wmask) | (result & wmask)
|
||||
}
|
||||
}
|
1001
src/main/scala/uncore/devices/Debug.scala
Normal file
1001
src/main/scala/uncore/devices/Debug.scala
Normal file
File diff suppressed because it is too large
Load Diff
187
src/main/scala/uncore/devices/Plic.scala
Normal file
187
src/main/scala/uncore/devices/Plic.scala
Normal file
@ -0,0 +1,187 @@
|
||||
// See LICENSE for license details.
|
||||
|
||||
package uncore.devices
|
||||
|
||||
import Chisel._
|
||||
import Chisel.ImplicitConversions._
|
||||
|
||||
import junctions._
|
||||
import uncore.tilelink._
|
||||
import cde.Parameters
|
||||
|
||||
class GatewayPLICIO extends Bundle {
|
||||
val valid = Bool(OUTPUT)
|
||||
val ready = Bool(INPUT)
|
||||
val complete = Bool(INPUT)
|
||||
}
|
||||
|
||||
class LevelGateway extends Module {
|
||||
val io = new Bundle {
|
||||
val interrupt = Bool(INPUT)
|
||||
val plic = new GatewayPLICIO
|
||||
}
|
||||
|
||||
val inFlight = Reg(init=Bool(false))
|
||||
when (io.interrupt && io.plic.ready) { inFlight := true }
|
||||
when (io.plic.complete) { inFlight := false }
|
||||
io.plic.valid := io.interrupt && !inFlight
|
||||
}
|
||||
|
||||
case class PLICConfig(nHartsIn: Int, supervisor: Boolean, nDevices: Int, nPriorities: Int) {
|
||||
def contextsPerHart = if (supervisor) 2 else 1
|
||||
def nHarts = contextsPerHart * nHartsIn
|
||||
def context(i: Int, mode: Char) = mode match {
|
||||
case 'M' => i * contextsPerHart
|
||||
case 'S' => require(supervisor); i * contextsPerHart + 1
|
||||
}
|
||||
def claimAddr(i: Int, mode: Char) = hartBase + hartOffset(context(i, mode)) + claimOffset
|
||||
def threshAddr(i: Int, mode: Char) = hartBase + hartOffset(context(i, mode))
|
||||
def enableAddr(i: Int, mode: Char) = enableBase + enableOffset(context(i, mode))
|
||||
def size = hartBase + hartOffset(maxHarts)
|
||||
|
||||
def maxDevices = 1023
|
||||
def maxHarts = 15872
|
||||
def pendingBase = 0x1000
|
||||
def enableBase = 0x2000
|
||||
def hartBase = 0x200000
|
||||
require(hartBase >= enableBase + enableOffset(maxHarts))
|
||||
|
||||
def enableOffset(i: Int) = i * ((maxDevices+7)/8)
|
||||
def hartOffset(i: Int) = i * 0x1000
|
||||
def claimOffset = 4
|
||||
def priorityBytes = 4
|
||||
|
||||
require(nDevices > 0 && nDevices <= maxDevices)
|
||||
require(nHarts > 0 && nHarts <= maxHarts)
|
||||
require(nPriorities >= 0 && nPriorities <= nDevices)
|
||||
}
|
||||
|
||||
/** Platform-Level Interrupt Controller */
|
||||
class PLIC(val cfg: PLICConfig)(implicit val p: Parameters) extends Module
|
||||
with HasTileLinkParameters
|
||||
with HasAddrMapParameters {
|
||||
val io = new Bundle {
|
||||
val devices = Vec(cfg.nDevices, new GatewayPLICIO).flip
|
||||
val harts = Vec(cfg.nHarts, Bool()).asOutput
|
||||
val tl = new ClientUncachedTileLinkIO().flip
|
||||
}
|
||||
|
||||
val priority =
|
||||
if (cfg.nPriorities > 0) Reg(Vec(cfg.nDevices+1, UInt(width=log2Up(cfg.nPriorities+1))))
|
||||
else Wire(init=Vec.fill(cfg.nDevices+1)(UInt(1)))
|
||||
val threshold =
|
||||
if (cfg.nPriorities > 0) Reg(Vec(cfg.nHarts, UInt(width = log2Up(cfg.nPriorities+1))))
|
||||
else Wire(init=Vec.fill(cfg.nHarts)(UInt(0)))
|
||||
val pending = Reg(init=Vec.fill(cfg.nDevices+1){Bool(false)})
|
||||
val enables = Reg(Vec(cfg.nHarts, Vec(cfg.nDevices+1, Bool())))
|
||||
|
||||
for ((p, g) <- pending.tail zip io.devices) {
|
||||
g.ready := !p
|
||||
g.complete := false
|
||||
when (g.valid) { p := true }
|
||||
}
|
||||
|
||||
def findMax(x: Seq[UInt]): (UInt, UInt) = {
|
||||
if (x.length > 1) {
|
||||
val half = 1 << (log2Ceil(x.length) - 1)
|
||||
val lMax = findMax(x take half)
|
||||
val rMax = findMax(x drop half)
|
||||
val useLeft = lMax._1 >= rMax._1
|
||||
(Mux(useLeft, lMax._1, rMax._1), Mux(useLeft, lMax._2, UInt(half) + rMax._2))
|
||||
} else (x.head, UInt(0))
|
||||
}
|
||||
|
||||
val maxDevs = Wire(Vec(cfg.nHarts, UInt(width = log2Up(pending.size))))
|
||||
for (hart <- 0 until cfg.nHarts) {
|
||||
val effectivePriority =
|
||||
for (((p, en), pri) <- (pending zip enables(hart) zip priority).tail)
|
||||
yield Cat(p && en, pri)
|
||||
val (maxPri, maxDev) = findMax((UInt(1) << priority(0).getWidth) +: effectivePriority)
|
||||
|
||||
maxDevs(hart) := Reg(next = maxDev)
|
||||
io.harts(hart) := Reg(next = maxPri) > Cat(UInt(1), threshold(hart))
|
||||
}
|
||||
|
||||
val acq = Queue(io.tl.acquire, 1)
|
||||
val read = acq.fire() && acq.bits.isBuiltInType(Acquire.getType)
|
||||
val write = acq.fire() && acq.bits.isBuiltInType(Acquire.putType)
|
||||
assert(!acq.fire() || read || write, "unsupported PLIC operation")
|
||||
val addr = acq.bits.full_addr()(log2Up(cfg.size)-1,0)
|
||||
|
||||
val claimant =
|
||||
if (cfg.nHarts == 1) UInt(0)
|
||||
else (addr - cfg.hartBase)(log2Up(cfg.hartOffset(cfg.nHarts))-1,log2Up(cfg.hartOffset(1)))
|
||||
val hart = Wire(init = claimant)
|
||||
val myMaxDev = maxDevs(claimant)
|
||||
val myEnables = enables(hart)
|
||||
val rdata = Wire(init = UInt(0, tlDataBits))
|
||||
val masked_wdata = (acq.bits.data & acq.bits.full_wmask()) | (rdata & ~acq.bits.full_wmask())
|
||||
|
||||
when (addr >= cfg.hartBase) {
|
||||
val word =
|
||||
if (tlDataBytes > cfg.claimOffset) UInt(0)
|
||||
else addr(log2Up(cfg.claimOffset),log2Up(tlDataBytes))
|
||||
rdata := Cat(myMaxDev, UInt(0, 8*cfg.priorityBytes-threshold(0).getWidth), threshold(claimant)) >> (word * tlDataBits)
|
||||
|
||||
when (read && addr(log2Ceil(cfg.claimOffset))) {
|
||||
pending(myMaxDev) := false
|
||||
}
|
||||
when (write) {
|
||||
when (if (tlDataBytes > cfg.claimOffset) acq.bits.wmask()(cfg.claimOffset) else addr(log2Ceil(cfg.claimOffset))) {
|
||||
val dev = (acq.bits.data >> ((8 * cfg.claimOffset) % tlDataBits))(log2Up(pending.size)-1,0)
|
||||
when (myEnables(dev)) { io.devices(dev-1).complete := true }
|
||||
}.otherwise {
|
||||
if (cfg.nPriorities > 0) threshold(claimant) := acq.bits.data
|
||||
}
|
||||
}
|
||||
}.elsewhen (addr >= cfg.enableBase) {
|
||||
val enableHart =
|
||||
if (cfg.nHarts > 1) (addr - cfg.enableBase)(log2Up(cfg.enableOffset(cfg.nHarts))-1,log2Up(cfg.enableOffset(1)))
|
||||
else UInt(0)
|
||||
hart := enableHart
|
||||
val word =
|
||||
if (tlDataBits >= cfg.nHarts) UInt(0)
|
||||
else addr(log2Up((cfg.nHarts+7)/8)-1,log2Up(tlDataBytes))
|
||||
for (i <- 0 until cfg.nHarts by tlDataBits) {
|
||||
when (word === i/tlDataBits) {
|
||||
rdata := Cat(myEnables.slice(i, i + tlDataBits).reverse)
|
||||
for (j <- 0 until (tlDataBits min (myEnables.size - i))) {
|
||||
when (write) { enables(enableHart)(i+j) := masked_wdata(j) }
|
||||
}
|
||||
}
|
||||
}
|
||||
}.elsewhen (addr >= cfg.pendingBase) {
|
||||
val word =
|
||||
if (tlDataBytes >= pending.size) UInt(0)
|
||||
else addr(log2Up(pending.size)-1,log2Up(tlDataBytes))
|
||||
rdata := pending.asUInt >> (word * tlDataBits)
|
||||
}.otherwise {
|
||||
val regsPerBeat = tlDataBytes >> log2Up(cfg.priorityBytes)
|
||||
val word =
|
||||
if (regsPerBeat >= priority.size) UInt(0)
|
||||
else addr(log2Up(priority.size*cfg.priorityBytes)-1,log2Up(tlDataBytes))
|
||||
for (i <- 0 until priority.size by regsPerBeat) {
|
||||
when (word === i/regsPerBeat) {
|
||||
rdata := Cat(priority.slice(i, i + regsPerBeat).map(p => Cat(UInt(0, 8*cfg.priorityBytes-p.getWidth), p)).reverse)
|
||||
for (j <- 0 until (regsPerBeat min (priority.size - i))) {
|
||||
if (cfg.nPriorities > 0) when (write) { priority(i+j) := masked_wdata >> (j * 8 * cfg.priorityBytes) }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
priority(0) := 0
|
||||
pending(0) := false
|
||||
for (e <- enables)
|
||||
e(0) := false
|
||||
|
||||
io.tl.grant.valid := acq.valid
|
||||
acq.ready := io.tl.grant.ready
|
||||
io.tl.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 = UInt(0),
|
||||
data = rdata)
|
||||
}
|
127
src/main/scala/uncore/devices/Prci.scala
Normal file
127
src/main/scala/uncore/devices/Prci.scala
Normal file
@ -0,0 +1,127 @@
|
||||
// See LICENSE for license details.
|
||||
|
||||
package uncore.devices
|
||||
|
||||
import Chisel._
|
||||
import Chisel.ImplicitConversions._
|
||||
import junctions._
|
||||
import junctions.NastiConstants._
|
||||
import uncore.tilelink._
|
||||
import cde.{Parameters, Field}
|
||||
|
||||
/** Number of tiles */
|
||||
case object NTiles extends Field[Int]
|
||||
|
||||
class PRCIInterrupts extends Bundle {
|
||||
val meip = Bool()
|
||||
val seip = Bool()
|
||||
val debug = Bool()
|
||||
}
|
||||
|
||||
class PRCITileIO(implicit p: Parameters) extends Bundle {
|
||||
val reset = Bool(OUTPUT)
|
||||
val id = UInt(OUTPUT, log2Up(p(NTiles)))
|
||||
val interrupts = new PRCIInterrupts {
|
||||
val mtip = Bool()
|
||||
val msip = Bool()
|
||||
}.asOutput
|
||||
|
||||
override def cloneType: this.type = new PRCITileIO().asInstanceOf[this.type]
|
||||
}
|
||||
|
||||
object PRCI {
|
||||
def msip(hart: Int) = hart * msipBytes
|
||||
def timecmp(hart: Int) = 0x4000 + hart * timecmpBytes
|
||||
def time = 0xbff8
|
||||
def msipBytes = 4
|
||||
def timecmpBytes = 8
|
||||
def size = 0xc000
|
||||
}
|
||||
|
||||
/** Power, Reset, Clock, Interrupt */
|
||||
class PRCI(implicit val p: Parameters) extends Module
|
||||
with HasTileLinkParameters
|
||||
with HasAddrMapParameters {
|
||||
val io = new Bundle {
|
||||
val interrupts = Vec(p(NTiles), new PRCIInterrupts).asInput
|
||||
val tl = new ClientUncachedTileLinkIO().flip
|
||||
val tiles = Vec(p(NTiles), new PRCITileIO)
|
||||
val rtcTick = Bool(INPUT)
|
||||
}
|
||||
|
||||
val timeWidth = 64
|
||||
val timecmp = Reg(Vec(p(NTiles), UInt(width = timeWidth)))
|
||||
val time = Reg(init=UInt(0, timeWidth))
|
||||
when (io.rtcTick) { time := time + UInt(1) }
|
||||
|
||||
val ipi = Reg(init=Vec.fill(p(NTiles))(UInt(0, 32)))
|
||||
|
||||
val acq = Queue(io.tl.acquire, 1)
|
||||
val addr = acq.bits.full_addr()(log2Ceil(PRCI.size)-1,0)
|
||||
val read = acq.bits.isBuiltInType(Acquire.getType)
|
||||
val rdata = Wire(init=UInt(0))
|
||||
io.tl.grant.valid := acq.valid
|
||||
acq.ready := io.tl.grant.ready
|
||||
io.tl.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 = UInt(0),
|
||||
data = rdata)
|
||||
|
||||
when (addr(log2Floor(PRCI.time))) {
|
||||
require(log2Floor(PRCI.timecmp(p(NTiles)-1)) < log2Floor(PRCI.time))
|
||||
rdata := load(Vec(time + UInt(0)), acq.bits)
|
||||
}.elsewhen (addr >= PRCI.timecmp(0)) {
|
||||
rdata := store(timecmp, acq.bits)
|
||||
}.otherwise {
|
||||
rdata := store(ipi, acq.bits) & Fill(tlDataBits/32, UInt(1, 32))
|
||||
}
|
||||
|
||||
for ((tile, i) <- io.tiles zipWithIndex) {
|
||||
tile.interrupts := io.interrupts(i)
|
||||
tile.interrupts.msip := ipi(i)(0)
|
||||
tile.interrupts.mtip := time >= timecmp(i)
|
||||
tile.id := UInt(i)
|
||||
}
|
||||
|
||||
// TODO generalize these to help other TL slaves
|
||||
def load(v: Vec[UInt], acq: Acquire): UInt = {
|
||||
val w = v.head.getWidth
|
||||
val a = acq.full_addr()
|
||||
require(isPow2(w) && w >= 8)
|
||||
if (w > tlDataBits) {
|
||||
(v(a(log2Up(w/8*v.size)-1,log2Up(w/8))) >> a(log2Up(w/8)-1,log2Up(tlDataBytes)))(tlDataBits-1,0)
|
||||
} else {
|
||||
val row = for (i <- 0 until v.size by tlDataBits/w)
|
||||
yield Cat(v.slice(i, i + tlDataBits/w).reverse)
|
||||
if (row.size == 1) row.head
|
||||
else Vec(row)(a(log2Up(w/8*v.size)-1,log2Up(tlDataBytes)))
|
||||
}
|
||||
}
|
||||
|
||||
def store(v: Vec[UInt], acq: Acquire): UInt = {
|
||||
val w = v.head.getWidth
|
||||
require(isPow2(w) && w >= 8)
|
||||
val a = acq.full_addr()
|
||||
val rdata = load(v, acq)
|
||||
val wdata = (acq.data & acq.full_wmask()) | (rdata & ~acq.full_wmask())
|
||||
if (w <= tlDataBits) {
|
||||
val word =
|
||||
if (tlDataBits/w >= v.size) UInt(0)
|
||||
else a(log2Up(w/8*v.size)-1,log2Up(tlDataBytes))
|
||||
for (i <- 0 until v.size) {
|
||||
when (acq.isBuiltInType(Acquire.putType) && word === i/(tlDataBits/w)) {
|
||||
val base = i % (tlDataBits/w)
|
||||
v(i) := wdata >> (w * (i % (tlDataBits/w)))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
val i = a(log2Up(w/8*v.size)-1,log2Up(w/8))
|
||||
val mask = FillInterleaved(tlDataBits, UIntToOH(a(log2Up(w/8)-1,log2Up(tlDataBytes))))
|
||||
v(i) := (wdata & mask) | (v(i) & ~mask)
|
||||
}
|
||||
rdata
|
||||
}
|
||||
}
|
66
src/main/scala/uncore/devices/Rom.scala
Normal file
66
src/main/scala/uncore/devices/Rom.scala
Normal file
@ -0,0 +1,66 @@
|
||||
package uncore.devices
|
||||
|
||||
import Chisel._
|
||||
import junctions._
|
||||
import uncore.tilelink._
|
||||
import uncore.util._
|
||||
import cde.{Parameters, Field}
|
||||
|
||||
class ROMSlave(contents: Seq[Byte])(implicit val p: Parameters) extends Module
|
||||
with HasTileLinkParameters
|
||||
with HasAddrMapParameters {
|
||||
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 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)
|
||||
}
|
Reference in New Issue
Block a user