Skip to content

Commit

Permalink
ICache: raise AF exception when parity wrong or L2 send corrupt (#1376)
Browse files Browse the repository at this point in the history
* ICache: raise access fault when L2 send corrupt

* ICache: add ECC error connection

* chores: add comments and code clean-up

* ICache: raise AF when Meta/Data Parity wrong

* Update Frontend.scala
  • Loading branch information
jinyue110 authored Dec 20, 2021
1 parent 184d2cf commit 58dbdfc
Show file tree
Hide file tree
Showing 7 changed files with 174 additions and 100 deletions.
5 changes: 2 additions & 3 deletions src/main/scala/xiangshan/frontend/Frontend.scala
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,6 @@ class FrontendImp (outer: Frontend) extends LazyModuleImp(outer)
itlbParams
)

icache.io.fencei := RegNext(io.fencei)

val needFlush = RegNext(io.backend.toFtq.redirect.valid)

Expand Down Expand Up @@ -129,8 +128,8 @@ class FrontendImp (outer: Frontend) extends LazyModuleImp(outer)

instrUncache.io.req <> ifu.io.uncacheInter.toUncache
ifu.io.uncacheInter.fromUncache <> instrUncache.io.resp
instrUncache.io.flush := false.B//icache.io.missQueue.flush
io.error <> DontCare
instrUncache.io.flush := false.B
io.error <> RegNext(RegNext(icache.io.error))

val frontendBubble = PopCount((0 until DecodeWidth).map(i => io.backend.cfVec(i).ready && !ibuffer.io.out(i).valid))
XSPerfAccumulate("FrontendBubble", frontendBubble)
Expand Down
78 changes: 55 additions & 23 deletions src/main/scala/xiangshan/frontend/IFU.scala
Original file line number Diff line number Diff line change
Expand Up @@ -122,11 +122,12 @@ class NewIFU(implicit p: Parameters) extends XSModule
val (preDecoderIn, preDecoderOut) = (preDecoder.io.in, preDecoder.io.out)
val (checkerIn, checkerOut) = (predChecker.io.in, predChecker.io.out)

//---------------------------------------------
// Fetch Stage 1 :
// * Send req to ICache Meta/Data
// * Check whether need 2 line fetch
//---------------------------------------------
/**
******************************************************************************
* IFU Stage 0
* - send cacheline fetch request to ICacheMainPipe
******************************************************************************
*/

val f0_valid = fromFtq.req.valid
val f0_ftq_req = fromFtq.req.bits
Expand Down Expand Up @@ -159,8 +160,20 @@ class NewIFU(implicit p: Parameters) extends XSModule
toICache(1).valid := fromFtq.req.valid && f0_doubleLine && !f0_flush
toICache(1).bits.vaddr := fromFtq.req.bits.fallThruAddr

/** <PERF> f0 fetch bubble */

/** Fetch Stage 1 */
XSPerfAccumulate("fetch_bubble_ftq_not_valid", !f0_valid )
XSPerfAccumulate("fetch_bubble_pipe_stall", f0_valid && toICache(0).ready && toICache(1).ready && !f1_ready )
XSPerfAccumulate("fetch_bubble_sram_0_busy", f0_valid && !toICache(0).ready )
XSPerfAccumulate("fetch_bubble_sram_1_busy", f0_valid && !toICache(1).ready )


/**
******************************************************************************
* IFU Stage 1
* - calculate pc/half_pc/cut_ptr for every instruction
******************************************************************************
*/

val f1_valid = RegInit(false.B)
val f1_ftq_req = RegEnable(next = f0_ftq_req, enable=f0_fire)
Expand All @@ -182,7 +195,17 @@ class NewIFU(implicit p: Parameters) extends XSModule
val f1_cut_ptr = if(HasCExtension) VecInit((0 until PredictWidth + 1).map(i => Cat(0.U(1.W), f1_ftq_req.startAddr(blockOffBits-1, 1)) + i.U ))
else VecInit((0 until PredictWidth).map(i => Cat(0.U(1.W), f1_ftq_req.startAddr(blockOffBits-1, 2)) + i.U ))

/** Fetch Stage 2 */
/**
******************************************************************************
* IFU Stage 2
* - icache response data (latched for pipeline stop)
* - generate exceprion bits for every instruciton (page fault/access fault/mmio)
* - generate predicted instruction range (1 means this instruciton is in this fetch packet)
* - cut data from cachlines to packet instruction code
* - instruction predecode and RVC expand
******************************************************************************
*/

