104665835SMaxpicca-Lipackage xiangshan.cache.wpu 204665835SMaxpicca-Li 38891a219SYinan Xuimport org.chipsalliance.cde.config.Parameters 404665835SMaxpicca-Liimport chisel3._ 504665835SMaxpicca-Liimport chisel3.util._ 6*bb2f3f51STang 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 wayConflictPredictor = Module(new WayConflictPredictor(nPorts)) 8504665835SMaxpicca-Li val io = IO(new DwpuIO(nWays, nPorts)) 8604665835SMaxpicca-Li 8704665835SMaxpicca-Li /** pred */ 8804665835SMaxpicca-Li val s0_dmSel = Wire(Vec(nPorts, Bool())) 8904665835SMaxpicca-Li val s0_pred_way_conflict = Wire(Vec(nPorts, Bool())) 9004665835SMaxpicca-Li val s0_pred_way_en = Wire(Vec(nPorts, UInt(nWays.W))) 9104665835SMaxpicca-Li val s1_lookup_valid = Wire(Vec(nPorts, Bool())) 9204665835SMaxpicca-Li val s1_dmSel = Wire(Vec(nPorts, Bool())) 9304665835SMaxpicca-Li val s1_pred_way_en = Wire(Vec(nPorts, UInt(nWays.W))) 9404665835SMaxpicca-Li val s1_pred_fail = Wire(Vec(nPorts, Bool())) 9504665835SMaxpicca-Li val s1_hit = Wire(Vec(nPorts, Bool())) 9604665835SMaxpicca-Li 9704665835SMaxpicca-Li for(i <- 0 until nPorts){ 9804665835SMaxpicca-Li wayConflictPredictor.io.pred(i).en := io.req(i).valid 9904665835SMaxpicca-Li wayConflictPredictor.io.pred(i).vaddr := io.cfpred(i).s0_vaddr 10004665835SMaxpicca-Li s0_pred_way_conflict(i) := wayConflictPredictor.io.pred(i).way_conflict 10104665835SMaxpicca-Li 10204665835SMaxpicca-Li s0_dmSel(i) := false.B 10304665835SMaxpicca-Li wpu.io.predVec(i).en := io.req(i).valid 10404665835SMaxpicca-Li wpu.io.predVec(i).vaddr := io.req(i).bits.vaddr 10504665835SMaxpicca-Li when(io.req(i).bits.replayCarry.valid) { 10604665835SMaxpicca-Li // replay carry 10704665835SMaxpicca-Li s0_pred_way_en(i) := io.req(i).bits.replayCarry.real_way_en 10804665835SMaxpicca-Li }.otherwise { 10904665835SMaxpicca-Li // way prediction 11004665835SMaxpicca-Li s0_pred_way_en(i) := wpu.io.predVec(i).way_en 11104665835SMaxpicca-Li 11204665835SMaxpicca-Li if (dwpuParam.enCfPred) { 11304665835SMaxpicca-Li // selective direct mapping 11404665835SMaxpicca-Li when(!s0_pred_way_conflict(i)) { 11504665835SMaxpicca-Li s0_pred_way_en(i) := UIntToOH(get_direct_map_way(io.req(i).bits.vaddr)) 11604665835SMaxpicca-Li s0_dmSel(i) := true.B 11704665835SMaxpicca-Li } 11804665835SMaxpicca-Li } 11904665835SMaxpicca-Li } 12004665835SMaxpicca-Li 12104665835SMaxpicca-Li /** check and update in s1 */ 12204665835SMaxpicca-Li s1_lookup_valid(i) := io.lookup_upd(i).valid 12304665835SMaxpicca-Li s1_dmSel(i) := RegNext(s0_dmSel(i)) 12404665835SMaxpicca-Li s1_pred_way_en(i) := io.lookup_upd(i).bits.s1_pred_way_en 12504665835SMaxpicca-Li s1_pred_fail(i) := io.lookup_upd(i).valid && s1_pred_way_en(i) =/= io.lookup_upd(i).bits.s1_real_way_en 12604665835SMaxpicca-Li s1_hit(i) := !s1_pred_fail(i) && s1_pred_way_en(i).orR 12704665835SMaxpicca-Li 12804665835SMaxpicca-Li val s0_replay_upd = Wire(new BaseWpuUpdateBundle(nWays)) 12904665835SMaxpicca-Li s0_replay_upd.en := io.req(i).valid && io.req(i).bits.replayCarry.valid 13004665835SMaxpicca-Li s0_replay_upd.vaddr := io.req(i).bits.vaddr 13104665835SMaxpicca-Li s0_replay_upd.way_en := io.req(i).bits.replayCarry.real_way_en 13204665835SMaxpicca-Li val s1_replay_upd = RegNext(s0_replay_upd) 13304665835SMaxpicca-Li 13404665835SMaxpicca-Li wayConflictPredictor.io.update(i).en := io.lookup_upd(i).valid 13504665835SMaxpicca-Li wayConflictPredictor.io.update(i).vaddr := io.cfpred(i).s1_vaddr 13604665835SMaxpicca-Li wayConflictPredictor.io.update(i).dm_hit := s1_dmSel(i) && io.cfpred(i).s1_dm_hit 13704665835SMaxpicca-Li wayConflictPredictor.io.update(i).sa_hit := !s1_dmSel(i) && s1_hit(i) 13804665835SMaxpicca-Li 13904665835SMaxpicca-Li // look up res 14004665835SMaxpicca-Li wpu.io.updLookup(i).en := io.lookup_upd(i).valid 14104665835SMaxpicca-Li wpu.io.updLookup(i).vaddr := io.lookup_upd(i).bits.vaddr 14204665835SMaxpicca-Li wpu.io.updLookup(i).way_en := io.lookup_upd(i).bits.s1_real_way_en 14304665835SMaxpicca-Li wpu.io.updLookup(i).pred_way_en := io.lookup_upd(i).bits.s1_pred_way_en 14404665835SMaxpicca-Li 14504665835SMaxpicca-Li // which will update in look up pred fail 14604665835SMaxpicca-Li wpu.io.updReplaycarry(i) := s1_replay_upd 14704665835SMaxpicca-Li 14804665835SMaxpicca-Li // replace / tag write 14904665835SMaxpicca-Li wpu.io.updTagwrite(i) := DontCare 15004665835SMaxpicca-Li 15104665835SMaxpicca-Li /** predict and response in s0 */ 15204665835SMaxpicca-Li io.req(i).ready := true.B 15304665835SMaxpicca-Li if (dwpuParam.enWPU) { 15404665835SMaxpicca-Li io.resp(i).valid := io.req(i).valid 15504665835SMaxpicca-Li } else { 15604665835SMaxpicca-Li io.resp(i).valid := false.B 15704665835SMaxpicca-Li } 15804665835SMaxpicca-Li io.resp(i).bits.s0_pred_way_en := s0_pred_way_en(i) 15904665835SMaxpicca-Li assert(PopCount(io.resp(i).bits.s0_pred_way_en) <= 1.U, "tag should not match with more than 1 way") 16004665835SMaxpicca-Li } 16104665835SMaxpicca-Li wpu.io.updTagwrite(0).en := io.tagwrite_upd.valid 16204665835SMaxpicca-Li wpu.io.updTagwrite(0).vaddr := io.tagwrite_upd.bits.vaddr 16304665835SMaxpicca-Li wpu.io.updTagwrite(0).way_en := io.tagwrite_upd.bits.s1_real_way_en 16404665835SMaxpicca-Li 16504665835SMaxpicca-Li // PerfLog 16604665835SMaxpicca-Li // pred situation 16704665835SMaxpicca-Li XSPerfAccumulate("wpu_pred_total", PopCount((0 until nPorts).map(i => RegNext(io.req(i).valid) && s1_lookup_valid(i)))) 16804665835SMaxpicca-Li XSPerfAccumulate("wpu_pred_succ", PopCount((0 until nPorts).map(i => RegNext(io.req(i).valid) && s1_lookup_valid(i) && !s1_pred_fail(i)))) 16904665835SMaxpicca-Li XSPerfAccumulate("wpu_pred_fail", PopCount((0 until nPorts).map(i => RegNext(io.req(i).valid) && s1_lookup_valid(i) && s1_pred_fail(i)))) 17004665835SMaxpicca-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))) 17104665835SMaxpicca-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))) 17204665835SMaxpicca-Li // pred component 17304665835SMaxpicca-Li XSPerfAccumulate("wpu_pred_replayCarry", PopCount((0 until nPorts).map(i => io.req(i).valid && io.req(i).bits.replayCarry.valid))) 17404665835SMaxpicca-Li if(!dwpuParam.enCfPred){ 17504665835SMaxpicca-Li XSPerfAccumulate("wpu_pred_wayPrediction", PopCount((0 until nPorts).map(i => io.req(i).valid && !io.req(i).bits.replayCarry.valid))) 17604665835SMaxpicca-Li }else{ 17704665835SMaxpicca-Li XSPerfAccumulate("wpu_pred_wayPrediction", PopCount((0 until nPorts).map(i => io.req(i).valid && !io.req(i).bits.replayCarry.valid && s0_pred_way_conflict(i)))) 17804665835SMaxpicca-Li XSPerfAccumulate("wpu_pred_directMap", PopCount((0 until nPorts).map(i => io.req(i).valid && !io.req(i).bits.replayCarry.valid && !s0_pred_way_conflict(i)))) 17904665835SMaxpicca-Li // dm situation 18004665835SMaxpicca-Li XSPerfAccumulate("direct_map_all", PopCount((0 until nPorts).map(i => io.lookup_upd(i).valid))) 18104665835SMaxpicca-Li XSPerfAccumulate("direct_map_ok", PopCount((0 until nPorts).map(i => io.lookup_upd(i).valid && io.cfpred(i).s1_dm_hit))) 18204665835SMaxpicca-Li } 18304665835SMaxpicca-Li} 18404665835SMaxpicca-Li 18504665835SMaxpicca-Li 18604665835SMaxpicca-Liclass ICacheWpuWrapper (nPorts: Int) (implicit p:Parameters) extends WPUModule with HasICacheParameters { 18704665835SMaxpicca-Li val wpu = AlgoWPUMap(iwpuParam, nPorts) 18804665835SMaxpicca-Li val io = IO(new IwpuIO(nWays, nPorts)) 18904665835SMaxpicca-Li 19004665835SMaxpicca-Li val s1_pred_fail = Wire(Vec(nPorts, Bool())) 19104665835SMaxpicca-Li val s0_pred_way_en = Wire(Vec(nPorts, UInt(nWays.W))) 19204665835SMaxpicca-Li val s1_pred_way_en = Wire(Vec(nPorts, UInt(nWays.W))) 19304665835SMaxpicca-Li val s1_real_way_en = Wire(Vec(nPorts, UInt(nWays.W))) 19404665835SMaxpicca-Li /** pred in s0*/ 19504665835SMaxpicca-Li for (i <- 0 until nPorts){ 19604665835SMaxpicca-Li wpu.io.predVec(i).en := io.req(i).valid 19704665835SMaxpicca-Li wpu.io.predVec(i).vaddr := io.req(i).bits.vaddr 19804665835SMaxpicca-Li s0_pred_way_en(i) := wpu.io.predVec(i).way_en 19904665835SMaxpicca-Li // io 20004665835SMaxpicca-Li io.req(i).ready := true.B 20104665835SMaxpicca-Li if (iwpuParam.enWPU) { 20204665835SMaxpicca-Li io.resp(i).valid := io.req(i).valid 20304665835SMaxpicca-Li } else { 20404665835SMaxpicca-Li io.resp(i).valid := false.B 20504665835SMaxpicca-Li } 20604665835SMaxpicca-Li io.resp(i).bits.s0_pred_way_en := s0_pred_way_en(i) 20704665835SMaxpicca-Li assert(PopCount(io.resp(i).bits.s0_pred_way_en) <= 1.U, "tag should not match with more than 1 way") 20804665835SMaxpicca-Li 20904665835SMaxpicca-Li /** update in s1 */ 21004665835SMaxpicca-Li s1_pred_way_en(i) := io.lookup_upd(i).bits.s1_pred_way_en 21104665835SMaxpicca-Li s1_real_way_en(i) := io.lookup_upd(i).bits.s1_real_way_en 21204665835SMaxpicca-Li s1_pred_fail(i) := io.lookup_upd(i).valid && s1_pred_way_en(i) =/= s1_real_way_en(i) 21304665835SMaxpicca-Li // look up res 21404665835SMaxpicca-Li wpu.io.updLookup(i).en := io.lookup_upd(i).valid 21504665835SMaxpicca-Li wpu.io.updLookup(i).vaddr := io.lookup_upd(i).bits.vaddr 21604665835SMaxpicca-Li wpu.io.updLookup(i).way_en := io.lookup_upd(i).bits.s1_real_way_en 21704665835SMaxpicca-Li wpu.io.updLookup(i).pred_way_en := io.lookup_upd(i).bits.s1_pred_way_en 21804665835SMaxpicca-Li // which will update in look up pred fail 21904665835SMaxpicca-Li wpu.io.updReplaycarry := DontCare 22004665835SMaxpicca-Li // replace / tag write 22104665835SMaxpicca-Li wpu.io.updTagwrite := DontCare 22204665835SMaxpicca-Li } 22304665835SMaxpicca-Li wpu.io.updTagwrite.head.en := io.tagwrite_upd.valid 22404665835SMaxpicca-Li wpu.io.updTagwrite.head.vaddr := io.tagwrite_upd.bits.vaddr 22504665835SMaxpicca-Li wpu.io.updTagwrite.head.way_en := io.tagwrite_upd.bits.s1_real_way_en 22604665835SMaxpicca-Li 22704665835SMaxpicca-Li XSPerfAccumulate("wpu_pred_total", PopCount((0 until nPorts).map{i => RegNext(io.req(i).valid) && io.lookup_upd(i).valid})) 22804665835SMaxpicca-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)})) 22904665835SMaxpicca-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)})) 23004665835SMaxpicca-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})) 23104665835SMaxpicca-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})) 23204665835SMaxpicca-Li} 23304665835SMaxpicca-Li 23404665835SMaxpicca-Li/** IdealWPU: 23504665835SMaxpicca-Li * req in s1 and resp in s1 23604665835SMaxpicca-Li */ 23704665835SMaxpicca-Liclass IdealWPU(implicit p:Parameters) extends WPUModule with HasDCacheParameters { 23804665835SMaxpicca-Li val io = IO(new Bundle{ 23904665835SMaxpicca-Li val req = Output(new Bundle { 24004665835SMaxpicca-Li val valid = Bool() 24104665835SMaxpicca-Li val s1_real_way_en = UInt(nWays.W) 24204665835SMaxpicca-Li }) 24304665835SMaxpicca-Li val resp = Output(new Bundle{ 24404665835SMaxpicca-Li val valid = Bool() 24504665835SMaxpicca-Li val s1_pred_way_en = UInt(nWays.W) 24604665835SMaxpicca-Li }) 24704665835SMaxpicca-Li }) 24804665835SMaxpicca-Li 24904665835SMaxpicca-Li val s1_pred_way_en = io.req.s1_real_way_en 25004665835SMaxpicca-Li 25104665835SMaxpicca-Li if(dwpuParam.enWPU){ 25204665835SMaxpicca-Li io.resp.valid := io.req.valid 25304665835SMaxpicca-Li }else{ 25404665835SMaxpicca-Li io.resp.valid := false.B 25504665835SMaxpicca-Li } 25604665835SMaxpicca-Li io.resp.s1_pred_way_en := s1_pred_way_en 25704665835SMaxpicca-Li}