xref: /XiangShan/src/main/scala/xiangshan/cache/wpu/WPU.scala (revision 0466583513e4c1ddbbb566b866b8963635acb20f)
1*04665835SMaxpicca-Lipackage xiangshan.cache.wpu
2*04665835SMaxpicca-Li
3*04665835SMaxpicca-Liimport chipsalliance.rocketchip.config.{Field, Parameters}
4*04665835SMaxpicca-Liimport chisel3._
5*04665835SMaxpicca-Liimport chisel3.util._
6*04665835SMaxpicca-Liimport utils.XSPerfAccumulate
7*04665835SMaxpicca-Liimport xiangshan.cache.{HasL1CacheParameters, L1CacheParameters}
8*04665835SMaxpicca-Liimport xiangshan.{XSBundle, XSModule}
9*04665835SMaxpicca-Li
10*04665835SMaxpicca-Li/*
11*04665835SMaxpicca-Li// TODO: need to learn the specific grammar
12*04665835SMaxpicca-Liabstract class WPUBaseModule[T <: Data](implicit P: Parameters) extends XSModule with HasWPUParameters{
13*04665835SMaxpicca-Li  def apply[T <: Data]
14*04665835SMaxpicca-Li  def pred(vaddr: UInt, en: Bool) : T
15*04665835SMaxpicca-Li  def update(vaddr: UInt, data: T ,en: Bool)
16*04665835SMaxpicca-Li}
17*04665835SMaxpicca-Li*/
18*04665835SMaxpicca-Li
19*04665835SMaxpicca-Licase object WPUParamsKey extends Field[WPUParameters]
20*04665835SMaxpicca-Licase class WPUParameters
21*04665835SMaxpicca-Li(
22*04665835SMaxpicca-Li  enWPU: Boolean = true,
23*04665835SMaxpicca-Li  algoName: String = "mru",
24*04665835SMaxpicca-Li  enCfPred: Boolean = false,
25*04665835SMaxpicca-Li  isICache: Boolean = false,
26*04665835SMaxpicca-Li  // how to impelement a extend inlcude hasL1Cache and L2 Cache
27*04665835SMaxpicca-Li)
28*04665835SMaxpicca-Li
29*04665835SMaxpicca-Litrait HasWPUParameters extends HasL1CacheParameters{
30*04665835SMaxpicca-Li  def AlgoWPUMap(wpuParam: WPUParameters, nPorts: Int): BaseWPU = {
31*04665835SMaxpicca-Li    wpuParam.algoName.toLowerCase match {
32*04665835SMaxpicca-Li      case "mru" => Module(new MruWPU(wpuParam, nPorts))
33*04665835SMaxpicca-Li      case "mmru" => Module(new MmruWPU(wpuParam, nPorts))
34*04665835SMaxpicca-Li      case "utag" => Module(new UtagWPU(wpuParam, nPorts))
35*04665835SMaxpicca-Li      case t => throw new IllegalArgumentException(s"unknown WPU Algorithm $t")
36*04665835SMaxpicca-Li    }
37*04665835SMaxpicca-Li  }
38*04665835SMaxpicca-Li}
39*04665835SMaxpicca-Li
40*04665835SMaxpicca-Liabstract class BaseWPUBundle(implicit P: Parameters) extends XSBundle
41*04665835SMaxpicca-Liabstract class WPUModule(implicit P: Parameters) extends XSModule with HasWPUParameters
42*04665835SMaxpicca-Li
43*04665835SMaxpicca-Liclass BaseWpuUpdateBundle(nWays: Int)(implicit p: Parameters) extends BaseWPUBundle{
44*04665835SMaxpicca-Li  val en = Bool()
45*04665835SMaxpicca-Li  val vaddr = UInt(VAddrBits.W)
46*04665835SMaxpicca-Li  val way_en = UInt(nWays.W)
47*04665835SMaxpicca-Li}
48*04665835SMaxpicca-Li
49*04665835SMaxpicca-Liclass LookupWpuUpdateBundle(nWays: Int)(implicit p: Parameters) extends BaseWpuUpdateBundle(nWays){
50*04665835SMaxpicca-Li  val pred_way_en = UInt(nWays.W)
51*04665835SMaxpicca-Li}
52*04665835SMaxpicca-Li
53*04665835SMaxpicca-Liclass BaseWpuPredictIO(nWays: Int)(implicit p: Parameters) extends BaseWPUBundle{
54*04665835SMaxpicca-Li  val en = Input(Bool())
55*04665835SMaxpicca-Li  val vaddr = Input(UInt(VAddrBits.W))
56*04665835SMaxpicca-Li  val way_en = Output(UInt(nWays.W))
57*04665835SMaxpicca-Li}
58*04665835SMaxpicca-Li
59*04665835SMaxpicca-Liclass WPUBaseIO(portNum: Int, nWays: Int)(implicit p:Parameters) extends BaseWPUBundle {
60*04665835SMaxpicca-Li  val predVec = Vec(portNum, new BaseWpuPredictIO(nWays))
61*04665835SMaxpicca-Li  val updLookup = Input(Vec(portNum, new LookupWpuUpdateBundle(nWays)))
62*04665835SMaxpicca-Li  val updReplaycarry = Input(Vec(portNum, new BaseWpuUpdateBundle(nWays)))
63*04665835SMaxpicca-Li  val updTagwrite = Input(Vec(portNum, new BaseWpuUpdateBundle(nWays)))
64*04665835SMaxpicca-Li}
65*04665835SMaxpicca-Li
66*04665835SMaxpicca-Liabstract class BaseWPU(wpuParam: WPUParameters, nPorts: Int)(implicit p:Parameters) extends WPUModule {
67*04665835SMaxpicca-Li  val cacheParams: L1CacheParameters = if (wpuParam.isICache) icacheParameters else dcacheParameters
68*04665835SMaxpicca-Li
69*04665835SMaxpicca-Li  val setSize = nSets
70*04665835SMaxpicca-Li  val nTagIdx = nWays
71*04665835SMaxpicca-Li  // auxiliary 1 bit is used to judge whether cache miss
72*04665835SMaxpicca-Li  val auxWayBits = wayBits + 1
73*04665835SMaxpicca-Li  val TagIdxBits = log2Up(nTagIdx)
74*04665835SMaxpicca-Li  val utagBits = 8
75*04665835SMaxpicca-Li
76*04665835SMaxpicca-Li  val io = IO(new WPUBaseIO(nPorts, nWays))
77*04665835SMaxpicca-Li
78*04665835SMaxpicca-Li  def get_wpu_idx(addr: UInt): UInt = {
79*04665835SMaxpicca-Li    addr(untagBits - 1, blockOffBits)
80*04665835SMaxpicca-Li  }
81*04665835SMaxpicca-Li}
82*04665835SMaxpicca-Li
83*04665835SMaxpicca-Liclass MruWPU(wpuParam: WPUParameters, nPorts: Int)(implicit p:Parameters) extends BaseWPU(wpuParam, nPorts){
84*04665835SMaxpicca-Li  println("  WpuType: MruWPU")
85*04665835SMaxpicca-Li  val predict_regs = RegInit(VecInit(Seq.fill(setSize)(0.U(wayBits.W))))
86*04665835SMaxpicca-Li
87*04665835SMaxpicca-Li  def write(upd: BaseWpuUpdateBundle): Unit = {
88*04665835SMaxpicca-Li    when(upd.en) {
89*04665835SMaxpicca-Li      val upd_setIdx = get_wpu_idx(upd.vaddr)
90*04665835SMaxpicca-Li      predict_regs(upd_setIdx) := OHToUInt(upd.way_en)
91*04665835SMaxpicca-Li    }
92*04665835SMaxpicca-Li  }
93*04665835SMaxpicca-Li
94*04665835SMaxpicca-Li  def predict(pred: BaseWpuPredictIO): Unit = {
95*04665835SMaxpicca-Li    val predSetIdx = get_wpu_idx(pred.vaddr)
96*04665835SMaxpicca-Li    when(pred.en) {
97*04665835SMaxpicca-Li      pred.way_en := UIntToOH(predict_regs(predSetIdx))
98*04665835SMaxpicca-Li    }.otherwise {
99*04665835SMaxpicca-Li      pred.way_en := 0.U(nWays.W)
100*04665835SMaxpicca-Li    }
101*04665835SMaxpicca-Li  }
102*04665835SMaxpicca-Li
103*04665835SMaxpicca-Li  for(i <- 0 until nPorts){
104*04665835SMaxpicca-Li    predict(io.predVec(i))
105*04665835SMaxpicca-Li    write(io.updLookup(i))
106*04665835SMaxpicca-Li    write(io.updReplaycarry(i))
107*04665835SMaxpicca-Li    write(io.updTagwrite(i))
108*04665835SMaxpicca-Li  }
109*04665835SMaxpicca-Li
110*04665835SMaxpicca-Li}
111*04665835SMaxpicca-Li
112*04665835SMaxpicca-Liclass MmruWPU(wpuParam: WPUParameters, nPorts: Int)(implicit p:Parameters) extends BaseWPU(wpuParam, nPorts){
113*04665835SMaxpicca-Li  println("  WpuType: MmruWPU")
114*04665835SMaxpicca-Li  val predict_regs = RegInit(VecInit(Seq.fill(setSize)(VecInit(Seq.fill(nTagIdx)(0.U(auxWayBits.W))))))
115*04665835SMaxpicca-Li
116*04665835SMaxpicca-Li  def write(upd: BaseWpuUpdateBundle): Unit = {
117*04665835SMaxpicca-Li    when(upd.en) {
118*04665835SMaxpicca-Li      val updSetIdx = get_wpu_idx(upd.vaddr)
119*04665835SMaxpicca-Li      val updTagIdx = get_vir_tag(upd.vaddr)
120*04665835SMaxpicca-Li      predict_regs(updSetIdx)(updTagIdx) := OHToUInt(upd.way_en)
121*04665835SMaxpicca-Li    }
122*04665835SMaxpicca-Li  }
123*04665835SMaxpicca-Li
124*04665835SMaxpicca-Li  def predict(pred: BaseWpuPredictIO): Unit = {
125*04665835SMaxpicca-Li    val predSetIdx = get_wpu_idx(pred.vaddr)
126*04665835SMaxpicca-Li    val predTagIdx = get_vir_tag(pred.vaddr)
127*04665835SMaxpicca-Li    when(pred.en) {
128*04665835SMaxpicca-Li      //UIntToOH(8.U(4.W))=100000000.U(16.W)=00000000.U(8.W)
129*04665835SMaxpicca-Li      //UIntToOH(8.U(4.W), 8)=00000001.U(8.W)
130*04665835SMaxpicca-Li      pred.way_en := UIntToOH(predict_regs(predSetIdx)(predTagIdx))
131*04665835SMaxpicca-Li    }.otherwise {
132*04665835SMaxpicca-Li      pred.way_en := 0.U(nWays.W)
133*04665835SMaxpicca-Li    }
134*04665835SMaxpicca-Li  }
135*04665835SMaxpicca-Li
136*04665835SMaxpicca-Li  for(i <- 0 until nPorts){
137*04665835SMaxpicca-Li    predict(io.predVec(i))
138*04665835SMaxpicca-Li    write(io.updLookup(i))
139*04665835SMaxpicca-Li    write(io.updReplaycarry(i))
140*04665835SMaxpicca-Li    write(io.updTagwrite(i))
141*04665835SMaxpicca-Li  }
142*04665835SMaxpicca-Li
143*04665835SMaxpicca-Li}
144*04665835SMaxpicca-Li
145*04665835SMaxpicca-Liclass UtagWPU(wpuParam: WPUParameters, nPorts: Int)(implicit p:Parameters) extends BaseWPU(wpuParam, nPorts){
146*04665835SMaxpicca-Li  println("  WpuType: UtagWPU")
147*04665835SMaxpicca-Li  val utag_regs = RegInit(VecInit(Seq.fill(setSize)(VecInit(Seq.fill(nWays)(0.U(utagBits.W))))))
148*04665835SMaxpicca-Li  val valid_regs = RegInit(VecInit(Seq.fill(setSize)(VecInit(Seq.fill(nWays)(false.B)))))
149*04665835SMaxpicca-Li
150*04665835SMaxpicca-Li  def get_hash_utag(addr: UInt): UInt = {
151*04665835SMaxpicca-Li    val utagQuotient = vtagBits / utagBits
152*04665835SMaxpicca-Li    val utagRemainder = vtagBits % utagBits
153*04665835SMaxpicca-Li    val vtag = get_vir_tag(addr)
154*04665835SMaxpicca-Li
155*04665835SMaxpicca-Li    /* old */
156*04665835SMaxpicca-Li    vtag(utagBits * 2 - 1, utagBits) ^ vtag(utagBits - 1, 0)
157*04665835SMaxpicca-Li
158*04665835SMaxpicca-Li    /* new */
159*04665835SMaxpicca-Li    // val tmp = vtag(utagQuotient * utagBits - 1, 0).asTypeOf(Vec(utagQuotient, UInt(utagBits.W)))
160*04665835SMaxpicca-Li    // val res1 = tmp.reduce(_ ^ _)
161*04665835SMaxpicca-Li    // val res2 = Wire(UInt(utagRemainder.W))
162*04665835SMaxpicca-Li    // if(utagRemainder!=0){
163*04665835SMaxpicca-Li    //   res2 := res1(utagRemainder - 1, 0) ^ vtag(vtagBits - 1, utagBits * utagQuotient)
164*04665835SMaxpicca-Li    //   Cat(res1(utagBits - 1, utagRemainder), res2)
165*04665835SMaxpicca-Li    // }else{
166*04665835SMaxpicca-Li    //   res1
167*04665835SMaxpicca-Li    // }
168*04665835SMaxpicca-Li  }
169*04665835SMaxpicca-Li
170*04665835SMaxpicca-Li  def write_utag(upd: BaseWpuUpdateBundle): Unit = {
171*04665835SMaxpicca-Li    when(upd.en){
172*04665835SMaxpicca-Li      val upd_setIdx = get_wpu_idx(upd.vaddr)
173*04665835SMaxpicca-Li      val upd_utag = get_hash_utag(upd.vaddr)
174*04665835SMaxpicca-Li      val upd_way = OHToUInt(upd.way_en)
175*04665835SMaxpicca-Li      utag_regs(upd_setIdx)(upd_way) := upd_utag
176*04665835SMaxpicca-Li      valid_regs(upd_setIdx)(upd_way) := true.B
177*04665835SMaxpicca-Li    }
178*04665835SMaxpicca-Li  }
179*04665835SMaxpicca-Li
180*04665835SMaxpicca-Li  def unvalid_utag(upd: LookupWpuUpdateBundle): Unit = {
181*04665835SMaxpicca-Li    when(upd.en){
182*04665835SMaxpicca-Li      val upd_setIdx = get_wpu_idx(upd.vaddr)
183*04665835SMaxpicca-Li      val upd_way = OHToUInt(upd.pred_way_en)
184*04665835SMaxpicca-Li      valid_regs(upd_setIdx)(upd_way) := false.B
185*04665835SMaxpicca-Li    }
186*04665835SMaxpicca-Li  }
187*04665835SMaxpicca-Li
188*04665835SMaxpicca-Li  def predict(pred: BaseWpuPredictIO): Unit = {
189*04665835SMaxpicca-Li    val req_setIdx = get_wpu_idx(pred.vaddr)
190*04665835SMaxpicca-Li    val req_utag = get_hash_utag(pred.vaddr)
191*04665835SMaxpicca-Li    val pred_way_en = Wire(UInt(nWays.W))
192*04665835SMaxpicca-Li    when(pred.en) {
193*04665835SMaxpicca-Li      pred_way_en := VecInit((0 until nWays).map(i =>
194*04665835SMaxpicca-Li        req_utag === utag_regs(req_setIdx)(i) && valid_regs(req_setIdx)(i)
195*04665835SMaxpicca-Li      )).asUInt
196*04665835SMaxpicca-Li    }.otherwise {
197*04665835SMaxpicca-Li      pred_way_en := 0.U(nWays.W)
198*04665835SMaxpicca-Li    }
199*04665835SMaxpicca-Li    // avoid hash conflict
200*04665835SMaxpicca-Li    pred.way_en := UIntToOH(OHToUInt(pred_way_en))
201*04665835SMaxpicca-Li  }
202*04665835SMaxpicca-Li
203*04665835SMaxpicca-Li  val hash_conflict = Wire(Vec(nPorts, Bool()))
204*04665835SMaxpicca-Li  for(i <- 0 until nPorts){
205*04665835SMaxpicca-Li    predict(io.predVec(i))
206*04665835SMaxpicca-Li    val real_way_en = io.updLookup(i).way_en
207*04665835SMaxpicca-Li    val pred_way_en = io.updLookup(i).pred_way_en
208*04665835SMaxpicca-Li    val pred_miss = io.updLookup(i).en && !pred_way_en.orR
209*04665835SMaxpicca-Li    val real_miss = io.updLookup(i).en && !real_way_en.orR
210*04665835SMaxpicca-Li    val way_match = io.updLookup(i).en && pred_way_en === real_way_en
211*04665835SMaxpicca-Li
212*04665835SMaxpicca-Li    hash_conflict(i) := !pred_miss && !way_match
213*04665835SMaxpicca-Li      // look up: vtag miss but tag hit
214*04665835SMaxpicca-Li    when(pred_miss && !real_miss) {
215*04665835SMaxpicca-Li      write_utag(io.updLookup(i))
216*04665835SMaxpicca-Li    }
217*04665835SMaxpicca-Li    // look up: vtag hit but other tag hit ==> unvalid pred way; write real way
218*04665835SMaxpicca-Li    when(!pred_miss && !way_match) {
219*04665835SMaxpicca-Li      unvalid_utag(io.updLookup(i))
220*04665835SMaxpicca-Li    }
221*04665835SMaxpicca-Li    when(!pred_miss && !real_miss && !way_match) {
222*04665835SMaxpicca-Li      write_utag(io.updLookup(i))
223*04665835SMaxpicca-Li    }
224*04665835SMaxpicca-Li    // replay carry
225*04665835SMaxpicca-Li    write_utag(io.updReplaycarry(i))
226*04665835SMaxpicca-Li    // tag write
227*04665835SMaxpicca-Li    write_utag(io.updTagwrite(i))
228*04665835SMaxpicca-Li  }
229*04665835SMaxpicca-Li
230*04665835SMaxpicca-Li  XSPerfAccumulate("utag_hash_conflict", PopCount(hash_conflict))
231*04665835SMaxpicca-Li}