From 14804c449b62784116103b94d1514feb6319d9ed Mon Sep 17 00:00:00 2001 From: ngc7331 Date: Fri, 28 Feb 2025 20:54:52 +0800 Subject: [PATCH] refactor(Frontend): rename bundles & reorganize IO with Ifu/Ftq Naming: - I/O: - ICache inner use only: xxxBundle - Other modules use: ICacheXxxBundle, consider move to FrontendBundle.scala - Sram/register: xxxEntry Try avoiding directed Bundle, unless it's req-resp pair Add ICacheToIfuIO & move resp/perf/topdown/icacheReady into it - ICacheIO.toIFU / IFUICacheIO.icacheReady -> ICacheToIfuIO.fetchReady - ICacheIO.perfInfo / NewIFUIO.icachePerfInfo -> ICacheToIfuIO.perf - ICacheMainPipeBundle.topdown.* / IFUICacheIO.topdown* -> ICacheToIfuIO.topdown.* Add IfuToICacheIO & move stall into it - NewIFUIO.icacheStop / ICacheIO.stop -> IfuToICacheIO.stall Add FtqToICacheIO - ICacheIO.fetch -> FtqToICacheIO.fetchReq - ICacheIO.ftqPrefetch / FtqToPrefetchIO -> FtqToICacheIO.prefetchReq Other renames - ICacheIO.softPrefetch -> ICacheIO.softPrefetchReq --- .../scala/xiangshan/frontend/Frontend.scala | 29 +-- .../xiangshan/frontend/FrontendBundle.scala | 35 ++- src/main/scala/xiangshan/frontend/IFU.scala | 21 +- .../scala/xiangshan/frontend/NewFtq.scala | 62 ++--- .../xiangshan/frontend/icache/Bundles.scala | 237 ++++++++++-------- .../frontend/icache/ICacheCtrlUnit.scala | 35 ++- .../frontend/icache/ICacheDataArray.scala | 33 ++- .../xiangshan/frontend/icache/ICacheImp.scala | 113 +++++---- .../frontend/icache/ICacheMSHR.scala | 40 +-- .../frontend/icache/ICacheMainPipe.scala | 134 +++++----- .../frontend/icache/ICacheMetaArray.scala | 94 +++---- .../frontend/icache/ICacheMissUnit.scala | 127 +++++----- .../frontend/icache/ICachePrefetchPipe.scala | 28 +-- .../frontend/icache/ICacheReplacer.scala | 28 +-- ...{WayLookup.scala => ICacheWayLookup.scala} | 34 +-- 15 files changed, 546 insertions(+), 504 deletions(-) rename src/main/scala/xiangshan/frontend/icache/{WayLookup.scala => ICacheWayLookup.scala} (81%) diff --git a/src/main/scala/xiangshan/frontend/Frontend.scala b/src/main/scala/xiangshan/frontend/Frontend.scala index 6f786ff000b..a4d6337a42a 100644 --- a/src/main/scala/xiangshan/frontend/Frontend.scala +++ b/src/main/scala/xiangshan/frontend/Frontend.scala @@ -165,12 +165,12 @@ class FrontendInlinedImp(outer: FrontendInlined) extends LazyModuleImp(outer) val itlbRepeater2 = PTWRepeaterNB(passReady = false, itlbParams.fenceDelay, itlbRepeater1.io.ptw, io.ptw, sfence, tlbCsr) - icache.io.ftqPrefetch <> ftq.io.toPrefetch - icache.io.softPrefetch <> io.softPrefetch + // ICache-Memblock + icache.io.softPrefetchReq <> io.softPrefetch // IFU-Ftq ifu.io.ftqInter.fromFtq <> ftq.io.toIfu - ftq.io.toIfu.req.ready := ifu.io.ftqInter.fromFtq.req.ready && icache.io.fetch.req.ready + ftq.io.toIfu.req.ready := ifu.io.ftqInter.fromFtq.req.ready && icache.io.fromFtq.fetchReq.ready ftq.io.fromIfu <> ifu.io.ftqInter.toFtq bpu.io.ftq_to_bpu <> ftq.io.toBpu @@ -178,22 +178,19 @@ class FrontendInlinedImp(outer: FrontendInlined) extends LazyModuleImp(outer) ftq.io.mmioCommitRead <> ifu.io.mmioCommitRead - // IFU-ICache - icache.io.fetch.req <> ftq.io.toICache.req - ftq.io.toICache.req.ready := ifu.io.ftqInter.fromFtq.req.ready && icache.io.fetch.req.ready + // ICache-Ftq + icache.io.fromFtq <> ftq.io.toICache + // override fetchReq.ready to sync with Ifu + ftq.io.toICache.fetchReq.ready := ifu.io.ftqInter.fromFtq.req.ready && icache.io.fromFtq.fetchReq.ready + icache.io.flush := ftq.io.icacheFlush - ifu.io.icacheInter.resp <> icache.io.fetch.resp - ifu.io.icacheInter.icacheReady := icache.io.toIFU - ifu.io.icacheInter.topdownIcacheMiss := icache.io.fetch.topdownIcacheMiss - ifu.io.icacheInter.topdownItlbMiss := icache.io.fetch.topdownItlbMiss - icache.io.stop := ifu.io.icacheStop - icache.io.flush := ftq.io.icacheFlush - - ifu.io.icachePerfInfo := icache.io.perfInfo + // Ifu-ICache + ifu.io.fromICache <> icache.io.toIfu + ifu.io.toICache <> icache.io.fromIfu + // ICache-Backend icache.io.csr_pf_enable := RegNext(csrCtrl.pf_ctrl.l1I_pf_enable) - - icache.io.fencei := RegNext(io.fencei) + icache.io.fencei := RegNext(io.fencei) // IFU-Ibuffer ifu.io.toIbuffer <> ibuffer.io.in diff --git a/src/main/scala/xiangshan/frontend/FrontendBundle.scala b/src/main/scala/xiangshan/frontend/FrontendBundle.scala index b1e590734fc..931e4b0232d 100644 --- a/src/main/scala/xiangshan/frontend/FrontendBundle.scala +++ b/src/main/scala/xiangshan/frontend/FrontendBundle.scala @@ -78,17 +78,34 @@ class FtqICacheInfo(implicit p: Parameters) extends XSBundle with HasICacheParam } } -class IFUICacheIO(implicit p: Parameters) extends XSBundle with HasICacheParameters { - val icacheReady = Output(Bool()) - val resp = ValidIO(new ICacheMainPipeResp) - val topdownIcacheMiss = Output(Bool()) - val topdownItlbMiss = Output(Bool()) +class FtqToPrefetchBundle(implicit p: Parameters) extends XSBundle { + val req: FtqICacheInfo = new FtqICacheInfo + val backendException: UInt = ExceptionType() } -class FtqToICacheRequestBundle(implicit p: Parameters) extends XSBundle with HasICacheParameters { - val pcMemRead = Vec(5, new FtqICacheInfo) - val readValid = Vec(5, Bool()) - val backendException = Bool() +class FtqToFetchBundle(implicit p: Parameters) extends XSBundle with HasICacheParameters { + val req: Vec[FtqICacheInfo] = Vec(5, new FtqICacheInfo) + val readValid: Vec[Bool] = Vec(5, Bool()) + val isBackendException: Bool = Bool() +} + +class FtqToICacheIO(implicit p: Parameters) extends XSBundle { + // NOTE: req.bits must be prepare in T cycle + // while req.valid is set true in T + 1 cycle + val fetchReq: DecoupledIO[FtqToFetchBundle] = DecoupledIO(new FtqToFetchBundle) + val prefetchReq: DecoupledIO[FtqToPrefetchBundle] = DecoupledIO(new FtqToPrefetchBundle) + val flushFromBpu: BpuFlushInfo = new BpuFlushInfo +} + +class ICacheToIfuIO(implicit p: Parameters) extends XSBundle { + val fetchResp: Valid[ICacheRespBundle] = ValidIO(new ICacheRespBundle) + val topdown: ICacheTopdownInfo = Output(new ICacheTopdownInfo) + val perf: ICachePerfInfo = Output(new ICachePerfInfo) + val fetchReady: Bool = Output(Bool()) +} + +class IfuToICacheIO(implicit p: Parameters) extends XSBundle { + val stall: Bool = Output(Bool()) } class PredecodeWritebackBundle(implicit p: Parameters) extends XSBundle { diff --git a/src/main/scala/xiangshan/frontend/IFU.scala b/src/main/scala/xiangshan/frontend/IFU.scala index 01cc6423831..73c8fbca272 100644 --- a/src/main/scala/xiangshan/frontend/IFU.scala +++ b/src/main/scala/xiangshan/frontend/IFU.scala @@ -69,16 +69,15 @@ class UncacheInterface(implicit p: Parameters) extends XSBundle { class NewIFUIO(implicit p: Parameters) extends XSBundle { val ftqInter = new FtqInterface - val icacheInter = Flipped(new IFUICacheIO) - val icacheStop = Output(Bool()) - val icachePerfInfo = Input(new ICachePerfInfo) + val fromICache = Flipped(new ICacheToIfuIO) + val toICache = new IfuToICacheIO val toIbuffer = Decoupled(new FetchToIBuffer) val toBackend = new IfuToBackendIO val uncacheInter = new UncacheInterface val frontendTrigger = Flipped(new FrontendTdataDistributeIO) val rob_commits = Flipped(Vec(CommitWidth, Valid(new RobCommitInfo))) val iTLBInter = new TlbRequestIO - val pmp = new ICachePMPBundle + val pmp = new PmpCheckBundle val mmioCommitRead = new mmioCommitRead val csr_fsIsOff = Input(Bool()) } @@ -137,7 +136,7 @@ class NewIFU(implicit p: Parameters) extends XSModule with HasTlbConst { val io = IO(new NewIFUIO) val (toFtq, fromFtq) = (io.ftqInter.toFtq, io.ftqInter.fromFtq) - val fromICache = io.icacheInter.resp + val fromICache = io.fromICache.fetchResp val (toUncache, fromUncache) = (io.uncacheInter.toUncache, io.uncacheInter.fromUncache) def isCrossLineReq(start: UInt, end: UInt): Bool = start(blockOffBits) ^ end(blockOffBits) @@ -260,7 +259,7 @@ class NewIFU(implicit p: Parameters) extends XSModule val f1_ready, f2_ready, f3_ready = WireInit(false.B) - fromFtq.req.ready := f1_ready && io.icacheInter.icacheReady + fromFtq.req.ready := f1_ready && io.fromICache.fetchReady when(wb_redirect) { when(f3_wb_not_flush) { @@ -371,10 +370,10 @@ class NewIFU(implicit p: Parameters) extends XSModule icacheRespAllValid := f2_icache_all_resp_reg || f2_icache_all_resp_wire - icacheMissBubble := io.icacheInter.topdownIcacheMiss - itlbMissBubble := io.icacheInter.topdownItlbMiss + icacheMissBubble := io.fromICache.topdown.icacheMiss + itlbMissBubble := io.fromICache.topdown.itlbMiss - io.icacheStop := !f3_ready + io.toICache.stall := !f3_ready when(f2_flush)(f2_icache_all_resp_reg := false.B) .elsewhen(f2_valid && f2_icache_all_resp_wire && !f3_ready)(f2_icache_all_resp_reg := true.B) @@ -385,7 +384,7 @@ class NewIFU(implicit p: Parameters) extends XSModule .elsewhen(f2_fire)(f2_valid := false.B) val f2_exception_in = fromICache.bits.exception - val f2_backendException = fromICache.bits.backendException + val f2_backendException = fromICache.bits.isBackendException // paddr and gpaddr of [startAddr, nextLineAddr] val f2_paddrs = fromICache.bits.paddr val f2_gpaddr = fromICache.bits.gpaddr @@ -453,7 +452,7 @@ class NewIFU(implicit p: Parameters) extends XSModule ) ) )) - val f2_perf_info = io.icachePerfInfo + val f2_perf_info = io.fromICache.perf def cut(cacheline: UInt, cutPtr: Vec[UInt]): Vec[UInt] = { require(HasCExtension) diff --git a/src/main/scala/xiangshan/frontend/NewFtq.scala b/src/main/scala/xiangshan/frontend/NewFtq.scala index 3f2007ae9c6..d793e7fe5e9 100644 --- a/src/main/scala/xiangshan/frontend/NewFtq.scala +++ b/src/main/scala/xiangshan/frontend/NewFtq.scala @@ -211,18 +211,6 @@ class FtqToIfuIO(implicit p: Parameters) extends XSBundle { val flushFromBpu = new BpuFlushInfo } -class FtqToICacheIO(implicit p: Parameters) extends XSBundle { - // NOTE: req.bits must be prepare in T cycle - // while req.valid is set true in T + 1 cycle - val req = Decoupled(new FtqToICacheRequestBundle) -} - -class FtqToPrefetchIO(implicit p: Parameters) extends XSBundle { - val req = Decoupled(new FtqICacheInfo) - val flushFromBpu = new BpuFlushInfo - val backendException = ExceptionType() -} - trait HasBackendRedirectInfo extends HasXSParameter { def isLoadReplay(r: Valid[Redirect]) = r.bits.flushItself() } @@ -494,7 +482,6 @@ class Ftq(implicit p: Parameters) extends XSModule with HasCircularQueuePtrHelpe val toIfu = new FtqToIfuIO val toICache = new FtqToICacheIO val toBackend = new FtqToCtrlIO - val toPrefetch = new FtqToPrefetchIO val icacheFlush = Output(Bool()) val bpuInfo = new Bundle { @@ -756,7 +743,7 @@ class Ftq(implicit p: Parameters) extends XSModule with HasCircularQueuePtrHelpe ifuPtrPlus1_write := ifuPtrPlus2 ifuPtrPlus2_write := ifuPtrPlus2 + 1.U } - when(io.toPrefetch.req.fire && allowToIfu) { + when(io.toICache.prefetchReq.fire && allowToIfu) { pfPtr_write := pfPtrPlus1 pfPtrPlus1_write := pfPtrPlus1 + 1.U } @@ -766,10 +753,10 @@ class Ftq(implicit p: Parameters) extends XSModule with HasCircularQueuePtrHelpe entry_hit_status(bpu_s2_resp.ftq_idx.value) := Mux(bpu_s2_resp.full_pred(3).hit, h_hit, h_not_hit) } - io.toIfu.flushFromBpu.s2.valid := bpu_s2_redirect - io.toIfu.flushFromBpu.s2.bits := bpu_s2_resp.ftq_idx - io.toPrefetch.flushFromBpu.s2.valid := bpu_s2_redirect - io.toPrefetch.flushFromBpu.s2.bits := bpu_s2_resp.ftq_idx + io.toIfu.flushFromBpu.s2.valid := bpu_s2_redirect + io.toIfu.flushFromBpu.s2.bits := bpu_s2_resp.ftq_idx + io.toICache.flushFromBpu.s2.valid := bpu_s2_redirect + io.toICache.flushFromBpu.s2.bits := bpu_s2_resp.ftq_idx when(bpu_s2_redirect) { bpuPtr := bpu_s2_resp.ftq_idx + 1.U copied_bpu_ptr.map(_ := bpu_s2_resp.ftq_idx + 1.U) @@ -785,10 +772,10 @@ class Ftq(implicit p: Parameters) extends XSModule with HasCircularQueuePtrHelpe } } - io.toIfu.flushFromBpu.s3.valid := bpu_s3_redirect - io.toIfu.flushFromBpu.s3.bits := bpu_s3_resp.ftq_idx - io.toPrefetch.flushFromBpu.s3.valid := bpu_s3_redirect - io.toPrefetch.flushFromBpu.s3.bits := bpu_s3_resp.ftq_idx + io.toIfu.flushFromBpu.s3.valid := bpu_s3_redirect + io.toIfu.flushFromBpu.s3.bits := bpu_s3_resp.ftq_idx + io.toICache.flushFromBpu.s3.valid := bpu_s3_redirect + io.toICache.flushFromBpu.s3.bits := bpu_s3_resp.ftq_idx when(bpu_s3_redirect) { bpuPtr := bpu_s3_resp.ftq_idx + 1.U copied_bpu_ptr.map(_ := bpu_s3_resp.ftq_idx + 1.U) @@ -819,7 +806,7 @@ class Ftq(implicit p: Parameters) extends XSModule with HasCircularQueuePtrHelpe val bpu_in_bypass_buf_for_ifu = bpu_in_bypass_buf val bpu_in_bypass_ptr = RegEnable(bpu_in_resp_ptr, bpu_in_fire) val last_cycle_to_ifu_fire = RegNext(io.toIfu.req.fire) - val last_cycle_to_pf_fire = RegNext(io.toPrefetch.req.fire) + val last_cycle_to_pf_fire = RegNext(io.toICache.prefetchReq.fire) val copied_bpu_in_bypass_ptr = VecInit(Seq.fill(copyNum)(RegEnable(bpu_in_resp_ptr, bpu_in_fire))) val copied_last_cycle_to_ifu_fire = VecInit(Seq.fill(copyNum)(RegNext(io.toIfu.req.fire))) @@ -874,7 +861,7 @@ class Ftq(implicit p: Parameters) extends XSModule with HasCircularQueuePtrHelpe when(bpu_in_fire && bpu_in_resp_ptr === pfPtr_write) { nextCycleToPrefetchPcBundle := ftq_pc_mem.io.wdata nextCycleToPrefetchEntryToSend := true.B - }.elsewhen(io.toPrefetch.req.fire) { + }.elsewhen(io.toICache.prefetchReq.fire) { nextCycleToPrefetchPcBundle := ftq_pc_mem.io.pfPtrPlus1_rdata nextCycleToPrefetchEntryToSend := entry_fetch_status(pfPtrPlus1.value) === f_to_send || last_cycle_bpu_in && bpu_in_bypass_ptr === pfPtrPlus1 @@ -916,22 +903,27 @@ class Ftq(implicit p: Parameters) extends XSModule with HasCircularQueuePtrHelpe io.toIfu.req.bits.ftqOffset := entry_ftq_offset io.toIfu.req.bits.fromFtqPcBundle(toIfuPcBundle) - io.toICache.req.valid := entry_is_to_send && ifuPtr =/= bpuPtr - io.toICache.req.bits.readValid.zipWithIndex.map { case (copy, i) => + io.toICache.fetchReq.valid := entry_is_to_send && ifuPtr =/= bpuPtr + io.toICache.fetchReq.bits.readValid.zipWithIndex.map { case (copy, i) => copy := toICacheEntryToSend(i) && copied_ifu_ptr(i) =/= copied_bpu_ptr(i) } - io.toICache.req.bits.pcMemRead.zipWithIndex.foreach { case (copy, i) => + io.toICache.fetchReq.bits.req.zipWithIndex.foreach { case (copy, i) => copy.fromFtqPcBundle(toICachePcBundle(i)) copy.ftqIdx := ifuPtr } - io.toICache.req.bits.backendException := ExceptionType.hasException(backendException) && backendPcFaultPtr === ifuPtr - - io.toPrefetch.req.valid := toPrefetchEntryToSend && pfPtr =/= bpuPtr - io.toPrefetch.req.bits.fromFtqPcBundle(toPrefetchPcBundle) - io.toPrefetch.req.bits.ftqIdx := pfPtr - io.toPrefetch.backendException := Mux(backendPcFaultPtr === pfPtr, backendException, ExceptionType.none) - // io.toICache.req.bits.bypassSelect := last_cycle_bpu_in && bpu_in_bypass_ptr === ifuPtr - // io.toICache.req.bits.bpuBypassWrite.zipWithIndex.map{case(bypassWrtie, i) => + io.toICache.fetchReq.bits.isBackendException := + ExceptionType.hasException(backendException) && backendPcFaultPtr === ifuPtr + + io.toICache.prefetchReq.valid := toPrefetchEntryToSend && pfPtr =/= bpuPtr + io.toICache.prefetchReq.bits.req.fromFtqPcBundle(toPrefetchPcBundle) + io.toICache.prefetchReq.bits.req.ftqIdx := pfPtr + io.toICache.prefetchReq.bits.backendException := Mux( + backendPcFaultPtr === pfPtr, + backendException, + ExceptionType.none + ) + // io.toICache.fetchReq.bits.bypassSelect := last_cycle_bpu_in && bpu_in_bypass_ptr === ifuPtr + // io.toICache.fetchReq.bits.bpuBypassWrite.zipWithIndex.map{case(bypassWrtie, i) => // bypassWrtie.startAddr := bpu_in_bypass_buf.tail(i).startAddr // bypassWrtie.nextlineStart := bpu_in_bypass_buf.tail(i).nextLineAddr // } diff --git a/src/main/scala/xiangshan/frontend/icache/Bundles.scala b/src/main/scala/xiangshan/frontend/icache/Bundles.scala index 53cca555ad9..e74ef41664a 100644 --- a/src/main/scala/xiangshan/frontend/icache/Bundles.scala +++ b/src/main/scala/xiangshan/frontend/icache/Bundles.scala @@ -27,7 +27,16 @@ import xiangshan.cache.mmu.Pbmt import xiangshan.frontend.ExceptionType import xiangshan.frontend.FtqICacheInfo import xiangshan.frontend.FtqPtr -import xiangshan.frontend.FtqToICacheRequestBundle + +/* *** + * Naming: + * - I/O: + * - ICache inner use only: xxxBundle + * - Other modules use: ICacheXxxBundle, consider move to FrontendBundle.scala + * - Sram/register: xxxEntry + * + * Try avoiding directed Bundle, unless it's req-resp pair + * *** */ // meta class ICacheMetadata(implicit p: Parameters) extends ICacheBundle { @@ -43,104 +52,122 @@ object ICacheMetadata { } /* ***** Array write ***** */ -// ICacheMissUnit -> ICacheMetaArray -class ICacheMetaWriteBundle(implicit p: Parameters) extends ICacheBundle { - val virIdx: UInt = UInt(idxBits.W) - val phyTag: UInt = UInt(tagBits.W) - val waymask: UInt = UInt(nWays.W) - val bankIdx: Bool = Bool() - val poison: Bool = Bool() +// ICacheMissUnit <-> ICacheMetaArray +class MetaWriteBundle(implicit p: Parameters) extends ICacheBundle { + class MetaWriteReqBundle(implicit p: Parameters) extends ICacheBundle { + val virIdx: UInt = UInt(idxBits.W) + val phyTag: UInt = UInt(tagBits.W) + val waymask: UInt = UInt(nWays.W) + val bankIdx: Bool = Bool() + val poison: Bool = Bool() - def generate(tag: UInt, idx: UInt, waymask: UInt, bankIdx: Bool, poison: Bool): Unit = { - this.virIdx := idx - this.phyTag := tag - this.waymask := waymask - this.bankIdx := bankIdx - this.poison := poison + def generate(tag: UInt, idx: UInt, waymask: UInt, bankIdx: Bool, poison: Bool): Unit = { + this.virIdx := idx + this.phyTag := tag + this.waymask := waymask + this.bankIdx := bankIdx + this.poison := poison + } } + val req: DecoupledIO[MetaWriteReqBundle] = DecoupledIO(new MetaWriteReqBundle) } -// ICacheMissUnit -> ICacheDataArray -class ICacheDataWriteBundle(implicit p: Parameters) extends ICacheBundle { - val virIdx: UInt = UInt(idxBits.W) - val data: UInt = UInt(blockBits.W) - val waymask: UInt = UInt(nWays.W) - val bankIdx: Bool = Bool() - val poison: Bool = Bool() +// ICacheMissUnit <-> ICacheDataArray +class DataWriteBundle(implicit p: Parameters) extends ICacheBundle { + class DataWriteReqBundle(implicit p: Parameters) extends ICacheBundle { + val virIdx: UInt = UInt(idxBits.W) + val data: UInt = UInt(blockBits.W) + val waymask: UInt = UInt(nWays.W) + val bankIdx: Bool = Bool() + val poison: Bool = Bool() - def generate(data: UInt, idx: UInt, waymask: UInt, bankIdx: Bool, poison: Bool): Unit = { - this.virIdx := idx - this.data := data - this.waymask := waymask - this.bankIdx := bankIdx - this.poison := poison + def generate(data: UInt, idx: UInt, waymask: UInt, bankIdx: Bool, poison: Bool): Unit = { + this.virIdx := idx + this.data := data + this.waymask := waymask + this.bankIdx := bankIdx + this.poison := poison + } } + val req: DecoupledIO[DataWriteReqBundle] = DecoupledIO(new DataWriteReqBundle) } /* ***** Array flush ***** */ -// ICacheMainPipe -> ICacheMetaArray -class ICacheMetaFlushBundle(implicit p: Parameters) extends ICacheBundle { - val virIdx: UInt = UInt(idxBits.W) - val waymask: UInt = UInt(nWays.W) +// ICacheMainPipe <-> ICacheMetaArray +class MetaFlushBundle(implicit p: Parameters) extends ICacheBundle { + class MetaFlushReqBundle(implicit p: Parameters) extends ICacheBundle { + val virIdx: UInt = UInt(idxBits.W) + val waymask: UInt = UInt(nWays.W) + } + val req: Vec[Valid[MetaFlushReqBundle]] = Vec(PortNumber, ValidIO(new MetaFlushReqBundle)) } /* ***** Array read ***** */ -// ICachePrefetchPipe / ICacheMainPipe -> ICacheMetaArray / ICacheDataArray -class ICacheReadBundle(implicit p: Parameters) extends ICacheBundle { - val vSetIdx: Vec[UInt] = Vec(2, UInt(idxBits.W)) - val waymask: Vec[Vec[Bool]] = Vec(2, Vec(nWays, Bool())) +class ArrayReadReqBundle(implicit p: Parameters) extends ICacheBundle { + val vSetIdx: Vec[UInt] = Vec(PortNumber, UInt(idxBits.W)) + val waymask: Vec[Vec[Bool]] = Vec(PortNumber, Vec(nWays, Bool())) val blkOffset: UInt = UInt(log2Ceil(blockBytes).W) val isDoubleLine: Bool = Bool() } -//class ICacheMetaReadBundle(implicit p: Parameters) extends ICacheReadBundle -class ICacheMetaRespBundle(implicit p: Parameters) extends ICacheBundle { - val metas: Vec[Vec[ICacheMetadata]] = Vec(PortNumber, Vec(nWays, new ICacheMetadata)) - val codes: Vec[Vec[UInt]] = Vec(PortNumber, Vec(nWays, UInt(ICacheMetaCodeBits.W))) - val entryValid: Vec[Vec[Bool]] = Vec(PortNumber, Vec(nWays, Bool())) - // for compatibility - def tags: Vec[Vec[UInt]] = VecInit(metas.map(port => VecInit(port.map(way => way.tag)))) -} - -class ICacheMetaReqBundle(implicit p: Parameters) extends ICacheBundle { - val toIMeta: DecoupledIO[ICacheReadBundle] = DecoupledIO(new ICacheReadBundle) - val fromIMeta: ICacheMetaRespBundle = Input(new ICacheMetaRespBundle) -} - -//class ICacheDataReadBundle(implicit p: Parameters) extends ICacheReadBundle -class ICacheDataRespBundle(implicit p: Parameters) extends ICacheBundle { - val datas: Vec[UInt] = Vec(ICacheDataBanks, UInt(ICacheDataBits.W)) - val codes: Vec[UInt] = Vec(ICacheDataBanks, UInt(ICacheDataCodeBits.W)) +// ICachePrefetchPipe / ICacheCtrlUnit <-> ICacheMetaArray +class MetaReadBundle(implicit p: Parameters) extends ICacheBundle { + class MetaReadReqBundle(implicit p: Parameters) extends ArrayReadReqBundle + class MetaReadRespBundle(implicit p: Parameters) extends ICacheBundle { + val metas: Vec[Vec[ICacheMetadata]] = Vec(PortNumber, Vec(nWays, new ICacheMetadata)) + val codes: Vec[Vec[UInt]] = Vec(PortNumber, Vec(nWays, UInt(ICacheMetaCodeBits.W))) + val entryValid: Vec[Vec[Bool]] = Vec(PortNumber, Vec(nWays, Bool())) + // for compatibility + def tags: Vec[Vec[UInt]] = VecInit(metas.map(port => VecInit(port.map(way => way.tag)))) + } + val req: DecoupledIO[MetaReadReqBundle] = DecoupledIO(new MetaReadReqBundle) + val resp: MetaReadRespBundle = Input(new MetaReadRespBundle) } -class ICacheDataReqBundle(implicit p: Parameters) extends ICacheBundle { - val toIData: Vec[DecoupledIO[ICacheReadBundle]] = Vec(partWayNum, DecoupledIO(new ICacheReadBundle)) - val fromIData: ICacheDataRespBundle = Input(new ICacheDataRespBundle) +// ICacheMainPipe -> ICacheDataArray +class DataReadBundle(implicit p: Parameters) extends ICacheBundle { + class DataReadReqBundle(implicit p: Parameters) extends ArrayReadReqBundle + class DataReadRespBundle(implicit p: Parameters) extends ICacheBundle { + val datas: Vec[UInt] = Vec(ICacheDataBanks, UInt(ICacheDataBits.W)) + val codes: Vec[UInt] = Vec(ICacheDataBanks, UInt(ICacheDataCodeBits.W)) + } + val req: Vec[DecoupledIO[DataReadReqBundle]] = Vec(partWayNum, DecoupledIO(new DataReadReqBundle)) + val resp: DataReadRespBundle = Input(new DataReadRespBundle) } /* ***** Replacer ***** */ -// ICacheMainPipe -> ICacheReplacer -class ReplacerTouch(implicit p: Parameters) extends ICacheBundle { - val vSetIdx: UInt = UInt(idxBits.W) - val way: UInt = UInt(wayBits.W) +// ICacheMainPipe <-> ICacheReplacer +class ReplacerTouchBundle(implicit p: Parameters) extends ICacheBundle { + class ReplacerTouchReqBundle(implicit p: Parameters) extends ICacheBundle { + val vSetIdx: UInt = UInt(idxBits.W) + val way: UInt = UInt(wayBits.W) + } + val req: Vec[Valid[ReplacerTouchReqBundle]] = Vec(PortNumber, ValidIO(new ReplacerTouchReqBundle)) } -// ICacheReplacer -> ICacheMissUnit -class ReplacerVictim(implicit p: Parameters) extends ICacheBundle { - val vSetIdx: Valid[UInt] = ValidIO(UInt(idxBits.W)) - val way: UInt = Input(UInt(wayBits.W)) + +// ICacheMissUnit <-> ICacheReplacer +class ReplacerVictimBundle(implicit p: Parameters) extends ICacheBundle { + class ReplacerVictimReqBundle(implicit p: Parameters) extends ICacheBundle { + val vSetIdx: UInt = UInt(idxBits.W) + } + class ReplacerVictimRespBundle(implicit p: Parameters) extends ICacheBundle { + val way: UInt = UInt(wayBits.W) + } + val req: Valid[ReplacerVictimReqBundle] = ValidIO(new ReplacerVictimReqBundle) + val resp: ReplacerVictimRespBundle = Input(new ReplacerVictimRespBundle) } /* ***** MainPipe ***** */ // ICache(MainPipe) -> IFU -class ICacheMainPipeResp(implicit p: Parameters) extends ICacheBundle { - val doubleline: Bool = Bool() - val vaddr: Vec[UInt] = Vec(PortNumber, UInt(VAddrBits.W)) - val data: UInt = UInt(blockBits.W) - val paddr: Vec[UInt] = Vec(PortNumber, UInt(PAddrBits.W)) - val exception: Vec[UInt] = Vec(PortNumber, ExceptionType()) - val pmp_mmio: Vec[Bool] = Vec(PortNumber, Bool()) - val itlb_pbmt: Vec[UInt] = Vec(PortNumber, UInt(Pbmt.width.W)) - val backendException: Bool = Bool() +class ICacheRespBundle(implicit p: Parameters) extends ICacheBundle { + val doubleline: Bool = Bool() + val vaddr: Vec[UInt] = Vec(PortNumber, UInt(VAddrBits.W)) + val data: UInt = UInt(blockBits.W) + val paddr: Vec[UInt] = Vec(PortNumber, UInt(PAddrBits.W)) + val exception: Vec[UInt] = Vec(PortNumber, ExceptionType()) + val pmp_mmio: Vec[Bool] = Vec(PortNumber, Bool()) + val itlb_pbmt: Vec[UInt] = Vec(PortNumber, UInt(Pbmt.width.W)) + val isBackendException: Bool = Bool() /* NOTE: GPAddrBits(=50bit) is not enough for gpaddr here, refer to PR#3795 * Sv48*4 only allows 50bit gpaddr, when software violates this requirement * it needs to fill the mtval2 register with the full XLEN(=64bit) gpaddr, @@ -150,15 +177,9 @@ class ICacheMainPipeResp(implicit p: Parameters) extends ICacheBundle { val gpaddr: UInt = UInt(PAddrBitsMax.W) val isForVSnonLeafPTE: Bool = Bool() } -class ICacheMainPipeBundle(implicit p: Parameters) extends ICacheBundle { - val req: DecoupledIO[FtqToICacheRequestBundle] = Flipped(DecoupledIO(new FtqToICacheRequestBundle)) - val resp: Valid[ICacheMainPipeResp] = ValidIO(new ICacheMainPipeResp) - val topdownIcacheMiss: Bool = Output(Bool()) - val topdownItlbMiss: Bool = Output(Bool()) -} /* ***** PrefetchPipe ***** */ -class IPrefetchReq(implicit p: Parameters) extends ICacheBundle { +class PrefetchReqBundle(implicit p: Parameters) extends ICacheBundle { val startAddr: UInt = UInt(VAddrBits.W) val nextlineStart: UInt = UInt(VAddrBits.W) val ftqIdx: FtqPtr = new FtqPtr @@ -166,7 +187,7 @@ class IPrefetchReq(implicit p: Parameters) extends ICacheBundle { val backendException: UInt = ExceptionType() def crossCacheline: Bool = startAddr(blockOffBits - 1) === 1.U - def fromFtqICacheInfo(info: FtqICacheInfo): IPrefetchReq = { + def fromFtqICacheInfo(info: FtqICacheInfo): PrefetchReqBundle = { this.startAddr := info.startAddr this.nextlineStart := info.nextlineStart this.ftqIdx := info.ftqIdx @@ -174,7 +195,7 @@ class IPrefetchReq(implicit p: Parameters) extends ICacheBundle { this } - def fromSoftPrefetch(req: SoftIfetchPrefetchBundle): IPrefetchReq = { + def fromSoftPrefetch(req: SoftIfetchPrefetchBundle): PrefetchReqBundle = { this.startAddr := req.vaddr this.nextlineStart := req.vaddr + (1 << blockOffBits).U this.ftqIdx := DontCare @@ -183,7 +204,7 @@ class IPrefetchReq(implicit p: Parameters) extends ICacheBundle { } } -/* ***** WayLookup ***** */ +/* ***** ICacheWayLookup ***** */ /* WayLookupEntry is for internal storage, while WayLookupInfo is for interface * Notes: * 1. there must be a flush (caused by guest page fault) after excp_tlb_gpf === true.B, @@ -199,15 +220,15 @@ class WayLookupEntry(implicit p: Parameters) extends ICacheBundle { val meta_codes: Vec[UInt] = Vec(PortNumber, UInt(ICacheMetaCodeBits.W)) } -class WayLookupGPFEntry(implicit p: Parameters) extends ICacheBundle { +class WayLookupGpfEntry(implicit p: Parameters) extends ICacheBundle { // NOTE: we don't use GPAddrBits here, refer to ICacheMainPipe.scala L43-48 and PR#3795 val gpaddr: UInt = UInt(PAddrBitsMax.W) val isForVSnonLeafPTE: Bool = Bool() } -class WayLookupInfo(implicit p: Parameters) extends ICacheBundle { +class WayLookupBundle(implicit p: Parameters) extends ICacheBundle { val entry = new WayLookupEntry - val gpf = new WayLookupGPFEntry + val gpf = new WayLookupGpfEntry // for compatibility def vSetIdx: Vec[UInt] = entry.vSetIdx @@ -222,47 +243,46 @@ class WayLookupInfo(implicit p: Parameters) extends ICacheBundle { /* ***** Miss ***** */ // ICacheMainPipe / ICachePrefetchPipe -> MissUnit -class ICacheMissReq(implicit p: Parameters) extends ICacheBundle { +class MissReqBundle(implicit p: Parameters) extends ICacheBundle { val blkPaddr: UInt = UInt((PAddrBits - blockOffBits).W) val vSetIdx: UInt = UInt(idxBits.W) } -// MissUnit -> ICacheMainPipe / ICachePrefetchPipe / WayLookup -class ICacheMissResp(implicit p: Parameters) extends ICacheBundle { +// MissUnit -> ICacheMainPipe / ICachePrefetchPipe / ICacheWayLookup +class MissRespBundle(implicit p: Parameters) extends ICacheBundle { val blkPaddr: UInt = UInt((PAddrBits - blockOffBits).W) val vSetIdx: UInt = UInt(idxBits.W) val waymask: UInt = UInt(nWays.W) val data: UInt = UInt(blockBits.W) val corrupt: Bool = Bool() } -// ICacheMainPipe <-> ICacheMissUnit -class ICacheMSHRBundle(implicit p: Parameters) extends ICacheBundle { - val req: DecoupledIO[ICacheMissReq] = DecoupledIO(new ICacheMissReq) - val resp: Valid[ICacheMissResp] = Flipped(ValidIO(new ICacheMissResp)) -} -/* ***** MSHR ***** */ -// ICacheMainPipe -> MSHR -class MSHRLookup(implicit p: Parameters) extends ICacheBundle { - val info: Valid[ICacheMissReq] = ValidIO(new ICacheMissReq) - val hit: Bool = Input(Bool()) +/* ***** Mshr ***** */ +// ICacheMissUnit <-> Mshr +class MshrLookupBundle(implicit p: Parameters) extends ICacheBundle { + class MshrLookupReqBundle(implicit p: Parameters) extends MissReqBundle + class MshrLookupRespBundle(implicit p: Parameters) extends ICacheBundle { + val hit: Bool = Bool() + } + val req: Valid[MshrLookupReqBundle] = ValidIO(new MshrLookupReqBundle) + val resp: MshrLookupRespBundle = Input(new MshrLookupRespBundle) } -// MSHR -> ICacheMissUnit -class MSHRResp(implicit p: Parameters) extends ICacheBundle { +// Mshr -> ICacheMissUnit +class MshrInfoBundle(implicit p: Parameters) extends ICacheBundle { val blkPaddr: UInt = UInt((PAddrBits - blockOffBits).W) val vSetIdx: UInt = UInt(idxBits.W) val way: UInt = UInt(wayBits.W) } -// MSHR -> tilelink bus -class MSHRAcquire(edge: TLEdgeOut)(implicit p: Parameters) extends ICacheBundle { +// Mshr -> tilelink bus +class MshrAcquireBundle(edge: TLEdgeOut)(implicit p: Parameters) extends ICacheBundle { val acquire: TLBundleA = new TLBundleA(edge.bundle) val vSetIdx: UInt = UInt(idxBits.W) } -/* ***** PMP ***** */ -// ICacheMainPipe / ICachePrefetchPipe <-> PMP -class ICachePMPBundle(implicit p: Parameters) extends ICacheBundle { +/* ***** Pmp ***** */ +// ICacheMainPipe / ICachePrefetchPipe <-> Pmp +class PmpCheckBundle(implicit p: Parameters) extends ICacheBundle { val req: Valid[PMPReqBundle] = ValidIO(new PMPReqBundle) val resp: PMPRespBundle = Input(new PMPRespBundle) } @@ -281,3 +301,8 @@ class ICachePerfInfo(implicit p: Parameters) extends ICacheBundle { val bank_hit: Vec[Bool] = Vec(PortNumber, Bool()) val hit: Bool = Bool() } + +class ICacheTopdownInfo(implicit p: Parameters) extends ICacheBundle { + val icacheMiss: Bool = Output(Bool()) + val itlbMiss: Bool = Output(Bool()) +} diff --git a/src/main/scala/xiangshan/frontend/icache/ICacheCtrlUnit.scala b/src/main/scala/xiangshan/frontend/icache/ICacheCtrlUnit.scala index 5a3b1ba31f2..38979b54e02 100644 --- a/src/main/scala/xiangshan/frontend/icache/ICacheCtrlUnit.scala +++ b/src/main/scala/xiangshan/frontend/icache/ICacheCtrlUnit.scala @@ -48,11 +48,10 @@ class ICacheCtrlUnit(params: ICacheCtrlUnitParams)(implicit p: Parameters) exten // ecc control val ecc_enable: Bool = Output(Bool()) // ecc inject - val injecting: Bool = Output(Bool()) - val metaRead: DecoupledIO[ICacheReadBundle] = DecoupledIO(new ICacheReadBundle) - val metaReadResp: ICacheMetaRespBundle = Input(new ICacheMetaRespBundle) - val metaWrite: DecoupledIO[ICacheMetaWriteBundle] = DecoupledIO(new ICacheMetaWriteBundle) - val dataWrite: DecoupledIO[ICacheDataWriteBundle] = DecoupledIO(new ICacheDataWriteBundle) + val injecting: Bool = Output(Bool()) + val metaRead: MetaReadBundle = new MetaReadBundle + val metaWrite: MetaWriteBundle = new MetaWriteBundle + val dataWrite: DataWriteBundle = new DataWriteBundle } val io: ICacheCtrlUnitIO = IO(new ICacheCtrlUnitIO) @@ -151,14 +150,14 @@ class ICacheCtrlUnit(params: ICacheCtrlUnitParams)(implicit p: Parameters) exten Enum(5) private val istate = RegInit(is_idle) - io.metaRead.valid := istate === is_readMetaReq - io.metaRead.bits.isDoubleLine := false.B // we inject into first cacheline and ignore the rest port - io.metaRead.bits.vSetIdx := VecInit(Seq.fill(PortNumber)(ivirIdx)) - io.metaRead.bits.waymask := VecInit(Seq.fill(PortNumber)(VecInit(Seq.fill(nWays)(false.B)))) // dontcare - io.metaRead.bits.blkOffset := 0.U(blockBits.W) // dontcare + io.metaRead.req.valid := istate === is_readMetaReq + io.metaRead.req.bits.isDoubleLine := false.B // we inject into first cacheline and ignore the rest port + io.metaRead.req.bits.vSetIdx := VecInit(Seq.fill(PortNumber)(ivirIdx)) + io.metaRead.req.bits.waymask := VecInit(Seq.fill(PortNumber)(VecInit(Seq.fill(nWays)(false.B)))) // dontcare + io.metaRead.req.bits.blkOffset := 0.U(blockBits.W) // dontcare - io.metaWrite.valid := istate === is_writeMeta - io.metaWrite.bits.generate( + io.metaWrite.req.valid := istate === is_writeMeta + io.metaWrite.req.bits.generate( tag = iphyTag, idx = ivirIdx, waymask = iwaymask, @@ -166,8 +165,8 @@ class ICacheCtrlUnit(params: ICacheCtrlUnitParams)(implicit p: Parameters) exten poison = true.B ) - io.dataWrite.valid := istate === is_writeData - io.dataWrite.bits.generate( + io.dataWrite.req.valid := istate === is_writeData + io.dataWrite.req.bits.generate( data = 0.U, // inject poisoned data, don't care actual data idx = ivirIdx, waymask = iwaymask, @@ -183,14 +182,14 @@ class ICacheCtrlUnit(params: ICacheCtrlUnitParams)(implicit p: Parameters) exten } } is(is_readMetaReq) { - when(io.metaRead.fire) { + when(io.metaRead.req.fire) { istate := is_readMetaResp } } is(is_readMetaResp) { // metaArray ensures resp is valid one cycle after req val waymask = VecInit((0 until nWays).map { w => - io.metaReadResp.entryValid.head(w) && io.metaReadResp.tags.head(w) === iphyTag + io.metaRead.resp.entryValid.head(w) && io.metaRead.resp.tags.head(w) === iphyTag }).asUInt iwaymask := waymask when(!waymask.orR) { @@ -203,13 +202,13 @@ class ICacheCtrlUnit(params: ICacheCtrlUnitParams)(implicit p: Parameters) exten } } is(is_writeMeta) { - when(io.metaWrite.fire) { + when(io.metaWrite.req.fire) { istate := is_idle eccctrl.istatus := eccctrlInjStatus.injected } } is(is_writeData) { - when(io.dataWrite.fire) { + when(io.dataWrite.req.fire) { istate := is_idle eccctrl.istatus := eccctrlInjStatus.injected } diff --git a/src/main/scala/xiangshan/frontend/icache/ICacheDataArray.scala b/src/main/scala/xiangshan/frontend/icache/ICacheDataArray.scala index ab8ebc46789..c9f227ee81d 100644 --- a/src/main/scala/xiangshan/frontend/icache/ICacheDataArray.scala +++ b/src/main/scala/xiangshan/frontend/icache/ICacheDataArray.scala @@ -22,9 +22,8 @@ import utility.mbist.MbistPipeline class ICacheDataArray(implicit p: Parameters) extends ICacheModule with ICacheECCHelper with ICacheDataSelHelper { class ICacheDataArrayIO(implicit p: Parameters) extends ICacheBundle { - val write: DecoupledIO[ICacheDataWriteBundle] = Flipped(DecoupledIO(new ICacheDataWriteBundle)) - val read: Vec[DecoupledIO[ICacheReadBundle]] = Flipped(Vec(partWayNum, DecoupledIO(new ICacheReadBundle))) - val readResp: ICacheDataRespBundle = Output(new ICacheDataRespBundle) + val write: DataWriteBundle = Flipped(new DataWriteBundle) + val read: DataReadBundle = Flipped(new DataReadBundle) } val io: ICacheDataArrayIO = IO(new ICacheDataArrayIO) @@ -48,13 +47,13 @@ class ICacheDataArray(implicit p: Parameters) extends ICacheModule with ICacheEC * data array ****************************************************************************** */ - private val writeDatas = io.write.bits.data.asTypeOf(Vec(ICacheDataBanks, UInt(ICacheDataBits.W))) - private val writeEntries = writeDatas.map(ICacheDataEntry(_, io.write.bits.poison).asUInt) + private val writeDatas = io.write.req.bits.data.asTypeOf(Vec(ICacheDataBanks, UInt(ICacheDataBits.W))) + private val writeEntries = writeDatas.map(ICacheDataEntry(_, io.write.req.bits.poison).asUInt) // io.read() are copies to control fan-out, we can simply use .head here - private val bankSel = getBankSel(io.read.head.bits.blkOffset, io.read.head.valid) - private val lineSel = getLineSel(io.read.head.bits.blkOffset) - private val waymasks = io.read.head.bits.waymask + private val bankSel = getBankSel(io.read.req.head.bits.blkOffset, io.read.req.head.valid) + private val lineSel = getLineSel(io.read.req.head.bits.blkOffset) + private val waymasks = io.read.req.head.bits.waymask private val masks = Wire(Vec(nWays, Vec(ICacheDataBanks, Bool()))) (0 until nWays).foreach { way => (0 until ICacheDataBanks).foreach { bank => @@ -80,15 +79,15 @@ class ICacheDataArray(implicit p: Parameters) extends ICacheModule with ICacheEC )) // read - sramBank.io.r.req.valid := io.read(bank % 4).valid && masks(way)(bank) + sramBank.io.r.req.valid := io.read.req(bank % 4).valid && masks(way)(bank) sramBank.io.r.req.bits.apply(setIdx = - Mux(lineSel(bank), io.read(bank % 4).bits.vSetIdx(1), io.read(bank % 4).bits.vSetIdx(0)) + Mux(lineSel(bank), io.read.req(bank % 4).bits.vSetIdx(1), io.read.req(bank % 4).bits.vSetIdx(0)) ) // write - sramBank.io.w.req.valid := io.write.valid && io.write.bits.waymask(way).asBool + sramBank.io.w.req.valid := io.write.req.valid && io.write.req.bits.waymask(way).asBool sramBank.io.w.req.bits.apply( data = writeEntries(bank), - setIdx = io.write.bits.virIdx, + setIdx = io.write.req.bits.virIdx, // waymask is invalid when way of SRAMTemplate <= 1 waymask = 0.U ) @@ -103,7 +102,7 @@ class ICacheDataArray(implicit p: Parameters) extends ICacheModule with ICacheEC * read logic ****************************************************************************** */ - private val masksReg = RegEnable(masks, 0.U.asTypeOf(masks), io.read(0).valid) + private val masksReg = RegEnable(masks, 0.U.asTypeOf(masks), io.read.req(0).valid) private val readDataWithCode = (0 until ICacheDataBanks).map { bank => Mux1H(VecInit(masksReg.map(_(bank))).asTypeOf(UInt(nWays.W)), dataArrays.map(_(bank).io.r.resp.asUInt)) } @@ -121,8 +120,8 @@ class ICacheDataArray(implicit p: Parameters) extends ICacheModule with ICacheEC * IO ****************************************************************************** */ - io.readResp.datas := readDatas - io.readResp.codes := readCodes - io.write.ready := true.B - io.read.foreach(_.ready := !io.write.valid) + io.read.resp.datas := readDatas + io.read.resp.codes := readCodes + io.write.req.ready := true.B + io.read.req.foreach(_.ready := !io.write.req.valid) } diff --git a/src/main/scala/xiangshan/frontend/icache/ICacheImp.scala b/src/main/scala/xiangshan/frontend/icache/ICacheImp.scala index ac96212c293..c445958f7b4 100644 --- a/src/main/scala/xiangshan/frontend/icache/ICacheImp.scala +++ b/src/main/scala/xiangshan/frontend/icache/ICacheImp.scala @@ -33,22 +33,23 @@ import utility.XSPerfAccumulate import xiangshan.L1CacheErrorInfo import xiangshan.SoftIfetchPrefetchBundle import xiangshan.cache.mmu.TlbRequestIO -import xiangshan.frontend.FtqToPrefetchIO +import xiangshan.frontend.FtqToICacheIO +import xiangshan.frontend.ICacheToIfuIO +import xiangshan.frontend.IfuToICacheIO class ICacheImp(outer: ICache) extends LazyModuleImp(outer) with HasICacheParameters with HasPerfEvents { class ICacheIO(implicit p: Parameters) extends ICacheBundle { val hartId: UInt = Input(UInt(hartIdLen.W)) // FTQ - val fetch: ICacheMainPipeBundle = new ICacheMainPipeBundle - val ftqPrefetch: FtqToPrefetchIO = Flipped(new FtqToPrefetchIO) + val fromFtq: FtqToICacheIO = Flipped(new FtqToICacheIO) // memblock - val softPrefetch: Vec[Valid[SoftIfetchPrefetchBundle]] = + val softPrefetchReq: Vec[Valid[SoftIfetchPrefetchBundle]] = Vec(backendParams.LduCnt, Flipped(Valid(new SoftIfetchPrefetchBundle))) // IFU - val stop: Bool = Input(Bool()) - val toIFU: Bool = Output(Bool()) + val toIfu: ICacheToIfuIO = new ICacheToIfuIO + val fromIfu: IfuToICacheIO = Flipped(new IfuToICacheIO) // PMP: mainPipe & prefetchPipe need PortNumber each - val pmp: Vec[ICachePMPBundle] = Vec(2 * PortNumber, new ICachePMPBundle) + val pmp: Vec[PmpCheckBundle] = Vec(2 * PortNumber, new PmpCheckBundle) // iTLB val itlb: Vec[TlbRequestIO] = Vec(PortNumber, new TlbRequestIO) val itlbFlushPipe: Bool = Bool() @@ -59,9 +60,6 @@ class ICacheImp(outer: ICache) extends LazyModuleImp(outer) with HasICacheParame // flush val fencei: Bool = Input(Bool()) val flush: Bool = Input(Bool()) - - // perf - val perfInfo: ICachePerfInfo = Output(new ICachePerfInfo) } val io: ICacheIO = IO(new ICacheIO) @@ -87,7 +85,7 @@ class ICacheImp(outer: ICache) extends LazyModuleImp(outer) with HasICacheParame private val missUnit = Module(new ICacheMissUnit(edge)) private val replacer = Module(new ICacheReplacer) private val prefetcher = Module(new ICachePrefetchPipe) - private val wayLookup = Module(new WayLookup) + private val wayLookup = Module(new ICacheWayLookup) private val ecc_enable = if (outer.ctrlUnitOpt.nonEmpty) outer.ctrlUnitOpt.get.module.io.ecc_enable else true.B @@ -96,48 +94,47 @@ class ICacheImp(outer: ICache) extends LazyModuleImp(outer) with HasICacheParame val ctrlUnit = outer.ctrlUnitOpt.get.module when(ctrlUnit.io.injecting) { dataArray.io.write <> ctrlUnit.io.dataWrite - missUnit.io.data_write.ready := false.B + missUnit.io.dataWrite.req.ready := false.B }.otherwise { - ctrlUnit.io.dataWrite.ready := false.B - dataArray.io.write <> missUnit.io.data_write + ctrlUnit.io.dataWrite.req.ready := false.B + dataArray.io.write <> missUnit.io.dataWrite } } else { - dataArray.io.write <> missUnit.io.data_write + dataArray.io.write <> missUnit.io.dataWrite } - dataArray.io.read <> mainPipe.io.dataArray.toIData - mainPipe.io.dataArray.fromIData := dataArray.io.readResp + dataArray.io.read <> mainPipe.io.dataRead // metaArray io metaArray.io.flushAll := io.fencei - metaArray.io.flush <> mainPipe.io.metaArrayFlush + metaArray.io.flush <> mainPipe.io.metaFlush if (outer.ctrlUnitOpt.nonEmpty) { val ctrlUnit = outer.ctrlUnitOpt.get.module when(ctrlUnit.io.injecting) { metaArray.io.write <> ctrlUnit.io.metaWrite metaArray.io.read <> ctrlUnit.io.metaRead - missUnit.io.meta_write.ready := false.B - prefetcher.io.metaRead.toIMeta.ready := false.B + missUnit.io.metaWrite.req.ready := false.B + prefetcher.io.metaRead.req.ready := false.B + prefetcher.io.metaRead.resp := DontCare }.otherwise { - ctrlUnit.io.metaWrite.ready := false.B - ctrlUnit.io.metaRead.ready := false.B - metaArray.io.write <> missUnit.io.meta_write - metaArray.io.read <> prefetcher.io.metaRead.toIMeta + ctrlUnit.io.metaWrite.req.ready := false.B + ctrlUnit.io.metaRead.req.ready := false.B + ctrlUnit.io.metaRead.resp := DontCare + metaArray.io.write <> missUnit.io.metaWrite + metaArray.io.read <> prefetcher.io.metaRead } - ctrlUnit.io.metaReadResp := metaArray.io.readResp } else { - metaArray.io.write <> missUnit.io.meta_write - metaArray.io.read <> prefetcher.io.metaRead.toIMeta + metaArray.io.write <> missUnit.io.metaWrite + metaArray.io.read <> prefetcher.io.metaRead } - prefetcher.io.metaRead.fromIMeta := metaArray.io.readResp prefetcher.io.flush := io.flush prefetcher.io.csr_pf_enable := io.csr_pf_enable prefetcher.io.ecc_enable := ecc_enable - prefetcher.io.MSHRResp := missUnit.io.fetch_resp - prefetcher.io.flushFromBpu := io.ftqPrefetch.flushFromBpu + prefetcher.io.missResp := missUnit.io.resp + prefetcher.io.flushFromBpu := io.fromFtq.flushFromBpu // cache softPrefetch private val softPrefetchValid = RegInit(false.B) - private val softPrefetch = RegInit(0.U.asTypeOf(new IPrefetchReq)) + private val softPrefetch = RegInit(0.U.asTypeOf(new PrefetchReqBundle)) /* FIXME: * If there is already a pending softPrefetch request, it will be overwritten. * Also, if there are multiple softPrefetch requests in the same cycle, only the first one will be accepted. @@ -145,46 +142,46 @@ class ICacheImp(outer: ICache) extends LazyModuleImp(outer) with HasICacheParame * However, the impact on performance still needs to be assessed. * Considering that the frequency of prefetch.i may not be high, let's start with a temporary dummy solution. */ - when(io.softPrefetch.map(_.valid).reduce(_ || _)) { + when(io.softPrefetchReq.map(_.valid).reduce(_ || _)) { softPrefetchValid := true.B softPrefetch.fromSoftPrefetch(MuxCase( 0.U.asTypeOf(new SoftIfetchPrefetchBundle), - io.softPrefetch.map(req => req.valid -> req.bits) + io.softPrefetchReq.map(req => req.valid -> req.bits) )) }.elsewhen(prefetcher.io.req.fire) { softPrefetchValid := false.B } // pass ftqPrefetch - private val ftqPrefetch = WireInit(0.U.asTypeOf(new IPrefetchReq)) - ftqPrefetch.fromFtqICacheInfo(io.ftqPrefetch.req.bits) + private val ftqPrefetch = WireInit(0.U.asTypeOf(new PrefetchReqBundle)) + ftqPrefetch.fromFtqICacheInfo(io.fromFtq.prefetchReq.bits.req) // software prefetch has higher priority - prefetcher.io.req.valid := softPrefetchValid || io.ftqPrefetch.req.valid + prefetcher.io.req.valid := softPrefetchValid || io.fromFtq.prefetchReq.valid prefetcher.io.req.bits := Mux(softPrefetchValid, softPrefetch, ftqPrefetch) - prefetcher.io.req.bits.backendException := io.ftqPrefetch.backendException - io.ftqPrefetch.req.ready := prefetcher.io.req.ready && !softPrefetchValid + prefetcher.io.req.bits.backendException := io.fromFtq.prefetchReq.bits.backendException + io.fromFtq.prefetchReq.ready := prefetcher.io.req.ready && !softPrefetchValid missUnit.io.hartId := io.hartId missUnit.io.fencei := io.fencei missUnit.io.flush := io.flush - missUnit.io.fetch_req <> mainPipe.io.mshr.req - missUnit.io.prefetch_req <> prefetcher.io.MSHRReq - missUnit.io.mem_grant.valid := false.B - missUnit.io.mem_grant.bits := DontCare - missUnit.io.mem_grant <> bus.d + missUnit.io.fetchReq <> mainPipe.io.missReq + missUnit.io.prefetchReq <> prefetcher.io.missReq + missUnit.io.memGrant.valid := false.B + missUnit.io.memGrant.bits := DontCare + missUnit.io.memGrant <> bus.d mainPipe.io.flush := io.flush - mainPipe.io.respStall := io.stop + mainPipe.io.respStall := io.fromIfu.stall mainPipe.io.ecc_enable := ecc_enable mainPipe.io.hartId := io.hartId - mainPipe.io.mshr.resp := missUnit.io.fetch_resp - mainPipe.io.fetch.req <> io.fetch.req + mainPipe.io.missResp := missUnit.io.resp + mainPipe.io.req <> io.fromFtq.fetchReq mainPipe.io.wayLookupRead <> wayLookup.io.read wayLookup.io.flush := io.flush wayLookup.io.write <> prefetcher.io.wayLookupWrite - wayLookup.io.update := missUnit.io.fetch_resp + wayLookup.io.update := missUnit.io.resp - replacer.io.touch <> mainPipe.io.touch + replacer.io.touch <> mainPipe.io.replacerTouch replacer.io.victim <> missUnit.io.victim io.pmp(0) <> mainPipe.io.pmp(0) @@ -197,12 +194,14 @@ class ICacheImp(outer: ICache) extends LazyModuleImp(outer) with HasICacheParame io.itlbFlushPipe := prefetcher.io.itlbFlushPipe // notify IFU that Icache pipeline is available - io.toIFU := mainPipe.io.fetch.req.ready - io.perfInfo := mainPipe.io.perfInfo + io.toIfu.fetchReady := mainPipe.io.req.ready + + // send resp + io.toIfu.fetchResp <> mainPipe.io.resp - io.fetch.resp <> mainPipe.io.fetch.resp - io.fetch.topdownIcacheMiss := mainPipe.io.fetch.topdownIcacheMiss - io.fetch.topdownItlbMiss := mainPipe.io.fetch.topdownItlbMiss + // perf + io.toIfu.perf := mainPipe.io.perf + io.toIfu.topdown := mainPipe.io.topdown bus.b.ready := false.B bus.c.valid := false.B @@ -210,7 +209,7 @@ class ICacheImp(outer: ICache) extends LazyModuleImp(outer) with HasICacheParame bus.e.valid := false.B bus.e.bits := DontCare - bus.a <> missUnit.io.mem_acquire + bus.a <> missUnit.io.memAcquire // Parity error port private val errors = mainPipe.io.errors @@ -224,10 +223,10 @@ class ICacheImp(outer: ICache) extends LazyModuleImp(outer) with HasICacheParame XSPerfAccumulate( "softPrefetch_drop_not_ready", - io.softPrefetch.map(_.valid).reduce(_ || _) && softPrefetchValid && !prefetcher.io.req.fire + io.softPrefetchReq.map(_.valid).reduce(_ || _) && softPrefetchValid && !prefetcher.io.req.fire ) - XSPerfAccumulate("softPrefetch_drop_multi_req", PopCount(io.softPrefetch.map(_.valid)) > 1.U) - XSPerfAccumulate("softPrefetch_block_ftq", softPrefetchValid && io.ftqPrefetch.req.valid) + XSPerfAccumulate("softPrefetch_drop_multi_req", PopCount(io.softPrefetchReq.map(_.valid)) > 1.U) + XSPerfAccumulate("softPrefetch_block_ftq", softPrefetchValid && io.fromFtq.prefetchReq.valid) val perfEvents: Seq[(String, Bool)] = Seq( ("icache_miss_cnt ", false.B), diff --git a/src/main/scala/xiangshan/frontend/icache/ICacheMSHR.scala b/src/main/scala/xiangshan/frontend/icache/ICacheMSHR.scala index 3f9b4229c79..97473d2dc20 100644 --- a/src/main/scala/xiangshan/frontend/icache/ICacheMSHR.scala +++ b/src/main/scala/xiangshan/frontend/icache/ICacheMSHR.scala @@ -24,14 +24,24 @@ import utility.ReqSourceKey class ICacheMSHR(edge: TLEdgeOut, isFetch: Boolean, ID: Int)(implicit p: Parameters) extends ICacheModule { class ICacheMSHRIO(edge: TLEdgeOut)(implicit p: Parameters) extends ICacheBundle { - val fencei: Bool = Input(Bool()) - val flush: Bool = Input(Bool()) - val invalid: Bool = Input(Bool()) - val req: DecoupledIO[ICacheMissReq] = Flipped(DecoupledIO(new ICacheMissReq)) - val acquire: DecoupledIO[MSHRAcquire] = DecoupledIO(new MSHRAcquire(edge)) - val lookUps: Vec[MSHRLookup] = Flipped(Vec(2, new MSHRLookup)) - val resp: Valid[MSHRResp] = ValidIO(new MSHRResp) - val victimWay: UInt = Input(UInt(wayBits.W)) + val fencei: Bool = Input(Bool()) + val flush: Bool = Input(Bool()) + + // request from mainPipe / prefetchPipe + val req: DecoupledIO[MissReqBundle] = Flipped(DecoupledIO(new MissReqBundle)) + // look up if the request is already in MSHR + // NOTE: lookUps Vec(2) is not Vec(PortNumber), it's mainPipe + prefetchPipe + val lookUps: Vec[MshrLookupBundle] = Flipped(Vec(2, new MshrLookupBundle)) + + // send request to L2 (tilelink bus) + val acquire: DecoupledIO[MshrAcquireBundle] = DecoupledIO(new MshrAcquireBundle(edge)) + // select the victim way when acquire fire + val victimWay: UInt = Input(UInt(wayBits.W)) + + // offer the information needed by responding to requester + val info: Valid[MshrInfoBundle] = ValidIO(new MshrInfoBundle) + // after respond to requester, invalid the MSHR + val invalid: Bool = Input(Bool()) } val io: ICacheMSHRIO = IO(new ICacheMSHRIO(edge)) @@ -49,11 +59,11 @@ class ICacheMSHR(edge: TLEdgeOut, isFetch: Boolean, ID: Int)(implicit p: Paramet // look up and return result at the same cycle private val hits = io.lookUps.map { lookup => - valid && !fencei && !flush && (lookup.info.bits.vSetIdx === vSetIdx) && - (lookup.info.bits.blkPaddr === blkPaddr) + valid && !fencei && !flush && (lookup.req.bits.vSetIdx === vSetIdx) && + (lookup.req.bits.blkPaddr === blkPaddr) } // Decoupling valid and bits - (0 until 2).foreach(i => io.lookUps(i).hit := hits(i)) + (0 until 2).foreach(i => io.lookUps(i).resp.hit := hits(i)) // disable wake up when hit MSHR (fencei is low) // when(hit) { @@ -103,8 +113,8 @@ class ICacheMSHR(edge: TLEdgeOut, isFetch: Boolean, ID: Int)(implicit p: Paramet } // offer the information other than data for write sram and response fetch - io.resp.valid := valid && (!flush && !fencei) - io.resp.bits.blkPaddr := blkPaddr - io.resp.bits.vSetIdx := vSetIdx - io.resp.bits.way := way + io.info.valid := valid && (!flush && !fencei) + io.info.bits.blkPaddr := blkPaddr + io.info.bits.vSetIdx := vSetIdx + io.info.bits.way := way } diff --git a/src/main/scala/xiangshan/frontend/icache/ICacheMainPipe.scala b/src/main/scala/xiangshan/frontend/icache/ICacheMainPipe.scala index 404a9834020..edfbc6c83c7 100644 --- a/src/main/scala/xiangshan/frontend/icache/ICacheMainPipe.scala +++ b/src/main/scala/xiangshan/frontend/icache/ICacheMainPipe.scala @@ -27,8 +27,9 @@ import utility.XSPerfHistogram import xiangshan.L1CacheErrorInfo import xiangshan.cache.mmu.Pbmt import xiangshan.cache.mmu.TlbCmd -import xiangshan.cache.mmu.ValidHoldBypass // FIXME: should move this to utility? +import xiangshan.cache.mmu.ValidHoldBypass import xiangshan.frontend.ExceptionType +import xiangshan.frontend.FtqToFetchBundle class ICacheMainPipe(implicit p: Parameters) extends ICacheModule with ICacheECCHelper @@ -39,35 +40,38 @@ class ICacheMainPipe(implicit p: Parameters) extends ICacheModule val hartId: UInt = Input(UInt(hartIdLen.W)) /*** internal interface ***/ - val dataArray: ICacheDataReqBundle = new ICacheDataReqBundle - val metaArrayFlush: Vec[Valid[ICacheMetaFlushBundle]] = Vec(PortNumber, ValidIO(new ICacheMetaFlushBundle)) - val touch: Vec[Valid[ReplacerTouch]] = Vec(PortNumber, ValidIO(new ReplacerTouch)) - val wayLookupRead: DecoupledIO[WayLookupInfo] = Flipped(DecoupledIO(new WayLookupInfo)) - val mshr: ICacheMSHRBundle = new ICacheMSHRBundle - val ecc_enable: Bool = Input(Bool()) + val dataRead: DataReadBundle = new DataReadBundle + val metaFlush: MetaFlushBundle = new MetaFlushBundle + val replacerTouch: ReplacerTouchBundle = new ReplacerTouchBundle + val wayLookupRead: DecoupledIO[WayLookupBundle] = Flipped(DecoupledIO(new WayLookupBundle)) + val missReq: DecoupledIO[MissReqBundle] = DecoupledIO(new MissReqBundle) + val missResp: Valid[MissRespBundle] = Flipped(ValidIO(new MissRespBundle)) + val ecc_enable: Bool = Input(Bool()) /*** outside interface ***/ // FTQ - val fetch: ICacheMainPipeBundle = new ICacheMainPipeBundle - val flush: Bool = Input(Bool()) + val req: DecoupledIO[FtqToFetchBundle] = Flipped(DecoupledIO(new FtqToFetchBundle)) + val flush: Bool = Input(Bool()) // PMP - val pmp: Vec[ICachePMPBundle] = Vec(PortNumber, new ICachePMPBundle) + val pmp: Vec[PmpCheckBundle] = Vec(PortNumber, new PmpCheckBundle) // IFU - val respStall: Bool = Input(Bool()) + val resp: Valid[ICacheRespBundle] = ValidIO(new ICacheRespBundle) + val respStall: Bool = Input(Bool()) // backend/BEU val errors: Vec[Valid[L1CacheErrorInfo]] = Output(Vec(PortNumber, ValidIO(new L1CacheErrorInfo))) /*** PERF ***/ - val perfInfo: ICachePerfInfo = Output(new ICachePerfInfo) + val perf: ICachePerfInfo = Output(new ICachePerfInfo) + val topdown: ICacheTopdownInfo = Output(new ICacheTopdownInfo) } val io: ICacheMainPipeIO = IO(new ICacheMainPipeIO) /** Input/Output port */ - private val (fromFtq, toIFU) = (io.fetch.req, io.fetch.resp) - private val (toData, fromData) = (io.dataArray.toIData, io.dataArray.fromIData) - private val toMetaFlush = io.metaArrayFlush - private val (toMSHR, fromMSHR) = (io.mshr.req, io.mshr.resp) + private val (fromFtq, toIfu) = (io.req, io.resp) + private val (toData, fromData) = (io.dataRead.req, io.dataRead.resp) + private val toMetaFlush = io.metaFlush.req + private val (toMSHR, fromMSHR) = (io.missReq, io.missResp) private val (toPMP, fromPMP) = (io.pmp.map(_.req), io.pmp.map(_.resp)) private val fromWayLookup = io.wayLookupRead private val ecc_enable = @@ -103,7 +107,7 @@ class ICacheMainPipe(implicit p: Parameters) extends ICacheModule /** s0 control */ // 0,1,2,3 -> dataArray(data); 4 -> mainPipe // Ftq RegNext Register - private val fromFtqReq = fromFtq.bits.pcMemRead + private val fromFtqReq = fromFtq.bits.req private val s0_valid = fromFtq.valid private val s0_req_valid_all = (0 until partWayNum + 1).map(i => fromFtq.bits.readValid(i)) private val s0_req_vaddr_all = @@ -117,7 +121,7 @@ class ICacheMainPipe(implicit p: Parameters) extends ICacheModule private val s0_req_vSetIdx = s0_req_vSetIdx_all.last private val s0_doubleline = s0_doubleline_all.last - private val s0_backendException = fromFtq.bits.backendException + private val s0_isBackendException = fromFtq.bits.isBackendException /** ****************************************************************************** @@ -180,13 +184,13 @@ class ICacheMainPipe(implicit p: Parameters) extends ICacheModule private val s1_req_gpaddr = RegEnable(s0_req_gpaddr, 0.U.asTypeOf(s0_req_gpaddr), s0_fire) private val s1_req_isForVSnonLeafPTE = RegEnable(s0_req_isForVSnonLeafPTE, 0.U.asTypeOf(s0_req_isForVSnonLeafPTE), s0_fire) - private val s1_doubleline = RegEnable(s0_doubleline, 0.U.asTypeOf(s0_doubleline), s0_fire) - private val s1_SRAMhits = RegEnable(s0_hits, 0.U.asTypeOf(s0_hits), s0_fire) - private val s1_itlb_exception = RegEnable(s0_itlb_exception, 0.U.asTypeOf(s0_itlb_exception), s0_fire) - private val s1_backendException = RegEnable(s0_backendException, false.B, s0_fire) - private val s1_itlb_pbmt = RegEnable(s0_itlb_pbmt, 0.U.asTypeOf(s0_itlb_pbmt), s0_fire) - private val s1_waymasks = RegEnable(s0_waymasks, 0.U.asTypeOf(s0_waymasks), s0_fire) - private val s1_meta_codes = RegEnable(s0_meta_codes, 0.U.asTypeOf(s0_meta_codes), s0_fire) + private val s1_doubleline = RegEnable(s0_doubleline, 0.U.asTypeOf(s0_doubleline), s0_fire) + private val s1_SRAMhits = RegEnable(s0_hits, 0.U.asTypeOf(s0_hits), s0_fire) + private val s1_itlb_exception = RegEnable(s0_itlb_exception, 0.U.asTypeOf(s0_itlb_exception), s0_fire) + private val s1_isBackendException = RegEnable(s0_isBackendException, false.B, s0_fire) + private val s1_itlb_pbmt = RegEnable(s0_itlb_pbmt, 0.U.asTypeOf(s0_itlb_pbmt), s0_fire) + private val s1_waymasks = RegEnable(s0_waymasks, 0.U.asTypeOf(s0_waymasks), s0_fire) + private val s1_meta_codes = RegEnable(s0_meta_codes, 0.U.asTypeOf(s0_meta_codes), s0_fire) private val s1_req_vSetIdx = s1_req_vaddr.map(get_idx) private val s1_req_paddr = getPaddrFromPtag(s1_req_vaddr, s1_req_ptags) @@ -211,11 +215,11 @@ class ICacheMainPipe(implicit p: Parameters) extends ICacheModule ****************************************************************************** */ (0 until PortNumber).foreach { i => - io.touch(i).bits.vSetIdx := s1_req_vSetIdx(i) - io.touch(i).bits.way := OHToUInt(s1_waymasks(i)) + io.replacerTouch.req(i).bits.vSetIdx := s1_req_vSetIdx(i) + io.replacerTouch.req(i).bits.way := OHToUInt(s1_waymasks(i)) } - io.touch(0).valid := RegNext(s0_fire) && s1_SRAMhits(0) - io.touch(1).valid := RegNext(s0_fire) && s1_SRAMhits(1) && s1_doubleline + io.replacerTouch.req(0).valid := RegNext(s0_fire) && s1_SRAMhits(0) + io.replacerTouch.req(1).valid := RegNext(s0_fire) && s1_SRAMhits(1) && s1_doubleline /** ****************************************************************************** @@ -287,12 +291,12 @@ class ICacheMainPipe(implicit p: Parameters) extends ICacheModule private val s2_req_gpaddr = RegEnable(s1_req_gpaddr, 0.U.asTypeOf(s1_req_gpaddr), s1_fire) private val s2_req_isForVSnonLeafPTE = RegEnable(s1_req_isForVSnonLeafPTE, 0.U.asTypeOf(s1_req_isForVSnonLeafPTE), s1_fire) - private val s2_doubleline = RegEnable(s1_doubleline, 0.U.asTypeOf(s1_doubleline), s1_fire) - private val s2_exception = RegEnable(s1_exception_out, 0.U.asTypeOf(s1_exception_out), s1_fire) - private val s2_backendException = RegEnable(s1_backendException, false.B, s1_fire) - private val s2_pmp_mmio = RegEnable(s1_pmp_mmio, 0.U.asTypeOf(s1_pmp_mmio), s1_fire) - private val s2_itlb_pbmt = RegEnable(s1_itlb_pbmt, 0.U.asTypeOf(s1_itlb_pbmt), s1_fire) - private val s2_waymasks = RegEnable(s1_waymasks, 0.U.asTypeOf(s1_waymasks), s1_fire) + private val s2_doubleline = RegEnable(s1_doubleline, 0.U.asTypeOf(s1_doubleline), s1_fire) + private val s2_exception = RegEnable(s1_exception_out, 0.U.asTypeOf(s1_exception_out), s1_fire) + private val s2_isBackendException = RegEnable(s1_isBackendException, false.B, s1_fire) + private val s2_pmp_mmio = RegEnable(s1_pmp_mmio, 0.U.asTypeOf(s1_pmp_mmio), s1_fire) + private val s2_itlb_pbmt = RegEnable(s1_itlb_pbmt, 0.U.asTypeOf(s1_itlb_pbmt), s1_fire) + private val s2_waymasks = RegEnable(s1_waymasks, 0.U.asTypeOf(s1_waymasks), s1_fire) private val s2_req_vSetIdx = s2_req_vaddr.map(get_idx) private val s2_req_offset = s2_req_vaddr(0)(log2Ceil(blockBytes) - 1, 0) @@ -432,7 +436,7 @@ class ICacheMainPipe(implicit p: Parameters) extends ICacheModule s2_mmio.take(i + 1).map(!_).reduce(_ && _) }) - private val toMSHRArbiter = Module(new Arbiter(new ICacheMissReq, PortNumber)) + private val toMSHRArbiter = Module(new Arbiter(new MissReqBundle, PortNumber)) // To avoid sending duplicate requests. private val s2_has_send = RegInit(VecInit(Seq.fill(PortNumber)(false.B))) @@ -470,21 +474,21 @@ class ICacheMainPipe(implicit p: Parameters) extends ICacheModule * response to IFU ****************************************************************************** */ - toIFU.valid := s2_fire - toIFU.bits.doubleline := s2_doubleline - toIFU.bits.data := s2_datas.asTypeOf(UInt(blockBits.W)) - toIFU.bits.backendException := s2_backendException + toIfu.valid := s2_fire + toIfu.bits.doubleline := s2_doubleline + toIfu.bits.data := s2_datas.asTypeOf(UInt(blockBits.W)) + toIfu.bits.isBackendException := s2_isBackendException (0 until PortNumber).foreach { i => - toIFU.bits.vaddr(i) := s2_req_vaddr(i) - toIFU.bits.paddr(i) := s2_req_paddr(i) + toIfu.bits.vaddr(i) := s2_req_vaddr(i) + toIfu.bits.paddr(i) := s2_req_paddr(i) val needThisLine = if (i == 0) true.B else s2_doubleline - toIFU.bits.exception(i) := Mux(needThisLine, s2_exception_out(i), ExceptionType.none) - toIFU.bits.pmp_mmio(i) := Mux(needThisLine, s2_pmp_mmio(i), false.B) - toIFU.bits.itlb_pbmt(i) := Mux(needThisLine, s2_itlb_pbmt(i), Pbmt.pma) + toIfu.bits.exception(i) := Mux(needThisLine, s2_exception_out(i), ExceptionType.none) + toIfu.bits.pmp_mmio(i) := Mux(needThisLine, s2_pmp_mmio(i), false.B) + toIfu.bits.itlb_pbmt(i) := Mux(needThisLine, s2_itlb_pbmt(i), Pbmt.pma) } // valid only for the first gpf - toIFU.bits.gpaddr := s2_req_gpaddr - toIFU.bits.isForVSnonLeafPTE := s2_req_isForVSnonLeafPTE + toIfu.bits.gpaddr := s2_req_gpaddr + toIfu.bits.isForVSnonLeafPTE := s2_req_isForVSnonLeafPTE s2_flush := io.flush s2_ready := (s2_fetch_finish && !io.respStall) || !s2_valid @@ -511,25 +515,25 @@ class ICacheMainPipe(implicit p: Parameters) extends ICacheModule * performance info. TODO: need to simplify the logic ***********************************************************s******************* */ - io.perfInfo.only_0_hit := s2_hits(0) && !s2_doubleline - io.perfInfo.only_0_miss := !s2_hits(0) && !s2_doubleline - io.perfInfo.hit_0_hit_1 := s2_hits(0) && s2_hits(1) && s2_doubleline - io.perfInfo.hit_0_miss_1 := s2_hits(0) && !s2_hits(1) && s2_doubleline - io.perfInfo.miss_0_hit_1 := !s2_hits(0) && s2_hits(1) && s2_doubleline - io.perfInfo.miss_0_miss_1 := !s2_hits(0) && !s2_hits(1) && s2_doubleline - io.perfInfo.hit_0_except_1 := s2_hits(0) && ExceptionType.hasException(s2_exception(1)) && s2_doubleline - io.perfInfo.miss_0_except_1 := !s2_hits(0) && ExceptionType.hasException(s2_exception(1)) && s2_doubleline - io.perfInfo.bank_hit(0) := s2_hits(0) - io.perfInfo.bank_hit(1) := s2_hits(1) && s2_doubleline - io.perfInfo.except_0 := ExceptionType.hasException(s2_exception(0)) - io.perfInfo.hit := s2_hits(0) && (!s2_doubleline || s2_hits(1)) + io.perf.only_0_hit := s2_hits(0) && !s2_doubleline + io.perf.only_0_miss := !s2_hits(0) && !s2_doubleline + io.perf.hit_0_hit_1 := s2_hits(0) && s2_hits(1) && s2_doubleline + io.perf.hit_0_miss_1 := s2_hits(0) && !s2_hits(1) && s2_doubleline + io.perf.miss_0_hit_1 := !s2_hits(0) && s2_hits(1) && s2_doubleline + io.perf.miss_0_miss_1 := !s2_hits(0) && !s2_hits(1) && s2_doubleline + io.perf.hit_0_except_1 := s2_hits(0) && ExceptionType.hasException(s2_exception(1)) && s2_doubleline + io.perf.miss_0_except_1 := !s2_hits(0) && ExceptionType.hasException(s2_exception(1)) && s2_doubleline + io.perf.bank_hit(0) := s2_hits(0) + io.perf.bank_hit(1) := s2_hits(1) && s2_doubleline + io.perf.except_0 := ExceptionType.hasException(s2_exception(0)) + io.perf.hit := s2_hits(0) && (!s2_doubleline || s2_hits(1)) /** fetch bubble generated by icache miss */ XSPerfAccumulate("icache_bubble_s2_miss", s2_valid && !s2_fetch_finish) XSPerfAccumulate("icache_bubble_s0_wayLookup", s0_valid && !fromWayLookup.ready) - io.fetch.topdownIcacheMiss := !s2_fetch_finish - io.fetch.topdownItlbMiss := s0_valid && !fromWayLookup.ready + io.topdown.icacheMiss := !s2_fetch_finish + io.topdown.itlbMiss := s0_valid && !fromWayLookup.ready // class ICacheTouchDB(implicit p: Parameters) extends ICacheBundle{ // val blkPaddr = UInt((PAddrBits - blockOffBits).W) @@ -549,7 +553,7 @@ class ICacheMainPipe(implicit p: Parameters) extends ICacheModule // ICacheTouchDumpData(i).waymask := OHToUInt(s2_tag_match_vec(i)) // ICacheTouchTable.log( // data = ICacheTouchDumpData(i), - // en = io.touch(i).valid, + // en = io.replacerTouch.req(i).valid, // site = "req_" + i.toString, // clock = clock, // reset = reset @@ -563,9 +567,9 @@ class ICacheMainPipe(implicit p: Parameters) extends ICacheModule */ if (env.EnableDifftest) { val discards = (0 until PortNumber).map { i => - ExceptionType.hasException(toIFU.bits.exception(i)) || - toIFU.bits.pmp_mmio(i) || - Pbmt.isUncache(toIFU.bits.itlb_pbmt(i)) + ExceptionType.hasException(toIfu.bits.exception(i)) || + toIfu.bits.pmp_mmio(i) || + Pbmt.isUncache(toIfu.bits.itlb_pbmt(i)) } val blkPaddrAll = s2_req_paddr.map(addr => (addr(PAddrBits - 1, blockOffBits) << blockOffBits).asUInt) (0 until ICacheDataBanks).foreach { i => diff --git a/src/main/scala/xiangshan/frontend/icache/ICacheMetaArray.scala b/src/main/scala/xiangshan/frontend/icache/ICacheMetaArray.scala index 2d23da53882..7d2645b6b48 100644 --- a/src/main/scala/xiangshan/frontend/icache/ICacheMetaArray.scala +++ b/src/main/scala/xiangshan/frontend/icache/ICacheMetaArray.scala @@ -24,11 +24,10 @@ import utility.sram.SRAMTemplate class ICacheMetaArray(implicit p: Parameters) extends ICacheModule with ICacheECCHelper { class ICacheMetaArrayIO(implicit p: Parameters) extends ICacheBundle { - val write: DecoupledIO[ICacheMetaWriteBundle] = Flipped(DecoupledIO(new ICacheMetaWriteBundle)) - val read: DecoupledIO[ICacheReadBundle] = Flipped(DecoupledIO(new ICacheReadBundle)) - val readResp: ICacheMetaRespBundle = Output(new ICacheMetaRespBundle) - val flush: Vec[Valid[ICacheMetaFlushBundle]] = Vec(PortNumber, Flipped(ValidIO(new ICacheMetaFlushBundle))) - val flushAll: Bool = Input(Bool()) + val write: MetaWriteBundle = Flipped(new MetaWriteBundle) + val read: MetaReadBundle = Flipped(new MetaReadBundle) + val flush: MetaFlushBundle = Flipped(new MetaFlushBundle) + val flushAll: Bool = Input(Bool()) } val io: ICacheMetaArrayIO = IO(new ICacheMetaArrayIO) @@ -50,27 +49,27 @@ class ICacheMetaArray(implicit p: Parameters) extends ICacheModule with ICacheEC // sanity check require(ICacheMetaEntryBits == (new ICacheMetaEntry).getWidth) - private val port_0_read_0 = io.read.valid && !io.read.bits.vSetIdx(0)(0) - private val port_0_read_1 = io.read.valid && io.read.bits.vSetIdx(0)(0) - private val port_1_read_1 = io.read.valid && io.read.bits.vSetIdx(1)(0) && io.read.bits.isDoubleLine - private val port_1_read_0 = io.read.valid && !io.read.bits.vSetIdx(1)(0) && io.read.bits.isDoubleLine + private val port_0_read_0 = io.read.req.valid && !io.read.req.bits.vSetIdx(0)(0) + private val port_0_read_1 = io.read.req.valid && io.read.req.bits.vSetIdx(0)(0) + private val port_1_read_1 = io.read.req.valid && io.read.req.bits.vSetIdx(1)(0) && io.read.req.bits.isDoubleLine + private val port_1_read_0 = io.read.req.valid && !io.read.req.bits.vSetIdx(1)(0) && io.read.req.bits.isDoubleLine - private val port_0_read_0_reg = RegEnable(port_0_read_0, 0.U.asTypeOf(port_0_read_0), io.read.fire) - private val port_0_read_1_reg = RegEnable(port_0_read_1, 0.U.asTypeOf(port_0_read_1), io.read.fire) - private val port_1_read_1_reg = RegEnable(port_1_read_1, 0.U.asTypeOf(port_1_read_1), io.read.fire) - private val port_1_read_0_reg = RegEnable(port_1_read_0, 0.U.asTypeOf(port_1_read_0), io.read.fire) + private val port_0_read_0_reg = RegEnable(port_0_read_0, 0.U.asTypeOf(port_0_read_0), io.read.req.fire) + private val port_0_read_1_reg = RegEnable(port_0_read_1, 0.U.asTypeOf(port_0_read_1), io.read.req.fire) + private val port_1_read_1_reg = RegEnable(port_1_read_1, 0.U.asTypeOf(port_1_read_1), io.read.req.fire) + private val port_1_read_0_reg = RegEnable(port_1_read_0, 0.U.asTypeOf(port_1_read_0), io.read.req.fire) - private val bank_0_idx = Mux(port_0_read_0, io.read.bits.vSetIdx(0), io.read.bits.vSetIdx(1)) - private val bank_1_idx = Mux(port_0_read_1, io.read.bits.vSetIdx(0), io.read.bits.vSetIdx(1)) + private val bank_0_idx = Mux(port_0_read_0, io.read.req.bits.vSetIdx(0), io.read.req.bits.vSetIdx(1)) + private val bank_1_idx = Mux(port_0_read_1, io.read.req.bits.vSetIdx(0), io.read.req.bits.vSetIdx(1)) - private val write_bank_0 = io.write.valid && !io.write.bits.bankIdx - private val write_bank_1 = io.write.valid && io.write.bits.bankIdx + private val write_bank_0 = io.write.req.valid && !io.write.req.bits.bankIdx + private val write_bank_1 = io.write.req.valid && io.write.req.bits.bankIdx private val write_meta_bits = ICacheMetaEntry( meta = ICacheMetadata( - tag = io.write.bits.phyTag + tag = io.write.req.bits.phyTag ), - poison = io.write.bits.poison + poison = io.write.req.bits.poison ) private val tagArrays = (0 until PortNumber) map { bank => @@ -92,8 +91,8 @@ class ICacheMetaArray(implicit p: Parameters) extends ICacheModule with ICacheEC tagArray.io.w.req.valid := write_bank_0 tagArray.io.w.req.bits.apply( data = write_meta_bits, - setIdx = io.write.bits.virIdx(highestIdxBit, 1), - waymask = io.write.bits.waymask + setIdx = io.write.req.bits.virIdx(highestIdxBit, 1), + waymask = io.write.req.bits.waymask ) } else { tagArray.io.r.req.valid := port_0_read_1 || port_1_read_1 @@ -101,8 +100,8 @@ class ICacheMetaArray(implicit p: Parameters) extends ICacheModule with ICacheEC tagArray.io.w.req.valid := write_bank_1 tagArray.io.w.req.bits.apply( data = write_meta_bits, - setIdx = io.write.bits.virIdx(highestIdxBit, 1), - waymask = io.write.bits.waymask + setIdx = io.write.req.bits.virIdx(highestIdxBit, 1), + waymask = io.write.req.bits.waymask ) } @@ -110,30 +109,31 @@ class ICacheMetaArray(implicit p: Parameters) extends ICacheModule with ICacheEC } private val mbistPl = MbistPipeline.PlaceMbistPipeline(1, "MbistPipeIcacheTag", hasMbist) - private val read_set_idx_next = RegEnable(io.read.bits.vSetIdx, 0.U.asTypeOf(io.read.bits.vSetIdx), io.read.fire) - private val valid_array = RegInit(VecInit(Seq.fill(nWays)(0.U(nSets.W)))) - private val valid_metas = Wire(Vec(PortNumber, Vec(nWays, Bool()))) + private val read_set_idx_next = + RegEnable(io.read.req.bits.vSetIdx, 0.U.asTypeOf(io.read.req.bits.vSetIdx), io.read.req.fire) + private val valid_array = RegInit(VecInit(Seq.fill(nWays)(0.U(nSets.W)))) + private val valid_metas = Wire(Vec(PortNumber, Vec(nWays, Bool()))) // valid read (0 until PortNumber).foreach(i => (0 until nWays).foreach(way => valid_metas(i)(way) := valid_array(way)(read_set_idx_next(i)) ) ) - io.readResp.entryValid := valid_metas + io.read.resp.entryValid := valid_metas - io.read.ready := !io.write.valid && !io.flush.map(_.valid).reduce(_ || _) && !io.flushAll && + io.read.req.ready := !io.write.req.valid && !io.flush.req.map(_.valid).reduce(_ || _) && !io.flushAll && tagArrays.map(_.io.r.req.ready).reduce(_ && _) // valid write - private val way_num = OHToUInt(io.write.bits.waymask) - when(io.write.valid) { - valid_array(way_num) := valid_array(way_num).bitSet(io.write.bits.virIdx, true.B) + private val way_num = OHToUInt(io.write.req.bits.waymask) + when(io.write.req.valid) { + valid_array(way_num) := valid_array(way_num).bitSet(io.write.req.bits.virIdx, true.B) } - XSPerfAccumulate("meta_refill_num", io.write.valid) + XSPerfAccumulate("meta_refill_num", io.write.req.valid) - io.readResp.metas <> DontCare - io.readResp.codes <> DontCare + io.read.resp.metas <> DontCare + io.read.resp.codes <> DontCare private val readMetaEntries = tagArrays.map(port => port.io.r.resp.asTypeOf(Vec(nWays, new ICacheMetaEntry()))) private val readMetas = readMetaEntries.map(_.map(_.meta)) private val readCodes = readMetaEntries.map(_.map(_.code)) @@ -144,34 +144,34 @@ class ICacheMetaArray(implicit p: Parameters) extends ICacheModule with ICacheEC } when(port_0_read_0_reg) { - io.readResp.metas(0) := readMetas(0) - io.readResp.codes(0) := readCodes(0) + io.read.resp.metas(0) := readMetas(0) + io.read.resp.codes(0) := readCodes(0) }.elsewhen(port_0_read_1_reg) { - io.readResp.metas(0) := readMetas(1) - io.readResp.codes(0) := readCodes(1) + io.read.resp.metas(0) := readMetas(1) + io.read.resp.codes(0) := readCodes(1) } when(port_1_read_0_reg) { - io.readResp.metas(1) := readMetas(0) - io.readResp.codes(1) := readCodes(0) + io.read.resp.metas(1) := readMetas(0) + io.read.resp.codes(1) := readCodes(0) }.elsewhen(port_1_read_1_reg) { - io.readResp.metas(1) := readMetas(1) - io.readResp.codes(1) := readCodes(1) + io.read.resp.metas(1) := readMetas(1) + io.read.resp.codes(1) := readCodes(1) } - io.write.ready := true.B // TODO : has bug ? should be !io.cacheOp.req.valid + io.write.req.ready := true.B // TODO : has bug ? should be !io.cacheOp.req.valid /* * flush logic */ // flush standalone set (e.g. flushed by mainPipe before doing re-fetch) - when(io.flush.map(_.valid).reduce(_ || _)) { + when(io.flush.req.map(_.valid).reduce(_ || _)) { (0 until nWays).foreach { w => valid_array(w) := (0 until PortNumber).map { i => Mux( // check if set `virIdx` in way `w` is requested to be flushed by port `i` - io.flush(i).valid && io.flush(i).bits.waymask(w), - valid_array(w).bitSet(io.flush(i).bits.virIdx, false.B), + io.flush.req(i).valid && io.flush.req(i).bits.waymask(w), + valid_array(w).bitSet(io.flush.req(i).bits.virIdx, false.B), valid_array(w) ) }.reduce(_ & _) @@ -184,6 +184,6 @@ class ICacheMetaArray(implicit p: Parameters) extends ICacheModule with ICacheEC } // PERF: flush counter - XSPerfAccumulate("flush", io.flush.map(_.valid).reduce(_ || _)) + XSPerfAccumulate("flush", io.flush.req.map(_.valid).reduce(_ || _)) XSPerfAccumulate("flush_all", io.flushAll) } diff --git a/src/main/scala/xiangshan/frontend/icache/ICacheMissUnit.scala b/src/main/scala/xiangshan/frontend/icache/ICacheMissUnit.scala index 37ae87aa853..50aa787d3e7 100644 --- a/src/main/scala/xiangshan/frontend/icache/ICacheMissUnit.scala +++ b/src/main/scala/xiangshan/frontend/icache/ICacheMissUnit.scala @@ -35,19 +35,20 @@ class ICacheMissUnit(edge: TLEdgeOut)(implicit p: Parameters) extends ICacheModu // control val fencei: Bool = Input(Bool()) val flush: Bool = Input(Bool()) - // fetch - val fetch_req: DecoupledIO[ICacheMissReq] = Flipped(DecoupledIO(new ICacheMissReq)) - val fetch_resp: Valid[ICacheMissResp] = ValidIO(new ICacheMissResp) - // prefetch - val prefetch_req: DecoupledIO[ICacheMissReq] = Flipped(DecoupledIO(new ICacheMissReq)) - // SRAM Write Req - val meta_write: DecoupledIO[ICacheMetaWriteBundle] = DecoupledIO(new ICacheMetaWriteBundle) - val data_write: DecoupledIO[ICacheDataWriteBundle] = DecoupledIO(new ICacheDataWriteBundle) + // request from mainPipe + val fetchReq: DecoupledIO[MissReqBundle] = Flipped(DecoupledIO(new MissReqBundle)) + // request from prefetchPipe + val prefetchReq: DecoupledIO[MissReqBundle] = Flipped(DecoupledIO(new MissReqBundle)) + // response to mainPipe / prefetchPipe / waylookup + val resp: Valid[MissRespBundle] = ValidIO(new MissRespBundle) + // SRAM Write + val metaWrite: MetaWriteBundle = new MetaWriteBundle + val dataWrite: DataWriteBundle = new DataWriteBundle // get victim from replacer - val victim: ReplacerVictim = new ReplacerVictim + val victim: ReplacerVictimBundle = new ReplacerVictimBundle // Tilelink - val mem_acquire: DecoupledIO[TLBundleA] = DecoupledIO(new TLBundleA(edge.bundle)) - val mem_grant: DecoupledIO[TLBundleD] = Flipped(DecoupledIO(new TLBundleD(edge.bundle))) + val memAcquire: DecoupledIO[TLBundleA] = DecoupledIO(new TLBundleA(edge.bundle)) + val memGrant: DecoupledIO[TLBundleD] = Flipped(DecoupledIO(new TLBundleD(edge.bundle))) } val io: ICacheMissUnitIO = IO(new ICacheMissUnitIO(edge)) @@ -73,37 +74,37 @@ class ICacheMissUnit(edge: TLEdgeOut)(implicit p: Parameters) extends ICacheModu ****************************************************************************** */ - private val fetchDemux = Module(new DeMultiplexer(new ICacheMissReq, nFetchMshr)) - private val prefetchDemux = Module(new DeMultiplexer(new ICacheMissReq, nPrefetchMshr)) - private val prefetchArb = Module(new MuxBundle(new MSHRAcquire(edge), nPrefetchMshr)) - private val acquireArb = Module(new Arbiter(new MSHRAcquire(edge), nFetchMshr + 1)) + private val fetchDemux = Module(new DeMultiplexer(new MissReqBundle, nFetchMshr)) + private val prefetchDemux = Module(new DeMultiplexer(new MissReqBundle, nPrefetchMshr)) + private val prefetchArb = Module(new MuxBundle(new MshrAcquireBundle(edge), nPrefetchMshr)) + private val acquireArb = Module(new Arbiter(new MshrAcquireBundle(edge), nFetchMshr + 1)) // To avoid duplicate request reception. private val fetchHit = Wire(Bool()) private val prefetchHit = Wire(Bool()) - fetchDemux.io.in <> io.fetch_req - fetchDemux.io.in.valid := io.fetch_req.valid && !fetchHit - io.fetch_req.ready := fetchDemux.io.in.ready || fetchHit - prefetchDemux.io.in <> io.prefetch_req - prefetchDemux.io.in.valid := io.prefetch_req.valid && !prefetchHit - io.prefetch_req.ready := prefetchDemux.io.in.ready || prefetchHit + fetchDemux.io.in <> io.fetchReq + fetchDemux.io.in.valid := io.fetchReq.valid && !fetchHit + io.fetchReq.ready := fetchDemux.io.in.ready || fetchHit + prefetchDemux.io.in <> io.prefetchReq + prefetchDemux.io.in.valid := io.prefetchReq.valid && !prefetchHit + io.prefetchReq.ready := prefetchDemux.io.in.ready || prefetchHit acquireArb.io.in.last <> prefetchArb.io.out // mem_acquire connect - io.mem_acquire.valid := acquireArb.io.out.valid - io.mem_acquire.bits := acquireArb.io.out.bits.acquire - acquireArb.io.out.ready := io.mem_acquire.ready + io.memAcquire.valid := acquireArb.io.out.valid + io.memAcquire.bits := acquireArb.io.out.bits.acquire + acquireArb.io.out.ready := io.memAcquire.ready private val fetchMSHRs = (0 until nFetchMshr).map { i => val mshr = Module(new ICacheMSHR(edge, true, i)) mshr.io.flush := false.B mshr.io.fencei := io.fencei mshr.io.req <> fetchDemux.io.out(i) - mshr.io.lookUps(0).info.valid := io.fetch_req.valid - mshr.io.lookUps(0).info.bits := io.fetch_req.bits - mshr.io.lookUps(1).info.valid := io.prefetch_req.valid - mshr.io.lookUps(1).info.bits := io.prefetch_req.bits - mshr.io.victimWay := io.victim.way + mshr.io.lookUps(0).req.valid := io.fetchReq.valid + mshr.io.lookUps(0).req.bits := io.fetchReq.bits + mshr.io.lookUps(1).req.valid := io.prefetchReq.valid + mshr.io.lookUps(1).req.bits := io.prefetchReq.bits + mshr.io.victimWay := io.victim.resp.way acquireArb.io.in(i) <> mshr.io.acquire mshr } @@ -113,11 +114,11 @@ class ICacheMissUnit(edge: TLEdgeOut)(implicit p: Parameters) extends ICacheModu mshr.io.flush := io.flush mshr.io.fencei := io.fencei mshr.io.req <> prefetchDemux.io.out(i) - mshr.io.lookUps(0).info.valid := io.fetch_req.valid - mshr.io.lookUps(0).info.bits := io.fetch_req.bits - mshr.io.lookUps(1).info.valid := io.prefetch_req.valid - mshr.io.lookUps(1).info.bits := io.prefetch_req.bits - mshr.io.victimWay := io.victim.way + mshr.io.lookUps(0).req.valid := io.fetchReq.valid + mshr.io.lookUps(0).req.bits := io.fetchReq.bits + mshr.io.lookUps(1).req.valid := io.prefetchReq.valid + mshr.io.lookUps(1).req.bits := io.prefetchReq.bits + mshr.io.victimWay := io.victim.resp.way prefetchArb.io.in(i) <> mshr.io.acquire mshr } @@ -129,11 +130,11 @@ class ICacheMissUnit(edge: TLEdgeOut)(implicit p: Parameters) extends ICacheModu ****************************************************************************** */ private val allMSHRs = fetchMSHRs ++ prefetchMSHRs - private val prefetchHitFetchReq = (io.prefetch_req.bits.blkPaddr === io.fetch_req.bits.blkPaddr) && - (io.prefetch_req.bits.vSetIdx === io.fetch_req.bits.vSetIdx) && - io.fetch_req.valid - fetchHit := allMSHRs.map(mshr => mshr.io.lookUps(0).hit).reduce(_ || _) - prefetchHit := allMSHRs.map(mshr => mshr.io.lookUps(1).hit).reduce(_ || _) || prefetchHitFetchReq + private val prefetchHitFetchReq = (io.prefetchReq.bits.blkPaddr === io.fetchReq.bits.blkPaddr) && + (io.prefetchReq.bits.vSetIdx === io.fetchReq.bits.vSetIdx) && + io.fetchReq.valid + fetchHit := allMSHRs.map(mshr => mshr.io.lookUps(0).resp.hit).reduce(_ || _) + prefetchHit := allMSHRs.map(mshr => mshr.io.lookUps(1).resp.hit).reduce(_ || _) || prefetchHitFetchReq /** ****************************************************************************** @@ -154,7 +155,7 @@ class ICacheMissUnit(edge: TLEdgeOut)(implicit p: Parameters) extends ICacheModu prefetchArb.io.sel := priorityFIFO.io.deq.bits assert( !(priorityFIFO.io.enq.fire ^ prefetchDemux.io.in.fire), - "priorityFIFO.io.enq and io.prefetch_req must fire at the same cycle" + "priorityFIFO.io.enq and io.prefetchReq must fire at the same cycle" ) assert( !(priorityFIFO.io.deq.fire ^ prefetchArb.io.out.fire), @@ -171,33 +172,33 @@ class ICacheMissUnit(edge: TLEdgeOut)(implicit p: Parameters) extends ICacheModu private val respDataReg = RegInit(VecInit(Seq.fill(refillCycles)(0.U(beatBits.W)))) private val wait_last = readBeatCnt === (refillCycles - 1).U - when(io.mem_grant.fire && edge.hasData(io.mem_grant.bits)) { - respDataReg(readBeatCnt) := io.mem_grant.bits.data + when(io.memGrant.fire && edge.hasData(io.memGrant.bits)) { + respDataReg(readBeatCnt) := io.memGrant.bits.data readBeatCnt := Mux(wait_last, 0.U, readBeatCnt + 1.U) } // last transition finish or corrupt - private val last_fire = io.mem_grant.fire && edge.hasData(io.mem_grant.bits) && wait_last + private val last_fire = io.memGrant.fire && edge.hasData(io.memGrant.bits) && wait_last - private val (_, _, refill_done, _) = edge.addr_inc(io.mem_grant) + private val (_, _, refill_done, _) = edge.addr_inc(io.memGrant) assert(!(refill_done ^ last_fire), "refill not done!") - io.mem_grant.ready := true.B + io.memGrant.ready := true.B private val last_fire_r = RegNext(last_fire) - private val id_r = RegNext(io.mem_grant.bits.source) + private val id_r = RegNext(io.memGrant.bits.source) // if any beat is corrupt, the whole response (to mainPipe/metaArray/dataArray) is corrupt private val corrupt_r = RegInit(false.B) - when(io.mem_grant.fire && edge.hasData(io.mem_grant.bits) && io.mem_grant.bits.corrupt) { + when(io.memGrant.fire && edge.hasData(io.memGrant.bits) && io.memGrant.bits.corrupt) { // Set corrupt_r when any beat is corrupt // This is actually when(xxx.fire && xxx.hasData) { corrupt_r := corrupt_r || io.mem_grant.bits.corrupt } corrupt_r := true.B }.elsewhen(last_fire_r) { // Clear corrupt_r when response it sent to mainPipe - // This used to be io.fetch_resp.valid (last_fire_r && mshr_valid) but when mshr is flushed by io.flush/fencei, + // This used to be io.resp.valid (last_fire_r && mshr_valid) but when mshr is flushed by io.flush/fencei, // mshr_valid is false.B and corrupt_r will never be cleared, that's not correct // so we remove mshr_valid here, and the condition leftover is last_fire_r - // or, actually, io.fetch_resp.valid || (last_fire_r && !mshr_valid) + // or, actually, io.resp.valid || (last_fire_r && !mshr_valid) corrupt_r := false.B } @@ -214,17 +215,17 @@ class ICacheMissUnit(edge: TLEdgeOut)(implicit p: Parameters) extends ICacheModu ****************************************************************************** */ // get request information from MSHRs - private val allMSHRs_resp = VecInit(allMSHRs.map(mshr => mshr.io.resp)) + private val allMSHRs_resp = VecInit(allMSHRs.map(mshr => mshr.io.info)) // select MSHR response 1 cycle before sending response to mainPipe/prefetchPipe for better timing private val mshr_resp = - RegEnable(allMSHRs_resp(io.mem_grant.bits.source).bits, 0.U.asTypeOf(allMSHRs_resp(0).bits), last_fire) + RegEnable(allMSHRs_resp(io.memGrant.bits.source).bits, 0.U.asTypeOf(allMSHRs_resp(0).bits), last_fire) // we can latch mshr.io.resp.bits since they are set on req.fire or acquire.fire, and keeps unchanged during response // however, we should not latch mshr.io.resp.valid, since io.flush/fencei may clear it at any time private val mshr_valid = allMSHRs_resp(id_r).valid // get waymask from replacer when acquire fire - io.victim.vSetIdx.valid := acquireArb.io.out.fire - io.victim.vSetIdx.bits := acquireArb.io.out.bits.vSetIdx + io.victim.req.valid := acquireArb.io.out.fire + io.victim.req.bits.vSetIdx := acquireArb.io.out.bits.vSetIdx private val waymask = UIntToOH(mshr_resp.way) // NOTE: when flush/fencei, missUnit will still send response to mainPipe/prefetchPipe // this is intentional to fix timing (io.flush -> mainPipe/prefetchPipe s2_miss -> s2_ready -> ftq ready) @@ -234,14 +235,14 @@ class ICacheMissUnit(edge: TLEdgeOut)(implicit p: Parameters) extends ICacheModu private val write_sram_valid = fetch_resp_valid && !corrupt_r && !io.flush && !io.fencei // write SRAM - io.meta_write.bits.generate( + io.metaWrite.req.bits.generate( tag = getPhyTagFromBlk(mshr_resp.blkPaddr), idx = mshr_resp.vSetIdx, waymask = waymask, bankIdx = mshr_resp.vSetIdx(0), poison = false.B ) - io.data_write.bits.generate( + io.dataWrite.req.bits.generate( data = respDataReg.asUInt, idx = mshr_resp.vSetIdx, waymask = waymask, @@ -249,16 +250,16 @@ class ICacheMissUnit(edge: TLEdgeOut)(implicit p: Parameters) extends ICacheModu poison = false.B ) - io.meta_write.valid := write_sram_valid - io.data_write.valid := write_sram_valid + io.metaWrite.req.valid := write_sram_valid + io.dataWrite.req.valid := write_sram_valid // response fetch - io.fetch_resp.valid := fetch_resp_valid - io.fetch_resp.bits.blkPaddr := mshr_resp.blkPaddr - io.fetch_resp.bits.vSetIdx := mshr_resp.vSetIdx - io.fetch_resp.bits.waymask := waymask - io.fetch_resp.bits.data := respDataReg.asUInt - io.fetch_resp.bits.corrupt := corrupt_r + io.resp.valid := fetch_resp_valid + io.resp.bits.blkPaddr := mshr_resp.blkPaddr + io.resp.bits.vSetIdx := mshr_resp.vSetIdx + io.resp.bits.waymask := waymask + io.resp.bits.data := respDataReg.asUInt + io.resp.bits.corrupt := corrupt_r /** ****************************************************************************** diff --git a/src/main/scala/xiangshan/frontend/icache/ICachePrefetchPipe.scala b/src/main/scala/xiangshan/frontend/icache/ICachePrefetchPipe.scala index 256ff69aa7f..6eb7d125d28 100644 --- a/src/main/scala/xiangshan/frontend/icache/ICachePrefetchPipe.scala +++ b/src/main/scala/xiangshan/frontend/icache/ICachePrefetchPipe.scala @@ -39,23 +39,23 @@ class ICachePrefetchPipe(implicit p: Parameters) extends ICacheModule val ecc_enable: Bool = Input(Bool()) val flush: Bool = Input(Bool()) - val req: DecoupledIO[IPrefetchReq] = Flipped(Decoupled(new IPrefetchReq)) - val flushFromBpu: BpuFlushInfo = Flipped(new BpuFlushInfo) - val itlb: Vec[TlbRequestIO] = Vec(PortNumber, new TlbRequestIO) - val itlbFlushPipe: Bool = Bool() - val pmp: Vec[ICachePMPBundle] = Vec(PortNumber, new ICachePMPBundle) - val metaRead: ICacheMetaReqBundle = new ICacheMetaReqBundle - val MSHRReq: DecoupledIO[ICacheMissReq] = DecoupledIO(new ICacheMissReq) - val MSHRResp: Valid[ICacheMissResp] = Flipped(ValidIO(new ICacheMissResp)) - val wayLookupWrite: DecoupledIO[WayLookupInfo] = DecoupledIO(new WayLookupInfo) + val req: DecoupledIO[PrefetchReqBundle] = Flipped(Decoupled(new PrefetchReqBundle)) + val flushFromBpu: BpuFlushInfo = Flipped(new BpuFlushInfo) + val itlb: Vec[TlbRequestIO] = Vec(PortNumber, new TlbRequestIO) + val itlbFlushPipe: Bool = Output(Bool()) + val pmp: Vec[PmpCheckBundle] = Vec(PortNumber, new PmpCheckBundle) + val metaRead: MetaReadBundle = new MetaReadBundle + val missReq: DecoupledIO[MissReqBundle] = DecoupledIO(new MissReqBundle) + val missResp: Valid[MissRespBundle] = Flipped(ValidIO(new MissRespBundle)) + val wayLookupWrite: DecoupledIO[WayLookupBundle] = DecoupledIO(new WayLookupBundle) } val io: ICachePrefetchPipeIO = IO(new ICachePrefetchPipeIO) private val (toITLB, fromITLB) = (io.itlb.map(_.req), io.itlb.map(_.resp)) private val (toPMP, fromPMP) = (io.pmp.map(_.req), io.pmp.map(_.resp)) - private val (toMeta, fromMeta) = (io.metaRead.toIMeta, io.metaRead.fromIMeta) - private val (toMSHR, fromMSHR) = (io.MSHRReq, io.MSHRResp) + private val (toMeta, fromMeta) = (io.metaRead.req, io.metaRead.resp) + private val (toMSHR, fromMSHR) = (io.missReq, io.missResp) private val toWayLookup = io.wayLookupWrite private val s0_fire, s1_fire, s2_fire = WireInit(false.B) @@ -320,7 +320,7 @@ class ICachePrefetchPipe(implicit p: Parameters) extends ICacheModule /** ****************************************************************************** - * send enqueue req to WayLookup + * send enqueue req to ICacheWayLookup ******** ********************************************************************** */ // Disallow enqueuing wayLookup when SRAM write occurs. @@ -335,7 +335,7 @@ class ICachePrefetchPipe(implicit p: Parameters) extends ICacheModule (0 until PortNumber).foreach { i => // exception in first line is always valid, in second line is valid iff is doubleline request val excpValid = if (i == 0) true.B else s1_doubleline - // Send s1_itlb_exception to WayLookup (instead of s1_exception_out) for better timing. + // Send s1_itlb_exception to ICacheWayLookup (instead of s1_exception_out) for better timing. // Will check pmp again in mainPipe toWayLookup.bits.itlb_exception(i) := Mux(excpValid, s1_itlb_exception(i), ExceptionType.none) toWayLookup.bits.itlb_pbmt(i) := Mux(excpValid, s1_itlb_pbmt(i), Pbmt.pma) @@ -523,7 +523,7 @@ class ICachePrefetchPipe(implicit p: Parameters) extends ICacheModule * send req to missUnit ****************************************************************************** */ - private val toMSHRArbiter = Module(new Arbiter(new ICacheMissReq, PortNumber)) + private val toMSHRArbiter = Module(new Arbiter(new MissReqBundle, PortNumber)) // To avoid sending duplicate requests. private val has_send = RegInit(VecInit(Seq.fill(PortNumber)(false.B))) diff --git a/src/main/scala/xiangshan/frontend/icache/ICacheReplacer.scala b/src/main/scala/xiangshan/frontend/icache/ICacheReplacer.scala index 9b16839564d..e41966b5c20 100644 --- a/src/main/scala/xiangshan/frontend/icache/ICacheReplacer.scala +++ b/src/main/scala/xiangshan/frontend/icache/ICacheReplacer.scala @@ -22,8 +22,8 @@ import utility.ReplacementPolicy class ICacheReplacer(implicit p: Parameters) extends ICacheModule { class ICacheReplacerIO(implicit p: Parameters) extends ICacheBundle { - val touch: Vec[Valid[ReplacerTouch]] = Vec(PortNumber, Flipped(ValidIO(new ReplacerTouch))) - val victim: ReplacerVictim = Flipped(new ReplacerVictim) + val touch: ReplacerTouchBundle = Flipped(new ReplacerTouchBundle) + val victim: ReplacerVictimBundle = Flipped(new ReplacerVictimBundle) } val io: ICacheReplacerIO = IO(new ICacheReplacerIO) @@ -36,29 +36,29 @@ class ICacheReplacer(implicit p: Parameters) extends ICacheModule { private val touchWays = Seq.fill(PortNumber)(Wire(Vec(PortNumber, Valid(UInt(wayBits.W))))) (0 until PortNumber).foreach { i => touchSets(i)(0) := Mux( - io.touch(i).bits.vSetIdx(0), - io.touch(1).bits.vSetIdx(highestIdxBit, 1), - io.touch(0).bits.vSetIdx(highestIdxBit, 1) + io.touch.req(i).bits.vSetIdx(0), + io.touch.req(1).bits.vSetIdx(highestIdxBit, 1), + io.touch.req(0).bits.vSetIdx(highestIdxBit, 1) ) - touchWays(i)(0).bits := Mux(io.touch(i).bits.vSetIdx(0), io.touch(1).bits.way, io.touch(0).bits.way) - touchWays(i)(0).valid := Mux(io.touch(i).bits.vSetIdx(0), io.touch(1).valid, io.touch(0).valid) + touchWays(i)(0).bits := Mux(io.touch.req(i).bits.vSetIdx(0), io.touch.req(1).bits.way, io.touch.req(0).bits.way) + touchWays(i)(0).valid := Mux(io.touch.req(i).bits.vSetIdx(0), io.touch.req(1).valid, io.touch.req(0).valid) } // victim - io.victim.way := Mux( - io.victim.vSetIdx.bits(0), - replacers(1).way(io.victim.vSetIdx.bits(highestIdxBit, 1)), - replacers(0).way(io.victim.vSetIdx.bits(highestIdxBit, 1)) + io.victim.resp.way := Mux( + io.victim.req.bits.vSetIdx(0), + replacers(1).way(io.victim.req.bits.vSetIdx(highestIdxBit, 1)), + replacers(0).way(io.victim.req.bits.vSetIdx(highestIdxBit, 1)) ) // touch the victim in next cycle private val victimVSetIdxReg = - RegEnable(io.victim.vSetIdx.bits, 0.U.asTypeOf(io.victim.vSetIdx.bits), io.victim.vSetIdx.valid) - private val victimWayReg = RegEnable(io.victim.way, 0.U.asTypeOf(io.victim.way), io.victim.vSetIdx.valid) + RegEnable(io.victim.req.bits.vSetIdx, 0.U.asTypeOf(io.victim.req.bits.vSetIdx), io.victim.req.valid) + private val victimWayReg = RegEnable(io.victim.resp.way, 0.U.asTypeOf(io.victim.resp.way), io.victim.req.valid) (0 until PortNumber).foreach { i => touchSets(i)(1) := victimVSetIdxReg(highestIdxBit, 1) touchWays(i)(1).bits := victimWayReg - touchWays(i)(1).valid := RegNext(io.victim.vSetIdx.valid) && (victimVSetIdxReg(0) === i.U) + touchWays(i)(1).valid := RegNext(io.victim.req.valid) && (victimVSetIdxReg(0) === i.U) } ((replacers zip touchSets) zip touchWays).foreach { case ((r, s), w) => r.access(s, w) } diff --git a/src/main/scala/xiangshan/frontend/icache/WayLookup.scala b/src/main/scala/xiangshan/frontend/icache/ICacheWayLookup.scala similarity index 81% rename from src/main/scala/xiangshan/frontend/icache/WayLookup.scala rename to src/main/scala/xiangshan/frontend/icache/ICacheWayLookup.scala index 93a63dd7ae0..b0464dddf18 100644 --- a/src/main/scala/xiangshan/frontend/icache/WayLookup.scala +++ b/src/main/scala/xiangshan/frontend/icache/ICacheWayLookup.scala @@ -21,23 +21,23 @@ import org.chipsalliance.cde.config.Parameters import utility.CircularQueuePtr import xiangshan.frontend.ExceptionType -class WayLookup(implicit p: Parameters) extends ICacheModule +class ICacheWayLookup(implicit p: Parameters) extends ICacheModule with ICacheECCHelper with ICacheAddrHelper { - class WayLookupIO(implicit p: Parameters) extends ICacheBundle { - val flush: Bool = Input(Bool()) - val read: DecoupledIO[WayLookupInfo] = DecoupledIO(new WayLookupInfo) - val write: DecoupledIO[WayLookupInfo] = Flipped(DecoupledIO(new WayLookupInfo)) - val update: Valid[ICacheMissResp] = Flipped(ValidIO(new ICacheMissResp)) + class ICacheWayLookupIO(implicit p: Parameters) extends ICacheBundle { + val flush: Bool = Input(Bool()) + val read: DecoupledIO[WayLookupBundle] = DecoupledIO(new WayLookupBundle) + val write: DecoupledIO[WayLookupBundle] = Flipped(DecoupledIO(new WayLookupBundle)) + val update: Valid[MissRespBundle] = Flipped(ValidIO(new MissRespBundle)) } - val io: WayLookupIO = IO(new WayLookupIO) + val io: ICacheWayLookupIO = IO(new ICacheWayLookupIO) - class WayLookupPtr extends CircularQueuePtr[WayLookupPtr](nWayLookupSize) - private object WayLookupPtr { - def apply(f: Bool, v: UInt): WayLookupPtr = { - val ptr = Wire(new WayLookupPtr) + class ICacheWayLookupPtr extends CircularQueuePtr[ICacheWayLookupPtr](nWayLookupSize) + private object ICacheWayLookupPtr { + def apply(f: Bool, v: UInt): ICacheWayLookupPtr = { + val ptr = Wire(new ICacheWayLookupPtr) ptr.flag := f ptr.value := v ptr @@ -45,8 +45,8 @@ class WayLookup(implicit p: Parameters) extends ICacheModule } private val entries = RegInit(VecInit(Seq.fill(nWayLookupSize)(0.U.asTypeOf(new WayLookupEntry)))) - private val readPtr = RegInit(WayLookupPtr(false.B, 0.U)) - private val writePtr = RegInit(WayLookupPtr(false.B, 0.U)) + private val readPtr = RegInit(ICacheWayLookupPtr(false.B, 0.U)) + private val writePtr = RegInit(ICacheWayLookupPtr(false.B, 0.U)) private val empty = readPtr === writePtr private val full = (readPtr.value === writePtr.value) && (readPtr.flag ^ writePtr.flag) @@ -65,14 +65,14 @@ class WayLookup(implicit p: Parameters) extends ICacheModule readPtr := readPtr + 1.U } - private val gpf_entry = RegInit(0.U.asTypeOf(Valid(new WayLookupGPFEntry))) - private val gpfPtr = RegInit(WayLookupPtr(false.B, 0.U)) + private val gpf_entry = RegInit(0.U.asTypeOf(Valid(new WayLookupGpfEntry))) + private val gpfPtr = RegInit(ICacheWayLookupPtr(false.B, 0.U)) private val gpf_hit = gpfPtr === readPtr && gpf_entry.valid when(io.flush) { // we don't need to reset gpfPtr, since the valid is actually gpf_entries.excp_tlb_gpf gpf_entry.valid := false.B - gpf_entry.bits := 0.U.asTypeOf(new WayLookupGPFEntry) + gpf_entry.bits := 0.U.asTypeOf(new WayLookupGpfEntry) } /** @@ -125,7 +125,7 @@ class WayLookup(implicit p: Parameters) extends ICacheModule gpf_entry.valid := false.B } }.otherwise { // gpf not hit - io.read.bits.gpf := 0.U.asTypeOf(new WayLookupGPFEntry) + io.read.bits.gpf := 0.U.asTypeOf(new WayLookupGpfEntry) } }