val icacheRespAllValid = WireInit(false.B)

val f2_valid = RegInit(false.B)
Expand Down Expand Up @@ -219,7 +242,6 @@ class NewIFU(implicit p: Parameters) extends XSModule
val f2_pc = RegEnable(next = f1_pc, enable = f1_fire)
val f2_half_snpc = RegEnable(next = f1_half_snpc, enable = f1_fire)
val f2_cut_ptr = RegEnable(next = f1_cut_ptr, enable = f1_fire)
val f2_half_match = VecInit(f2_half_snpc.map(_ === f2_ftq_req.fallThruAddr))


def isNextLine(pc: UInt, startAddr: UInt) = {
Expand All @@ -230,7 +252,6 @@ class NewIFU(implicit p: Parameters) extends XSModule
pc(blockOffBits - 1, 0) === "b111110".U
}

//calculate
val f2_foldpc = VecInit(f2_pc.map(i => XORFold(i(VAddrBits-1,1), MemPredPCWidth)))
val f2_jump_range = Fill(PredictWidth, !f2_ftq_req.ftqOffset.valid) | Fill(PredictWidth, 1.U(1.W)) >> ~f2_ftq_req.ftqOffset.bits
val f2_ftr_range = Fill(PredictWidth, f2_ftq_req.oversize) | Fill(PredictWidth, 1.U(1.W)) >> ~getBasicBlockIdx(f2_ftq_req.fallThruAddr, f2_ftq_req.startAddr)
Expand Down Expand Up @@ -262,24 +283,35 @@ class NewIFU(implicit p: Parameters) extends XSModule
val f2_datas = VecInit((0 until PortNumber).map(i => f2_cache_response_data(i)))
val f2_cut_data = cut( Cat(f2_datas.map(cacheline => cacheline.asUInt ).reverse).asUInt, f2_cut_ptr )

//** predecoder **//
/** predecode (include RVC expander) */
preDecoderIn.data := f2_cut_data
// preDecoderIn.lastHalfMatch := f2_lastHalfMatch
preDecoderIn.frontendTrigger := io.frontendTrigger
preDecoderIn.csrTriggerEnable := io.csrTriggerEnable
preDecoderIn.pc := f2_pc

val f2_expd_instr = preDecoderOut.expInstr
val f2_pd = preDecoderOut.pd
val f2_jump_offset = preDecoderOut.jumpOffset
// val f2_triggered = preDecoderOut.triggered
val f2_hasHalfValid = preDecoderOut.hasHalfValid
val f2_crossPageFault = VecInit((0 until PredictWidth).map(i => isLastInLine(f2_pc(i)) && !f2_except_pf(0) && f2_doubleLine && f2_except_pf(1) && !f2_pd(i).isRVC ))

val predecodeOutValid = WireInit(false.B)


/** Fetch Stage 3 */
/**
******************************************************************************
* IFU Stage 3
* - handle MMIO instruciton
* -send request to Uncache fetch Unit
* -every packet include 1 MMIO instruction
* -MMIO instructions will stop fetch pipeline until commiting from RoB
* -flush to snpc (send ifu_redirect to Ftq)
* - Ibuffer enqueue
* - check predict result in Frontend (jalFault/retFault/notCFIFault/invalidTakenFault/targetFault)
* - handle last half RVI instruction
******************************************************************************
*/

val f3_valid = RegInit(false.B)
val f3_ftq_req = RegEnable(next = f2_ftq_req, enable=f2_fire)
val f3_situation = RegEnable(next = f2_situation, enable=f2_fire)
Expand All @@ -301,7 +333,6 @@ class NewIFU(implicit p: Parameters) extends XSModule
val f3_pf_vec = RegEnable(next = f2_pf_vec , enable = f2_fire)
val f3_pc = RegEnable(next = f2_pc, enable = f2_fire)
val f3_half_snpc = RegEnable(next = f2_half_snpc, enable = f2_fire)
val f3_half_match = RegEnable(next = f2_half_match, enable = f2_fire)
val f3_instr_range = RegEnable(next = f2_instr_range, enable = f2_fire)
val f3_foldpc = RegEnable(next = f2_foldpc, enable = f2_fire)
val f3_crossPageFault = RegEnable(next = f2_crossPageFault, enable = f2_fire)
Expand All @@ -315,9 +346,6 @@ class NewIFU(implicit p: Parameters) extends XSModule
/*** MMIO State Machine***/
val f3_mmio_data = Reg(UInt(maxInstrLen.W))

