提交 e4e77596 编写于 作者: Y Yinan Xu

Merge branch 'dev-soc' of github.com:RISCVERS/XiangShan into dev-soc

......@@ -23,6 +23,7 @@ case class DCacheParameters(
nMissEntries: Int = 1,
nLoadMissEntries: Int = 1,
nStoreMissEntries: Int = 1,
nMiscMissEntries: Int = 1,
nMMIOEntries: Int = 1,
nSDQ: Int = 17,
nRPQ: Int = 16,
......@@ -75,8 +76,13 @@ trait HasDCacheParameters extends HasL1CacheParameters {
def missQueueEntryIdWidth = log2Up(cfg.nMissEntries)
def loadMissQueueEntryIdWidth = log2Up(cfg.nLoadMissEntries)
def storeMissQueueEntryIdWidth = log2Up(cfg.nStoreMissEntries)
def clientMissQueueEntryIdWidth = max(loadMissQueueEntryIdWidth, storeMissQueueEntryIdWidth)
def nClientMissQueues = 2
def miscMissQueueEntryIdWidth = log2Up(cfg.nMiscMissEntries)
def clientMissQueueEntryIdWidth = max(
max(loadMissQueueEntryIdWidth,
storeMissQueueEntryIdWidth),
miscMissQueueEntryIdWidth)
def nClientMissQueues = 3
def clientIdWidth = log2Up(nClientMissQueues)
def missQueueClientIdWidth = clientIdWidth + clientMissQueueEntryIdWidth
def clientIdMSB = missQueueClientIdWidth - 1
......
......@@ -69,13 +69,15 @@ class DCacheStoreIO extends DCacheBundle
}
class DCacheToLsuIO extends DCacheBundle {
val load = Vec(LoadPipelineWidth, Flipped(new DCacheLoadIO)) // for speculative load
val lsroq = Flipped(new DCacheLoadIO) // lsroq load/store
val store = Flipped(new DCacheStoreIO) // for sbuffer
val load = Vec(LoadPipelineWidth, Flipped(new DCacheLoadIO)) // for speculative load
val lsroq = Flipped(new DCacheLoadIO) // lsroq load/store
val store = Flipped(new DCacheStoreIO) // for sbuffer
val misc = Flipped(new DCacheLoadIO) // misc reqs
}
class DCacheIO extends DCacheBundle {
val lsu = new DCacheToLsuIO
val ptw = Flipped(new DCacheLoadIO)
val bus = new TLCached(cfg.busParams)
}
......@@ -92,8 +94,10 @@ class DCache extends DCacheModule {
// core modules
val ldu = Seq.fill(LoadPipelineWidth) { Module(new LoadPipe) }
val stu = Module(new StorePipe)
val misc = Module(new MiscPipe)
val loadMissQueue = Module(new LoadMissQueue)
val storeMissQueue = Module(new StoreMissQueue)
val miscMissQueue = Module(new MiscMissQueue)
val missQueue = Module(new MissQueue)
val wb = Module(new WritebackUnit)
......@@ -113,11 +117,13 @@ class DCache extends DCacheModule {
// To simplify port arbitration
// MissQueue, Prober and StorePipe all use port 0
val MetaReadPortCount = 4
// if contention got severe, considering load balancing on two ports?
val MetaReadPortCount = 5
val MissQueueMetaReadPort = 0
val ProberMetaReadPort = 1
val StorePipeMetaReadPort = 2
val LoadPipeMetaReadPort = 3
val MiscPipeMetaReadPort = 4
val metaReadArb = Module(new Arbiter(new L1MetaReadReq, MetaReadPortCount))
......@@ -126,6 +132,7 @@ class DCache extends DCacheModule {
metaReadArb.io.in(ProberMetaReadPort).bits := DontCare
metaReadArb.io.in(StorePipeMetaReadPort) <> stu.io.meta_read
metaReadArb.io.in(LoadPipeMetaReadPort) <> ldu(0).io.meta_read
metaReadArb.io.in(MiscPipeMetaReadPort) <> misc.io.meta_read
metaArray.io.read(0) <> metaReadArb.io.out
......@@ -133,6 +140,7 @@ class DCache extends DCacheModule {
// metaArray.io.resp(0) <> prober.io.meta_resp
metaArray.io.resp(0) <> stu.io.meta_resp
metaArray.io.resp(0) <> ldu(0).io.meta_resp
metaArray.io.resp(0) <> misc.io.meta_resp
for (w <- 1 until LoadPipelineWidth) {
metaArray.io.read(w) <> ldu(w).io.meta_read
......@@ -140,34 +148,39 @@ class DCache extends DCacheModule {
}
//----------------------------------------
// meta array
val DataWritePortCount = 2
val MissQueueDataWritePort = 0
val StorePipeDataWritePort = 1
// data array
val DataWritePortCount = 3
val StorePipeDataWritePort = 0
val MissQueueDataWritePort = 1
val MiscPipeDataWritePort = 2
val dataWriteArb = Module(new Arbiter(new L1DataWriteReq, DataWritePortCount))
dataWriteArb.io.in(MissQueueDataWritePort) <> missQueue.io.refill
dataWriteArb.io.in(StorePipeDataWritePort) <> stu.io.data_write
dataWriteArb.io.in(MissQueueDataWritePort) <> missQueue.io.refill
dataWriteArb.io.in(MiscPipeDataWritePort) <> misc.io.data_write
dataArray.io.write <> dataWriteArb.io.out
// To simplify port arbitration
// WritebackUnit and StorePipe use port 0
val DataReadPortCount = 3
val DataReadPortCount = 4
val WritebackDataReadPort = 0
val StorePipeDataReadPort = 1
val LoadPipeDataReadPort = 2
val MiscPipeDataReadPort = 3
val dataReadArb = Module(new Arbiter(new L1DataReadReq, DataReadPortCount))
dataReadArb.io.in(WritebackDataReadPort) <> wb.io.data_req
dataReadArb.io.in(StorePipeDataReadPort) <> stu.io.data_read
dataReadArb.io.in(MiscPipeDataReadPort) <> misc.io.data_read
dataReadArb.io.in(LoadPipeDataReadPort) <> ldu(0).io.data_read
dataArray.io.read(0) <> dataReadArb.io.out
dataArray.io.resp(0) <> wb.io.data_resp
dataArray.io.resp(0) <> stu.io.data_resp
dataArray.io.resp(0) <> misc.io.data_resp
dataArray.io.resp(0) <> ldu(0).io.data_resp
for (w <- 1 until LoadPipelineWidth) {
......@@ -230,32 +243,102 @@ class DCache extends DCacheModule {
block_decoupled(storeMissQueue.io.replay.req, stu.io.lsu.req, store_block && !storeMissQueue.io.replay.req.bits.meta.replay)
storeMissQueue.io.replay.resp <> stu.io.lsu.resp
//----------------------------------------
// misc pipe
miscMissQueue.io.replay <> misc.io.lsu
val miscClientIdWidth = 1
val lsuMiscClientId = 0.U(miscClientIdWidth.W)
val ptwMiscClientId = 1.U(miscClientIdWidth.W)
val miscClientIdMSB = reqIdWidth - 1
val miscClientIdLSB = reqIdWidth - miscClientIdWidth
// Request
val miscReqArb = Module(new Arbiter(new DCacheWordReq, 2))
val miscReq = miscMissQueue.io.lsu.req
val lsuMiscReq = io.lsu.misc.req
val ptwMiscReq = io.ptw.req
miscReqArb.io.in(0).valid := lsuMiscReq.valid
lsuMiscReq.ready := miscReqArb.io.in(0).ready
miscReqArb.io.in(0).bits := lsuMiscReq.bits
miscReqArb.io.in(0).bits.meta.id := Cat(lsuMiscClientId,
lsuMiscReq.bits.meta.id(miscClientIdLSB - 1, 0))
miscReqArb.io.in(1).valid := ptwMiscReq.valid
ptwMiscReq.ready := miscReqArb.io.in(1).ready
miscReqArb.io.in(1).bits := ptwMiscReq.bits
miscReqArb.io.in(1).bits.meta.id := Cat(ptwMiscClientId,
ptwMiscReq.bits.meta.id(miscClientIdLSB - 1, 0))
val misc_block = block_misc(miscReqArb.io.out.bits.addr)
block_decoupled(miscReqArb.io.out, miscReq, misc_block)
// Response
val miscResp = miscMissQueue.io.lsu.resp
val lsuMiscResp = io.lsu.misc.resp
val ptwMiscResp = io.ptw.resp
miscResp.ready := false.B
val miscClientId = miscResp.bits.meta.id(miscClientIdMSB, miscClientIdLSB)
val isLsuMiscResp = miscClientId === lsuMiscClientId
lsuMiscResp.valid := miscResp.valid && isLsuMiscResp
lsuMiscResp.bits := miscResp.bits
lsuMiscResp.bits.meta.id := miscResp.bits.meta.id(miscClientIdLSB - 1, 0)
when (lsuMiscResp.valid) {
miscResp.ready := lsuMiscResp.ready
}
val isPTWMiscResp = miscClientId === ptwMiscClientId
ptwMiscResp.valid := miscResp.valid && isPTWMiscResp
ptwMiscResp.bits := miscResp.bits
ptwMiscResp.bits.meta.id := miscResp.bits.meta.id(miscClientIdLSB - 1, 0)
when (ptwMiscResp.valid) {
miscResp.ready := ptwMiscResp.ready
}
// some other stuff
miscMissQueue.io.lsu.s1_kill := false.B
assert(!(miscReq.fire() && miscReq.bits.meta.replay),
"Misc should not replay requests")
assert(!io.lsu.misc.s1_kill, "Lsroq should never use s1 kill on misc")
assert(!io.ptw.s1_kill, "Lsroq should never use s1 kill on misc")
//----------------------------------------
// miss queue
val loadMissQueueClientId = 0.U(clientIdWidth.W)
val loadMissQueueClientId = 0.U(clientIdWidth.W)
val storeMissQueueClientId = 1.U(clientIdWidth.W)
val miscMissQueueClientId = 2.U(clientIdWidth.W)
// Request
val missReqArb = Module(new Arbiter(new MissReq, 2))
val missReqArb = Module(new Arbiter(new MissReq, 3))
val missReq = missQueue.io.req
val loadMissReq = loadMissQueue.io.miss_req
val storeMissReq = storeMissQueue.io.miss_req
val miscMissReq = miscMissQueue.io.miss_req
missReqArb.io.in(0).valid := loadMissReq.valid
loadMissReq.ready := missReqArb.io.in(0).ready
missReqArb.io.in(0).bits.cmd := loadMissReq.bits.cmd
missReqArb.io.in(0).bits.addr := loadMissReq.bits.addr
missReqArb.io.in(0).bits := loadMissReq.bits
missReqArb.io.in(0).bits.client_id := Cat(loadMissQueueClientId,
loadMissReq.bits.client_id(entryIdMSB, entryIdLSB))
missReqArb.io.in(1).valid := storeMissReq.valid
storeMissReq.ready := missReqArb.io.in(1).ready
missReqArb.io.in(1).bits.cmd := storeMissReq.bits.cmd
missReqArb.io.in(1).bits.addr := storeMissReq.bits.addr
missReqArb.io.in(1).bits := storeMissReq.bits
missReqArb.io.in(1).bits.client_id := Cat(storeMissQueueClientId,
storeMissReq.bits.client_id(entryIdMSB, entryIdLSB))
missReqArb.io.in(2).valid := miscMissReq.valid
miscMissReq.ready := missReqArb.io.in(2).ready
missReqArb.io.in(2).bits := miscMissReq.bits
missReqArb.io.in(2).bits.client_id := Cat(miscMissQueueClientId,
miscMissReq.bits.client_id(entryIdMSB, entryIdLSB))
val miss_block = block_miss(missReqArb.io.out.bits.addr)
block_decoupled(missReqArb.io.out, missReq, miss_block)
......@@ -263,6 +346,7 @@ class DCache extends DCacheModule {
val missResp = missQueue.io.resp
val loadMissResp = loadMissQueue.io.miss_resp
val storeMissResp = storeMissQueue.io.miss_resp
val miscMissResp = miscMissQueue.io.miss_resp
val clientId = missResp.bits.client_id(clientIdMSB, clientIdLSB)
......@@ -276,12 +360,18 @@ class DCache extends DCacheModule {
storeMissResp.bits.entry_id := missResp.bits.entry_id
storeMissResp.bits.client_id := missResp.bits.client_id(entryIdMSB, entryIdLSB)
val isMiscMissResp = clientId === miscMissQueueClientId
miscMissResp.valid := missResp.valid && isMiscMissResp
miscMissResp.bits.entry_id := missResp.bits.entry_id
miscMissResp.bits.client_id := missResp.bits.client_id(entryIdMSB, entryIdLSB)
// Finish
val missFinish = missQueue.io.finish
val loadMissFinish = loadMissQueue.io.miss_finish
val storeMissFinish = storeMissQueue.io.miss_finish
val miscMissFinish = miscMissQueue.io.miss_finish
val missFinishArb = Module(new Arbiter(new MissFinish, 2))
val missFinishArb = Module(new Arbiter(new MissFinish, 3))
missFinishArb.io.in(0).valid := loadMissFinish.valid
loadMissFinish.ready := missFinishArb.io.in(0).ready
missFinishArb.io.in(0).bits.entry_id := loadMissFinish.bits.entry_id
......@@ -294,6 +384,12 @@ class DCache extends DCacheModule {
missFinishArb.io.in(1).bits.client_id := Cat(storeMissQueueClientId,
storeMissFinish.bits.client_id(entryIdMSB, entryIdLSB))
missFinishArb.io.in(2).valid := miscMissFinish.valid
miscMissFinish.ready := missFinishArb.io.in(2).ready
missFinishArb.io.in(2).bits.entry_id := miscMissFinish.bits.entry_id
missFinishArb.io.in(2).bits.client_id := Cat(miscMissQueueClientId,
miscMissFinish.bits.client_id(entryIdMSB, entryIdLSB))
missFinish <> missFinishArb.io.out
// tilelink stuff
......@@ -332,26 +428,44 @@ class DCache extends DCacheModule {
val store_addr_matches = VecInit(stu.io.inflight_req_block_addrs map (entry => entry.valid && entry.bits === get_block_addr(addr)))
val store_addr_match = store_addr_matches.reduce(_||_)
val misc_addr_matches = VecInit(misc.io.inflight_req_block_addrs map (entry => entry.valid && entry.bits === get_block_addr(addr)))
val misc_addr_match = misc_addr_matches.reduce(_||_)
val miss_idx_matches = VecInit(missQueue.io.inflight_req_idxes map (entry => entry.valid && entry.bits === get_idx(addr)))
val miss_idx_match = miss_idx_matches.reduce(_||_)
store_addr_match || miss_idx_match
store_addr_match || misc_addr_match || miss_idx_match
}
def block_store(addr: UInt) = {
val misc_addr_matches = VecInit(misc.io.inflight_req_block_addrs map (entry => entry.valid && entry.bits === get_block_addr(addr)))
val misc_addr_match = misc_addr_matches.reduce(_||_)
val miss_idx_matches = VecInit(missQueue.io.inflight_req_idxes map (entry => entry.valid && entry.bits === get_idx(addr)))
val miss_idx_match = miss_idx_matches.reduce(_||_)
miss_idx_match
misc_addr_match || miss_idx_match
}
def block_misc(addr: UInt) = {
val store_addr_matches = VecInit(stu.io.inflight_req_block_addrs map (entry => entry.valid && entry.bits === get_block_addr(addr)))
val store_addr_match = store_addr_matches.reduce(_||_)
val miss_idx_matches = VecInit(missQueue.io.inflight_req_idxes map (entry => entry.valid && entry.bits === get_idx(addr)))
val miss_idx_match = miss_idx_matches.reduce(_||_)
store_addr_match || miss_idx_match
}
def block_miss(addr: UInt) = {
val store_idx_matches = VecInit(stu.io.inflight_req_idxes map (entry => entry.valid && entry.bits === get_idx(addr)))
val store_idx_match = store_idx_matches.reduce(_||_)
val misc_idx_matches = VecInit(misc.io.inflight_req_idxes map (entry => entry.valid && entry.bits === get_idx(addr)))
val misc_idx_match = misc_idx_matches.reduce(_||_)
val miss_idx_matches = VecInit(missQueue.io.inflight_req_idxes map (entry => entry.valid && entry.bits === get_idx(addr)))
val miss_idx_match = miss_idx_matches.reduce(_||_)
store_idx_match || miss_idx_match
store_idx_match || misc_idx_match || miss_idx_match
}
def block_decoupled[T <: Data](source: DecoupledIO[T], sink: DecoupledIO[T], block_signal: Bool) = {
......
package xiangshan.cache
import chisel3._
import chisel3.util._
import utils.XSDebug
// this is a traditional cache pipeline:
// it handles load/store/amo/lr,sc
class MiscPipe extends DCacheModule
{
val io = IO(new DCacheBundle{
val lsu = Flipped(new DCacheLoadIO)
val data_read = DecoupledIO(new L1DataReadReq)
val data_resp = Input(Vec(nWays, Vec(refillCycles, Bits(encRowBits.W))))
val data_write = DecoupledIO(new L1DataWriteReq)
val meta_read = DecoupledIO(new L1MetaReadReq)
val meta_resp = Input(Vec(nWays, new L1Metadata))
val inflight_req_idxes = Output(Vec(3, Valid(UInt())))
val inflight_req_block_addrs = Output(Vec(3, Valid(UInt())))
})
// LSU requests
io.lsu.req.ready := io.meta_read.ready && io.data_read.ready
io.meta_read.valid := io.lsu.req.valid
io.data_read.valid := io.lsu.req.valid
val meta_read = io.meta_read.bits
val data_read = io.data_read.bits
// Tag read for new requests
meta_read.idx := get_idx(io.lsu.req.bits.addr)
meta_read.way_en := ~0.U(nWays.W)
meta_read.tag := DontCare
// Data read for new requests
data_read.addr := io.lsu.req.bits.addr
data_read.way_en := ~0.U(nWays.W)
// only needs to read the specific beat
data_read.rmask := UIntToOH(get_beat(io.lsu.req.bits.addr))
// Pipeline
// stage 0
val s0_valid = io.lsu.req.fire()
val s0_req = io.lsu.req.bits
dump_pipeline_reqs("MiscPipe s0", s0_valid, s0_req)
// stage 1
val s1_req = RegNext(s0_req)
val s1_valid = RegNext(s0_valid, init = false.B)
val s1_addr = s1_req.addr
val s1_nack = false.B
dump_pipeline_reqs("MiscPipe s1", s1_valid, s1_req)
// tag check
val meta_resp = io.meta_resp
def wayMap[T <: Data](f: Int => T) = VecInit((0 until nWays).map(f))
val s1_tag_eq_way = wayMap((w: Int) => meta_resp(w).tag === (get_tag(s1_addr))).asUInt
val s1_tag_match_way = wayMap((w: Int) => s1_tag_eq_way(w) && meta_resp(w).coh.isValid()).asUInt
// stage 2
val s2_req = RegNext(s1_req)
val s2_valid = RegNext(s1_valid && !io.lsu.s1_kill, init = false.B)
dump_pipeline_reqs("MiscPipe s2", s2_valid, s2_req)
val s2_tag_match_way = RegNext(s1_tag_match_way)
val s2_tag_match = s2_tag_match_way.orR
val s2_hit_state = Mux1H(s2_tag_match_way, wayMap((w: Int) => RegNext(meta_resp(w).coh)))
val s2_has_permission = s2_hit_state.onAccess(s2_req.cmd)._1
val s2_new_hit_state = s2_hit_state.onAccess(s2_req.cmd)._3
// we not only need permissions
// we also require that state does not change on hit
// thus we require new_hit_state === old_hit_state
//
// If state changes on hit,
// we should treat it as not hit, and let mshr deal with it,
// since we can not write meta data on the main pipeline.
// It's possible that we had permission but state changes on hit:
// eg: write to exclusive but clean block
val s2_hit = s2_tag_match && s2_has_permission && s2_hit_state === s2_new_hit_state
val s2_nack = Wire(Bool())
val s2_data = Wire(Vec(nWays, UInt(encRowBits.W)))
val data_resp = io.data_resp
for (w <- 0 until nWays) {
s2_data(w) := data_resp(w)(get_beat(s2_req.addr))
}
val s2_data_muxed = Mux1H(s2_tag_match_way, s2_data)
// the index of word in a row, in case rowBits != wordBits
val s2_word_idx = if (rowWords == 1) 0.U else s2_req.addr(log2Up(rowWords*wordBytes)-1, log2Up(wordBytes))
val s2_nack_hit = RegNext(s1_nack)
// Can't allocate MSHR for same set currently being written back
// the same set is busy
val s2_nack_set_busy = s2_valid && false.B
// Bank conflict on data arrays
val s2_nack_data = false.B
s2_nack := s2_nack_hit || s2_nack_set_busy || s2_nack_data
// only dump these signals when they are actually valid
dump_pipeline_valids("MiscPipe s2", "s2_hit", s2_valid && s2_hit)
dump_pipeline_valids("MiscPipe s2", "s2_nack", s2_valid && s2_nack)
dump_pipeline_valids("MiscPipe s2", "s2_nack_hit", s2_valid && s2_nack_hit)
dump_pipeline_valids("MiscPipe s2", "s2_nack_set_busy", s2_valid && s2_nack_set_busy)
// load data gen
val s2_data_word = s2_data_muxed >> Cat(s2_word_idx, 0.U(log2Ceil(wordBits).W))
val resp = Wire(ValidIO(new DCacheResp))
resp.valid := s2_valid
resp.bits.data := s2_data_word
resp.bits.meta := s2_req.meta
resp.bits.miss := !s2_hit
resp.bits.nack := s2_nack
io.lsu.resp.valid := resp.valid
io.lsu.resp.bits := resp.bits
assert(!(resp.valid && !io.lsu.resp.ready))
when (resp.valid) {
XSDebug(s"MiscPipe resp: data: %x id: %d replay: %b miss: %b nack: %b\n",
resp.bits.data, resp.bits.meta.id, resp.bits.meta.replay, resp.bits.miss, resp.bits.nack)
}
// assign default value to output signals
io.data_write.valid := false.B
io.data_write.bits := DontCare
io.inflight_req_idxes(0).valid := io.lsu.req.valid
io.inflight_req_idxes(1).valid := s1_valid
io.inflight_req_idxes(2).valid := s2_valid
io.inflight_req_idxes(0).bits := get_idx(s0_req.addr)
io.inflight_req_idxes(1).bits := get_idx(s1_req.addr)
io.inflight_req_idxes(2).bits := get_idx(s2_req.addr)
io.inflight_req_block_addrs(0).valid := io.lsu.req.valid
io.inflight_req_block_addrs(1).valid := s1_valid
io.inflight_req_block_addrs(2).valid := s2_valid
io.inflight_req_block_addrs(0).bits := get_block_addr(s0_req.addr)
io.inflight_req_block_addrs(1).bits := get_block_addr(s1_req.addr)
io.inflight_req_block_addrs(2).bits := get_block_addr(s2_req.addr)
// -------
// Debug logging functions
def dump_pipeline_reqs(pipeline_stage_name: String, valid: Bool,
req: DCacheWordReq ) = {
when (valid) {
XSDebug(s"$pipeline_stage_name cmd: %x addr: %x data: %x mask: %x id: %d replay: %b\n",
req.cmd, req.addr, req.data, req.mask, req.meta.id, req.meta.replay)
}
}
def dump_pipeline_valids(pipeline_stage_name: String, signal_name: String, valid: Bool) = {
when (valid) {
XSDebug(s"$pipeline_stage_name $signal_name\n")
}
}
}
package xiangshan.cache
import chisel3._
import chisel3.util._
import utils.XSDebug
// wraps around MiscPipe
// when requests misse, send miss req to missQueue and replays reqs
class MiscMissQueue extends DCacheModule
{
val io = IO(new DCacheBundle {
val lsu = Flipped(new DCacheLoadIO)
val replay = new DCacheLoadIO
val miss_req = DecoupledIO(new MissReq)
val miss_resp = Flipped(ValidIO(new MissResp))
val miss_finish = DecoupledIO(new MissFinish)
})
val s_invalid :: s_replay_req :: s_replay_resp :: s_resp :: s_miss_req :: s_miss_resp :: s_miss_finish :: Nil = Enum(7)
val state = RegInit(s_invalid)
val id = 0.U
val req = Reg(new DCacheWordReq)
val resp = Reg(new DCacheResp)
val req_block_addr = get_block_addr(req.addr)
val reg_miss_resp = Reg(new MissResp)
// assign default values to output signals
io.lsu.req.ready := state === s_invalid
io.lsu.resp.valid := false.B
io.lsu.resp.bits := DontCare
io.replay.req.valid := false.B
io.replay.req.bits := DontCare
io.replay.resp.ready := false.B
io.replay.s1_kill := false.B
io.miss_req.valid := false.B
io.miss_req.bits := DontCare
io.miss_finish.valid := false.B
io.miss_finish.bits := DontCare
XSDebug("state: %d\n", state)
// --------------------------------------------
// s_invalid: receive requests
when (state === s_invalid) {
when (io.lsu.req.fire()) {
assert(!io.lsu.req.bits.meta.replay)
req := io.lsu.req.bits
state := s_replay_req
}
}
// --------------------------------------------
// replay
when (state === s_replay_req) {
io.replay.req.valid := true.B
io.replay.req.bits := req
when (io.replay.req.fire()) {
state := s_replay_resp
}
}
when (state === s_replay_resp) {
io.replay.resp.ready := true.B
when (io.replay.resp.fire()) {
when (io.replay.resp.bits.miss) {
// replayed reqs should not miss
assert(!req.meta.replay)
when (!req.meta.replay) {
state := s_miss_req
}
} .otherwise {
resp := io.replay.resp.bits
when (!req.meta.replay) {
state := s_resp
} .otherwise {
state := s_miss_finish
}
}
assert(!io.replay.resp.bits.nack)
}
}
// --------------------------------------------
when (state === s_miss_req) {
io.miss_req.valid := true.B
io.miss_req.bits.cmd := req.cmd
io.miss_req.bits.addr := req_block_addr
io.miss_req.bits.client_id := id
when (io.miss_req.fire()) {
state := s_miss_resp
}
}
when (state === s_miss_resp) {
when (io.miss_resp.fire()) {
reg_miss_resp := io.miss_resp.bits
// mark req as replayed req
req.meta.replay := true.B
state := s_replay_req
}
}
when (state === s_miss_finish) {
io.miss_finish.valid := true.B
io.miss_finish.bits.client_id := id
io.miss_finish.bits.entry_id := reg_miss_resp.entry_id
when (io.miss_finish.fire()) {
state := s_resp
}
}
// --------------------------------------------
when (state === s_resp) {
io.lsu.resp.valid := true.B
io.lsu.resp.bits := resp
when (io.lsu.resp.fire()) {
state := s_invalid
}
}
}
......@@ -142,7 +142,7 @@ class StorePipe extends DCacheModule
resp.bits.data, resp.bits.meta.id, resp.bits.meta.replay, resp.bits.miss, resp.bits.nack)
}
io.inflight_req_idxes(0).valid := s0_valid
io.inflight_req_idxes(0).valid := io.lsu.req.valid
io.inflight_req_idxes(1).valid := s1_valid
io.inflight_req_idxes(2).valid := s2_valid
......@@ -150,7 +150,7 @@ class StorePipe extends DCacheModule
io.inflight_req_idxes(1).bits := get_idx(s1_req.addr)
io.inflight_req_idxes(2).bits := get_idx(s2_req.addr)
io.inflight_req_block_addrs(0).valid := s0_valid
io.inflight_req_block_addrs(0).valid := io.lsu.req.valid
io.inflight_req_block_addrs(1).valid := s1_valid
io.inflight_req_block_addrs(2).valid := s2_valid
......
......@@ -132,6 +132,8 @@ class Memend extends XSModule {
dcache.io.bus <> io.mem
uncache.io.bus <> io.mmio
dcache.io.lsu.misc <> DontCare
dcache.io.ptw <> DontCare
// LoadUnit
for (i <- 0 until exuParameters.LduCnt) {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册