1*8882eb68SXin Tian/*************************************************************************************** 2*8882eb68SXin Tian* Copyright (c) 2024-2025 Institute of Information Engineering, Chinese Academy of Sciences 3*8882eb68SXin Tian* 4*8882eb68SXin Tian* XiangShan is licensed under Mulan PSL v2. 5*8882eb68SXin Tian* You can use this software according to the terms and conditions of the Mulan PSL v2. 6*8882eb68SXin Tian* You may obtain a copy of Mulan PSL v2 at: 7*8882eb68SXin Tian* http://license.coscl.org.cn/MulanPSL2 8*8882eb68SXin Tian* 9*8882eb68SXin Tian* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 10*8882eb68SXin Tian* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 11*8882eb68SXin Tian* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 12*8882eb68SXin Tian* 13*8882eb68SXin Tian* See the Mulan PSL v2 for more details. 14*8882eb68SXin Tian***************************************************************************************/ 15*8882eb68SXin Tian 16*8882eb68SXin Tianpackage xiangshan.cache.mmu 17*8882eb68SXin Tian 18*8882eb68SXin Tianimport org.chipsalliance.cde.config.Parameters 19*8882eb68SXin Tianimport chisel3._ 20*8882eb68SXin Tianimport chisel3.util._ 21*8882eb68SXin Tianimport xiangshan._ 22*8882eb68SXin Tianimport xiangshan.cache.{HasDCacheParameters, MemoryOpConstants} 23*8882eb68SXin Tianimport utils._ 24*8882eb68SXin Tianimport utility._ 25*8882eb68SXin Tianimport freechips.rocketchip.diplomacy.{LazyModule, LazyModuleImp} 26*8882eb68SXin Tianimport freechips.rocketchip.tilelink._ 27*8882eb68SXin Tianimport xiangshan.backend.fu.{PMPReqBundle, PMPRespBundle} 28*8882eb68SXin Tian 29*8882eb68SXin Tianclass bitmapReqBundle(implicit p: Parameters) extends XSBundle with HasPtwConst { 30*8882eb68SXin Tian val bmppn = UInt(ppnLen.W) 31*8882eb68SXin Tian val id = UInt(log2Up(l2tlbParams.llptwsize+2).W) 32*8882eb68SXin Tian val vpn = UInt(vpnLen.W) 33*8882eb68SXin Tian val level = UInt(log2Up(Level).W) 34*8882eb68SXin Tian val way_info = UInt(l2tlbParams.l0nWays.W) 35*8882eb68SXin Tian val hptw_bypassed = Bool() 36*8882eb68SXin Tian} 37*8882eb68SXin Tian 38*8882eb68SXin Tianclass bitmapRespBundle(implicit p: Parameters) extends XSBundle with HasPtwConst { 39*8882eb68SXin Tian val cf = Bool() 40*8882eb68SXin Tian val cfs = Vec(tlbcontiguous,Bool()) 41*8882eb68SXin Tian val id = UInt(log2Up(l2tlbParams.llptwsize+2).W) 42*8882eb68SXin Tian} 43*8882eb68SXin Tian 44*8882eb68SXin Tianclass bitmapEntry(implicit p: Parameters) extends XSBundle with HasPtwConst { 45*8882eb68SXin Tian val ppn = UInt(ppnLen.W) 46*8882eb68SXin Tian val vpn = UInt(vpnLen.W) 47*8882eb68SXin Tian val id = UInt(bMemID.W) 48*8882eb68SXin Tian val wait_id = UInt(log2Up(l2tlbParams.llptwsize+2).W) 49*8882eb68SXin Tian // bitmap check faild? : 0 success, 1 faild 50*8882eb68SXin Tian val cf = Bool() 51*8882eb68SXin Tian val hit = Bool() 52*8882eb68SXin Tian val cfs = Vec(tlbcontiguous,Bool()) 53*8882eb68SXin Tian val level = UInt(log2Up(Level).W) 54*8882eb68SXin Tian val way_info = UInt(l2tlbParams.l0nWays.W) 55*8882eb68SXin Tian val hptw_bypassed = Bool() 56*8882eb68SXin Tian val data = UInt(XLEN.W) 57*8882eb68SXin Tian} 58*8882eb68SXin Tian 59*8882eb68SXin Tianclass bitmapIO(implicit p: Parameters) extends MMUIOBaseBundle with HasPtwConst { 60*8882eb68SXin Tian val mem = new Bundle { 61*8882eb68SXin Tian val req = DecoupledIO(new L2TlbMemReqBundle()) 62*8882eb68SXin Tian val resp = Flipped(DecoupledIO(new Bundle { 63*8882eb68SXin Tian val id = Output(UInt(bMemID.W)) 64*8882eb68SXin Tian val value = Output(UInt(blockBits.W)) 65*8882eb68SXin Tian })) 66*8882eb68SXin Tian val req_mask = Input(Vec(l2tlbParams.llptwsize+2, Bool())) 67*8882eb68SXin Tian } 68*8882eb68SXin Tian val req = Flipped(DecoupledIO(new bitmapReqBundle())) 69*8882eb68SXin Tian val resp = DecoupledIO(new bitmapRespBundle()) 70*8882eb68SXin Tian 71*8882eb68SXin Tian val pmp = new Bundle { 72*8882eb68SXin Tian val req = ValidIO(new PMPReqBundle()) 73*8882eb68SXin Tian val resp = Flipped(new PMPRespBundle()) 74*8882eb68SXin Tian } 75*8882eb68SXin Tian 76*8882eb68SXin Tian val wakeup = ValidIO(new Bundle { 77*8882eb68SXin Tian val setIndex = UInt(PtwL0SetIdxLen.W) 78*8882eb68SXin Tian val tag = UInt(SPTagLen.W) 79*8882eb68SXin Tian val isSp = Bool() 80*8882eb68SXin Tian val way_info = UInt(l2tlbParams.l0nWays.W) 81*8882eb68SXin Tian val pte_index = UInt(sectortlbwidth.W) 82*8882eb68SXin Tian val check_success = Bool() 83*8882eb68SXin Tian }) 84*8882eb68SXin Tian 85*8882eb68SXin Tian // bitmap cache req/resp and refill port 86*8882eb68SXin Tian val cache = new Bundle { 87*8882eb68SXin Tian val req = DecoupledIO(new bitmapCacheReqBundle()) 88*8882eb68SXin Tian val resp = Flipped(DecoupledIO(new bitmapCacheRespBundle())) 89*8882eb68SXin Tian } 90*8882eb68SXin Tian val refill = Output(ValidIO(new Bundle { 91*8882eb68SXin Tian val tag = UInt(ppnLen.W) 92*8882eb68SXin Tian val data = UInt(XLEN.W) 93*8882eb68SXin Tian })) 94*8882eb68SXin Tian} 95*8882eb68SXin Tian 96*8882eb68SXin Tianclass Bitmap(implicit p: Parameters) extends XSModule with HasPtwConst { 97*8882eb68SXin Tian def getBitmapAddr(ppn: UInt): UInt = { 98*8882eb68SXin Tian val effective_ppn = ppn(ppnLen-KeyIDBits-1, 0) 99*8882eb68SXin Tian bitmap_base + (effective_ppn >> log2Ceil(XLEN) << log2Ceil(8)) 100*8882eb68SXin Tian } 101*8882eb68SXin Tian 102*8882eb68SXin Tian val io = IO(new bitmapIO) 103*8882eb68SXin Tian 104*8882eb68SXin Tian val csr = io.csr 105*8882eb68SXin Tian val sfence = io.sfence 106*8882eb68SXin Tian val flush = sfence.valid || csr.satp.changed || csr.vsatp.changed || csr.hgatp.changed 107*8882eb68SXin Tian val bitmap_base = csr.mbmc.BMA << 6 108*8882eb68SXin Tian 109*8882eb68SXin Tian val entries = Reg(Vec(l2tlbParams.llptwsize+2, new bitmapEntry())) 110*8882eb68SXin Tian // add pmp check 111*8882eb68SXin Tian val state_idle :: state_addr_check :: state_cache_req :: state_cache_resp ::state_mem_req :: state_mem_waiting :: state_mem_out :: Nil = Enum(7) 112*8882eb68SXin Tian val state = RegInit(VecInit(Seq.fill(l2tlbParams.llptwsize+2)(state_idle))) 113*8882eb68SXin Tian 114*8882eb68SXin Tian val is_emptys = state.map(_ === state_idle) 115*8882eb68SXin Tian val is_cache_req = state.map (_ === state_cache_req) 116*8882eb68SXin Tian val is_cache_resp = state.map (_ === state_cache_resp) 117*8882eb68SXin Tian val is_mems = state.map(_ === state_mem_req) 118*8882eb68SXin Tian val is_waiting = state.map(_ === state_mem_waiting) 119*8882eb68SXin Tian val is_having = state.map(_ === state_mem_out) 120*8882eb68SXin Tian 121*8882eb68SXin Tian val full = !ParallelOR(is_emptys).asBool 122*8882eb68SXin Tian val waiting = ParallelOR(is_waiting).asBool 123*8882eb68SXin Tian val enq_ptr = ParallelPriorityEncoder(is_emptys) 124*8882eb68SXin Tian 125*8882eb68SXin Tian val mem_ptr = ParallelPriorityEncoder(is_having) 126*8882eb68SXin Tian val mem_arb = Module(new RRArbiter(new bitmapEntry(), l2tlbParams.llptwsize+2)) 127*8882eb68SXin Tian 128*8882eb68SXin Tian val bitmapdata = Wire(Vec(blockBits / XLEN, UInt(XLEN.W))) 129*8882eb68SXin Tian if (HasBitmapCheckDefault) { 130*8882eb68SXin Tian for (i <- 0 until blockBits / XLEN) { 131*8882eb68SXin Tian bitmapdata(i) := 0.U 132*8882eb68SXin Tian } 133*8882eb68SXin Tian } else { 134*8882eb68SXin Tian bitmapdata := io.mem.resp.bits.value.asTypeOf(Vec(blockBits / XLEN, UInt(XLEN.W))) 135*8882eb68SXin Tian } 136*8882eb68SXin Tian 137*8882eb68SXin Tian for (i <- 0 until l2tlbParams.llptwsize+2) { 138*8882eb68SXin Tian mem_arb.io.in(i).bits := entries(i) 139*8882eb68SXin Tian mem_arb.io.in(i).valid := is_mems(i) && !io.mem.req_mask(i) 140*8882eb68SXin Tian } 141*8882eb68SXin Tian 142*8882eb68SXin Tian val cache_req_arb = Module(new Arbiter(new bitmapCacheReqBundle(),l2tlbParams.llptwsize + 2)) 143*8882eb68SXin Tian for (i <- 0 until l2tlbParams.llptwsize+2) { 144*8882eb68SXin Tian cache_req_arb.io.in(i).valid := is_cache_req(i) 145*8882eb68SXin Tian cache_req_arb.io.in(i).bits.tag := entries(i).ppn 146*8882eb68SXin Tian cache_req_arb.io.in(i).bits.order := i.U; 147*8882eb68SXin Tian } 148*8882eb68SXin Tian 149*8882eb68SXin Tian val dup_vec = state.indices.map(i => 150*8882eb68SXin Tian dupBitmapPPN(io.req.bits.bmppn, entries(i).ppn) 151*8882eb68SXin Tian ) 152*8882eb68SXin Tian val dup_req_fire = mem_arb.io.out.fire && dupBitmapPPN(io.req.bits.bmppn, mem_arb.io.out.bits.ppn) 153*8882eb68SXin Tian val dup_vec_wait = dup_vec.zip(is_waiting).map{case (d, w) => d && w} 154*8882eb68SXin Tian val dup_wait_resp = io.mem.resp.fire && VecInit(dup_vec_wait)(io.mem.resp.bits.id - (l2tlbParams.llptwsize + 2).U) 155*8882eb68SXin Tian val wait_id = Mux(dup_req_fire, mem_arb.io.chosen, ParallelMux(dup_vec_wait zip entries.map(_.wait_id))) 156*8882eb68SXin Tian 157*8882eb68SXin Tian val to_wait = Cat(dup_vec_wait).orR || dup_req_fire 158*8882eb68SXin Tian val to_mem_out = dup_wait_resp 159*8882eb68SXin Tian 160*8882eb68SXin Tian val enq_state_normal = MuxCase(state_addr_check, Seq( 161*8882eb68SXin Tian to_mem_out -> state_mem_out, 162*8882eb68SXin Tian to_wait -> state_mem_waiting 163*8882eb68SXin Tian )) 164*8882eb68SXin Tian val enq_state = enq_state_normal 165*8882eb68SXin Tian val enq_ptr_reg = RegNext(enq_ptr) 166*8882eb68SXin Tian 167*8882eb68SXin Tian val need_addr_check = RegNext(enq_state === state_addr_check && io.req.fire && !flush) 168*8882eb68SXin Tian 169*8882eb68SXin Tian io.pmp.req.valid := need_addr_check 170*8882eb68SXin Tian io.pmp.req.bits.addr := RegEnable(getBitmapAddr(io.req.bits.bmppn),io.req.fire) 171*8882eb68SXin Tian io.pmp.req.bits.cmd := TlbCmd.read 172*8882eb68SXin Tian io.pmp.req.bits.size := 3.U 173*8882eb68SXin Tian val pmp_resp_valid = io.pmp.req.valid 174*8882eb68SXin Tian 175*8882eb68SXin Tian when (io.req.fire) { 176*8882eb68SXin Tian state(enq_ptr) := enq_state 177*8882eb68SXin Tian entries(enq_ptr).ppn := io.req.bits.bmppn 178*8882eb68SXin Tian entries(enq_ptr).vpn := io.req.bits.vpn 179*8882eb68SXin Tian entries(enq_ptr).id := io.req.bits.id 180*8882eb68SXin Tian entries(enq_ptr).wait_id := Mux(to_wait, wait_id, enq_ptr) 181*8882eb68SXin Tian entries(enq_ptr).cf := false.B 182*8882eb68SXin Tian for (i <- 0 until tlbcontiguous) { 183*8882eb68SXin Tian entries(enq_ptr).cfs(i) := false.B 184*8882eb68SXin Tian } 185*8882eb68SXin Tian entries(enq_ptr).hit := to_wait 186*8882eb68SXin Tian entries(enq_ptr).level := io.req.bits.level 187*8882eb68SXin Tian entries(enq_ptr).way_info := io.req.bits.way_info 188*8882eb68SXin Tian entries(enq_ptr).hptw_bypassed := io.req.bits.hptw_bypassed 189*8882eb68SXin Tian } 190*8882eb68SXin Tian 191*8882eb68SXin Tian // when pmp check failed, use cf bit represent 192*8882eb68SXin Tian when (pmp_resp_valid) { 193*8882eb68SXin Tian val ptr = enq_ptr_reg 194*8882eb68SXin Tian val accessFault = io.pmp.resp.ld || io.pmp.resp.mmio 195*8882eb68SXin Tian entries(ptr).cf := accessFault 196*8882eb68SXin Tian for (i <- 0 until tlbcontiguous) { 197*8882eb68SXin Tian entries(ptr).cfs(i) := accessFault 198*8882eb68SXin Tian } 199*8882eb68SXin Tian // firstly req bitmap cache 200*8882eb68SXin Tian state(ptr) := Mux(accessFault, state_mem_out, state_cache_req) 201*8882eb68SXin Tian } 202*8882eb68SXin Tian 203*8882eb68SXin Tian val cache_wait = ParallelOR(is_cache_resp).asBool 204*8882eb68SXin Tian io.cache.resp.ready := !flush && cache_wait 205*8882eb68SXin Tian 206*8882eb68SXin Tian val hit = WireInit(false.B) 207*8882eb68SXin Tian io.cache.req.valid := cache_req_arb.io.out.valid && !flush 208*8882eb68SXin Tian io.cache.req.bits.tag := cache_req_arb.io.out.bits.tag 209*8882eb68SXin Tian io.cache.req.bits.order := cache_req_arb.io.out.bits.order 210*8882eb68SXin Tian cache_req_arb.io.out.ready := io.cache.req.ready 211*8882eb68SXin Tian 212*8882eb68SXin Tian 213*8882eb68SXin Tian when (cache_req_arb.io.out.fire) { 214*8882eb68SXin Tian for (i <- state.indices) { 215*8882eb68SXin Tian when (state(i) === state_cache_req && cache_req_arb.io.chosen === i.U) { 216*8882eb68SXin Tian state(i) := state_cache_resp 217*8882eb68SXin Tian } 218*8882eb68SXin Tian } 219*8882eb68SXin Tian } 220*8882eb68SXin Tian 221*8882eb68SXin Tian when (io.cache.resp.fire) { 222*8882eb68SXin Tian for (i <- state.indices) { 223*8882eb68SXin Tian val cm_dup_vec = state.indices.map(j => 224*8882eb68SXin Tian dupBitmapPPN(entries(i).ppn, entries(j).ppn) 225*8882eb68SXin Tian ) 226*8882eb68SXin Tian val cm_dup_req_fire = mem_arb.io.out.fire && dupBitmapPPN(entries(i).ppn, mem_arb.io.out.bits.ppn) 227*8882eb68SXin Tian val cm_dup_vec_wait = cm_dup_vec.zip(is_waiting).map{case (d, w) => d && w} 228*8882eb68SXin Tian val cm_dup_wait_resp = io.mem.resp.fire && VecInit(cm_dup_vec_wait)(io.mem.resp.bits.id - (l2tlbParams.llptwsize + 2).U) 229*8882eb68SXin Tian val cm_wait_id = Mux(cm_dup_req_fire, mem_arb.io.chosen, ParallelMux(cm_dup_vec_wait zip entries.map(_.wait_id))) 230*8882eb68SXin Tian val cm_to_wait = Cat(cm_dup_vec_wait).orR || cm_dup_req_fire 231*8882eb68SXin Tian val cm_to_mem_out = cm_dup_wait_resp 232*8882eb68SXin Tian val cm_next_state_normal = MuxCase(state_mem_req, Seq( 233*8882eb68SXin Tian cm_to_mem_out -> state_mem_out, 234*8882eb68SXin Tian cm_to_wait -> state_mem_waiting 235*8882eb68SXin Tian )) 236*8882eb68SXin Tian when (state(i) === state_cache_resp && io.cache.resp.bits.order === i.U) { 237*8882eb68SXin Tian hit := io.cache.resp.bits.hit 238*8882eb68SXin Tian when (hit) { 239*8882eb68SXin Tian entries(i).cf := io.cache.resp.bits.cfs(entries(i).ppn(5,0)) 240*8882eb68SXin Tian entries(i).hit := true.B 241*8882eb68SXin Tian entries(i).cfs := io.cache.resp.bits.cfs 242*8882eb68SXin Tian state(i) := state_mem_out 243*8882eb68SXin Tian } .otherwise { 244*8882eb68SXin Tian state(i) := cm_next_state_normal 245*8882eb68SXin Tian entries(i).wait_id := Mux(cm_to_wait, cm_wait_id, entries(i).wait_id) 246*8882eb68SXin Tian entries(i).hit := cm_to_wait 247*8882eb68SXin Tian } 248*8882eb68SXin Tian } 249*8882eb68SXin Tian } 250*8882eb68SXin Tian } 251*8882eb68SXin Tian 252*8882eb68SXin Tian when (mem_arb.io.out.fire) { 253*8882eb68SXin Tian for (i <- state.indices) { 254*8882eb68SXin Tian when (state(i) === state_mem_req && dupBitmapPPN(entries(i).ppn, mem_arb.io.out.bits.ppn)) { 255*8882eb68SXin Tian state(i) := state_mem_waiting 256*8882eb68SXin Tian entries(i).wait_id := mem_arb.io.chosen 257*8882eb68SXin Tian } 258*8882eb68SXin Tian } 259*8882eb68SXin Tian } 260*8882eb68SXin Tian 261*8882eb68SXin Tian when (io.mem.resp.fire) { 262*8882eb68SXin Tian state.indices.map{i => 263*8882eb68SXin Tian when (state(i) === state_mem_waiting && io.mem.resp.bits.id === entries(i).wait_id + (l2tlbParams.llptwsize + 2).U) { 264*8882eb68SXin Tian state(i) := state_mem_out 265*8882eb68SXin Tian val index = getBitmapAddr(entries(i).ppn)(log2Up(l2tlbParams.blockBytes)-1, log2Up(XLEN/8)) 266*8882eb68SXin Tian entries(i).data := bitmapdata(index) 267*8882eb68SXin Tian entries(i).cf := bitmapdata(index)(entries(i).ppn(5,0)) 268*8882eb68SXin Tian val ppnPart = entries(i).ppn(5,3) 269*8882eb68SXin Tian val start = (ppnPart << 3.U) 270*8882eb68SXin Tian val end = start + 7.U 271*8882eb68SXin Tian val mask = (1.U << 8) - 1.U 272*8882eb68SXin Tian val selectedBits = (bitmapdata(index) >> start) & mask 273*8882eb68SXin Tian for (j <- 0 until tlbcontiguous) { 274*8882eb68SXin Tian entries(i).cfs(j) := selectedBits(j) 275*8882eb68SXin Tian } 276*8882eb68SXin Tian } 277*8882eb68SXin Tian } 278*8882eb68SXin Tian } 279*8882eb68SXin Tian 280*8882eb68SXin Tian when (io.resp.fire) { 281*8882eb68SXin Tian state(mem_ptr) := state_idle 282*8882eb68SXin Tian } 283*8882eb68SXin Tian 284*8882eb68SXin Tian when (flush) { 285*8882eb68SXin Tian state.map(_ := state_idle) 286*8882eb68SXin Tian } 287*8882eb68SXin Tian 288*8882eb68SXin Tian io.req.ready := !full 289*8882eb68SXin Tian 290*8882eb68SXin Tian io.resp.valid := ParallelOR(is_having).asBool 291*8882eb68SXin Tian // if cache hit, resp the cache's resp 292*8882eb68SXin Tian io.resp.bits.cf := entries(mem_ptr).cf 293*8882eb68SXin Tian io.resp.bits.cfs := entries(mem_ptr).cfs 294*8882eb68SXin Tian io.resp.bits.id := entries(mem_ptr).id 295*8882eb68SXin Tian 296*8882eb68SXin Tian io.mem.req.valid := mem_arb.io.out.valid && !flush 297*8882eb68SXin Tian io.mem.req.bits.addr := getBitmapAddr(mem_arb.io.out.bits.ppn) 298*8882eb68SXin Tian io.mem.req.bits.id := mem_arb.io.chosen + (l2tlbParams.llptwsize + 2).U 299*8882eb68SXin Tian mem_arb.io.out.ready := io.mem.req.ready 300*8882eb68SXin Tian 301*8882eb68SXin Tian io.mem.resp.ready := waiting 302*8882eb68SXin Tian 303*8882eb68SXin Tian io.mem.req.bits.hptw_bypassed := false.B 304*8882eb68SXin Tian 305*8882eb68SXin Tian io.wakeup.valid := io.resp.valid && !entries(mem_ptr).hptw_bypassed 306*8882eb68SXin Tian io.wakeup.bits.setIndex := genPtwL0SetIdx(entries(mem_ptr).vpn) 307*8882eb68SXin Tian io.wakeup.bits.tag := entries(mem_ptr).vpn(vpnLen - 1, vpnLen - SPTagLen) 308*8882eb68SXin Tian io.wakeup.bits.isSp := entries(mem_ptr).level =/= 0.U 309*8882eb68SXin Tian io.wakeup.bits.way_info := entries(mem_ptr).way_info 310*8882eb68SXin Tian io.wakeup.bits.pte_index := entries(mem_ptr).vpn(sectortlbwidth - 1, 0) 311*8882eb68SXin Tian io.wakeup.bits.check_success := !entries(mem_ptr).cf 312*8882eb68SXin Tian 313*8882eb68SXin Tian // when don't hit, refill the data to bitmap cache 314*8882eb68SXin Tian io.refill.valid := io.resp.valid && !entries(mem_ptr).hit 315*8882eb68SXin Tian io.refill.bits.tag := entries(mem_ptr).ppn 316*8882eb68SXin Tian io.refill.bits.data := entries(mem_ptr).data 317*8882eb68SXin Tian 318*8882eb68SXin Tian XSPerfAccumulate("bitmap_req", io.req.fire) 319*8882eb68SXin Tian XSPerfAccumulate("bitmap_mem_req", io.mem.req.fire) 320*8882eb68SXin Tian} 321*8882eb68SXin Tian 322*8882eb68SXin Tian// add bitmap cache 323*8882eb68SXin Tianclass bitmapCacheReqBundle(implicit p: Parameters) extends PtwBundle{ 324*8882eb68SXin Tian val order = UInt((l2tlbParams.llptwsize + 2).W) 325*8882eb68SXin Tian val tag = UInt(ppnLen.W) 326*8882eb68SXin Tian} 327*8882eb68SXin Tianclass bitmapCacheRespBundle(implicit p: Parameters) extends PtwBundle{ 328*8882eb68SXin Tian val hit = Bool() 329*8882eb68SXin Tian val cfs = Vec(tlbcontiguous,Bool()) 330*8882eb68SXin Tian val order = UInt((l2tlbParams.llptwsize + 2).W) 331*8882eb68SXin Tian def apply(hit : Bool, cfs : Vec[Bool], order : UInt) = { 332*8882eb68SXin Tian this.hit := hit 333*8882eb68SXin Tian this.cfs := cfs 334*8882eb68SXin Tian this.order := order 335*8882eb68SXin Tian } 336*8882eb68SXin Tian} 337*8882eb68SXin Tianclass bitmapCacheIO(implicit p: Parameters) extends MMUIOBaseBundle with HasPtwConst { 338*8882eb68SXin Tian val req = Flipped(DecoupledIO(new bitmapCacheReqBundle())) 339*8882eb68SXin Tian val resp = DecoupledIO(new bitmapCacheRespBundle()) 340*8882eb68SXin Tian val refill = Flipped(ValidIO(new Bundle { 341*8882eb68SXin Tian val tag = UInt(ppnLen.W) 342*8882eb68SXin Tian val data = UInt(XLEN.W) 343*8882eb68SXin Tian })) 344*8882eb68SXin Tian} 345*8882eb68SXin Tianclass bitmapCacheEntry(implicit p: Parameters) extends PtwBundle{ 346*8882eb68SXin Tian val tag = UInt((ppnLen-log2Ceil(XLEN)).W) 347*8882eb68SXin Tian val data = UInt(XLEN.W) // store 64bits in one entry 348*8882eb68SXin Tian val valid = Bool() 349*8882eb68SXin Tian def hit(tag : UInt) = { 350*8882eb68SXin Tian (this.tag === tag(ppnLen-1,log2Ceil(XLEN))) && this.valid === 1.B 351*8882eb68SXin Tian } 352*8882eb68SXin Tian def refill(tag : UInt,data : UInt,valid : Bool) = { 353*8882eb68SXin Tian this.tag := tag(ppnLen-1,log2Ceil(XLEN)) 354*8882eb68SXin Tian this.data := data 355*8882eb68SXin Tian this.valid := valid 356*8882eb68SXin Tian } 357*8882eb68SXin Tian} 358*8882eb68SXin Tian 359*8882eb68SXin Tianclass BitmapCache(implicit p: Parameters) extends XSModule with HasPtwConst { 360*8882eb68SXin Tian val io = IO(new bitmapCacheIO) 361*8882eb68SXin Tian 362*8882eb68SXin Tian val csr = io.csr 363*8882eb68SXin Tian val sfence = io.sfence 364*8882eb68SXin Tian val flush = sfence.valid || csr.satp.changed || csr.vsatp.changed || csr.hgatp.changed 365*8882eb68SXin Tian val bitmap_cache_clear = csr.mbmc.BCLEAR 366*8882eb68SXin Tian 367*8882eb68SXin Tian val bitmapCachesize = 16 368*8882eb68SXin Tian val bitmapcache = Reg(Vec(bitmapCachesize,new bitmapCacheEntry())) 369*8882eb68SXin Tian val bitmapReplace = ReplacementPolicy.fromString(l2tlbParams.l3Replacer, bitmapCachesize) 370*8882eb68SXin Tian 371*8882eb68SXin Tian // ----- 372*8882eb68SXin Tian // -S0-- 373*8882eb68SXin Tian // ----- 374*8882eb68SXin Tian val addr_search = io.req.bits.tag 375*8882eb68SXin Tian val hitVecT = bitmapcache.map(_.hit(addr_search)) 376*8882eb68SXin Tian 377*8882eb68SXin Tian // ----- 378*8882eb68SXin Tian // -S1-- 379*8882eb68SXin Tian // ----- 380*8882eb68SXin Tian val index = RegEnable(addr_search(log2Up(XLEN)-1,0), io.req.fire) 381*8882eb68SXin Tian val order = RegEnable(io.req.bits.order, io.req.fire) 382*8882eb68SXin Tian val hitVec = RegEnable(VecInit(hitVecT), io.req.fire) 383*8882eb68SXin Tian val CacheData = RegEnable(ParallelPriorityMux(hitVecT zip bitmapcache.map(_.data)), io.req.fire) 384*8882eb68SXin Tian val cfs = Wire(Vec(tlbcontiguous, Bool())) 385*8882eb68SXin Tian 386*8882eb68SXin Tian val start = (index(5, 3) << 3.U) 387*8882eb68SXin Tian val end = start + 7.U 388*8882eb68SXin Tian val mask = (1.U << 8) - 1.U 389*8882eb68SXin Tian val cfsdata = (CacheData >> start) & mask 390*8882eb68SXin Tian for (i <- 0 until tlbcontiguous) { 391*8882eb68SXin Tian cfs(i) := cfsdata(i) 392*8882eb68SXin Tian } 393*8882eb68SXin Tian val hit = ParallelOR(hitVec) 394*8882eb68SXin Tian 395*8882eb68SXin Tian val resp_res = Wire(new bitmapCacheRespBundle()) 396*8882eb68SXin Tian resp_res.apply(hit,cfs,order) 397*8882eb68SXin Tian 398*8882eb68SXin Tian val resp_valid_reg = RegInit(false.B) 399*8882eb68SXin Tian when (flush) { 400*8882eb68SXin Tian resp_valid_reg := false.B 401*8882eb68SXin Tian } .elsewhen(io.req.fire) { 402*8882eb68SXin Tian resp_valid_reg := true.B 403*8882eb68SXin Tian } .elsewhen(io.resp.fire) { 404*8882eb68SXin Tian resp_valid_reg := false.B 405*8882eb68SXin Tian } .otherwise { 406*8882eb68SXin Tian resp_valid_reg := resp_valid_reg 407*8882eb68SXin Tian } 408*8882eb68SXin Tian 409*8882eb68SXin Tian io.req.ready := !resp_valid_reg || io.resp.fire 410*8882eb68SXin Tian io.resp.valid := resp_valid_reg 411*8882eb68SXin Tian io.resp.bits := resp_res 412*8882eb68SXin Tian 413*8882eb68SXin Tian when (!flush && hit && io.resp.fire) { 414*8882eb68SXin Tian bitmapReplace.access(OHToUInt(hitVec)) 415*8882eb68SXin Tian } 416*8882eb68SXin Tian 417*8882eb68SXin Tian // ----- 418*8882eb68SXin Tian // refill 419*8882eb68SXin Tian // ----- 420*8882eb68SXin Tian val rf_addr = io.refill.bits.tag 421*8882eb68SXin Tian val rf_data = io.refill.bits.data 422*8882eb68SXin Tian val rf_vd = io.refill.valid 423*8882eb68SXin Tian when (!flush && rf_vd) { 424*8882eb68SXin Tian val refillindex = bitmapReplace.way 425*8882eb68SXin Tian dontTouch(refillindex) 426*8882eb68SXin Tian bitmapcache(refillindex).refill(rf_addr,rf_data,true.B) 427*8882eb68SXin Tian bitmapReplace.access(refillindex) 428*8882eb68SXin Tian } 429*8882eb68SXin Tian when (bitmap_cache_clear === 1.U) { 430*8882eb68SXin Tian bitmapcache.foreach(_.valid := false.B) 431*8882eb68SXin Tian } 432*8882eb68SXin Tian 433*8882eb68SXin Tian XSPerfAccumulate("bitmap_cache_resp", io.resp.fire) 434*8882eb68SXin Tian XSPerfAccumulate("bitmap_cache_resp_miss", io.resp.fire && !io.resp.bits.hit) 435*8882eb68SXin Tian} 436