xref: /XiangShan/src/main/scala/xiangshan/cache/wpu/WPU.scala (revision bb2f3f51dd67f6e16e0cc1ffe43368c9fc7e4aef)
104665835SMaxpicca-Lipackage xiangshan.cache.wpu
204665835SMaxpicca-Li
38891a219SYinan Xuimport org.chipsalliance.cde.config.{Field, Parameters}
404665835SMaxpicca-Liimport chisel3._
504665835SMaxpicca-Liimport chisel3.util._
6*bb2f3f51STang Haojinimport utility.XSPerfAccumulate
704665835SMaxpicca-Liimport xiangshan.cache.{HasL1CacheParameters, L1CacheParameters}
804665835SMaxpicca-Liimport xiangshan.{XSBundle, XSModule}
904665835SMaxpicca-Li
1004665835SMaxpicca-Li/*
1104665835SMaxpicca-Li// TODO: need to learn the specific grammar
1204665835SMaxpicca-Liabstract class WPUBaseModule[T <: Data](implicit P: Parameters) extends XSModule with HasWPUParameters{
1304665835SMaxpicca-Li  def apply[T <: Data]
1404665835SMaxpicca-Li  def pred(vaddr: UInt, en: Bool) : T
1504665835SMaxpicca-Li  def update(vaddr: UInt, data: T ,en: Bool)
1604665835SMaxpicca-Li}
1704665835SMaxpicca-Li*/
1804665835SMaxpicca-Li
1904665835SMaxpicca-Licase object WPUParamsKey extends Field[WPUParameters]
2004665835SMaxpicca-Licase class WPUParameters
2104665835SMaxpicca-Li(
2204665835SMaxpicca-Li  enWPU: Boolean = true,
2304665835SMaxpicca-Li  algoName: String = "mru",
2404665835SMaxpicca-Li  enCfPred: Boolean = false,
2504665835SMaxpicca-Li  isICache: Boolean = false,
2604665835SMaxpicca-Li  // how to impelement a extend inlcude hasL1Cache and L2 Cache
2704665835SMaxpicca-Li)
2804665835SMaxpicca-Li
2904665835SMaxpicca-Litrait HasWPUParameters extends HasL1CacheParameters{
3004665835SMaxpicca-Li  def AlgoWPUMap(wpuParam: WPUParameters, nPorts: Int): BaseWPU = {
3104665835SMaxpicca-Li    wpuParam.algoName.toLowerCase match {
3204665835SMaxpicca-Li      case "mru" => Module(new MruWPU(wpuParam, nPorts))
3304665835SMaxpicca-Li      case "mmru" => Module(new MmruWPU(wpuParam, nPorts))
3404665835SMaxpicca-Li      case "utag" => Module(new UtagWPU(wpuParam, nPorts))
3504665835SMaxpicca-Li      case t => throw new IllegalArgumentException(s"unknown WPU Algorithm $t")
3604665835SMaxpicca-Li    }
3704665835SMaxpicca-Li  }
3804665835SMaxpicca-Li}
3904665835SMaxpicca-Li
4004665835SMaxpicca-Liabstract class BaseWPUBundle(implicit P: Parameters) extends XSBundle
4104665835SMaxpicca-Liabstract class WPUModule(implicit P: Parameters) extends XSModule with HasWPUParameters
4204665835SMaxpicca-Li
4304665835SMaxpicca-Liclass BaseWpuUpdateBundle(nWays: Int)(implicit p: Parameters) extends BaseWPUBundle{
4404665835SMaxpicca-Li  val en = Bool()
4504665835SMaxpicca-Li  val vaddr = UInt(VAddrBits.W)
4604665835SMaxpicca-Li  val way_en = UInt(nWays.W)
4704665835SMaxpicca-Li}
4804665835SMaxpicca-Li
4904665835SMaxpicca-Liclass LookupWpuUpdateBundle(nWays: Int)(implicit p: Parameters) extends BaseWpuUpdateBundle(nWays){
5004665835SMaxpicca-Li  val pred_way_en = UInt(nWays.W)
5104665835SMaxpicca-Li}
5204665835SMaxpicca-Li
5304665835SMaxpicca-Liclass BaseWpuPredictIO(nWays: Int)(implicit p: Parameters) extends BaseWPUBundle{
5404665835SMaxpicca-Li  val en = Input(Bool())
5504665835SMaxpicca-Li  val vaddr = Input(UInt(VAddrBits.W))
5604665835SMaxpicca-Li  val way_en = Output(UInt(nWays.W))
5704665835SMaxpicca-Li}
5804665835SMaxpicca-Li
5904665835SMaxpicca-Liclass WPUBaseIO(portNum: Int, nWays: Int)(implicit p:Parameters) extends BaseWPUBundle {
6004665835SMaxpicca-Li  val predVec = Vec(portNum, new BaseWpuPredictIO(nWays))
6104665835SMaxpicca-Li  val updLookup = Input(Vec(portNum, new LookupWpuUpdateBundle(nWays)))
6204665835SMaxpicca-Li  val updReplaycarry = Input(Vec(portNum, new BaseWpuUpdateBundle(nWays)))
6304665835SMaxpicca-Li  val updTagwrite = Input(Vec(portNum, new BaseWpuUpdateBundle(nWays)))
6404665835SMaxpicca-Li}
6504665835SMaxpicca-Li
6604665835SMaxpicca-Liabstract class BaseWPU(wpuParam: WPUParameters, nPorts: Int)(implicit p:Parameters) extends WPUModule {
6704665835SMaxpicca-Li  val cacheParams: L1CacheParameters = if (wpuParam.isICache) icacheParameters else dcacheParameters
6804665835SMaxpicca-Li
6904665835SMaxpicca-Li  val setSize = nSets
7004665835SMaxpicca-Li  val nTagIdx = nWays
7104665835SMaxpicca-Li  // auxiliary 1 bit is used to judge whether cache miss
7204665835SMaxpicca-Li  val auxWayBits = wayBits + 1
7304665835SMaxpicca-Li  val TagIdxBits = log2Up(nTagIdx)
7404665835SMaxpicca-Li  val utagBits = 8
7504665835SMaxpicca-Li
7604665835SMaxpicca-Li  val io = IO(new WPUBaseIO(nPorts, nWays))
7704665835SMaxpicca-Li
7804665835SMaxpicca-Li  def get_wpu_idx(addr: UInt): UInt = {
7904665835SMaxpicca-Li    addr(untagBits - 1, blockOffBits)
8004665835SMaxpicca-Li  }
8104665835SMaxpicca-Li}
8204665835SMaxpicca-Li
8304665835SMaxpicca-Liclass MruWPU(wpuParam: WPUParameters, nPorts: Int)(implicit p:Parameters) extends BaseWPU(wpuParam, nPorts){
8404665835SMaxpicca-Li  println("  WpuType: MruWPU")
8504665835SMaxpicca-Li  val predict_regs = RegInit(VecInit(Seq.fill(setSize)(0.U(wayBits.W))))
8604665835SMaxpicca-Li
8704665835SMaxpicca-Li  def write(upd: BaseWpuUpdateBundle): Unit = {
8804665835SMaxpicca-Li    when(upd.en) {
8904665835SMaxpicca-Li      val upd_setIdx = get_wpu_idx(upd.vaddr)
9004665835SMaxpicca-Li      predict_regs(upd_setIdx) := OHToUInt(upd.way_en)
9104665835SMaxpicca-Li    }
9204665835SMaxpicca-Li  }
9304665835SMaxpicca-Li
9404665835SMaxpicca-Li  def predict(pred: BaseWpuPredictIO): Unit = {
9504665835SMaxpicca-Li    val predSetIdx = get_wpu_idx(pred.vaddr)
9604665835SMaxpicca-Li    when(pred.en) {
9704665835SMaxpicca-Li      pred.way_en := UIntToOH(predict_regs(predSetIdx))
9804665835SMaxpicca-Li    }.otherwise {
9904665835SMaxpicca-Li      pred.way_en := 0.U(nWays.W)
10004665835SMaxpicca-Li    }
10104665835SMaxpicca-Li  }
10204665835SMaxpicca-Li
10304665835SMaxpicca-Li  for(i <- 0 until nPorts){
10404665835SMaxpicca-Li    predict(io.predVec(i))
10504665835SMaxpicca-Li    write(io.updLookup(i))
10604665835SMaxpicca-Li    write(io.updReplaycarry(i))
10704665835SMaxpicca-Li    write(io.updTagwrite(i))
10804665835SMaxpicca-Li  }
10904665835SMaxpicca-Li
11004665835SMaxpicca-Li}
11104665835SMaxpicca-Li
11204665835SMaxpicca-Liclass MmruWPU(wpuParam: WPUParameters, nPorts: Int)(implicit p:Parameters) extends BaseWPU(wpuParam, nPorts){
11304665835SMaxpicca-Li  println("  WpuType: MmruWPU")
11404665835SMaxpicca-Li  val predict_regs = RegInit(VecInit(Seq.fill(setSize)(VecInit(Seq.fill(nTagIdx)(0.U(auxWayBits.W))))))
11504665835SMaxpicca-Li
11604665835SMaxpicca-Li  def write(upd: BaseWpuUpdateBundle): Unit = {
11704665835SMaxpicca-Li    when(upd.en) {
11804665835SMaxpicca-Li      val updSetIdx = get_wpu_idx(upd.vaddr)
11904665835SMaxpicca-Li      val updTagIdx = get_vir_tag(upd.vaddr)
12004665835SMaxpicca-Li      predict_regs(updSetIdx)(updTagIdx) := OHToUInt(upd.way_en)
12104665835SMaxpicca-Li    }
12204665835SMaxpicca-Li  }
12304665835SMaxpicca-Li
12404665835SMaxpicca-Li  def predict(pred: BaseWpuPredictIO): Unit = {
12504665835SMaxpicca-Li    val predSetIdx = get_wpu_idx(pred.vaddr)
12604665835SMaxpicca-Li    val predTagIdx = get_vir_tag(pred.vaddr)
12704665835SMaxpicca-Li    when(pred.en) {
12804665835SMaxpicca-Li      //UIntToOH(8.U(4.W))=100000000.U(16.W)=00000000.U(8.W)
12904665835SMaxpicca-Li      //UIntToOH(8.U(4.W), 8)=00000001.U(8.W)
13004665835SMaxpicca-Li      pred.way_en := UIntToOH(predict_regs(predSetIdx)(predTagIdx))
13104665835SMaxpicca-Li    }.otherwise {
13204665835SMaxpicca-Li      pred.way_en := 0.U(nWays.W)
13304665835SMaxpicca-Li    }
13404665835SMaxpicca-Li  }
13504665835SMaxpicca-Li
13604665835SMaxpicca-Li  for(i <- 0 until nPorts){
13704665835SMaxpicca-Li    predict(io.predVec(i))
13804665835SMaxpicca-Li    write(io.updLookup(i))
13904665835SMaxpicca-Li    write(io.updReplaycarry(i))
14004665835SMaxpicca-Li    write(io.updTagwrite(i))
14104665835SMaxpicca-Li  }
14204665835SMaxpicca-Li
14304665835SMaxpicca-Li}
14404665835SMaxpicca-Li
14504665835SMaxpicca-Liclass UtagWPU(wpuParam: WPUParameters, nPorts: Int)(implicit p:Parameters) extends BaseWPU(wpuParam, nPorts){
14604665835SMaxpicca-Li  println("  WpuType: UtagWPU")
14704665835SMaxpicca-Li  val utag_regs = RegInit(VecInit(Seq.fill(setSize)(VecInit(Seq.fill(nWays)(0.U(utagBits.W))))))
14804665835SMaxpicca-Li  val valid_regs = RegInit(VecInit(Seq.fill(setSize)(VecInit(Seq.fill(nWays)(false.B)))))
14904665835SMaxpicca-Li
15004665835SMaxpicca-Li  def get_hash_utag(addr: UInt): UInt = {
15104665835SMaxpicca-Li    val utagQuotient = vtagBits / utagBits
15204665835SMaxpicca-Li    val utagRemainder = vtagBits % utagBits
15304665835SMaxpicca-Li    val vtag = get_vir_tag(addr)
15404665835SMaxpicca-Li
15504665835SMaxpicca-Li    /* old */
15604665835SMaxpicca-Li    vtag(utagBits * 2 - 1, utagBits) ^ vtag(utagBits - 1, 0)
15704665835SMaxpicca-Li
15804665835SMaxpicca-Li    /* new */
15904665835SMaxpicca-Li    // val tmp = vtag(utagQuotient * utagBits - 1, 0).asTypeOf(Vec(utagQuotient, UInt(utagBits.W)))
16004665835SMaxpicca-Li    // val res1 = tmp.reduce(_ ^ _)
16104665835SMaxpicca-Li    // val res2 = Wire(UInt(utagRemainder.W))
16204665835SMaxpicca-Li    // if(utagRemainder!=0){
16304665835SMaxpicca-Li    //   res2 := res1(utagRemainder - 1, 0) ^ vtag(vtagBits - 1, utagBits * utagQuotient)
16404665835SMaxpicca-Li    //   Cat(res1(utagBits - 1, utagRemainder), res2)
16504665835SMaxpicca-Li    // }else{
16604665835SMaxpicca-Li    //   res1
16704665835SMaxpicca-Li    // }
16804665835SMaxpicca-Li  }
16904665835SMaxpicca-Li
17004665835SMaxpicca-Li  def write_utag(upd: BaseWpuUpdateBundle): Unit = {
17104665835SMaxpicca-Li    when(upd.en){
17204665835SMaxpicca-Li      val upd_setIdx = get_wpu_idx(upd.vaddr)
17304665835SMaxpicca-Li      val upd_utag = get_hash_utag(upd.vaddr)
17404665835SMaxpicca-Li      val upd_way = OHToUInt(upd.way_en)
17504665835SMaxpicca-Li      utag_regs(upd_setIdx)(upd_way) := upd_utag
17604665835SMaxpicca-Li      valid_regs(upd_setIdx)(upd_way) := true.B
17704665835SMaxpicca-Li    }
17804665835SMaxpicca-Li  }
17904665835SMaxpicca-Li
18004665835SMaxpicca-Li  def unvalid_utag(upd: LookupWpuUpdateBundle): Unit = {
18104665835SMaxpicca-Li    when(upd.en){
18204665835SMaxpicca-Li      val upd_setIdx = get_wpu_idx(upd.vaddr)
18304665835SMaxpicca-Li      val upd_way = OHToUInt(upd.pred_way_en)
18404665835SMaxpicca-Li      valid_regs(upd_setIdx)(upd_way) := false.B
18504665835SMaxpicca-Li    }
18604665835SMaxpicca-Li  }
18704665835SMaxpicca-Li
18804665835SMaxpicca-Li  def predict(pred: BaseWpuPredictIO): Unit = {
18904665835SMaxpicca-Li    val req_setIdx = get_wpu_idx(pred.vaddr)
19004665835SMaxpicca-Li    val req_utag = get_hash_utag(pred.vaddr)
19104665835SMaxpicca-Li    val pred_way_en = Wire(UInt(nWays.W))
19204665835SMaxpicca-Li    when(pred.en) {
19304665835SMaxpicca-Li      pred_way_en := VecInit((0 until nWays).map(i =>
19404665835SMaxpicca-Li        req_utag === utag_regs(req_setIdx)(i) && valid_regs(req_setIdx)(i)
19504665835SMaxpicca-Li      )).asUInt
19604665835SMaxpicca-Li    }.otherwise {
19704665835SMaxpicca-Li      pred_way_en := 0.U(nWays.W)
19804665835SMaxpicca-Li    }
19904665835SMaxpicca-Li    // avoid hash conflict
20004665835SMaxpicca-Li    pred.way_en := UIntToOH(OHToUInt(pred_way_en))
20104665835SMaxpicca-Li  }
20204665835SMaxpicca-Li
20304665835SMaxpicca-Li  val hash_conflict = Wire(Vec(nPorts, Bool()))
20404665835SMaxpicca-Li  for(i <- 0 until nPorts){
20504665835SMaxpicca-Li    predict(io.predVec(i))
20604665835SMaxpicca-Li    val real_way_en = io.updLookup(i).way_en
20704665835SMaxpicca-Li    val pred_way_en = io.updLookup(i).pred_way_en
20804665835SMaxpicca-Li    val pred_miss = io.updLookup(i).en && !pred_way_en.orR
20904665835SMaxpicca-Li    val real_miss = io.updLookup(i).en && !real_way_en.orR
21004665835SMaxpicca-Li    val way_match = io.updLookup(i).en && pred_way_en === real_way_en
21104665835SMaxpicca-Li
21204665835SMaxpicca-Li    hash_conflict(i) := !pred_miss && !way_match
21304665835SMaxpicca-Li      // look up: vtag miss but tag hit
21404665835SMaxpicca-Li    when(pred_miss && !real_miss) {
21504665835SMaxpicca-Li      write_utag(io.updLookup(i))
21604665835SMaxpicca-Li    }
21704665835SMaxpicca-Li    // look up: vtag hit but other tag hit ==> unvalid pred way; write real way
21804665835SMaxpicca-Li    when(!pred_miss && !way_match) {
21904665835SMaxpicca-Li      unvalid_utag(io.updLookup(i))
22004665835SMaxpicca-Li    }
22104665835SMaxpicca-Li    when(!pred_miss && !real_miss && !way_match) {
22204665835SMaxpicca-Li      write_utag(io.updLookup(i))
22304665835SMaxpicca-Li    }
22404665835SMaxpicca-Li    // replay carry
22504665835SMaxpicca-Li    write_utag(io.updReplaycarry(i))
22604665835SMaxpicca-Li    // tag write
22704665835SMaxpicca-Li    write_utag(io.updTagwrite(i))
22804665835SMaxpicca-Li  }
22904665835SMaxpicca-Li
23004665835SMaxpicca-Li  XSPerfAccumulate("utag_hash_conflict", PopCount(hash_conflict))
23104665835SMaxpicca-Li}