xref: /XiangShan/src/main/scala/xiangshan/cache/wpu/WPUWrapper.scala (revision 4a0e27ecb184507a75a30529c824cb060e35b912)
104665835SMaxpicca-Lipackage xiangshan.cache.wpu
204665835SMaxpicca-Li
38891a219SYinan Xuimport org.chipsalliance.cde.config.Parameters
404665835SMaxpicca-Liimport chisel3._
504665835SMaxpicca-Liimport chisel3.util._
6bb2f3f51STang Haojinimport utility.XSPerfAccumulate
704665835SMaxpicca-Liimport xiangshan._
804665835SMaxpicca-Liimport xiangshan.cache.{DCacheModule, HasDCacheParameters}
904665835SMaxpicca-Liimport xiangshan.frontend.icache.HasICacheParameters
1004665835SMaxpicca-Li
1104665835SMaxpicca-Liclass ReplayCarry(nWays: Int)(implicit p: Parameters) extends XSBundle {
1204665835SMaxpicca-Li  val real_way_en = UInt(nWays.W)
1304665835SMaxpicca-Li  val valid = Bool()
1404665835SMaxpicca-Li}
1504665835SMaxpicca-Li
1604665835SMaxpicca-Liobject ReplayCarry{
1704665835SMaxpicca-Li  def apply(nWays: Int, rwe: UInt = 0.U, v: Bool = false.B)(implicit p: Parameters): ReplayCarry = {
1804665835SMaxpicca-Li    val rcry = Wire(new ReplayCarry(nWays))
1904665835SMaxpicca-Li    rcry.real_way_en := rwe
2004665835SMaxpicca-Li    rcry.valid := v
2104665835SMaxpicca-Li    rcry
2204665835SMaxpicca-Li  }
2304665835SMaxpicca-Li
2404665835SMaxpicca-Li  def init(nWays: Int)(implicit p: Parameters): ReplayCarry = {
2504665835SMaxpicca-Li    val rcry = Wire(new ReplayCarry(nWays))
2604665835SMaxpicca-Li    rcry.real_way_en := 0.U
2704665835SMaxpicca-Li    rcry.valid := false.B
2804665835SMaxpicca-Li    rcry
2904665835SMaxpicca-Li  }
3004665835SMaxpicca-Li}
3104665835SMaxpicca-Li
3204665835SMaxpicca-Liclass WPUBaseReq(implicit p: Parameters) extends BaseWPUBundle{
3304665835SMaxpicca-Li  val vaddr = UInt(VAddrBits.W)
3404665835SMaxpicca-Li}
3504665835SMaxpicca-Li
3604665835SMaxpicca-Liclass WPUReplayedReq(nWays: Int)(implicit p: Parameters) extends WPUBaseReq {
3704665835SMaxpicca-Li  val replayCarry = new ReplayCarry(nWays)
3804665835SMaxpicca-Li}
3904665835SMaxpicca-Li
4004665835SMaxpicca-Liclass WPUResp(nWays:Int)(implicit p:Parameters) extends BaseWPUBundle{
4104665835SMaxpicca-Li  val s0_pred_way_en = UInt(nWays.W)
4204665835SMaxpicca-Li}
4304665835SMaxpicca-Li
4404665835SMaxpicca-Liclass WPUUpdate(nWays:Int)(implicit p:Parameters) extends BaseWPUBundle{
4504665835SMaxpicca-Li  val vaddr = UInt(VAddrBits.W)
4604665835SMaxpicca-Li  val s1_real_way_en = UInt(nWays.W)
4704665835SMaxpicca-Li}
4804665835SMaxpicca-Li
4904665835SMaxpicca-Liclass WPUUpdateLookup(nWays:Int)(implicit p:Parameters) extends WPUUpdate(nWays){
5004665835SMaxpicca-Li  val s1_pred_way_en = UInt(nWays.W)
5104665835SMaxpicca-Li}
5204665835SMaxpicca-Li
5304665835SMaxpicca-Liclass ConflictPredictIO(nWays:Int)(implicit p:Parameters) extends BaseWPUBundle{
5404665835SMaxpicca-Li  // pred
5504665835SMaxpicca-Li  val s0_vaddr = Input(UInt(VAddrBits.W))
5604665835SMaxpicca-Li  // update
5704665835SMaxpicca-Li  val s1_vaddr = Input(UInt(VAddrBits.W))
5804665835SMaxpicca-Li  val s1_dm_hit = Input(Bool())
5904665835SMaxpicca-Li}
6004665835SMaxpicca-Li
6104665835SMaxpicca-Liclass IwpuBaseIO(nWays:Int, nPorts: Int)(implicit p:Parameters) extends BaseWPUBundle{
6204665835SMaxpicca-Li  val req = Vec(nPorts, Flipped(Decoupled(new WPUBaseReq)))
6304665835SMaxpicca-Li  val resp = Vec(nPorts, ValidIO(new WPUResp(nWays)))
6404665835SMaxpicca-Li  val lookup_upd = Vec(nPorts, Flipped(ValidIO(new WPUUpdateLookup(nWays))))
6504665835SMaxpicca-Li}
6604665835SMaxpicca-Li
6704665835SMaxpicca-Liclass IwpuIO(nWays:Int, nPorts: Int)(implicit p:Parameters) extends IwpuBaseIO(nWays, nPorts){
6804665835SMaxpicca-Li  val tagwrite_upd = Flipped(ValidIO(new WPUUpdate(nWays)))
6904665835SMaxpicca-Li}
7004665835SMaxpicca-Li
7104665835SMaxpicca-Liclass DwpuBaseIO(nWays:Int, nPorts: Int)(implicit p:Parameters) extends BaseWPUBundle{
7204665835SMaxpicca-Li  val req = Vec(nPorts, Flipped(Decoupled(new WPUReplayedReq(nWays))))
7304665835SMaxpicca-Li  val resp = Vec(nPorts, ValidIO(new WPUResp(nWays)))
7404665835SMaxpicca-Li  val lookup_upd = Vec(nPorts, Flipped(ValidIO(new WPUUpdateLookup(nWays))))
7504665835SMaxpicca-Li  val cfpred = Vec(nPorts, new ConflictPredictIO(nWays))
7604665835SMaxpicca-Li}
7704665835SMaxpicca-Li
7804665835SMaxpicca-Liclass DwpuIO(nWays:Int, nPorts:Int)(implicit p:Parameters) extends DwpuBaseIO(nWays, nPorts){
7904665835SMaxpicca-Li  val tagwrite_upd = Flipped(ValidIO(new WPUUpdate(nWays)))
8004665835SMaxpicca-Li}
8104665835SMaxpicca-Li
8204665835SMaxpicca-Liclass DCacheWpuWrapper (nPorts: Int = 1) (implicit p:Parameters) extends DCacheModule with HasWPUParameters  {
8304665835SMaxpicca-Li  val wpu = AlgoWPUMap(dwpuParam, nPorts)
8404665835SMaxpicca-Li  val io = IO(new DwpuIO(nWays, nPorts))
8504665835SMaxpicca-Li
8604665835SMaxpicca-Li  /** pred */
8704665835SMaxpicca-Li  val s0_dmSel = Wire(Vec(nPorts, Bool()))
8804665835SMaxpicca-Li  val s0_pred_way_en = Wire(Vec(nPorts, UInt(nWays.W)))
8904665835SMaxpicca-Li  val s1_lookup_valid = Wire(Vec(nPorts, Bool()))
9004665835SMaxpicca-Li  val s1_dmSel = Wire(Vec(nPorts, Bool()))
9104665835SMaxpicca-Li  val s1_pred_way_en = Wire(Vec(nPorts, UInt(nWays.W)))
9204665835SMaxpicca-Li  val s1_pred_fail = Wire(Vec(nPorts, Bool()))
9304665835SMaxpicca-Li  val s1_hit = Wire(Vec(nPorts, Bool()))
9404665835SMaxpicca-Li
9504665835SMaxpicca-Li  for(i <- 0 until nPorts){
9604665835SMaxpicca-Li    s0_dmSel(i) := false.B
9704665835SMaxpicca-Li    wpu.io.predVec(i).en := io.req(i).valid
9804665835SMaxpicca-Li    wpu.io.predVec(i).vaddr := io.req(i).bits.vaddr
9904665835SMaxpicca-Li    when(io.req(i).bits.replayCarry.valid) {
10004665835SMaxpicca-Li      // replay carry
10104665835SMaxpicca-Li      s0_pred_way_en(i) := io.req(i).bits.replayCarry.real_way_en
10204665835SMaxpicca-Li    }.otherwise {
10304665835SMaxpicca-Li      // way prediction
10404665835SMaxpicca-Li      s0_pred_way_en(i) := wpu.io.predVec(i).way_en
10504665835SMaxpicca-Li    }
10604665835SMaxpicca-Li
10704665835SMaxpicca-Li    /** check and update in s1 */
10804665835SMaxpicca-Li    s1_lookup_valid(i) := io.lookup_upd(i).valid
10904665835SMaxpicca-Li    s1_dmSel(i) := RegNext(s0_dmSel(i))
11004665835SMaxpicca-Li    s1_pred_way_en(i) := io.lookup_upd(i).bits.s1_pred_way_en
11104665835SMaxpicca-Li    s1_pred_fail(i) := io.lookup_upd(i).valid && s1_pred_way_en(i) =/= io.lookup_upd(i).bits.s1_real_way_en
11204665835SMaxpicca-Li    s1_hit(i) := !s1_pred_fail(i) && s1_pred_way_en(i).orR
11304665835SMaxpicca-Li
11404665835SMaxpicca-Li    val s0_replay_upd = Wire(new BaseWpuUpdateBundle(nWays))
11504665835SMaxpicca-Li    s0_replay_upd.en := io.req(i).valid && io.req(i).bits.replayCarry.valid
11604665835SMaxpicca-Li    s0_replay_upd.vaddr := io.req(i).bits.vaddr
11704665835SMaxpicca-Li    s0_replay_upd.way_en := io.req(i).bits.replayCarry.real_way_en
118*4a0e27ecSYanqin Li    val s1_replay_upd = RegEnable(s0_replay_upd, io.req(i).valid)
11904665835SMaxpicca-Li
12004665835SMaxpicca-Li
12104665835SMaxpicca-Li    // look up res
12204665835SMaxpicca-Li    wpu.io.updLookup(i).en := io.lookup_upd(i).valid
12304665835SMaxpicca-Li    wpu.io.updLookup(i).vaddr := io.lookup_upd(i).bits.vaddr
12404665835SMaxpicca-Li    wpu.io.updLookup(i).way_en := io.lookup_upd(i).bits.s1_real_way_en
12504665835SMaxpicca-Li    wpu.io.updLookup(i).pred_way_en := io.lookup_upd(i).bits.s1_pred_way_en
12604665835SMaxpicca-Li
12704665835SMaxpicca-Li    // which will update in look up pred fail
12804665835SMaxpicca-Li    wpu.io.updReplaycarry(i) := s1_replay_upd
12904665835SMaxpicca-Li
13004665835SMaxpicca-Li    // replace / tag write
13104665835SMaxpicca-Li    wpu.io.updTagwrite(i) := DontCare
13204665835SMaxpicca-Li
13304665835SMaxpicca-Li    /** predict and response in s0 */
13404665835SMaxpicca-Li    io.req(i).ready := true.B
13504665835SMaxpicca-Li    if (dwpuParam.enWPU) {
13604665835SMaxpicca-Li      io.resp(i).valid := io.req(i).valid
13704665835SMaxpicca-Li    } else {
13804665835SMaxpicca-Li      io.resp(i).valid := false.B
13904665835SMaxpicca-Li    }
14004665835SMaxpicca-Li    io.resp(i).bits.s0_pred_way_en := s0_pred_way_en(i)
14104665835SMaxpicca-Li    assert(PopCount(io.resp(i).bits.s0_pred_way_en) <= 1.U, "tag should not match with more than 1 way")
14204665835SMaxpicca-Li  }
14304665835SMaxpicca-Li  wpu.io.updTagwrite(0).en := io.tagwrite_upd.valid
14404665835SMaxpicca-Li  wpu.io.updTagwrite(0).vaddr := io.tagwrite_upd.bits.vaddr
14504665835SMaxpicca-Li  wpu.io.updTagwrite(0).way_en := io.tagwrite_upd.bits.s1_real_way_en
14604665835SMaxpicca-Li  // PerfLog
14704665835SMaxpicca-Li  // pred situation
14804665835SMaxpicca-Li  XSPerfAccumulate("wpu_pred_total", PopCount((0 until nPorts).map(i => RegNext(io.req(i).valid) && s1_lookup_valid(i))))
14904665835SMaxpicca-Li  XSPerfAccumulate("wpu_pred_succ", PopCount((0 until nPorts).map(i => RegNext(io.req(i).valid) && s1_lookup_valid(i) && !s1_pred_fail(i))))
15004665835SMaxpicca-Li  XSPerfAccumulate("wpu_pred_fail", PopCount((0 until nPorts).map(i => RegNext(io.req(i).valid) && s1_lookup_valid(i) && s1_pred_fail(i))))
15104665835SMaxpicca-Li  XSPerfAccumulate("wpu_pred_miss", PopCount((0 until nPorts).map(i => RegNext(io.req(i).valid) && s1_lookup_valid(i) && !s1_pred_way_en(i).orR)))
15204665835SMaxpicca-Li  XSPerfAccumulate("wpu_real_miss", PopCount((0 until nPorts).map(i => RegNext(io.req(i).valid) && s1_lookup_valid(i) && !io.lookup_upd(i).bits.s1_real_way_en.orR)))
15304665835SMaxpicca-Li  // pred component
15404665835SMaxpicca-Li  XSPerfAccumulate("wpu_pred_replayCarry", PopCount((0 until nPorts).map(i => io.req(i).valid && io.req(i).bits.replayCarry.valid)))
15504665835SMaxpicca-Li  XSPerfAccumulate("wpu_pred_wayPrediction", PopCount((0 until nPorts).map(i => io.req(i).valid && !io.req(i).bits.replayCarry.valid)))
156*4a0e27ecSYanqin Li
157*4a0e27ecSYanqin Li  /* selective direct mapping */
158*4a0e27ecSYanqin Li  if(dwpuParam.enCfPred){
159*4a0e27ecSYanqin Li    val wayConflictPredictor = Module(new WayConflictPredictor(nPorts))
160*4a0e27ecSYanqin Li    val s0_pred_way_conflict = Wire(Vec(nPorts, Bool()))
161*4a0e27ecSYanqin Li    for(i <- 0 until nPorts){
162*4a0e27ecSYanqin Li      wayConflictPredictor.io.pred(i).en := io.req(i).valid
163*4a0e27ecSYanqin Li      wayConflictPredictor.io.pred(i).vaddr := io.cfpred(i).s0_vaddr
164*4a0e27ecSYanqin Li      s0_pred_way_conflict(i) := wayConflictPredictor.io.pred(i).way_conflict
165*4a0e27ecSYanqin Li      when(!s0_pred_way_conflict(i)) {
166*4a0e27ecSYanqin Li        s0_pred_way_en(i) := UIntToOH(get_direct_map_way(io.req(i).bits.vaddr))
167*4a0e27ecSYanqin Li        s0_dmSel(i) := true.B
168*4a0e27ecSYanqin Li      }
169*4a0e27ecSYanqin Li      wayConflictPredictor.io.update(i).en := io.lookup_upd(i).valid
170*4a0e27ecSYanqin Li      wayConflictPredictor.io.update(i).vaddr := io.cfpred(i).s1_vaddr
171*4a0e27ecSYanqin Li      wayConflictPredictor.io.update(i).dm_hit := s1_dmSel(i) && io.cfpred(i).s1_dm_hit
172*4a0e27ecSYanqin Li      wayConflictPredictor.io.update(i).sa_hit := !s1_dmSel(i) && s1_hit(i)
173*4a0e27ecSYanqin Li    }
174*4a0e27ecSYanqin Li    XSPerfAccumulate("wpu_pred_from_prediction", PopCount((0 until nPorts).map(i => io.req(i).valid && !io.req(i).bits.replayCarry.valid && s0_pred_way_conflict(i))))
175*4a0e27ecSYanqin Li    XSPerfAccumulate("wpu_pred_from_directMap", PopCount((0 until nPorts).map(i => io.req(i).valid && !io.req(i).bits.replayCarry.valid && !s0_pred_way_conflict(i))))
17604665835SMaxpicca-Li    // dm situation
17704665835SMaxpicca-Li    XSPerfAccumulate("direct_map_all", PopCount((0 until nPorts).map(i => io.lookup_upd(i).valid)))
17804665835SMaxpicca-Li    XSPerfAccumulate("direct_map_ok", PopCount((0 until nPorts).map(i => io.lookup_upd(i).valid && io.cfpred(i).s1_dm_hit)))
17904665835SMaxpicca-Li  }
18004665835SMaxpicca-Li}
18104665835SMaxpicca-Li
18204665835SMaxpicca-Li
18304665835SMaxpicca-Liclass ICacheWpuWrapper (nPorts: Int) (implicit p:Parameters) extends WPUModule with HasICacheParameters {
18404665835SMaxpicca-Li  val wpu = AlgoWPUMap(iwpuParam, nPorts)
18504665835SMaxpicca-Li  val io = IO(new IwpuIO(nWays, nPorts))
18604665835SMaxpicca-Li
18704665835SMaxpicca-Li  val s1_pred_fail = Wire(Vec(nPorts, Bool()))
18804665835SMaxpicca-Li  val s0_pred_way_en = Wire(Vec(nPorts, UInt(nWays.W)))
18904665835SMaxpicca-Li  val s1_pred_way_en = Wire(Vec(nPorts, UInt(nWays.W)))
19004665835SMaxpicca-Li  val s1_real_way_en = Wire(Vec(nPorts, UInt(nWays.W)))
19104665835SMaxpicca-Li  /** pred in s0*/
19204665835SMaxpicca-Li  for (i <- 0 until nPorts){
19304665835SMaxpicca-Li    wpu.io.predVec(i).en := io.req(i).valid
19404665835SMaxpicca-Li    wpu.io.predVec(i).vaddr := io.req(i).bits.vaddr
19504665835SMaxpicca-Li    s0_pred_way_en(i) := wpu.io.predVec(i).way_en
19604665835SMaxpicca-Li    // io
19704665835SMaxpicca-Li    io.req(i).ready := true.B
19804665835SMaxpicca-Li    if (iwpuParam.enWPU) {
19904665835SMaxpicca-Li      io.resp(i).valid := io.req(i).valid
20004665835SMaxpicca-Li    } else {
20104665835SMaxpicca-Li      io.resp(i).valid := false.B
20204665835SMaxpicca-Li    }
20304665835SMaxpicca-Li    io.resp(i).bits.s0_pred_way_en := s0_pred_way_en(i)
20404665835SMaxpicca-Li    assert(PopCount(io.resp(i).bits.s0_pred_way_en) <= 1.U, "tag should not match with more than 1 way")
20504665835SMaxpicca-Li
20604665835SMaxpicca-Li    /** update in s1 */
20704665835SMaxpicca-Li    s1_pred_way_en(i) := io.lookup_upd(i).bits.s1_pred_way_en
20804665835SMaxpicca-Li    s1_real_way_en(i) := io.lookup_upd(i).bits.s1_real_way_en
20904665835SMaxpicca-Li    s1_pred_fail(i) := io.lookup_upd(i).valid && s1_pred_way_en(i) =/= s1_real_way_en(i)
21004665835SMaxpicca-Li    // look up res
21104665835SMaxpicca-Li    wpu.io.updLookup(i).en := io.lookup_upd(i).valid
21204665835SMaxpicca-Li    wpu.io.updLookup(i).vaddr := io.lookup_upd(i).bits.vaddr
21304665835SMaxpicca-Li    wpu.io.updLookup(i).way_en := io.lookup_upd(i).bits.s1_real_way_en
21404665835SMaxpicca-Li    wpu.io.updLookup(i).pred_way_en := io.lookup_upd(i).bits.s1_pred_way_en
21504665835SMaxpicca-Li    // which will update in look up pred fail
21604665835SMaxpicca-Li    wpu.io.updReplaycarry := DontCare
21704665835SMaxpicca-Li    // replace / tag write
21804665835SMaxpicca-Li    wpu.io.updTagwrite := DontCare
21904665835SMaxpicca-Li  }
22004665835SMaxpicca-Li  wpu.io.updTagwrite.head.en := io.tagwrite_upd.valid
22104665835SMaxpicca-Li  wpu.io.updTagwrite.head.vaddr := io.tagwrite_upd.bits.vaddr
22204665835SMaxpicca-Li  wpu.io.updTagwrite.head.way_en := io.tagwrite_upd.bits.s1_real_way_en
22304665835SMaxpicca-Li
22404665835SMaxpicca-Li  XSPerfAccumulate("wpu_pred_total", PopCount((0 until nPorts).map{i => RegNext(io.req(i).valid) && io.lookup_upd(i).valid}))
22504665835SMaxpicca-Li  XSPerfAccumulate("wpu_pred_succ",  PopCount((0 until nPorts).map{i => RegNext(io.req(i).valid) && io.lookup_upd(i).valid && !s1_pred_fail(i)}))
22604665835SMaxpicca-Li  XSPerfAccumulate("wpu_pred_fail",  PopCount((0 until nPorts).map{i => RegNext(io.req(i).valid) && io.lookup_upd(i).valid && s1_pred_fail(i)}))
22704665835SMaxpicca-Li  XSPerfAccumulate("wpu_pred_miss",  PopCount((0 until nPorts).map{i => RegNext(io.req(i).valid) && io.lookup_upd(i).valid && !RegNext(s0_pred_way_en(i)).orR}))
22804665835SMaxpicca-Li  XSPerfAccumulate("wpu_real_miss",  PopCount((0 until nPorts).map{i => RegNext(io.req(i).valid) && io.lookup_upd(i).valid && !RegNext(s1_real_way_en(i)).orR}))
22904665835SMaxpicca-Li}
23004665835SMaxpicca-Li
23104665835SMaxpicca-Li/** IdealWPU:
23204665835SMaxpicca-Li  * req in s1 and resp in s1
23304665835SMaxpicca-Li  */
23404665835SMaxpicca-Liclass IdealWPU(implicit p:Parameters) extends WPUModule with HasDCacheParameters {
23504665835SMaxpicca-Li  val io = IO(new Bundle{
23604665835SMaxpicca-Li    val req = Output(new Bundle {
23704665835SMaxpicca-Li      val valid = Bool()
23804665835SMaxpicca-Li      val s1_real_way_en = UInt(nWays.W)
23904665835SMaxpicca-Li    })
24004665835SMaxpicca-Li    val resp = Output(new Bundle{
24104665835SMaxpicca-Li      val valid = Bool()
24204665835SMaxpicca-Li      val s1_pred_way_en = UInt(nWays.W)
24304665835SMaxpicca-Li    })
24404665835SMaxpicca-Li  })
24504665835SMaxpicca-Li
24604665835SMaxpicca-Li  val s1_pred_way_en = io.req.s1_real_way_en
24704665835SMaxpicca-Li
24804665835SMaxpicca-Li  if(dwpuParam.enWPU){
24904665835SMaxpicca-Li    io.resp.valid := io.req.valid
25004665835SMaxpicca-Li  }else{
25104665835SMaxpicca-Li    io.resp.valid := false.B
25204665835SMaxpicca-Li  }
25304665835SMaxpicca-Li  io.resp.s1_pred_way_en := s1_pred_way_en
25404665835SMaxpicca-Li}