// val f3_data = if(HasCExtension) Wire(Vec(PredictWidth + 1, UInt(16.W))) else Wire(Vec(PredictWidth, UInt(32.W)))
// f3_data := f3_cut_data

val mmio_idle :: mmio_send_req :: mmio_w_resp :: mmio_resend :: mmio_resend_w_resp :: mmio_wait_commit :: mmio_commited :: Nil = Enum(7)
val mmio_state = RegInit(mmio_idle)

Expand Down Expand Up @@ -416,7 +444,7 @@ class NewIFU(implicit p: Parameters) extends XSModule
checkerIn.pds := f3_pd
checkerIn.pc := f3_pc

/*** process half RVI in the last 2 Bytes ***/
/*** handle half RVI in the last 2 Bytes ***/

def hasLastHalf(idx: UInt) = {
!f3_pd(idx).isRVC && checkerOut.fixedRange(idx) && f3_instr_valid(idx) && !checkerOut.fixedTaken(idx) && !checkerOut.fixedMissPred(idx) && ! f3_req_is_mmio && !f3_ftq_req.oversize
Expand Down Expand Up @@ -515,11 +543,15 @@ class NewIFU(implicit p: Parameters) extends XSModule

mmio_redirect := (f3_req_is_mmio && mmio_state === mmio_wait_commit && RegNext(fromUncache.fire()) && f3_mmio_use_seq_pc)

/* ---------------------------------------------------------------------
* Ftq Write back :
*
* ---------------------------------------------------------------------
*/
/**
******************************************************************************
* IFU Write Back Stage
* - write back predecode information to Ftq to update
* - redirect if found fault prediction
* - redirect if has false hit last half (last PC is not start + 32 Bytes, but in the midle of an notCFI RVI instruction)
******************************************************************************
*/

val wb_valid = RegNext(RegNext(f2_fire && !f2_flush) && !f3_req_is_mmio && !f3_flush)
val wb_ftq_req = RegNext(f3_ftq_req)

Expand Down
29 changes: 8 additions & 21 deletions src/main/scala/xiangshan/frontend/icache/ICache.scala
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,6 @@ class ICacheMetaArray()(implicit p: Parameters) extends ICacheArray
val write = Flipped(DecoupledIO(new ICacheMetaWriteBundle))
val read = Flipped(DecoupledIO(new ICacheReadBundle))
val readResp = Output(new ICacheMetaRespBundle)
val fencei = Input(Bool())
val cacheOp = Flipped(new L1CacheInnerOpIO) // customized cache op port
}}

Expand All @@ -155,6 +154,7 @@ class ICacheMetaArray()(implicit p: Parameters) extends ICacheArray

val bank_0_idx = Mux(port_0_read_0, io.read.bits.vSetIdx(0), io.read.bits.vSetIdx(1))
val bank_1_idx = Mux(port_0_read_1, io.read.bits.vSetIdx(0), io.read.bits.vSetIdx(1))
val bank_idx = Seq(bank_0_idx, bank_1_idx)

val write_bank_0 = io.write.valid && !io.write.bits.bankIdx
val write_bank_1 = io.write.valid && io.write.bits.bankIdx
Expand Down Expand Up @@ -195,31 +195,15 @@ class ICacheMetaArray()(implicit p: Parameters) extends ICacheArray
val read_meta_wrong = read_meta_decoded.map{ way_bits_decoded => way_bits_decoded.error}
val read_meta_corrected = VecInit(read_meta_decoded.map{ way_bits_decoded => way_bits_decoded.corrected})
read_metas(i) := read_meta_corrected.asTypeOf(Vec(nWays,new ICacheMetadata()))
(0 until nWays).map{ w => io.readResp.errors(i)(w) := RegNext(io.read.fire()) && read_meta_wrong(w)}
(0 until nWays).map{ w => io.readResp.errors(i)(w) := read_meta_wrong(w) && RegNext(io.read.fire)}
}

//Parity Encode
val write = io.write.bits
write_meta_bits := cacheParams.tagCode.encode(ICacheMetadata(tag = write.phyTag, coh = write.coh).asUInt)

