From 9de78046e5efcde0fa4e33d1a717fa7d126e352a Mon Sep 17 00:00:00 2001 From: ssszwic <114381825+ssszwic@users.noreply.github.com> Date: Mon, 16 Oct 2023 10:24:20 +0800 Subject: [PATCH] fdip: use a simple sram to replace the prefetch meta with bank (#2376) --- .../xiangshan/frontend/icache/ICache.scala | 6 +- .../frontend/icache/ICacheBankedArray.scala | 121 +++++++++++++++++- .../xiangshan/frontend/icache/IPrefetch.scala | 8 +- 3 files changed, 124 insertions(+), 11 deletions(-) diff --git a/src/main/scala/xiangshan/frontend/icache/ICache.scala b/src/main/scala/xiangshan/frontend/icache/ICache.scala index 2ea993f9d5..5d642d2adc 100644 --- a/src/main/scala/xiangshan/frontend/icache/ICache.scala +++ b/src/main/scala/xiangshan/frontend/icache/ICache.scala @@ -548,7 +548,7 @@ class ICacheImp(outer: ICache) extends LazyModuleImp(outer) with HasICacheParame val metaArray = Module(new ICacheMetaArray) val dataArray = Module(new ICacheDataArray) - val prefetchMetaArray = Module(new ICacheBankedMetaArray(prefetchPipeNum)) // need add 1 port for IPF filter + val prefetchMetaArray = Module(new ICacheMetaArrayNoBanked) val mainPipe = Module(new ICacheMainPipe) val missUnit = Module(new ICacheMissUnit(edge)) val fdipPrefetch = Module(new FDIPPrefetch(edge)) @@ -556,8 +556,8 @@ class ICacheImp(outer: ICache) extends LazyModuleImp(outer) with HasICacheParame fdipPrefetch.io.hartId := io.hartId fdipPrefetch.io.fencei := io.fencei fdipPrefetch.io.ftqReq <> io.prefetch - fdipPrefetch.io.metaReadReq <> prefetchMetaArray.io.read(0) - fdipPrefetch.io.metaReadResp <> prefetchMetaArray.io.readResp(0) + fdipPrefetch.io.metaReadReq <> prefetchMetaArray.io.read + fdipPrefetch.io.metaReadResp <> prefetchMetaArray.io.readResp fdipPrefetch.io.ICacheMissUnitInfo <> missUnit.io.ICacheMissUnitInfo fdipPrefetch.io.ICacheMainPipeInfo <> mainPipe.io.ICacheMainPipeInfo fdipPrefetch.io.IPFBufferRead <> mainPipe.io.IPFBufferRead diff --git a/src/main/scala/xiangshan/frontend/icache/ICacheBankedArray.scala b/src/main/scala/xiangshan/frontend/icache/ICacheBankedArray.scala index fbb8258686..709ddc8985 100644 --- a/src/main/scala/xiangshan/frontend/icache/ICacheBankedArray.scala +++ b/src/main/scala/xiangshan/frontend/icache/ICacheBankedArray.scala @@ -23,11 +23,11 @@ import xiangshan.cache._ import utils._ import utility._ -class ICacheMetaReadReqBundle(implicit p: Parameters) extends ICacheBundle { +class PrefetchMetaReadBundle(implicit p: Parameters) extends ICacheBundle { val idx = UInt(idxBits.W) } -class ICacheMetaReadRespBundle(implicit p: Parameters) extends ICacheBundle { +class PrefetchMetaRespBundle(implicit p: Parameters) extends ICacheBundle { val metaData = Vec(nWays, new ICacheMetadata) val errors = Vec(nWays ,Bool()) val entryValid = Vec(nWays, Bool()) @@ -57,9 +57,9 @@ class ICacheBankedMetaArray(readPortNum: Int)(implicit p: Parameters) extends IC val metaEntryBits = cacheParams.tagCode.width(metaBits) val io=IO{new Bundle{ - val read = Vec(ICacheMetaReadPortNum, Flipped(DecoupledIO(new ICacheMetaReadReqBundle))) + val read = Vec(ICacheMetaReadPortNum, Flipped(DecoupledIO(new PrefetchMetaReadBundle))) // TODO : does need support old read bundle? - val readResp = Vec(ICacheMetaReadPortNum, Output(new ICacheMetaReadRespBundle)) + val readResp = Vec(ICacheMetaReadPortNum, Output(new PrefetchMetaRespBundle)) val write = Flipped(DecoupledIO(new ICacheMetaWriteBundle)) val cacheOp = Flipped(new L1CacheInnerOpIO) val fencei = Input(Bool()) @@ -186,6 +186,119 @@ class ICacheBankedMetaArray(readPortNum: Int)(implicit p: Parameters) extends IC ) io.cacheOp.resp.bits.read_tag_ecc := DontCare + // fencei logic : reset valid_array + when (io.fencei) { + (0 until nWays).foreach( way => + valid_array(way) := 0.U + ) + } +} + + +class ICacheMetaArrayNoBanked()(implicit p: Parameters) extends ICacheArray +{ + def onReset = ICacheMetadata(0.U) + val metaBits = onReset.getWidth + val metaEntryBits = cacheParams.tagCode.width(metaBits) + + val io=IO{new Bundle{ + val read = Flipped(DecoupledIO(new PrefetchMetaReadBundle)) + val readResp = Output(new PrefetchMetaRespBundle) + val write = Flipped(DecoupledIO(new ICacheMetaWriteBundle)) + val cacheOp = Flipped(new L1CacheInnerOpIO) + val fencei = Input(Bool()) + }} + + io.read.ready := !io.write.valid + + val write_meta_bits = Wire(UInt(metaEntryBits.W)) + + val tagArray = Module(new SRAMTemplate( + UInt(metaEntryBits.W), + set = nSets, + way = nWays, + shouldReset = true, + holdRead = true, + singlePort = true + )) + tagArray.io.r.req.valid := io.read.valid + tagArray.io.r.req.bits.apply(setIdx=io.read.bits.idx) + tagArray.io.w.req.valid := io.write.valid + tagArray.io.w.req.bits.apply(data=write_meta_bits, setIdx=io.write.bits.virIdx, waymask=io.write.bits.waymask) + + val read_set_idx_next = RegEnable(io.read.bits.idx, io.read.fire) + val valid_array = RegInit(VecInit(Seq.fill(nWays)(0.U(nSets.W)))) + val valid_metas = Wire(Vec(nWays, Bool())) + (0 until nWays).foreach( way => + valid_metas(way) := valid_array(way)(read_set_idx_next) + ) + io.readResp.entryValid := valid_metas + + // Parity Decode + val read_metas = Wire(Vec(nWays,new ICacheMetadata())) + val read_meta_bits = tagArray.io.r.resp.asTypeOf(Vec(nWays,UInt(metaEntryBits.W))) + val read_meta_decoded = read_meta_bits.map{ way_bits => cacheParams.tagCode.decode(way_bits)} + val read_meta_wrong = read_meta_decoded.map{ way_bits_decoded => way_bits_decoded.error} + val read_meta_corrected = VecInit(read_meta_decoded.map{ way_bits_decoded => way_bits_decoded.corrected}) + read_metas := read_meta_corrected.asTypeOf(Vec(nWays,new ICacheMetadata())) + (0 until nWays).map{ w => io.readResp.errors(w) := RegNext(read_meta_wrong(w)) && RegNext(RegNext(io.read.fire))} + + // Parity Encode + val write = io.write.bits + write_meta_bits := cacheParams.tagCode.encode(ICacheMetadata(tag = write.phyTag).asUInt) + + // valid write + 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) + } + + XSPerfAccumulate("meta_refill_num", io.write.valid) + + io.readResp.metaData := read_metas + + io.write.ready := true.B // TODO : has bug ? should be !io.cacheOp.req.valid + // deal with customized cache op + require(nWays <= 32) + io.cacheOp.resp.bits := DontCare + val cacheOpShouldResp = WireInit(false.B) + when(io.cacheOp.req.valid){ + when( + CacheInstrucion.isReadTag(io.cacheOp.req.bits.opCode) || + CacheInstrucion.isReadTagECC(io.cacheOp.req.bits.opCode) + ){ + tagArray.io.r.req.valid := true.B + tagArray.io.r.req.bits.apply(setIdx = io.cacheOp.req.bits.index) + cacheOpShouldResp := true.B + } + when(CacheInstrucion.isWriteTag(io.cacheOp.req.bits.opCode)){ + tagArray.io.w.req.valid := true.B + tagArray.io.w.req.bits.apply( + data = io.cacheOp.req.bits.write_tag_low, + setIdx = io.cacheOp.req.bits.index, + waymask = UIntToOH(io.cacheOp.req.bits.wayNum(4, 0)) + ) + cacheOpShouldResp := true.B + } + // TODO + // when(CacheInstrucion.isWriteTagECC(io.cacheOp.req.bits.opCode)){ + // for (i <- 0 until readPorts) { + // array(i).io.ecc_write.valid := true.B + // array(i).io.ecc_write.bits.idx := io.cacheOp.req.bits.index + // array(i).io.ecc_write.bits.way_en := UIntToOH(io.cacheOp.req.bits.wayNum(4, 0)) + // array(i).io.ecc_write.bits.ecc := io.cacheOp.req.bits.write_tag_ecc + // } + // cacheOpShouldResp := true.B + // } + } + io.cacheOp.resp.valid := RegNext(io.cacheOp.req.valid && cacheOpShouldResp) + io.cacheOp.resp.bits.read_tag_low := Mux(io.cacheOp.resp.valid, + tagArray.io.r.resp.asTypeOf(Vec(nWays, UInt(tagBits.W)))(io.cacheOp.req.bits.wayNum), + 0.U + ) + io.cacheOp.resp.bits.read_tag_ecc := DontCare // TODO + // TODO: deal with duplicated array + // fencei logic : reset valid_array when (io.fencei) { (0 until nWays).foreach( way => diff --git a/src/main/scala/xiangshan/frontend/icache/IPrefetch.scala b/src/main/scala/xiangshan/frontend/icache/IPrefetch.scala index b11e67e7bf..131c6dc19d 100644 --- a/src/main/scala/xiangshan/frontend/icache/IPrefetch.scala +++ b/src/main/scala/xiangshan/frontend/icache/IPrefetch.scala @@ -267,8 +267,8 @@ class IPredfetchIO(implicit p: Parameters) extends IPrefetchBundle { val ftqReq = Flipped(new FtqPrefechBundle) val iTLBInter = new TlbRequestIO val pmp = new ICachePMPBundle - val metaReadReq = Decoupled(new ICacheMetaReadReqBundle) - val metaReadResp = Input(new ICacheMetaReadRespBundle) + val metaReadReq = Decoupled(new PrefetchMetaReadBundle) + val metaReadResp = Input(new PrefetchMetaRespBundle) val prefetchReq = DecoupledIO(new PrefetchReq) val IPFFilterRead = Flipped(new IPFBufferFilterRead) @@ -822,8 +822,8 @@ class FDIPPrefetchIO(edge: TLEdgeOut)(implicit p: Parameters) extends IPrefetchB val ftqReq = Flipped(new FtqPrefechBundle) val iTLBInter = new TlbRequestIO val pmp = new ICachePMPBundle - val metaReadReq = Decoupled(new ICacheMetaReadReqBundle) - val metaReadResp = Input(new ICacheMetaReadRespBundle) + val metaReadReq = Decoupled(new PrefetchMetaReadBundle) + val metaReadResp = Input(new PrefetchMetaRespBundle) val ICacheMissUnitInfo = Flipped(new ICacheMissUnitInfo) val ICacheMainPipeInfo = Flipped(new ICacheMainPipeInfo)