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}