// when(io.write.valid){
// printf("[time:%d ] idx:%x ptag:%x waymask:%x coh:%x\n", GTimer().asUInt, write.virIdx, write.phyTag, write.waymask, write.coh.asUInt)
// }

val readIdxNext = RegEnable(next = io.read.bits.vSetIdx, enable = io.read.fire())
val validArray = RegInit(0.U((nSets * nWays).W))
val validMetas = VecInit((0 until 2).map{ bank =>
val validMeta = Cat((0 until nWays).map{w => validArray( Cat(readIdxNext(bank), w.U(log2Ceil(nWays).W)) )}.reverse).asUInt
validMeta
})

val wayNum = OHToUInt(io.write.bits.waymask)
val validPtr = Cat(io.write.bits.virIdx, wayNum)
when(io.write.valid){
validArray := validArray.bitSet(validPtr, true.B)
}

when(io.fencei){ validArray := 0.U }

io.readResp.metaData <> DontCare
when(port_0_read_0_reg){
Expand All @@ -234,7 +218,6 @@ class ICacheMetaArray()(implicit p: Parameters) extends ICacheArray
io.readResp.metaData(1) := read_metas(1)
}

(io.readResp.valid zip validMetas).map {case (io, reg) => io := reg.asTypeOf(Vec(nWays,Bool()))}

io.write.ready := true.B
// deal with customized cache op
Expand Down Expand Up @@ -305,6 +288,7 @@ class ICacheDataArray(implicit p: Parameters) extends ICacheArray

val bank_0_idx = Mux(port_0_read_0, io.read.bits.vSetIdx(0), io.read.bits.vSetIdx(1))
val bank_1_idx = Mux(port_0_read_1, io.read.bits.vSetIdx(0), io.read.bits.vSetIdx(1))
val bank_idx = Seq(bank_0_idx, bank_1_idx)

val write_bank_0 = WireInit(io.write.valid && !io.write.bits.bankIdx)
val write_bank_1 = WireInit(io.write.valid && io.write.bits.bankIdx)
Expand Down Expand Up @@ -407,13 +391,13 @@ class ICacheDataArray(implicit p: Parameters) extends ICacheArray

class ICacheIO(implicit p: Parameters) extends ICacheBundle
{
val fencei = Input(Bool())
val stop = Input(Bool())
val csr = new L1CacheToCsrIO
val fetch = Vec(PortNumber, new ICacheMainPipeBundle)
val pmp = Vec(PortNumber, new ICachePMPBundle)
val itlb = Vec(PortNumber, new BlockTlbRequestIO)
val perfInfo = Output(new ICachePerfInfo)
val error = new L1CacheErrorInfo
}

class ICache()(implicit p: Parameters) extends LazyModule with HasICacheParameters {
Expand Down Expand Up @@ -488,7 +472,6 @@ class ICacheImp(outer: ICache) extends LazyModuleImp(outer) with HasICacheParame
bus.e.valid := false.B
bus.e.bits := DontCare

metaArray.io.fencei := io.fencei
bus.a <> missUnit.io.mem_acquire
bus.e <> missUnit.io.mem_finish

Expand All @@ -506,6 +489,10 @@ class ICacheImp(outer: ICache) extends LazyModuleImp(outer) with HasICacheParame
//Probe through bus b
probeQueue.io.mem_probe <> bus.b

//Parity error port
val errors = mainPipe.io.errors ++ Seq(replacePipe.io.error)
io.error <> RegNext(Mux1H(errors.map(e => e.ecc_error.valid -> e)))


/** Block set-conflict request */
val probeReqValid = probeQueue.io.pipe_req.valid
Expand Down
3 changes: 1 addition & 2 deletions src/main/scala/xiangshan/frontend/icache/ICacheBundle.scala
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,7 @@ class ICacheReadBundle(implicit p: Parameters) extends ICacheBundle
class ICacheMetaRespBundle(implicit p: Parameters) extends ICacheBundle
{
val metaData = Vec(2, Vec(nWays, new ICacheMetadata))
val valid = Vec(2, Vec(nWays ,Bool()))
val errors = Vec(2, Vec(nWays ,Bool()))
val errors = Vec(2, Vec(nWays ,Bool() ))

def tags = VecInit(metaData.map(port => VecInit(port.map( way=> way.tag ))))
def cohs = VecInit(metaData.map(port => VecInit(port.map( way=> way.coh ))))
Expand Down
Loading

0 comments on commit 58dbdfc

Please sign in to comment.