xref: /XiangShan/src/main/scala/xiangshan/cache/mmu/BitmapCheck.scala (revision 8882eb685de93177da606ee717b5ec8e459a768a)
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