1package xiangshan.mem.prefetch 2 3import chipsalliance.rocketchip.config.Parameters 4import chisel3._ 5import chisel3.util._ 6import huancun.utils.ValidIODelay 7import xiangshan._ 8import utils._ 9import xiangshan.cache.mmu._ 10 11case class SMSParams 12( 13 region_size: Int = 1024, 14 vaddr_hash_width: Int = 5, 15 block_addr_raw_width: Int = 10, 16 filter_table_size: Int = 16, 17 active_gen_table_size: Int = 16, 18 pht_size: Int = 64, 19 pht_ways: Int = 2, 20 pht_hist_bits: Int = 2, 21 pht_tag_bits: Int = 13, 22 pht_lookup_queue_size: Int = 4, 23 pf_filter_size: Int = 16 24) extends PrefetcherParams 25 26trait HasSMSModuleHelper extends HasCircularQueuePtrHelper 27{ this: HasXSParameter => 28 val smsParams = coreParams.prefetcher.get.asInstanceOf[SMSParams] 29 val BLK_ADDR_WIDTH = VAddrBits - log2Up(dcacheParameters.blockBytes) 30 val REGION_SIZE = smsParams.region_size 31 val REGION_BLKS = smsParams.region_size / dcacheParameters.blockBytes 32 val REGION_ADDR_BITS = VAddrBits - log2Up(REGION_SIZE) 33 val REGION_OFFSET = log2Up(REGION_BLKS) 34 val VADDR_HASH_WIDTH = smsParams.vaddr_hash_width 35 val BLK_ADDR_RAW_WIDTH = smsParams.block_addr_raw_width 36 val REGION_ADDR_RAW_WIDTH = BLK_ADDR_RAW_WIDTH - REGION_OFFSET 37 val BLK_TAG_WIDTH = BLK_ADDR_RAW_WIDTH + VADDR_HASH_WIDTH 38 val REGION_TAG_WIDTH = REGION_ADDR_RAW_WIDTH + VADDR_HASH_WIDTH 39 val PHT_INDEX_BITS = log2Up(smsParams.pht_size / smsParams.pht_ways) 40 val PHT_TAG_BITS = smsParams.pht_tag_bits 41 val PHT_HIST_BITS = smsParams.pht_hist_bits 42 43 def block_addr(x: UInt): UInt = { 44 val offset = log2Up(dcacheParameters.blockBytes) 45 x(x.getWidth - 1, offset) 46 } 47 48 def region_addr(x: UInt): UInt = { 49 val offset = log2Up(REGION_SIZE) 50 x(x.getWidth - 1, offset) 51 } 52 53 def region_offset_to_bits(off: UInt): UInt = { 54 (1.U << off).asUInt 55 } 56 57 def region_hash_tag(rg_addr: UInt): UInt = { 58 val low = rg_addr(REGION_ADDR_RAW_WIDTH - 1, 0) 59 val high = rg_addr(REGION_ADDR_RAW_WIDTH + 3 * VADDR_HASH_WIDTH - 1, REGION_ADDR_RAW_WIDTH) 60 val high_hash = vaddr_hash(high) 61 Cat(high_hash, low) 62 } 63 64 def page_bit(region_addr: UInt): UInt = { 65 region_addr(log2Up(dcacheParameters.pageSize/REGION_SIZE)) 66 } 67 68 def block_hash_tag(x: UInt): UInt = { 69 val blk_addr = block_addr(x) 70 val low = blk_addr(BLK_ADDR_RAW_WIDTH - 1, 0) 71 val high = blk_addr(BLK_ADDR_RAW_WIDTH - 1 + 3 * VADDR_HASH_WIDTH, BLK_ADDR_RAW_WIDTH) 72 val high_hash = vaddr_hash(high) 73 Cat(high_hash, low) 74 } 75 76 def vaddr_hash(x: UInt): UInt = { 77 val width = VADDR_HASH_WIDTH 78 val low = x(width - 1, 0) 79 val mid = x(2 * width - 1, width) 80 val high = x(3 * width - 1, 2 * width) 81 low ^ mid ^ high 82 } 83 84 def pht_index(pc: UInt): UInt = { 85 val low_bits = pc(PHT_INDEX_BITS, 2) 86 val hi_bit = pc(1) ^ pc(PHT_INDEX_BITS+1) 87 Cat(hi_bit, low_bits) 88 } 89 90 def pht_tag(pc: UInt): UInt = { 91 pc(PHT_INDEX_BITS + 2 + PHT_TAG_BITS - 1, PHT_INDEX_BITS + 2) 92 } 93} 94 95class FilterTable()(implicit p: Parameters) extends XSModule with HasSMSModuleHelper { 96 val io = IO(new Bundle() { 97 val s0_lookup = Flipped(ValidIO(new FilterEntry())) 98 val s1_result = ValidIO(new FilterEntry()) 99 val s1_update = Input(Bool()) 100 }) 101 102 val s0_lookup_entry = io.s0_lookup.bits 103 val s0_lookup_valid = io.s0_lookup.valid 104 105 val entries = Seq.fill(smsParams.filter_table_size){ Reg(new FilterEntry()) } 106 val valids = Seq.fill(smsParams.filter_table_size){ RegInit(false.B) } 107 val w_ptr = RegInit(0.U(log2Up(smsParams.filter_table_size).W)) 108 109 val prev_entry = RegEnable(s0_lookup_entry, s0_lookup_valid) 110 val prev_lookup_valid = RegNext(s0_lookup_valid, false.B) 111 112 val s0_entry_match_vec = entries.zip(valids).map({ 113 case (ent, v) => v && ent.region_tag === s0_lookup_entry.region_tag && ent.offset =/= s0_lookup_entry.offset 114 }) 115 val s0_any_entry_match = Cat(s0_entry_match_vec).orR 116 val s0_matched_entry = Mux1H(s0_entry_match_vec, entries) 117 val s0_match_s1 = prev_lookup_valid && prev_entry.region_tag === s0_lookup_entry.region_tag 118 119 val s0_hit = s0_lookup_valid && (s0_any_entry_match || s0_match_s1) 120 121 val s0_lookup_result = Wire(new FilterEntry()) 122 s0_lookup_result := Mux(s0_match_s1, prev_entry, s0_matched_entry) 123 io.s1_result.valid := RegNext(s0_hit, false.B) 124 io.s1_result.bits := RegEnable(s0_lookup_result, s0_hit) 125 126 val s0_invalid_mask = valids.map(!_) 127 val s0_has_invalid_entry = Cat(s0_invalid_mask).orR 128 val s0_invalid_index = PriorityEncoder(s0_invalid_mask) 129 // if match, invalidte entry 130 for((v, i) <- valids.zipWithIndex){ 131 when(s0_lookup_valid && s0_entry_match_vec(i)){ 132 v := false.B 133 } 134 } 135 136 // stage1 137 val s1_has_invalid_entry = RegEnable(s0_has_invalid_entry, s0_lookup_valid) 138 val s1_invalid_index = RegEnable(s0_invalid_index, s0_lookup_valid) 139 // alloc entry if (s0 miss && s1_update) 140 val s1_do_update = io.s1_update && prev_lookup_valid && !io.s1_result.valid 141 val update_ptr = Mux(s1_has_invalid_entry, s1_invalid_index, w_ptr) 142 when(s1_do_update && !s1_has_invalid_entry){ w_ptr := w_ptr + 1.U } 143 for((ent, i) <- entries.zipWithIndex){ 144 val wen = s1_do_update && update_ptr === i.U 145 when(wen){ 146 valids(i) := true.B 147 ent := prev_entry 148 } 149 } 150 151 XSPerfAccumulate("sms_filter_table_hit", io.s1_result.valid) 152 XSPerfAccumulate("sms_filter_table_update", s1_do_update) 153 for(i <- 0 until smsParams.filter_table_size){ 154 XSPerfAccumulate(s"sms_filter_table_access_$i", 155 s1_do_update && update_ptr === i.U 156 ) 157 } 158} 159 160class FilterEntry()(implicit p: Parameters) extends XSBundle with HasSMSModuleHelper { 161 val pht_index = UInt(PHT_INDEX_BITS.W) 162 val pht_tag = UInt(PHT_TAG_BITS.W) 163 val region_tag = UInt(REGION_TAG_WIDTH.W) 164 val offset = UInt(REGION_OFFSET.W) 165} 166 167class AGTEntry()(implicit p: Parameters) extends XSBundle with HasSMSModuleHelper { 168 val pht_index = UInt(PHT_INDEX_BITS.W) 169 val pht_tag = UInt(PHT_TAG_BITS.W) 170 val region_bits = UInt(REGION_BLKS.W) 171 val region_tag = UInt(REGION_TAG_WIDTH.W) 172 val access_cnt = UInt((REGION_BLKS-1).U.getWidth.W) 173 val decr_mode = Bool() 174} 175 176class PfGenReq()(implicit p: Parameters) extends XSBundle with HasSMSModuleHelper { 177 val region_tag = UInt(REGION_TAG_WIDTH.W) 178 val region_addr = UInt(REGION_ADDR_BITS.W) 179 val region_bits = UInt(REGION_BLKS.W) 180 val paddr_valid = Bool() 181 val decr_mode = Bool() 182} 183 184class ActiveGenerationTable()(implicit p: Parameters) extends XSModule with HasSMSModuleHelper { 185 val io = IO(new Bundle() { 186 val s0_lookup = Flipped(ValidIO(new Bundle() { 187 val region_tag = UInt(REGION_TAG_WIDTH.W) 188 val region_p1_tag = UInt(REGION_TAG_WIDTH.W) 189 val region_m1_tag = UInt(REGION_TAG_WIDTH.W) 190 val region_offset = UInt(REGION_OFFSET.W) 191 val pht_index = UInt(PHT_INDEX_BITS.W) 192 val pht_tag = UInt(PHT_TAG_BITS.W) 193 val allow_cross_region_p1 = Bool() 194 val allow_cross_region_m1 = Bool() 195 val region_p1_cross_page = Bool() 196 val region_m1_cross_page = Bool() 197 val region_paddr = UInt(REGION_ADDR_BITS.W) 198 val region_vaddr = UInt(REGION_ADDR_BITS.W) 199 })) 200 // do not alloc entry in filter table if agt hit 201 val s1_match_or_alloc = Output(Bool()) 202 // if agt missed, try lookup pht 203 val s2_pht_lookup = ValidIO(new PhtLookup()) 204 // receive second hit from filter table 205 val s1_recv_entry = Flipped(ValidIO(new AGTEntry())) 206 // evict entry to pht 207 val s2_evict = ValidIO(new AGTEntry()) 208 val s2_pf_gen_req = ValidIO(new PfGenReq()) 209 }) 210 211 val entries = Seq.fill(smsParams.active_gen_table_size){ Reg(new AGTEntry()) } 212 val valids = Seq.fill(smsParams.active_gen_table_size){ RegInit(false.B) } 213 val replacement = ReplacementPolicy.fromString("plru", smsParams.active_gen_table_size) 214 215 val s0_lookup = io.s0_lookup.bits 216 val s0_lookup_valid = io.s0_lookup.valid 217 218 val prev_lookup = RegEnable(s0_lookup, s0_lookup_valid) 219 val prev_lookup_valid = RegNext(s0_lookup_valid, false.B) 220 221 val s0_match_prev = prev_lookup_valid && s0_lookup.region_tag === prev_lookup.region_tag 222 223 def gen_match_vec(region_tag: UInt): Seq[Bool] = { 224 entries.zip(valids).map({ 225 case (ent, v) => v && ent.region_tag === region_tag 226 }) 227 } 228 229 val region_match_vec_s0 = gen_match_vec(s0_lookup.region_tag) 230 val region_p1_match_vec_s0 = gen_match_vec(s0_lookup.region_p1_tag) 231 val region_m1_match_vec_s0 = gen_match_vec(s0_lookup.region_m1_tag) 232 233 val any_region_match = Cat(region_match_vec_s0).orR 234 val any_region_p1_match = Cat(region_p1_match_vec_s0).orR && s0_lookup.allow_cross_region_p1 235 val any_region_m1_match = Cat(region_m1_match_vec_s0).orR && s0_lookup.allow_cross_region_m1 236 237 val s0_region_hit = any_region_match 238 // region miss, but cross region match 239 val s0_alloc = !s0_region_hit && (any_region_p1_match || any_region_m1_match) && !s0_match_prev 240 val s0_match_or_alloc = any_region_match || any_region_p1_match || any_region_m1_match 241 val s0_pf_gen_match_vec = valids.indices.map(i => { 242 Mux(any_region_match, 243 region_match_vec_s0(i), 244 Mux(any_region_m1_match, 245 region_m1_match_vec_s0(i), region_p1_match_vec_s0(i) 246 ) 247 ) 248 }) 249 val s0_agt_entry = Wire(new AGTEntry()) 250 251 s0_agt_entry.pht_index := s0_lookup.pht_index 252 s0_agt_entry.pht_tag := s0_lookup.pht_tag 253 s0_agt_entry.region_bits := region_offset_to_bits(s0_lookup.region_offset) 254 s0_agt_entry.region_tag := s0_lookup.region_tag 255 s0_agt_entry.access_cnt := 1.U 256 // lookup_region + 1 == entry_region 257 // lookup_region = entry_region - 1 => decr mode 258 s0_agt_entry.decr_mode := !s0_region_hit && !any_region_m1_match && any_region_p1_match 259 val s0_replace_mask = UIntToOH(replacement.way) 260 // s0 hit a entry that may be replaced in s1 261 val s0_update_conflict = Cat(VecInit(region_match_vec_s0).asUInt & s0_replace_mask).orR 262 263 // stage1: update/alloc 264 val s1_agt_entry = RegEnable(s0_agt_entry, s0_lookup_valid) 265 val s1_recv_entry = io.s1_recv_entry 266 // cross region match or filter table second hit 267 val s1_cross_region_match = RegNext(s0_lookup_valid && s0_alloc, false.B) 268 val s1_alloc = s1_cross_region_match || s1_recv_entry.valid 269 val s1_alloc_entry = Mux(s1_recv_entry.valid, s1_recv_entry.bits, s1_agt_entry) 270 val s1_replace_mask = RegEnable(s0_replace_mask, s0_lookup_valid) 271 val s1_evict_entry = Mux1H(s1_replace_mask, entries) 272 val s1_evict_valid = Mux1H(s1_replace_mask, valids) 273 // region hit, update entry 274 val s1_update_conflict = RegEnable(s0_update_conflict, s0_lookup_valid && s0_region_hit) 275 val s1_update = RegNext(s0_lookup_valid && s0_region_hit, false.B) && !s1_update_conflict 276 val s1_update_mask = RegEnable( 277 VecInit(region_match_vec_s0), 278 VecInit(Seq.fill(smsParams.active_gen_table_size){ false.B }), 279 s0_lookup_valid 280 ) 281 val s1_allow_cross_region_p1 = RegEnable(s0_lookup.allow_cross_region_p1, s0_lookup_valid) 282 val s1_allow_cross_region_m1 = RegEnable(s0_lookup.allow_cross_region_m1, s0_lookup_valid) 283 val s1_region_p1_cross_page = RegEnable(s0_lookup.region_p1_cross_page, s0_lookup_valid) 284 val s1_region_m1_cross_page = RegEnable(s0_lookup.region_m1_cross_page, s0_lookup_valid) 285 val s1_pf_gen_match_vec = RegEnable(VecInit(s0_pf_gen_match_vec), s0_lookup_valid) 286 val s1_region_paddr = RegEnable(s0_lookup.region_paddr, s0_lookup_valid) 287 val s1_region_vaddr = RegEnable(s0_lookup.region_vaddr, s0_lookup_valid) 288 val s1_region_offset = RegEnable(s0_lookup.region_offset, s0_lookup_valid) 289 for(i <- entries.indices){ 290 val alloc = s1_replace_mask(i) && s1_alloc 291 val update = s1_update_mask(i) && s1_update 292 val update_entry = WireInit(entries(i)) 293 update_entry.region_bits := entries(i).region_bits | s1_agt_entry.region_bits 294 update_entry.access_cnt := Mux(entries(i).access_cnt === (REGION_BLKS - 1).U, 295 entries(i).access_cnt, 296 entries(i).access_cnt + (s1_agt_entry.region_bits & (~entries(i).region_bits).asUInt).orR 297 ) 298 valids(i) := valids(i) || alloc 299 entries(i) := Mux(alloc, s1_alloc_entry, Mux(update, update_entry, entries(i))) 300 } 301 when(s1_update) { 302 replacement.access(OHToUInt(s1_update_mask)) 303 }.elsewhen(s1_alloc){ 304 replacement.access(OHToUInt(s1_replace_mask)) 305 } 306 307 io.s1_match_or_alloc := s1_update || s1_alloc 308 309 310 // pf_addr 311 // 1.hit => pf_addr = lookup_addr + (decr ? -1 : 1) 312 // 2.lookup region - 1 hit => lookup_addr + 1 (incr mode) 313 // 3.lookup region + 1 hit => lookup_addr - 1 (decr mode) 314 val s1_hited_entry_decr = Mux1H(s1_update_mask, entries.map(_.decr_mode)) 315 val s1_pf_gen_decr_mode = Mux(s1_update, 316 s1_hited_entry_decr, 317 s1_agt_entry.decr_mode 318 ) 319 val s1_pf_gen_paddr_valid = Mux(s1_pf_gen_decr_mode, 320 !s1_region_m1_cross_page, 321 !s1_region_p1_cross_page 322 ) 323 324 val s1_pf_gen_vaddr_inc = Cat(0.U, s1_region_vaddr, s1_region_offset) + 30.U 325 val s1_pf_gen_vaddr_dec = Cat(0.U, s1_region_vaddr, s1_region_offset) - 30.U 326 val PAGE_BIT = log2Up(dcacheParameters.pageSize / dcacheParameters.blockBytes) 327 val s1_vaddr_inc_cross_page = s1_pf_gen_vaddr_inc(PAGE_BIT) =/= s1_region_vaddr(PAGE_BIT - REGION_OFFSET) 328 val s1_vaddr_dec_cross_page = s1_pf_gen_vaddr_dec(PAGE_BIT) =/= s1_region_vaddr(PAGE_BIT - REGION_OFFSET) 329 val s1_vaddr_inc_cross_max_lim = s1_pf_gen_vaddr_inc.head(1).asBool 330 val s1_vaddr_dec_cross_max_lim = s1_pf_gen_vaddr_dec.head(1).asBool 331 332 //val s1_pf_gen_vaddr_p1 = s1_region_vaddr(REGION_TAG_WIDTH - 1, 0) + 1.U 333 //val s1_pf_gen_vaddr_m1 = s1_region_vaddr(REGION_TAG_WIDTH - 1, 0) - 1.U 334 val s1_pf_gen_vaddr = Cat( 335 s1_region_vaddr(REGION_ADDR_BITS - 1, REGION_TAG_WIDTH), 336 Mux(s1_pf_gen_decr_mode, 337 s1_pf_gen_vaddr_dec.tail(1).head(REGION_TAG_WIDTH), 338 s1_pf_gen_vaddr_inc.tail(1).head(REGION_TAG_WIDTH) 339 ) 340 ) 341 val s1_pf_gen_offset = Mux(s1_pf_gen_decr_mode, 342 s1_pf_gen_vaddr_dec(REGION_OFFSET - 1, 0), 343 s1_pf_gen_vaddr_inc(REGION_OFFSET - 1, 0) 344 ) 345 val s1_pf_gen_offset_mask = UIntToOH(s1_pf_gen_offset) 346 val s1_pf_gen_access_cnt = Mux1H(s1_pf_gen_match_vec, entries.map(_.access_cnt)) 347 val s1_pf_gen_valid = prev_lookup_valid && io.s1_match_or_alloc && Mux(s1_pf_gen_decr_mode, 348 !s1_vaddr_dec_cross_page || !s1_vaddr_dec_cross_max_lim, 349 !s1_vaddr_inc_cross_page || !s1_vaddr_inc_cross_max_lim 350 ) && (s1_pf_gen_access_cnt > (REGION_BLKS * 3 / 4).U) 351 val s1_pf_gen_region_tag = s1_agt_entry.region_tag 352 val s1_pf_gen_region_addr = Mux(s1_pf_gen_paddr_valid, 353 s1_region_paddr, s1_pf_gen_vaddr 354 ) 355 val s1_pf_gen_incr_region_bits = VecInit((0 until REGION_BLKS).map(i => { 356 if(i == 0) true.B else !s1_pf_gen_offset_mask(i - 1, 0).orR 357 })).asUInt 358 val s1_pf_gen_decr_region_bits = VecInit((0 until REGION_BLKS).map(i => { 359 if(i == REGION_BLKS - 1) true.B 360 else !s1_pf_gen_offset_mask(REGION_BLKS - 1, i + 1).orR 361 })).asUInt 362 val s1_pf_gen_region_bits = Mux(s1_pf_gen_decr_mode, 363 s1_pf_gen_decr_region_bits, 364 s1_pf_gen_incr_region_bits 365 ) 366 val s1_pht_lookup_valid = Wire(Bool()) 367 val s1_pht_lookup = Wire(new PhtLookup()) 368 369 s1_pht_lookup_valid := !s1_pf_gen_valid && prev_lookup_valid 370 s1_pht_lookup.pht_index := s1_agt_entry.pht_index 371 s1_pht_lookup.pht_tag := s1_agt_entry.pht_tag 372 s1_pht_lookup.region_tag := s1_agt_entry.region_tag 373 s1_pht_lookup.region_addr := s1_region_paddr 374 s1_pht_lookup.paddr_valid := true.B 375 s1_pht_lookup.region_offset := s1_region_offset 376 377 // stage2: gen pf reg / evict entry to pht 378 val s2_evict_entry = RegEnable(s1_evict_entry, s1_alloc) 379 val s2_evict_valid = RegNext(s1_alloc && s1_evict_valid, false.B) 380 val s2_paddr_valid = RegEnable(s1_pf_gen_paddr_valid, s1_pf_gen_valid) 381 val s2_pf_gen_region_tag = RegEnable(s1_pf_gen_region_tag, s1_pf_gen_valid) 382 val s2_pf_gen_decr_mode = RegEnable(s1_pf_gen_decr_mode, s1_pf_gen_valid) 383 val s2_pf_gen_region_paddr = RegEnable(s1_pf_gen_region_addr, s1_pf_gen_valid) 384 val s2_pf_gen_region_bits = RegEnable(s1_pf_gen_region_bits, s1_pf_gen_valid) 385 val s2_pf_gen_valid = RegNext(s1_pf_gen_valid, false.B) 386 val s2_pht_lookup_valid = RegNext(s1_pht_lookup_valid, false.B) 387 val s2_pht_lookup = RegEnable(s1_pht_lookup, s1_pht_lookup_valid) 388 389 io.s2_evict.valid := s2_evict_valid 390 io.s2_evict.bits := s2_evict_entry 391 392 io.s2_pf_gen_req.bits.region_tag := s2_pf_gen_region_tag 393 io.s2_pf_gen_req.bits.region_addr := s2_pf_gen_region_paddr 394 io.s2_pf_gen_req.bits.region_bits := s2_pf_gen_region_bits 395 io.s2_pf_gen_req.bits.paddr_valid := s2_paddr_valid 396 io.s2_pf_gen_req.bits.decr_mode := s2_pf_gen_decr_mode 397 io.s2_pf_gen_req.valid := s2_pf_gen_valid 398 399 io.s2_pht_lookup.valid := s2_pht_lookup_valid 400 io.s2_pht_lookup.bits := s2_pht_lookup 401 402 XSPerfAccumulate("sms_agt_alloc", s1_alloc) // cross region match or filter evict 403 XSPerfAccumulate("sms_agt_update", s1_update) // entry hit 404 XSPerfAccumulate("sms_agt_pf_gen", io.s2_pf_gen_req.valid) 405 XSPerfAccumulate("sms_agt_pf_gen_paddr_valid", 406 io.s2_pf_gen_req.valid && io.s2_pf_gen_req.bits.paddr_valid 407 ) 408 XSPerfAccumulate("sms_agt_pf_gen_decr_mode", 409 io.s2_pf_gen_req.valid && io.s2_pf_gen_req.bits.decr_mode 410 ) 411 for(i <- 0 until smsParams.active_gen_table_size){ 412 XSPerfAccumulate(s"sms_agt_access_entry_$i", 413 s1_alloc && s1_replace_mask(i) || s1_update && s1_update_mask(i) 414 ) 415 } 416 417} 418 419class PhtLookup()(implicit p: Parameters) extends XSBundle with HasSMSModuleHelper { 420 val pht_index = UInt(PHT_INDEX_BITS.W) 421 val pht_tag = UInt(PHT_TAG_BITS.W) 422 val region_tag = UInt(REGION_TAG_WIDTH.W) 423 val region_addr = UInt(REGION_ADDR_BITS.W) 424 val paddr_valid = Bool() 425 val region_offset = UInt(REGION_OFFSET.W) 426} 427 428class PhtEntry()(implicit p: Parameters) extends XSBundle with HasSMSModuleHelper { 429 val hist = Vec(REGION_BLKS, UInt(PHT_HIST_BITS.W)) 430 val tag = UInt(PHT_TAG_BITS.W) 431 val decr_mode = Bool() 432} 433 434class PatternHistoryTable()(implicit p: Parameters) extends XSModule with HasSMSModuleHelper { 435 val io = IO(new Bundle() { 436 // receive agt evicted entry 437 val agt_update = Flipped(ValidIO(new AGTEntry())) 438 // at stage2, if we know agt missed, lookup pht 439 val s2_agt_lookup = Flipped(ValidIO(new PhtLookup())) 440 // pht-generated prefetch req 441 val pf_gen_req = ValidIO(new PfGenReq()) 442 }) 443 444 val pht_ram = Module(new SRAMTemplate[PhtEntry](new PhtEntry, 445 set = smsParams.pht_size / smsParams.pht_ways, 446 way =smsParams.pht_ways, 447 singlePort = true 448 )) 449 def PHT_SETS = smsParams.pht_size / smsParams.pht_ways 450 val pht_valids = Seq.fill(smsParams.pht_ways){ 451 RegInit(VecInit(Seq.fill(PHT_SETS){false.B})) 452 } 453 val replacement = Seq.fill(PHT_SETS) { ReplacementPolicy.fromString("plru", smsParams.pht_ways) } 454 455 val lookup_queue = Module(new OverrideableQueue(new PhtLookup, smsParams.pht_lookup_queue_size)) 456 lookup_queue.io.in := io.s2_agt_lookup 457 val lookup = lookup_queue.io.out 458 459 val evict_queue = Module(new OverrideableQueue(new AGTEntry, smsParams.pht_lookup_queue_size)) 460 evict_queue.io.in := io.agt_update 461 val evict = evict_queue.io.out 462 463 val s3_ram_en = Wire(Bool()) 464 val s1_valid = Wire(Bool()) 465 // pipe s0: select an op from [lookup, update], generate ram read addr 466 val s0_valid = lookup.valid || evict.valid 467 val s0_ready = !s1_valid || s1_valid && !s3_ram_en 468 469 evict.ready := !s1_valid || !s3_ram_en 470 lookup.ready := evict.ready && !evict.valid 471 472 val s0_ram_raddr = Mux(evict.valid, 473 evict.bits.pht_index, 474 lookup.bits.pht_index 475 ) 476 val s0_tag = Mux(evict.valid, evict.bits.pht_tag, lookup.bits.pht_tag) 477 val s0_region_addr = lookup.bits.region_addr 478 val s0_region_tag = lookup.bits.region_tag 479 val s0_region_offset = lookup.bits.region_offset 480 val s0_paddr_valid = lookup.bits.paddr_valid 481 val s0_region_bits = evict.bits.region_bits 482 val s0_decr_mode = evict.bits.decr_mode 483 val s0_evict = evict.valid 484 485 // pipe s1: send addr to ram 486 val s1_valid_r = RegInit(false.B) 487 s1_valid_r := Mux(s3_ram_en, s1_valid, s0_valid) 488 s1_valid := s1_valid_r 489 val s1_reg_en = s0_valid && (!s3_ram_en || !s1_valid) 490 val s1_ram_raddr = RegEnable(s0_ram_raddr, s1_reg_en) 491 val s1_tag = RegEnable(s0_tag, s1_reg_en) 492 val s1_region_bits = RegEnable(s0_region_bits, s1_reg_en) 493 val s1_decr_mode = RegEnable(s0_decr_mode, s1_reg_en) 494 val s1_region_addr = RegEnable(s0_region_addr, s1_reg_en) 495 val s1_region_tag = RegEnable(s0_region_tag, s1_reg_en) 496 val s1_region_offset = RegEnable(s0_region_offset, s1_reg_en) 497 val s1_paddr_valid = RegEnable(s0_paddr_valid, s1_reg_en) 498 val s1_pht_valids = pht_valids.map(way => Mux1H( 499 (0 until PHT_SETS).map(i => i.U === s1_ram_raddr), 500 way 501 )) 502 val s1_evict = RegEnable(s0_evict, s1_reg_en) 503 val s1_replace_way = Mux1H( 504 (0 until PHT_SETS).map(i => i.U === s1_ram_raddr), 505 replacement.map(_.way) 506 ) 507 508 // pipe s2: generate ram write addr/data 509 val s2_valid = RegNext(s1_valid && !s3_ram_en, false.B) 510 val s2_reg_en = s1_valid && !s3_ram_en 511 val s2_tag = RegEnable(s1_tag, s2_reg_en) 512 val s2_region_bits = RegEnable(s1_region_bits, s2_reg_en) 513 val s2_decr_mode = RegEnable(s1_decr_mode, s2_reg_en) 514 val s2_region_addr = RegEnable(s1_region_addr, s2_reg_en) 515 val s2_region_tag = RegEnable(s1_region_tag, s2_reg_en) 516 val s2_region_offset = RegEnable(s1_region_offset, s2_reg_en) 517 val s2_region_offset_mask = region_offset_to_bits(s2_region_offset) 518 val s2_paddr_valid = RegEnable(s1_paddr_valid, s2_reg_en) 519 val s2_evict = RegEnable(s1_evict, s2_reg_en) 520 val s2_pht_valids = s1_pht_valids.map(v => RegEnable(v, s2_reg_en)) 521 val s2_replace_way = RegEnable(s1_replace_way, s2_reg_en) 522 val s2_ram_waddr = RegEnable(s1_ram_raddr, s2_reg_en) 523 val s2_ram_rdata = pht_ram.io.r.resp.data 524 val s2_ram_rtags = s2_ram_rdata.map(_.tag) 525 val s2_tag_match_vec = s2_ram_rtags.map(t => t === s2_tag) 526 val s2_hit_vec = s2_tag_match_vec.zip(s2_pht_valids).map({ 527 case (tag_match, v) => v && tag_match 528 }) 529 val s2_hist_update = s2_ram_rdata.map(way => VecInit(way.hist.zipWithIndex.map({ 530 case (h, i) => Mux(s2_region_bits(i), 531 Mux(h === ((1 << PHT_HIST_BITS) - 1).U, h, h + 1.U), 532 Mux(h === 0.U, 0.U, h - 1.U) 533 ) 534 }))) 535 val s2_hits_pf_gen = s2_ram_rdata.map(way => VecInit(way.hist.map(_.head(1))).asUInt) 536 val s2_new_hist = VecInit((0 until REGION_BLKS).map(i => { 537 Cat(0.U((PHT_HIST_BITS - 1).W), s2_region_bits(i)) 538 })) 539 val s2_pht_hit = Cat(s2_hit_vec).orR 540 val s2_hist = Mux(s2_pht_hit, Mux1H(s2_hit_vec, s2_hist_update), s2_new_hist) 541 val s2_repl_way_mask = UIntToOH(s2_replace_way) 542 val s2_pf_gen_region_bits = Mux1H(s2_hit_vec, s2_hits_pf_gen) 543 544 // pipe s3: send addr/data to ram, gen pf_req 545 val s3_valid = RegNext(s2_valid, false.B) 546 val s3_evict = RegEnable(s2_evict, s2_valid) 547 val s3_hist = RegEnable(s2_hist, s2_valid) 548 val s3_pf_gen_region_bits = RegEnable(s2_pf_gen_region_bits, s2_valid) 549 val s3_decr_mode = RegEnable(s2_decr_mode, s2_valid) 550 val s3_region_addr = RegEnable(s2_region_addr, s2_valid) 551 val s3_region_tag = RegEnable(s2_region_tag, s2_valid) 552 val s3_region_offset_mask = RegEnable(s2_region_offset_mask, s2_valid) 553 val s3_paddr_valid = RegEnable(s2_paddr_valid, s2_valid) 554 val s3_pht_tag = RegEnable(s2_tag, s2_valid) 555 val s3_hit_vec = s2_hit_vec.map(h => RegEnable(h, s2_valid)) 556 val s3_hit = Cat(s3_hit_vec).orR 557 val s3_hit_way = OHToUInt(s3_hit_vec) 558 val s3_repl_way = RegEnable(s2_replace_way, s2_valid) 559 val s3_repl_way_mask = RegEnable(s2_repl_way_mask, s2_valid) 560 val s3_repl_update_mask = RegEnable(VecInit((0 until PHT_SETS).map(i => i.U === s2_ram_waddr)), s2_valid) 561 val s3_ram_waddr = RegEnable(s2_ram_waddr, s2_valid) 562 s3_ram_en := s3_valid && s3_evict 563 val s3_ram_wdata = Wire(new PhtEntry()) 564 s3_ram_wdata.hist := s3_hist 565 s3_ram_wdata.tag := s3_pht_tag 566 s3_ram_wdata.decr_mode := s3_decr_mode 567 568 for((valids, way_idx) <- pht_valids.zipWithIndex){ 569 val update_way = s3_repl_way_mask(way_idx) 570 for((v, set_idx) <- valids.zipWithIndex){ 571 val update_set = s3_repl_update_mask(set_idx) 572 when(s3_valid && s3_evict && !s3_hit && update_set && update_way){ 573 v := true.B 574 } 575 } 576 } 577 for((r, i) <- replacement.zipWithIndex){ 578 when(s3_valid && s3_repl_update_mask(i)){ 579 when(s3_hit){ 580 r.access(s3_hit_way) 581 }.elsewhen(s3_evict){ 582 r.access(s3_repl_way) 583 } 584 } 585 } 586 587 val s3_way_mask = Mux(s3_hit, 588 VecInit(s3_hit_vec).asUInt, 589 s3_repl_way_mask, 590 ).asUInt 591 592 pht_ram.io.r( 593 s1_valid, s1_ram_raddr 594 ) 595 pht_ram.io.w( 596 s3_ram_en, s3_ram_wdata, s3_ram_waddr, s3_way_mask 597 ) 598 // generate pf req if hit 599 val s3_pf_gen_region_masked = s3_pf_gen_region_bits & (~s3_region_offset_mask).asUInt 600 io.pf_gen_req.valid := s3_valid && !s3_evict && s3_hit && s3_pf_gen_region_masked.orR 601 io.pf_gen_req.bits.region_addr := s3_region_addr 602 io.pf_gen_req.bits.region_tag := s3_region_tag 603 // mask out current req 604 io.pf_gen_req.bits.region_bits := s3_pf_gen_region_masked 605 io.pf_gen_req.bits.paddr_valid := s3_paddr_valid 606 io.pf_gen_req.bits.decr_mode := s3_decr_mode 607 608 XSPerfAccumulate("sms_pht_update", io.agt_update.valid) 609 XSPerfAccumulate("sms_pht_update_hit", s2_valid && s2_evict && s2_pht_hit) 610 XSPerfAccumulate("sms_pht_lookup", io.s2_agt_lookup.valid) 611 XSPerfAccumulate("sms_pht_lookup_hit", s2_valid && !s2_evict && s2_pht_hit) 612 for(i <- 0 until smsParams.pht_ways){ 613 XSPerfAccumulate(s"sms_pht_write_way_$i", pht_ram.io.w.req.fire && pht_ram.io.w.req.bits.waymask.get(i)) 614 } 615 for(i <- 0 until PHT_SETS){ 616 XSPerfAccumulate(s"sms_pht_write_set_$i", pht_ram.io.w.req.fire && pht_ram.io.w.req.bits.setIdx === i.U) 617 } 618 XSPerfAccumulate(s"sms_pht_hit_but_no_region", s3_valid && !s3_evict && s3_hit && !s3_pf_gen_region_masked.orR) 619 XSPerfAccumulate(s"sms_pht_pf_gen", io.pf_gen_req.valid) 620} 621 622class PrefetchFilterEntry()(implicit p: Parameters) extends XSBundle with HasSMSModuleHelper { 623 val region_tag = UInt(REGION_TAG_WIDTH.W) 624 val region_addr = UInt(REGION_ADDR_BITS.W) 625 val region_bits = UInt(REGION_BLKS.W) 626 val filter_bits = UInt(REGION_BLKS.W) 627 val paddr_valid = Bool() 628 val decr_mode = Bool() 629} 630 631class PrefetchFilter()(implicit p: Parameters) extends XSModule with HasSMSModuleHelper { 632 val io = IO(new Bundle() { 633 val gen_req = Flipped(ValidIO(new PfGenReq())) 634 val tlb_req = new TlbRequestIO(2) 635 val l2_pf_addr = ValidIO(UInt(PAddrBits.W)) 636 }) 637 val entries = Seq.fill(smsParams.pf_filter_size){ Reg(new PrefetchFilterEntry()) } 638 val valids = Seq.fill(smsParams.pf_filter_size){ RegInit(false.B) } 639 val replacement = ReplacementPolicy.fromString("plru", smsParams.pf_filter_size) 640 641 val prev_valid = RegNext(io.gen_req.valid, false.B) 642 val prev_gen_req = RegEnable(io.gen_req.bits, io.gen_req.valid) 643 644 val tlb_req_arb = Module(new RRArbiter(new TlbReq, smsParams.pf_filter_size)) 645 val pf_req_arb = Module(new RRArbiter(UInt(PAddrBits.W), smsParams.pf_filter_size)) 646 647 io.tlb_req.req <> tlb_req_arb.io.out 648 io.tlb_req.req_kill := false.B 649 io.tlb_req.resp.ready := true.B 650 io.l2_pf_addr.valid := pf_req_arb.io.out.valid 651 io.l2_pf_addr.bits := pf_req_arb.io.out.bits 652 pf_req_arb.io.out.ready := true.B 653 654 val s1_valid = Wire(Bool()) 655 val s1_replace_vec = Wire(UInt(smsParams.pf_filter_size.W)) 656 val s1_tlb_fire_vec = Wire(UInt(smsParams.pf_filter_size.W)) 657 658 // s0: entries lookup 659 val s0_gen_req = io.gen_req.bits 660 val s0_match_prev = prev_valid && (s0_gen_req.region_tag === prev_gen_req.region_tag) 661 val s0_gen_req_valid = io.gen_req.valid && !s0_match_prev 662 val s0_match_vec = valids.indices.map(i => { 663 valids(i) && entries(i).region_tag === s0_gen_req.region_tag && !(s1_valid && s1_replace_vec(i)) 664 }) 665 val s0_any_matched = Cat(s0_match_vec).orR 666 val s0_replace_vec = UIntToOH(replacement.way) 667 val s0_hit = s0_gen_req_valid && s0_any_matched 668 669 for(((v, ent), i) <- valids.zip(entries).zipWithIndex){ 670 val is_evicted = s1_valid && s1_replace_vec(i) 671 tlb_req_arb.io.in(i).valid := v && !s1_tlb_fire_vec(i) && !ent.paddr_valid && !is_evicted 672 tlb_req_arb.io.in(i).bits.vaddr := Cat(ent.region_addr, 0.U(log2Up(REGION_SIZE).W)) 673 tlb_req_arb.io.in(i).bits.cmd := TlbCmd.read 674 tlb_req_arb.io.in(i).bits.size := 3.U 675 tlb_req_arb.io.in(i).bits.robIdx := DontCare 676 tlb_req_arb.io.in(i).bits.debug := DontCare 677 678 val pending_req_vec = ent.region_bits & (~ent.filter_bits).asUInt 679 val first_one_offset = PriorityMux( 680 pending_req_vec.asBools, 681 (0 until smsParams.filter_table_size).map(_.U(REGION_OFFSET.W)) 682 ) 683 val last_one_offset = PriorityMux( 684 pending_req_vec.asBools.reverse, 685 (0 until smsParams.filter_table_size).reverse.map(_.U(REGION_OFFSET.W)) 686 ) 687 val pf_addr = Cat( 688 ent.region_addr, 689 Mux(ent.decr_mode, last_one_offset, first_one_offset), 690 0.U(log2Up(dcacheParameters.blockBytes).W) 691 ) 692 pf_req_arb.io.in(i).valid := v && Cat(pending_req_vec).orR && ent.paddr_valid && !is_evicted 693 pf_req_arb.io.in(i).bits := pf_addr 694 } 695 696 val s0_tlb_fire_vec = VecInit(tlb_req_arb.io.in.map(_.fire)) 697 val s0_pf_fire_vec = VecInit(pf_req_arb.io.in.map(_.fire)) 698 699 // s1: update or alloc 700 val s1_valid_r = RegNext(s0_gen_req_valid, false.B) 701 val s1_hit = RegEnable(s0_hit, s0_gen_req_valid) 702 val s1_gen_req = RegEnable(s0_gen_req, s0_gen_req_valid) 703 val s1_replace_vec_r = RegEnable(s0_replace_vec, s0_gen_req_valid && !s0_hit) 704 val s1_update_vec = RegEnable(VecInit(s0_match_vec).asUInt, s0_gen_req_valid && s0_hit) 705 val s1_tlb_fire_vec_r = RegNext(s0_tlb_fire_vec, 0.U.asTypeOf(s0_tlb_fire_vec)) 706 val s1_alloc_entry = Wire(new PrefetchFilterEntry()) 707 s1_valid := s1_valid_r 708 s1_replace_vec := s1_replace_vec_r 709 s1_tlb_fire_vec := s1_tlb_fire_vec_r.asUInt 710 s1_alloc_entry.region_tag := s1_gen_req.region_tag 711 s1_alloc_entry.region_addr := s1_gen_req.region_addr 712 s1_alloc_entry.region_bits := s1_gen_req.region_bits 713 s1_alloc_entry.paddr_valid := s1_gen_req.paddr_valid 714 s1_alloc_entry.decr_mode := s1_gen_req.decr_mode 715 s1_alloc_entry.filter_bits := 0.U 716 for(((v, ent), i) <- valids.zip(entries).zipWithIndex){ 717 val alloc = s1_valid && !s1_hit && s1_replace_vec(i) 718 val update = s1_valid && s1_hit && s1_update_vec(i) 719 // for pf: use s0 data 720 val pf_fired = s0_pf_fire_vec(i) 721 val tlb_fired = s1_tlb_fire_vec(i) && !io.tlb_req.resp.bits.miss 722 when(tlb_fired){ 723 ent.paddr_valid := !io.tlb_req.resp.bits.miss 724 ent.region_addr := region_addr(io.tlb_req.resp.bits.paddr.head) 725 } 726 when(update){ 727 ent.region_bits := ent.region_bits | s1_gen_req.region_bits 728 } 729 when(pf_fired){ 730 val curr_bit = UIntToOH(block_addr(pf_req_arb.io.in(i).bits)(REGION_OFFSET - 1, 0)) 731 ent.filter_bits := ent.filter_bits | curr_bit 732 } 733 when(alloc){ 734 ent := s1_alloc_entry 735 v := true.B 736 } 737 } 738 val s1_access_mask = Mux(s1_hit, s1_update_vec, s1_replace_vec) 739 val s1_access_way = OHToUInt(s1_access_mask.asUInt) 740 when(s1_valid){ 741 replacement.access(s1_access_way) 742 } 743 744 XSPerfAccumulate("sms_pf_filter_recv_req", io.gen_req.valid) 745 XSPerfAccumulate("sms_pf_filter_hit", s1_valid && s1_hit) 746 XSPerfAccumulate("sms_pf_filter_tlb_req", io.tlb_req.req.fire) 747 XSPerfAccumulate("sms_pf_filter_tlb_resp_miss", io.tlb_req.resp.fire && io.tlb_req.resp.bits.miss) 748 for(i <- 0 until smsParams.pf_filter_size){ 749 XSPerfAccumulate(s"sms_pf_filter_access_way_$i", s1_valid && s1_access_way === i.U) 750 } 751 XSPerfAccumulate("sms_pf_filter_l2_req", io.l2_pf_addr.valid) 752} 753 754class SMSPrefetcher()(implicit p: Parameters) extends BasePrefecher with HasSMSModuleHelper { 755 756 require(exuParameters.LduCnt == 2) 757 758 val io_agt_en = IO(Input(Bool())) 759 val io_pht_en = IO(Input(Bool())) 760 761 val ld_curr = io.ld_in.map(_.bits) 762 val ld_curr_block_tag = ld_curr.map(x => block_hash_tag(x.vaddr)) 763 764 // block filter 765 val ld_prev = io.ld_in.map(ld => RegEnable(ld.bits, ld.valid)) 766 val ld_prev_block_tag = ld_curr_block_tag.zip(io.ld_in.map(_.valid)).map({ 767 case (tag, v) => RegEnable(tag, v) 768 }) 769 val ld_prev_vld = io.ld_in.map(ld => RegNext(ld.valid, false.B)) 770 771 val ld_curr_match_prev = ld_curr_block_tag.map(cur_tag => 772 Cat(ld_prev_block_tag.zip(ld_prev_vld).map({ 773 case (prev_tag, prev_vld) => prev_vld && prev_tag === cur_tag 774 })).orR 775 ) 776 val ld0_match_ld1 = io.ld_in.head.valid && io.ld_in.last.valid && ld_curr_block_tag.head === ld_curr_block_tag.last 777 val ld_curr_vld = Seq( 778 io.ld_in.head.valid && !ld_curr_match_prev.head, 779 io.ld_in.last.valid && !ld_curr_match_prev.last && !ld0_match_ld1 780 ) 781 val ld0_older_than_ld1 = Cat(ld_curr_vld).andR && isBefore(ld_curr.head.uop.robIdx, ld_curr.last.uop.robIdx) 782 val pending_vld = RegNext(Cat(ld_curr_vld).andR, false.B) 783 val pending_sel_ld0 = RegNext(Mux(pending_vld, ld0_older_than_ld1, !ld0_older_than_ld1)) 784 val pending_ld = Mux(pending_sel_ld0, ld_prev.head, ld_prev.last) 785 val pending_ld_block_tag = Mux(pending_sel_ld0, ld_prev_block_tag.head, ld_prev_block_tag.last) 786 787 // prepare training data 788 val train_ld = RegEnable( 789 Mux(pending_vld, pending_ld, Mux(ld0_older_than_ld1 || !ld_curr_vld.last, ld_curr.head, ld_curr.last)), 790 pending_vld || Cat(ld_curr_vld).orR 791 ) 792 793 val train_block_tag = RegEnable( 794 Mux(pending_vld, pending_ld_block_tag, 795 Mux(ld0_older_than_ld1 || !ld_curr_vld.last, ld_curr_block_tag.head, ld_curr_block_tag.last) 796 ), 797 pending_vld || Cat(ld_curr_vld).orR 798 ) 799 val train_region_tag = train_block_tag.head(REGION_TAG_WIDTH) 800 801 val train_region_addr_raw = region_addr(train_ld.vaddr)(REGION_TAG_WIDTH + 2 * VADDR_HASH_WIDTH - 1, 0) 802 val train_region_addr_p1 = Cat(0.U(1.W), train_region_addr_raw) + 1.U 803 val train_region_addr_m1 = Cat(0.U(1.W), train_region_addr_raw) - 1.U 804 // addr_p1 or addr_m1 is valid? 805 val train_allow_cross_region_p1 = !train_region_addr_p1.head(1).asBool 806 val train_allow_cross_region_m1 = !train_region_addr_m1.head(1).asBool 807 808 val train_region_p1_tag = region_hash_tag(train_region_addr_p1.tail(1)) 809 val train_region_m1_tag = region_hash_tag(train_region_addr_m1.tail(1)) 810 811 val train_region_p1_cross_page = page_bit(train_region_addr_p1) ^ page_bit(train_region_addr_raw) 812 val train_region_m1_cross_page = page_bit(train_region_addr_m1) ^ page_bit(train_region_addr_raw) 813 814 val train_region_paddr = region_addr(train_ld.paddr) 815 val train_region_vaddr = region_addr(train_ld.vaddr) 816 val train_region_offset = train_block_tag(REGION_OFFSET - 1, 0) 817 val train_vld = RegNext(pending_vld || Cat(ld_curr_vld).orR, false.B) 818 819 820 // prefetch stage0 821 val filter_table = Module(new FilterTable()) 822 val active_gen_table = Module(new ActiveGenerationTable()) 823 val pht = Module(new PatternHistoryTable()) 824 val pf_filter = Module(new PrefetchFilter()) 825 826 val train_vld_s0 = RegNext(train_vld, false.B) 827 val train_s0 = RegEnable(train_ld, train_vld) 828 val train_region_tag_s0 = RegEnable(train_region_tag, train_vld) 829 val train_region_p1_tag_s0 = RegEnable(train_region_p1_tag, train_vld) 830 val train_region_m1_tag_s0 = RegEnable(train_region_m1_tag, train_vld) 831 val train_allow_cross_region_p1_s0 = RegEnable(train_allow_cross_region_p1, train_vld) 832 val train_allow_cross_region_m1_s0 = RegEnable(train_allow_cross_region_m1, train_vld) 833 val train_pht_tag_s0 = RegEnable(pht_tag(train_ld.uop.cf.pc), train_vld) 834 val train_pht_index_s0 = RegEnable(pht_index(train_ld.uop.cf.pc), train_vld) 835 val train_region_offset_s0 = RegEnable(train_region_offset, train_vld) 836 val train_region_p1_cross_page_s0 = RegEnable(train_region_p1_cross_page, train_vld) 837 val train_region_m1_cross_page_s0 = RegEnable(train_region_m1_cross_page, train_vld) 838 val train_region_paddr_s0 = RegEnable(train_region_paddr, train_vld) 839 val train_region_vaddr_s0 = RegEnable(train_region_vaddr, train_vld) 840 841 filter_table.io.s0_lookup.valid := train_vld_s0 842 filter_table.io.s0_lookup.bits.pht_tag := train_pht_tag_s0 843 filter_table.io.s0_lookup.bits.pht_index := train_pht_index_s0 844 filter_table.io.s0_lookup.bits.region_tag := train_region_tag_s0 845 filter_table.io.s0_lookup.bits.offset := train_region_offset_s0 846 filter_table.io.s1_update := !active_gen_table.io.s1_match_or_alloc 847 848 active_gen_table.io.s0_lookup.valid := train_vld_s0 849 active_gen_table.io.s0_lookup.bits.region_tag := train_region_tag_s0 850 active_gen_table.io.s0_lookup.bits.region_p1_tag := train_region_p1_tag_s0 851 active_gen_table.io.s0_lookup.bits.region_m1_tag := train_region_m1_tag_s0 852 active_gen_table.io.s0_lookup.bits.region_offset := train_region_offset_s0 853 active_gen_table.io.s0_lookup.bits.pht_index := train_pht_index_s0 854 active_gen_table.io.s0_lookup.bits.pht_tag := train_pht_tag_s0 855 active_gen_table.io.s0_lookup.bits.allow_cross_region_p1 := train_allow_cross_region_p1_s0 856 active_gen_table.io.s0_lookup.bits.allow_cross_region_m1 := train_allow_cross_region_m1_s0 857 active_gen_table.io.s0_lookup.bits.region_p1_cross_page := train_region_p1_cross_page_s0 858 active_gen_table.io.s0_lookup.bits.region_m1_cross_page := train_region_m1_cross_page_s0 859 active_gen_table.io.s0_lookup.bits.region_paddr := train_region_paddr_s0 860 active_gen_table.io.s0_lookup.bits.region_vaddr := train_region_vaddr_s0 861 862 val train_region_offset_s1 = RegEnable(train_region_offset_s0, train_vld_s0) 863 val agt_region_bits_s1 = region_offset_to_bits(train_region_offset_s1) | 864 region_offset_to_bits(filter_table.io.s1_result.bits.offset) 865 866 active_gen_table.io.s1_recv_entry.valid := filter_table.io.s1_result.valid 867 active_gen_table.io.s1_recv_entry.bits.pht_index := filter_table.io.s1_result.bits.pht_index 868 active_gen_table.io.s1_recv_entry.bits.pht_tag := filter_table.io.s1_result.bits.pht_tag 869 active_gen_table.io.s1_recv_entry.bits.region_bits := agt_region_bits_s1 870 active_gen_table.io.s1_recv_entry.bits.region_tag := filter_table.io.s1_result.bits.region_tag 871 active_gen_table.io.s1_recv_entry.bits.access_cnt := 2.U 872 active_gen_table.io.s1_recv_entry.bits.decr_mode := false.B 873 874 pht.io.s2_agt_lookup := active_gen_table.io.s2_pht_lookup 875 pht.io.agt_update := active_gen_table.io.s2_evict 876 877 val pht_gen_valid = pht.io.pf_gen_req.valid && io_pht_en 878 val agt_gen_valid = active_gen_table.io.s2_pf_gen_req.valid && io_agt_en 879 val pf_gen_req = Mux(pht_gen_valid, 880 pht.io.pf_gen_req.bits, 881 active_gen_table.io.s2_pf_gen_req.bits 882 ) 883 pf_filter.io.gen_req.valid := pht_gen_valid || agt_gen_valid 884 pf_filter.io.gen_req.bits := pf_gen_req 885 io.tlb_req <> pf_filter.io.tlb_req 886 io.pf_addr.valid := pf_filter.io.l2_pf_addr.valid && io.enable 887 io.pf_addr.bits := pf_filter.io.l2_pf_addr.bits 888 889 XSPerfAccumulate("sms_pf_gen_conflict", 890 pht.io.pf_gen_req.valid && active_gen_table.io.s2_pf_gen_req.valid 891 ) 892 XSPerfAccumulate("sms_pht_disabled", pht.io.pf_gen_req.valid && !io_pht_en) 893 XSPerfAccumulate("sms_agt_disabled", active_gen_table.io.s2_pf_gen_req.valid && !io_agt_en) 894 XSPerfAccumulate("sms_pf_real_issued", io.pf_addr.valid) 895} 896