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}