1package xiangshan.mem.prefetch 2 3import org.chipsalliance.cde.config.Parameters 4import chisel3._ 5import chisel3.util._ 6import utils._ 7import utility._ 8import xiangshan._ 9import xiangshan.mem.L1PrefetchReq 10import xiangshan.mem.Bundles.LsPrefetchTrainBundle 11 12trait HasPrefetcherMonitorHelper { 13 val TIMELY_CHECK_INTERVAL = 1000 14 val VALIDITY_CHECK_INTERVAL = 1000 15 16 val BAD_THRESHOLD = 400 17 val DISABLE_THRESHOLD = 900 18 val LATE_HIT_THRESHOLD = 900 19 val LATE_MISS_THRESHOLD = 200 20 21 val BACK_OFF_INTERVAL = 100000 22 val LOW_CONF_INTERVAL = 200000 23 24 // val enableDynamicPrefetcher = false 25} 26 27class PrefetchControlBundle()(implicit p: Parameters) extends XSBundle with HasStreamPrefetchHelper { 28 val dynamic_depth = UInt(DEPTH_BITS.W) 29 val flush = Bool() 30 val enable = Bool() 31 val confidence = UInt(1.W) 32} 33 34class PrefetcherMonitorBundle()(implicit p: Parameters) extends XSBundle { 35 val timely = new XSBundle { 36 val total_prefetch = Input(Bool()) 37 val late_hit_prefetch = Input(Bool()) 38 val late_miss_prefetch = Input(Bool()) 39 val prefetch_hit = Input(UInt(2.W)) 40 } 41 42 val validity = new XSBundle { 43 val good_prefetch = Input(Bool()) 44 val bad_prefetch = Input(Bool()) 45 } 46 47 val pf_ctrl = Output(new PrefetchControlBundle) 48} 49 50class PrefetcherMonitor()(implicit p: Parameters) extends XSModule with HasPrefetcherMonitorHelper with HasStreamPrefetchHelper { 51 val io = IO(new PrefetcherMonitorBundle) 52 53 val depth = Reg(UInt(DEPTH_BITS.W)) 54 val flush = RegInit(false.B) 55 val enable = RegInit(true.B) 56 val confidence = RegInit(1.U(1.W)) 57 58 // TODO: mshr number 59 // mshr full && load miss && load send mshr req && !load match, -> decr nmax prefetch 60 // mshr free 61 62 io.pf_ctrl.dynamic_depth := depth 63 io.pf_ctrl.flush := flush 64 io.pf_ctrl.enable := enable 65 io.pf_ctrl.confidence := confidence 66 67 val depth_const = Wire(UInt(DEPTH_BITS.W)) 68 depth_const := Constantin.createRecord(s"depth${p(XSCoreParamsKey).HartId}", initValue = 32) 69 70 val total_prefetch_cnt = RegInit(0.U((log2Up(TIMELY_CHECK_INTERVAL) + 1).W)) 71 val late_hit_prefetch_cnt = RegInit(0.U((log2Up(TIMELY_CHECK_INTERVAL) + 1).W)) 72 val late_miss_prefetch_cnt = RegInit(0.U((log2Up(TIMELY_CHECK_INTERVAL) + 1).W)) 73 val prefetch_hit_cnt = RegInit(0.U(32.W)) 74 75 val good_prefetch_cnt = RegInit(0.U((log2Up(VALIDITY_CHECK_INTERVAL) + 1).W)) 76 val bad_prefetch_cnt = RegInit(0.U((log2Up(VALIDITY_CHECK_INTERVAL) + 1).W)) 77 78 val back_off_cnt = RegInit(0.U((log2Up(BACK_OFF_INTERVAL) + 1).W)) 79 val low_conf_cnt = RegInit(0.U((log2Up(LOW_CONF_INTERVAL) + 1).W)) 80 81 val timely_reset = (total_prefetch_cnt === TIMELY_CHECK_INTERVAL.U) || (late_hit_prefetch_cnt >= TIMELY_CHECK_INTERVAL.U) 82 val validity_reset = (good_prefetch_cnt + bad_prefetch_cnt) === VALIDITY_CHECK_INTERVAL.U 83 val back_off_reset = back_off_cnt === BACK_OFF_INTERVAL.U 84 val conf_reset = low_conf_cnt === LOW_CONF_INTERVAL.U 85 86 total_prefetch_cnt := Mux(timely_reset, 0.U, total_prefetch_cnt + io.timely.total_prefetch) 87 late_hit_prefetch_cnt := Mux(timely_reset, 0.U, late_hit_prefetch_cnt + io.timely.late_hit_prefetch) 88 late_miss_prefetch_cnt := Mux(timely_reset, 0.U, late_miss_prefetch_cnt + io.timely.late_miss_prefetch) 89 prefetch_hit_cnt := Mux(timely_reset, 0.U, prefetch_hit_cnt + io.timely.prefetch_hit) 90 91 good_prefetch_cnt := Mux(validity_reset, 0.U, good_prefetch_cnt + io.validity.good_prefetch) 92 bad_prefetch_cnt := Mux(validity_reset, 0.U, bad_prefetch_cnt + io.validity.bad_prefetch) 93 94 back_off_cnt := Mux(back_off_reset, 0.U, back_off_cnt + !enable) 95 low_conf_cnt := Mux(conf_reset, 0.U, low_conf_cnt + !confidence.asBool) 96 97 val trigger_late_hit = timely_reset && (late_hit_prefetch_cnt >= LATE_HIT_THRESHOLD.U) 98 val trigger_late_miss = timely_reset && (late_miss_prefetch_cnt >= LATE_MISS_THRESHOLD.U) 99 val trigger_bad_prefetch = validity_reset && (bad_prefetch_cnt >= BAD_THRESHOLD.U) 100 val trigger_disable = validity_reset && (bad_prefetch_cnt >= DISABLE_THRESHOLD.U) 101 102 flush := Mux(flush, false.B, flush) 103 enable := Mux(back_off_reset, true.B, enable) 104 confidence := Mux(conf_reset, 1.U(1.W), confidence) 105 106 when(trigger_bad_prefetch) { 107 depth := Mux(depth === 1.U, depth, depth >> 1) 108 } 109 when(trigger_disable) { 110 confidence := 0.U(1.W) 111 enable := false.B 112 flush := true.B 113 } 114 115 when(trigger_late_miss) { 116 depth := Mux(depth === (1 << (DEPTH_BITS - 1)).U, depth, depth << 1) 117 }.elsewhen(trigger_late_hit) { 118 // for now, late hit will disable the prefether 119 confidence := 0.U(1.W) 120 enable := false.B 121 } 122 123 val enableDynamicPrefetcher_const = Constantin.createRecord(s"enableDynamicPrefetcher${p(XSCoreParamsKey).HartId}", initValue = 1) 124 val enableDynamicPrefetcher = enableDynamicPrefetcher_const === 1.U 125 126 when(!enableDynamicPrefetcher) { 127 depth := depth_const 128 flush := false.B 129 enable := true.B 130 confidence := 1.U 131 }.otherwise { 132 // for now, only dynamically disable prefetcher, without depth and flush 133 depth := depth_const 134 flush := false.B 135 } 136 137 when(reset.asBool) { 138 depth := depth_const 139 } 140 141 XSPerfAccumulate("total_prefetch", io.timely.total_prefetch) 142 XSPerfAccumulate("late_hit_prefetch", io.timely.late_hit_prefetch) 143 XSPerfAccumulate("late_miss_prefetch", io.timely.late_miss_prefetch) 144 XSPerfAccumulate("good_prefetch", io.validity.good_prefetch) 145 XSPerfAccumulate("bad_prefetch", io.validity.bad_prefetch) 146 for(i <- (0 until DEPTH_BITS)) { 147 val t = (1 << i) 148 XSPerfAccumulate(s"depth${t}", depth === t.U) 149 } 150 XSPerfAccumulate("trigger_disable", trigger_disable) 151 XSPerfAccumulate("prefetch_hit", io.timely.prefetch_hit) 152 XSPerfAccumulate("disable_time", !enable) 153 154 assert(depth =/= 0.U, "depth should not be zero") 155} 156