xref: /XiangShan/src/main/scala/xiangshan/mem/prefetch/PrefetcherMonitor.scala (revision 99ce5576f0ecce1b5045b7bc0dbbb2debd934fbb)
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