1
0

factor out more global constants

This commit is contained in:
Andrew Waterman
2012-11-05 23:52:32 -08:00
parent ee081d1671
commit c5b93798fb
10 changed files with 268 additions and 327 deletions

View File

@ -4,162 +4,157 @@ import Chisel._
import Constants._
import uncore._
class ioReplacementWayGen extends Bundle {
val pick_new_way = Bool(dir = INPUT)
val way_en = Bits(width = NWAYS, dir = INPUT)
val way_id = UFix(width = log2Up(NWAYS), dir = OUTPUT)
case class DCacheConfig(sets: Int, ways: Int, co: CoherencePolicy,
nmshr: Int, nsecondary: Int, nsdq: Int,
reqtagbits: Int = -1)
{
require(isPow2(sets))
require(isPow2(ways)) // TODO: relax this
def lines = sets*ways
def dm = ways == 1
def ppnbits = PPN_BITS
def pgidxbits = PGIDX_BITS
def offbits = OFFSET_BITS
def paddrbits = ppnbits + pgidxbits
def lineaddrbits = ppnbits - offbits
def idxbits = log2Up(sets)
def waybits = log2Up(ways)
def tagbits = lineaddrbits - idxbits
def databytes = 8 // assumed by StoreGen/LoadGen/AMOALU
def databits = databytes*8
}
class RandomReplacementWayGen extends Component {
val io = new ioReplacementWayGen()
//TODO: Actually limit selection based on which ways are allowed (io.ways_en)
io.way_id := UFix(0)
if(NWAYS > 1)
{
val rand_way_id = LFSR16(io.pick_new_way)(log2Up(NWAYS)-1,0)
when (rand_way_id < UFix(NWAYS)) { io.way_id := rand_way_id }
}
abstract class ReplacementPolicy
{
def way: UFix
def miss: Unit
def hit: Unit
}
class StoreMaskGen extends Component {
val io = new Bundle {
val typ = Bits(INPUT, 3)
val addr = Bits(INPUT, 3)
val wmask = Bits(OUTPUT, 8)
}
class RandomReplacement(implicit conf: DCacheConfig) extends ReplacementPolicy
{
private val replace = Bool()
replace := Bool(false)
val lfsr = LFSR16(replace)
val word = (io.typ === MT_W) || (io.typ === MT_WU)
val half = (io.typ === MT_H) || (io.typ === MT_HU)
val byte_ = (io.typ === MT_B) || (io.typ === MT_BU)
io.wmask := Mux(byte_, Bits( 1,1) << io.addr(2,0).toUFix,
Mux(half, Bits( 3,2) << Cat(io.addr(2,1), Bits(0,1)).toUFix,
Mux(word, Bits( 15,4) << Cat(io.addr(2), Bits(0,2)).toUFix,
Bits(255,8))));
def way = if (conf.dm) UFix(0) else lfsr(conf.waybits-1,0)
def miss = replace := Bool(true)
def hit = {}
}
class StoreDataGen extends Component {
val io = new Bundle {
val typ = Bits(INPUT, 3)
val din = Bits(INPUT, 64)
val dout = Bits(OUTPUT, 64)
}
val word = (io.typ === MT_W) || (io.typ === MT_WU)
val half = (io.typ === MT_H) || (io.typ === MT_HU)
val byte_ = (io.typ === MT_B) || (io.typ === MT_BU)
io.dout := Mux(byte_, Fill(8, io.din( 7,0)),
Mux(half, Fill(4, io.din(15,0)),
Mux(word, Fill(2, io.din(31,0)),
io.din)))
case class StoreGen(typ: Bits, addr: Bits, dat: Bits)
{
val byte = typ === MT_B || typ === MT_BU
val half = typ === MT_H || typ === MT_HU
val word = typ === MT_W || typ === MT_WU
def mask =
Mux(byte, Bits( 1) << addr(2,0),
Mux(half, Bits( 3) << Cat(addr(2,1), Bits(0,1)),
Mux(word, Bits( 15) << Cat(addr(2), Bits(0,2)),
Bits(255))))
def data =
Mux(byte, Fill(8, dat( 7,0)),
Mux(half, Fill(4, dat(15,0)),
Mux(word, Fill(2, dat(31,0)),
dat)))
}
// this currently requires that CPU_DATA_BITS == 64
class LoadDataGen extends Component {
val io = new Bundle {
val typ = Bits(INPUT, 3)
val addr = Bits(INPUT, log2Up(MEM_DATA_BITS/8))
val din = Bits(INPUT, MEM_DATA_BITS)
val dout = Bits(OUTPUT, 64)
val r_dout = Bits(OUTPUT, 64)
val r_dout_subword = Bits(OUTPUT, 64)
}
case class LoadGen(typ: Bits, addr: Bits, dat: Bits)
{
val t = StoreGen(typ, addr, dat)
val sign = typ === MT_B || typ === MT_H || typ === MT_W || typ === MT_D
val sext = (io.typ === MT_B) || (io.typ === MT_H) ||
(io.typ === MT_W) || (io.typ === MT_D)
val word = (io.typ === MT_W) || (io.typ === MT_WU)
val half = (io.typ === MT_H) || (io.typ === MT_HU)
val byte_ = (io.typ === MT_B) || (io.typ === MT_BU)
val shifted = io.din >> Cat(io.addr(io.addr.width-1,2), Bits(0, 5)).toUFix
val extended =
Mux(word, Cat(Fill(32, sext & shifted(31)), shifted(31,0)), shifted)
val r_extended = Reg(extended)
val r_sext = Reg(sext)
val r_half = Reg(half)
val r_byte = Reg(byte_)
val r_addr = Reg(io.addr)
val shifted_subword = r_extended >> Cat(r_addr(1,0), Bits(0, 3)).toUFix
val extended_subword =
Mux(r_byte, Cat(Fill(56, r_sext & shifted_subword( 7)), shifted_subword( 7,0)),
Mux(r_half, Cat(Fill(48, r_sext & shifted_subword(15)), shifted_subword(15,0)),
shifted_subword))
io.dout := extended
io.r_dout := r_extended
io.r_dout_subword := extended_subword
val wordShift = Mux(addr(2), dat(63,32), dat(31,0))
val word = Cat(Mux(t.word, Fill(32, sign && wordShift(31)), dat(63,32)), wordShift)
val halfShift = Mux(addr(1), word(31,16), word(15,0))
val half = Cat(Mux(t.half, Fill(48, sign && halfShift(15)), word(63,16)), halfShift)
val byteShift = Mux(addr(0), half(15,8), half(7,0))
val byte = Cat(Mux(t.byte, Fill(56, sign && byteShift(7)), half(63,8)), byteShift)
}
class MSHRReq extends Bundle {
class MSHRReq(implicit conf: DCacheConfig) extends Bundle {
val tag_miss = Bool()
val old_dirty = Bool()
val old_tag = Bits(width = TAG_BITS)
val old_tag = Bits(width = conf.tagbits)
val tag = Bits(width = TAG_BITS)
val idx = Bits(width = IDX_BITS)
val way_oh = Bits(width = NWAYS)
val tag = Bits(width = conf.tagbits)
val idx = Bits(width = conf.idxbits)
val way_oh = Bits(width = conf.ways)
val offset = Bits(width = OFFSET_BITS)
val offset = Bits(width = conf.offbits)
val cmd = Bits(width = 4)
val typ = Bits(width = 3)
val cpu_tag = Bits(width = DCACHE_TAG_BITS)
val data = Bits(width = CPU_DATA_BITS)
val cpu_tag = Bits(width = conf.reqtagbits)
val data = Bits(width = conf.databits)
override def clone = new MSHRReq().asInstanceOf[this.type]
}
class RPQEntry extends Bundle {
val offset = Bits(width = OFFSET_BITS)
class RPQEntry(implicit conf: DCacheConfig) extends Bundle {
val offset = Bits(width = conf.offbits)
val cmd = Bits(width = 4)
val typ = Bits(width = 3)
val sdq_id = UFix(width = log2Up(NSDQ))
val cpu_tag = Bits(width = DCACHE_TAG_BITS)
val sdq_id = UFix(width = log2Up(conf.nsdq))
val cpu_tag = Bits(width = conf.reqtagbits)
override def clone = new RPQEntry().asInstanceOf[this.type]
}
class Replay extends RPQEntry {
val idx = Bits(width = IDX_BITS)
val way_oh = Bits(width = NWAYS)
class Replay(implicit conf: DCacheConfig) extends RPQEntry {
val idx = Bits(width = conf.idxbits)
val way_oh = Bits(width = conf.ways)
override def clone = new Replay().asInstanceOf[this.type]
}
class DataReq extends Bundle {
val idx = Bits(width = IDX_BITS)
val offset = Bits(width = OFFSET_BITS)
class DataReq(implicit conf: DCacheConfig) extends Bundle {
val idx = Bits(width = conf.idxbits)
val offset = Bits(width = conf.offbits)
val cmd = Bits(width = 4)
val typ = Bits(width = 3)
val data = Bits(width = CPU_DATA_BITS)
val way_oh = Bits(width = NWAYS)
val data = Bits(width = conf.databits)
val way_oh = Bits(width = conf.ways)
override def clone = new DataReq().asInstanceOf[this.type]
}
class DataArrayReq extends Bundle {
val way_en = Bits(width = NWAYS)
val idx = Bits(width = IDX_BITS)
class DataArrayReq(implicit conf: DCacheConfig) extends Bundle {
val way_en = Bits(width = conf.ways)
val idx = Bits(width = conf.idxbits)
val offset = Bits(width = log2Up(REFILL_CYCLES))
val rw = Bool()
val wmask = Bits(width = MEM_DATA_BITS/8)
val data = Bits(width = MEM_DATA_BITS)
override def clone = new DataArrayReq().asInstanceOf[this.type]
}
class WritebackReq extends Bundle {
val tag = Bits(width = TAG_BITS)
val idx = Bits(width = IDX_BITS)
val way_oh = Bits(width = NWAYS)
class WritebackReq(implicit conf: DCacheConfig) extends Bundle {
val tag = Bits(width = conf.tagbits)
val idx = Bits(width = conf.idxbits)
val way_oh = Bits(width = conf.ways)
val tile_xact_id = Bits(width = TILE_XACT_ID_BITS)
override def clone = new WritebackReq().asInstanceOf[this.type]
}
class MetaData extends Bundle {
class MetaData(implicit conf: DCacheConfig) extends Bundle {
val state = UFix(width = 2)
val tag = Bits(width = TAG_BITS)
val tag = Bits(width = conf.tagbits)
override def clone = new MetaData().asInstanceOf[this.type]
}
class MetaArrayReq extends Bundle {
val way_en = Bits(width = NWAYS)
val idx = Bits(width = IDX_BITS)
class MetaArrayReq(implicit conf: DCacheConfig) extends Bundle {
val way_en = Bits(width = conf.ways)
val idx = Bits(width = conf.idxbits)
val rw = Bool()
val data = new MetaData()
override def clone = new MetaArrayReq().asInstanceOf[this.type]
}
class MSHR(id: Int)(implicit conf: RocketConfiguration) extends Component {
class MSHR(id: Int)(implicit conf: DCacheConfig) extends Component {
val io = new Bundle {
val req_pri_val = Bool(INPUT)
val req_pri_rdy = Bool(OUTPUT)
@ -169,10 +164,10 @@ class MSHR(id: Int)(implicit conf: RocketConfiguration) extends Component {
val req_sdq_id = UFix(INPUT, log2Up(NSDQ))
val idx_match = Bool(OUTPUT)
val idx = Bits(OUTPUT, IDX_BITS)
val idx = Bits(OUTPUT, conf.idxbits)
val refill_count = Bits(OUTPUT, log2Up(REFILL_CYCLES))
val tag = Bits(OUTPUT, TAG_BITS)
val way_oh = Bits(OUTPUT, NWAYS)
val tag = Bits(OUTPUT, conf.tagbits)
val way_oh = Bits(OUTPUT, conf.ways)
val mem_req = (new FIFOIO) { new TransactionInit }
val meta_req = (new FIFOIO) { new MetaArrayReq() }
@ -293,14 +288,14 @@ class MSHR(id: Int)(implicit conf: RocketConfiguration) extends Component {
io.replay.bits.way_oh := req.way_oh
}
class MSHRFile(implicit conf: RocketConfiguration) extends Component {
class MSHRFile(implicit conf: DCacheConfig) extends Component {
val io = new Bundle {
val req = (new FIFOIO) { new MSHRReq }.flip
val secondary_miss = Bool(OUTPUT)
val mem_resp_idx = Bits(OUTPUT, IDX_BITS)
val mem_resp_idx = Bits(OUTPUT, conf.idxbits)
val mem_resp_offset = Bits(OUTPUT, log2Up(REFILL_CYCLES))
val mem_resp_way_oh = Bits(OUTPUT, NWAYS)
val mem_resp_way_oh = Bits(OUTPUT, conf.ways)
val fence_rdy = Bool(OUTPUT)
@ -314,7 +309,7 @@ class MSHRFile(implicit conf: RocketConfiguration) extends Component {
val probe = (new FIFOIO) { Bool() }.flip
val cpu_resp_val = Bool(OUTPUT)
val cpu_resp_tag = Bits(OUTPUT, DCACHE_TAG_BITS)
val cpu_resp_tag = Bits(OUTPUT, conf.reqtagbits)
}
val sdq_val = Reg(resetVal = Bits(0, NSDQ))
@ -416,7 +411,7 @@ class MSHRFile(implicit conf: RocketConfiguration) extends Component {
}
class WritebackUnit(implicit conf: RocketConfiguration) extends Component {
class WritebackUnit(implicit conf: DCacheConfig) extends Component {
val io = new Bundle {
val req = (new FIFOIO) { new WritebackReq() }.flip
val probe = (new FIFOIO) { new WritebackReq() }.flip
@ -485,16 +480,16 @@ class WritebackUnit(implicit conf: RocketConfiguration) extends Component {
io.probe_rep_data.bits.data := io.data_resp
}
class ProbeUnit(implicit conf: RocketConfiguration) extends Component {
class ProbeUnit(implicit conf: DCacheConfig) extends Component {
val io = new Bundle {
val req = (new FIFOIO) { new ProbeRequest }.flip
val rep = (new FIFOIO) { new ProbeReply }
val meta_req = (new FIFOIO) { new MetaArrayReq }
val mshr_req = (new FIFOIO) { Bool() }
val wb_req = (new FIFOIO) { new WritebackReq }
val tag_match_way_oh = Bits(INPUT, NWAYS)
val tag_match_way_oh = Bits(INPUT, conf.ways)
val line_state = UFix(INPUT, 2)
val addr = Bits(OUTPUT, PADDR_BITS-OFFSET_BITS)
val addr = Bits(OUTPUT, conf.lineaddrbits)
}
val s_reset :: s_invalid :: s_meta_req :: s_meta_resp :: s_mshr_req :: s_probe_rep :: s_writeback_req :: s_writeback_resp :: Nil = Enum(8) { UFix() }
@ -535,21 +530,21 @@ class ProbeUnit(implicit conf: RocketConfiguration) extends Component {
io.rep.bits := conf.co.newProbeReply(req, Mux(hit, line_state, conf.co.newStateOnFlush))
io.meta_req.valid := state === s_meta_req || state === s_meta_resp || state === s_mshr_req || state === s_probe_rep && hit
io.meta_req.bits.way_en := Mux(state === s_probe_rep, way_oh, ~UFix(0, NWAYS))
io.meta_req.bits.way_en := Mux(state === s_probe_rep, way_oh, Fix(-1))
io.meta_req.bits.rw := state === s_probe_rep
io.meta_req.bits.idx := req.addr
io.meta_req.bits.data.state := conf.co.newStateOnProbeRequest(req, line_state)
io.meta_req.bits.data.tag := req.addr >> UFix(IDX_BITS)
io.meta_req.bits.data.tag := req.addr >> UFix(conf.idxbits)
io.mshr_req.valid := state === s_meta_resp || state === s_mshr_req
io.addr := req.addr
io.wb_req.valid := state === s_writeback_req
io.wb_req.bits.way_oh := way_oh
io.wb_req.bits.idx := req.addr
io.wb_req.bits.tag := req.addr >> UFix(IDX_BITS)
io.wb_req.bits.tag := req.addr >> UFix(conf.idxbits)
}
class FlushUnit(lines: Int)(implicit conf: RocketConfiguration) extends Component {
class FlushUnit(lines: Int)(implicit conf: DCacheConfig) extends Component {
val io = new Bundle {
val req = (new FIFOIO) { Bool() }.flip
val meta_req = (new FIFOIO) { new MetaArrayReq() }
@ -560,15 +555,15 @@ class FlushUnit(lines: Int)(implicit conf: RocketConfiguration) extends Componen
val state = Reg(resetVal = s_reset)
val idx_cnt = Reg(resetVal = UFix(0, log2Up(lines)))
val next_idx_cnt = idx_cnt + UFix(1)
val way_cnt = if (NWAYS == 1) UFix(0) else Reg(resetVal = UFix(0, log2Up(NWAYS)))
val way_cnt = if (conf.dm) UFix(0) else Reg(resetVal = UFix(0, conf.waybits))
val next_way_cnt = way_cnt + UFix(1)
switch (state) {
is(s_reset) {
when (io.meta_req.ready) {
state := Mux(way_cnt === UFix(NWAYS-1) && idx_cnt.andR, s_ready, s_reset);
when (way_cnt === UFix(NWAYS-1)) { idx_cnt := next_idx_cnt };
if (NWAYS > 1) way_cnt := next_way_cnt;
state := Mux(way_cnt === UFix(conf.ways-1) && idx_cnt.andR, s_ready, s_reset);
when (way_cnt === UFix(conf.ways-1)) { idx_cnt := next_idx_cnt };
if (!conf.dm) way_cnt := next_way_cnt;
}
}
is(s_ready) { when (io.req.valid) { state := s_meta_read } }
@ -577,13 +572,13 @@ class FlushUnit(lines: Int)(implicit conf: RocketConfiguration) extends Componen
state := s_meta_read
when (io.mshr_req.ready) {
state := s_meta_read
when (way_cnt === UFix(NWAYS-1)) {
when (way_cnt === UFix(conf.ways-1)) {
when (idx_cnt.andR) {
state := s_ready
}
idx_cnt := next_idx_cnt
}
if (NWAYS > 1) way_cnt := next_way_cnt;
if (!conf.dm) way_cnt := next_way_cnt;
}
}
}
@ -591,35 +586,35 @@ class FlushUnit(lines: Int)(implicit conf: RocketConfiguration) extends Componen
io.req.ready := state === s_ready
io.mshr_req.valid := state === s_meta_wait
io.meta_req.valid := (state === s_meta_read) || (state === s_reset)
io.meta_req.bits.way_en := UFixToOH(way_cnt, NWAYS)
io.meta_req.bits.way_en := UFixToOH(way_cnt)
io.meta_req.bits.idx := idx_cnt
io.meta_req.bits.rw := (state === s_reset)
io.meta_req.bits.data.state := conf.co.newStateOnFlush()
io.meta_req.bits.data.tag := UFix(0)
}
class MetaDataArrayArray(lines: Int) extends Component {
class MetaDataArrayArray(lines: Int)(implicit conf: DCacheConfig) extends Component {
val io = new Bundle {
val req = (new FIFOIO) { new MetaArrayReq() }.flip
val resp = Vec(NWAYS){ (new MetaData).asOutput }
val resp = Vec(conf.ways){ (new MetaData).asOutput }
val state_req = (new FIFOIO) { new MetaArrayReq() }.flip
val way_en = Bits(width = NWAYS, dir = OUTPUT)
val way_en = Bits(OUTPUT, conf.ways)
}
val permBits = io.req.bits.data.state.width
val perms = Mem(lines) { UFix(width = permBits*NWAYS) }
val tags = Mem(lines, seqRead = true) { Bits(width = TAG_BITS*NWAYS) }
val perms = Mem(lines) { UFix(width = permBits*conf.ways) }
val tags = Mem(lines, seqRead = true) { Bits(width = conf.tagbits*conf.ways) }
val tag = Reg() { Bits() }
val raddr = Reg() { Bits() }
val way_en_ = Reg { Bits(width=NWAYS) }
val way_en_ = Reg { Bits(width = conf.ways) }
when (io.state_req.valid && io.state_req.bits.rw) {
perms.write(io.state_req.bits.idx, Fill(NWAYS, io.state_req.bits.data.state), FillInterleaved(permBits, io.state_req.bits.way_en))
perms.write(io.state_req.bits.idx, Fill(conf.ways, io.state_req.bits.data.state), FillInterleaved(permBits, io.state_req.bits.way_en))
}
when (io.req.valid) {
when (io.req.bits.rw) {
perms.write(io.req.bits.idx, Fill(NWAYS, io.req.bits.data.state), FillInterleaved(permBits, io.req.bits.way_en))
tags.write(io.req.bits.idx, Fill(NWAYS, io.req.bits.data.tag), FillInterleaved(TAG_BITS, io.req.bits.way_en))
perms.write(io.req.bits.idx, Fill(conf.ways, io.req.bits.data.state), FillInterleaved(permBits, io.req.bits.way_en))
tags.write(io.req.bits.idx, Fill(conf.ways, io.req.bits.data.tag), FillInterleaved(conf.tagbits, io.req.bits.way_en))
}
.otherwise {
raddr := io.req.bits.idx
@ -629,9 +624,9 @@ class MetaDataArrayArray(lines: Int) extends Component {
}
val perm = perms(raddr)
for(w <- 0 until NWAYS) {
for (w <- 0 until conf.ways) {
io.resp(w).state := perm(permBits*(w+1)-1, permBits*w)
io.resp(w).tag := tag(TAG_BITS*(w+1)-1, TAG_BITS*w)
io.resp(w).tag := tag(conf.tagbits*(w+1)-1, conf.tagbits*w)
}
io.way_en := way_en_
@ -639,7 +634,7 @@ class MetaDataArrayArray(lines: Int) extends Component {
io.state_req.ready := Bool(true)
}
class DataArray(lines: Int) extends Component {
class DataArray(lines: Int)(implicit conf: DCacheConfig) extends Component {
val io = new Bundle {
val req = (new FIFOIO) { new DataArrayReq() }.flip
val resp = Bits(width = MEM_DATA_BITS, dir = OUTPUT)
@ -659,19 +654,19 @@ class DataArray(lines: Int) extends Component {
io.req.ready := Bool(true)
}
class DataArrayArray(lines: Int) extends Component {
class DataArrayArray(lines: Int)(implicit conf: DCacheConfig) extends Component {
val io = new Bundle {
val req = (new FIFOIO) { new DataArrayReq() }.flip
val resp = Vec(NWAYS){ Bits(dir = OUTPUT, width = MEM_DATA_BITS) }
val way_en = Bits(width = NWAYS, dir = OUTPUT)
val resp = Vec(conf.ways){ Bits(OUTPUT, MEM_DATA_BITS) }
val way_en = Bits(OUTPUT, conf.ways)
}
val way_en_ = Reg { Bits(width=NWAYS) }
val way_en_ = Reg { Bits(width = conf.ways) }
when (io.req.valid && io.req.ready) {
way_en_ := io.req.bits.way_en
}
for(w <- 0 until NWAYS) {
for (w <- 0 until conf.ways) {
val way = new DataArray(lines)
way.io.req.bits <> io.req.bits
way.io.req.valid := io.req.valid && io.req.bits.way_en(w).toBool
@ -713,24 +708,28 @@ class AMOALU extends Component {
io.out := Mux(word, Cat(out(31,0), out(31,0)).toUFix, out)
}
class HellaCacheReq extends Bundle {
class HellaCacheReq(implicit conf: DCacheConfig) extends Bundle {
val kill = Bool()
val typ = Bits(width = 3)
val idx = Bits(width = PGIDX_BITS)
val ppn = Bits(width = PPN_BITS)
val data = Bits(width = 64)
val tag = Bits(width = DCACHE_TAG_BITS)
val idx = Bits(width = conf.pgidxbits)
val ppn = Bits(width = conf.ppnbits)
val data = Bits(width = conf.databits)
val tag = Bits(width = conf.reqtagbits)
val cmd = Bits(width = 4)
override def clone = new HellaCacheReq().asInstanceOf[this.type]
}
class HellaCacheResp extends Bundle {
class HellaCacheResp(implicit conf: DCacheConfig) extends Bundle {
val miss = Bool()
val nack = Bool()
val replay = Bool()
val typ = Bits(width = 3)
val data = Bits(width = 64)
val data_subword = Bits(width = 64)
val tag = Bits(width = DCACHE_TAG_BITS)
val data = Bits(width = conf.databits)
val data_subword = Bits(width = conf.databits)
val tag = Bits(width = conf.reqtagbits)
override def clone = new HellaCacheResp().asInstanceOf[this.type]
}
class AlignmentExceptions extends Bundle {
@ -743,29 +742,27 @@ class HellaCacheExceptions extends Bundle {
}
// interface between D$ and processor/DTLB
class ioHellaCache extends Bundle {
class ioHellaCache(implicit conf: DCacheConfig) extends Bundle {
val req = (new FIFOIO){ new HellaCacheReq }
val resp = (new PipeIO){ new HellaCacheResp }.flip
val xcpt = (new HellaCacheExceptions).asInput
}
class HellaCache(implicit conf: RocketConfiguration) extends Component {
class HellaCache(implicit conf: DCacheConfig) extends Component {
val io = new Bundle {
val cpu = (new ioHellaCache).flip
val mem = new ioTileLink
}
val lines = 1 << IDX_BITS
val addrbits = PADDR_BITS
val indexbits = IDX_BITS
val offsetbits = OFFSET_BITS
val tagmsb = PADDR_BITS-1
val taglsb = indexbits+offsetbits
val lines = 1 << conf.idxbits
val indexbits = conf.idxbits
val tagmsb = conf.paddrbits-1
val taglsb = indexbits+conf.offbits
val tagbits = tagmsb-taglsb+1
val indexmsb = taglsb-1
val indexlsb = offsetbits
val indexlsb = conf.offbits
val offsetmsb = indexlsb-1
val offsetlsb = log2Up(CPU_DATA_BITS/8)
val offsetlsb = log2Up(conf.databytes)
val ramindexlsb = log2Up(MEM_DATA_BITS/8)
val early_nack = Reg { Bool() }
@ -821,9 +818,9 @@ class HellaCache(implicit conf: RocketConfiguration) extends Component {
r_cpu_req_tag := io.cpu.req.bits.tag
}
when (prober.io.meta_req.valid) {
r_cpu_req_idx := Cat(prober.io.meta_req.bits.data.tag, prober.io.meta_req.bits.idx, mshr.io.data_req.bits.offset)(PGIDX_BITS-1,0)
r_cpu_req_idx := Cat(prober.io.meta_req.bits.data.tag, prober.io.meta_req.bits.idx, mshr.io.data_req.bits.offset)(conf.pgidxbits-1,0)
}
when (replay_amo_val) {
when (mshr.io.data_req.valid) {
r_cpu_req_idx := Cat(mshr.io.data_req.bits.idx, mshr.io.data_req.bits.offset)
r_cpu_req_cmd := mshr.io.data_req.bits.cmd
r_cpu_req_type := mshr.io.data_req.bits.typ
@ -860,17 +857,17 @@ class HellaCache(implicit conf: RocketConfiguration) extends Component {
meta_arb.io.in(3).valid := io.cpu.req.valid
meta_arb.io.in(3).bits.idx := io.cpu.req.bits.idx(indexmsb,indexlsb)
meta_arb.io.in(3).bits.rw := Bool(false)
meta_arb.io.in(3).bits.way_en := ~UFix(0, NWAYS)
meta_arb.io.in(3).bits.way_en := Fix(-1)
val early_tag_nack = !meta_arb.io.in(3).ready
val cpu_req_ppn = Mux(prober.io.mshr_req.valid, prober.io.addr >> UFix(PGIDX_BITS-OFFSET_BITS), io.cpu.req.bits.ppn)
val cpu_req_ppn = Mux(prober.io.mshr_req.valid, prober.io.addr >> UFix(conf.pgidxbits-conf.offbits), io.cpu.req.bits.ppn)
val cpu_req_tag = Cat(cpu_req_ppn, r_cpu_req_idx)(tagmsb,taglsb)
val tag_match_arr = (0 until NWAYS).map( w => conf.co.isValid(meta.io.resp(w).state) && (meta.io.resp(w).tag === cpu_req_tag))
val tag_match_arr = (0 until conf.ways).map( w => conf.co.isValid(meta.io.resp(w).state) && (meta.io.resp(w).tag === cpu_req_tag))
val tag_match = Cat(Bits(0),tag_match_arr:_*).orR
val tag_match_way_oh = Cat(Bits(0),tag_match_arr.reverse:_*)(NWAYS-1, 0) //TODO: use Vec
val tag_hit_arr = (0 until NWAYS).map( w => conf.co.isHit(r_cpu_req_cmd, meta.io.resp(w).state) && (meta.io.resp(w).tag === cpu_req_tag))
val tag_match_way_oh = Cat(Bits(0),tag_match_arr.reverse:_*)(conf.ways-1, 0) //TODO: use Vec
val tag_hit_arr = (0 until conf.ways).map( w => conf.co.isHit(r_cpu_req_cmd, meta.io.resp(w).state) && (meta.io.resp(w).tag === cpu_req_tag))
val tag_hit = Cat(Bits(0),tag_hit_arr:_*).orR
val meta_resp_way_oh = Mux(meta.io.way_en === ~UFix(0, NWAYS), tag_match_way_oh, meta.io.way_en)
val data_resp_way_oh = Mux(data.io.way_en === ~UFix(0, NWAYS), tag_match_way_oh, data.io.way_en)
val meta_resp_way_oh = Mux(meta.io.way_en.andR, tag_match_way_oh, meta.io.way_en)
val data_resp_way_oh = Mux(data.io.way_en.andR, tag_match_way_oh, data.io.way_en)
val meta_resp_mux = Mux1H(meta_resp_way_oh, meta.io.resp)
val data_resp_mux = Mux1H(data_resp_way_oh, data.io.resp)
@ -881,9 +878,8 @@ class HellaCache(implicit conf: RocketConfiguration) extends Component {
wb.io.probe_rep_data <> io.mem.probe_rep_data
// replacement policy
val replacer = new RandomReplacementWayGen()
replacer.io.way_en := ~UFix(0, NWAYS)
val replaced_way_oh = Mux(flusher.io.mshr_req.valid, r_way_oh, UFixToOH(replacer.io.way_id, NWAYS))
val replacer = new RandomReplacement
val replaced_way_oh = Mux(flusher.io.mshr_req.valid, r_way_oh, UFixToOH(replacer.way))
val meta_wb_mux = Mux1H(replaced_way_oh, meta.io.resp)
// refill response
@ -900,8 +896,8 @@ class HellaCache(implicit conf: RocketConfiguration) extends Component {
data_arb.io.in(4).bits.idx := io.cpu.req.bits.idx(indexmsb,indexlsb)
data_arb.io.in(4).bits.rw := Bool(false)
data_arb.io.in(4).valid := io.cpu.req.valid && req_read
data_arb.io.in(4).bits.way_en := ~UFix(0, NWAYS) // intiate load on all ways, mux after tag check
val early_load_nack = req_read && !data_arb.io.in(4).ready
data_arb.io.in(4).bits.way_en := Fix(-1) // intiate load on all ways, mux after tag check
val early_load_nack = !data_arb.io.in(4).ready
// store hits and AMO hits and misses use a pending store register.
// we nack new stores if a pending store can't retire for some reason.
@ -963,7 +959,7 @@ class HellaCache(implicit conf: RocketConfiguration) extends Component {
mshr.io.mem_abort.bits := io.mem.xact_abort.bits
io.mem.xact_abort.ready := Bool(true)
mshr.io.meta_req <> meta_arb.io.in(1)
replacer.io.pick_new_way := mshr.io.req.valid && mshr.io.req.ready
when (mshr.io.req.fire()) { replacer.miss }
// replays
val replay = mshr.io.data_req.bits
@ -992,13 +988,11 @@ class HellaCache(implicit conf: RocketConfiguration) extends Component {
// store write mask generation.
// assumes store replays are higher-priority than pending stores.
val maskgen = new StoreMaskGen
val store_offset = Mux(!replay_fire, p_store_idx(offsetmsb,0), replay.offset)
maskgen.io.typ := Mux(!replay_fire, p_store_type, replay.typ)
maskgen.io.addr := store_offset(offsetlsb-1,0)
val store_wmask_wide = maskgen.io.wmask << Cat(store_offset(ramindexlsb-1,offsetlsb), Bits(0, log2Up(CPU_DATA_BITS/8))).toUFix
val store_type = Mux(!replay_fire, p_store_type, replay.typ)
val store_wmask_wide = StoreGen(store_type, store_offset, Bits(0)).mask << Cat(store_offset(ramindexlsb-1,offsetlsb), Bits(0, log2Up(conf.databytes))).toUFix
val store_data = Mux(!replay_fire, p_store_data, replay.data)
val store_data_wide = Fill(MEM_DATA_BITS/CPU_DATA_BITS, store_data)
val store_data_wide = Fill(MEM_DATA_BITS/conf.databits, store_data)
data_arb.io.in(1).bits.data := store_data_wide
data_arb.io.in(1).bits.wmask := store_wmask_wide
data_arb.io.in(2).bits.data := store_data_wide
@ -1006,15 +1000,12 @@ class HellaCache(implicit conf: RocketConfiguration) extends Component {
// load data subword mux/sign extension.
// subword loads are delayed by one cycle.
val loadgen = new LoadDataGen
val loadgen_use_replay = Reg(replay_fire)
loadgen.io.typ := Mux(loadgen_use_replay, Reg(replay.typ), r_cpu_req_type)
loadgen.io.addr := Mux(loadgen_use_replay, Reg(replay.offset), r_cpu_req_idx)(ramindexlsb-1,0)
loadgen.io.din := data_resp_mux
val loadgen_data = data_resp_mux >> Cat(r_cpu_req_idx(log2Up(MEM_DATA_BITS/8)-1,3), Bits(0,6))
val loadgen = LoadGen(r_cpu_req_type, r_cpu_req_idx, loadgen_data)
amoalu.io.cmd := p_store_cmd
amoalu.io.typ := p_store_type
amoalu.io.lhs := loadgen.io.r_dout.toUFix
amoalu.io.lhs := Reg(loadgen.word).toUFix
amoalu.io.rhs := p_store_data.toUFix
early_nack := early_tag_nack || early_load_nack || r_cpu_req_val && r_req_amo || replay_amo_val || r_replay_amo
@ -1036,9 +1027,9 @@ class HellaCache(implicit conf: RocketConfiguration) extends Component {
io.cpu.resp.bits.replay := mshr.io.cpu_resp_val
io.cpu.resp.bits.miss := r_cpu_req_val_ && (!tag_hit || mshr.io.secondary_miss) && r_req_read
io.cpu.resp.bits.tag := Mux(mshr.io.cpu_resp_val, mshr.io.cpu_resp_tag, r_cpu_req_tag)
io.cpu.resp.bits.typ := loadgen.io.typ
io.cpu.resp.bits.data := loadgen.io.dout
io.cpu.resp.bits.data_subword := loadgen.io.r_dout_subword
io.cpu.resp.bits.typ := r_cpu_req_type
io.cpu.resp.bits.data := loadgen.word
io.cpu.resp.bits.data_subword := Reg(loadgen.byte)
val xact_init_arb = (new Arbiter(2)) { new TransactionInit }
xact_init_arb.io.in(0) <> wb.io.mem_req