1*1d8f4dcbSJay/*************************************************************************************** 2*1d8f4dcbSJay* Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences 3*1d8f4dcbSJay* Copyright (c) 2020-2021 Peng Cheng Laboratory 4*1d8f4dcbSJay* 5*1d8f4dcbSJay* XiangShan is licensed under Mulan PSL v2. 6*1d8f4dcbSJay* You can use this software according to the terms and conditions of the Mulan PSL v2. 7*1d8f4dcbSJay* You may obtain a copy of Mulan PSL v2 at: 8*1d8f4dcbSJay* http://license.coscl.org.cn/MulanPSL2 9*1d8f4dcbSJay* 10*1d8f4dcbSJay* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 11*1d8f4dcbSJay* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 12*1d8f4dcbSJay* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 13*1d8f4dcbSJay* 14*1d8f4dcbSJay* See the Mulan PSL v2 for more details. 15*1d8f4dcbSJay***************************************************************************************/ 16*1d8f4dcbSJay 17*1d8f4dcbSJaypackage xiangshan.frontend.icache 18*1d8f4dcbSJay 19*1d8f4dcbSJayimport chipsalliance.rocketchip.config.Parameters 20*1d8f4dcbSJayimport chisel3._ 21*1d8f4dcbSJayimport chisel3.util._ 22*1d8f4dcbSJayimport freechips.rocketchip.diplomacy.IdRange 23*1d8f4dcbSJayimport freechips.rocketchip.tilelink.ClientStates._ 24*1d8f4dcbSJayimport freechips.rocketchip.tilelink.TLPermissions._ 25*1d8f4dcbSJayimport freechips.rocketchip.tilelink._ 26*1d8f4dcbSJayimport xiangshan._ 27*1d8f4dcbSJayimport huancun.{AliasKey, DirtyKey} 28*1d8f4dcbSJayimport xiangshan.cache._ 29*1d8f4dcbSJayimport utils._ 30*1d8f4dcbSJay 31*1d8f4dcbSJay 32*1d8f4dcbSJayabstract class ICacheMissUnitModule(implicit p: Parameters) extends XSModule 33*1d8f4dcbSJay with HasICacheParameters 34*1d8f4dcbSJay 35*1d8f4dcbSJayabstract class ICacheMissUnitBundle(implicit p: Parameters) extends XSBundle 36*1d8f4dcbSJay with HasICacheParameters 37*1d8f4dcbSJay 38*1d8f4dcbSJayclass ICacheMissReq(implicit p: Parameters) extends ICacheBundle 39*1d8f4dcbSJay{ 40*1d8f4dcbSJay val paddr = UInt(PAddrBits.W) 41*1d8f4dcbSJay val vaddr = UInt(VAddrBits.W) 42*1d8f4dcbSJay val waymask = UInt(nWays.W) 43*1d8f4dcbSJay val coh = new ClientMetadata 44*1d8f4dcbSJay //val release = ValidUndirectioned(new ReleaseReq) 45*1d8f4dcbSJay 46*1d8f4dcbSJay def getVirSetIdx = get_idx(vaddr) 47*1d8f4dcbSJay def getPhyTag = get_phy_tag(paddr) 48*1d8f4dcbSJay} 49*1d8f4dcbSJay 50*1d8f4dcbSJay 51*1d8f4dcbSJayclass ICacheMissResp(implicit p: Parameters) extends ICacheBundle 52*1d8f4dcbSJay{ 53*1d8f4dcbSJay val data = UInt(blockBits.W) 54*1d8f4dcbSJay} 55*1d8f4dcbSJay 56*1d8f4dcbSJayclass ICacheMissBundle(implicit p: Parameters) extends ICacheBundle{ 57*1d8f4dcbSJay val req = Vec(2, Flipped(DecoupledIO(new ICacheMissReq))) 58*1d8f4dcbSJay val resp = Vec(2,ValidIO(new ICacheMissResp)) 59*1d8f4dcbSJay val flush = Input(Bool()) 60*1d8f4dcbSJay} 61*1d8f4dcbSJay 62*1d8f4dcbSJay 63*1d8f4dcbSJayclass ICacheMissEntry(edge: TLEdgeOut, id: Int)(implicit p: Parameters) extends ICacheMissUnitModule 64*1d8f4dcbSJay with MemoryOpConstants 65*1d8f4dcbSJay{ 66*1d8f4dcbSJay val io = IO(new Bundle { 67*1d8f4dcbSJay val id = Input(UInt(log2Ceil(nMissEntries).W)) 68*1d8f4dcbSJay 69*1d8f4dcbSJay val req = Flipped(DecoupledIO(new ICacheMissReq)) 70*1d8f4dcbSJay val resp = ValidIO(new ICacheMissResp) 71*1d8f4dcbSJay 72*1d8f4dcbSJay //tilelink channel 73*1d8f4dcbSJay val mem_acquire = DecoupledIO(new TLBundleA(edge.bundle)) 74*1d8f4dcbSJay val mem_grant = Flipped(DecoupledIO(new TLBundleD(edge.bundle))) 75*1d8f4dcbSJay val mem_finish = DecoupledIO(new TLBundleE(edge.bundle)) 76*1d8f4dcbSJay 77*1d8f4dcbSJay val meta_write = DecoupledIO(new ICacheMetaWriteBundle) 78*1d8f4dcbSJay val data_write = DecoupledIO(new ICacheDataWriteBundle) 79*1d8f4dcbSJay 80*1d8f4dcbSJay// val release = DecoupledIO(new ReleaseReq) 81*1d8f4dcbSJay// val victimInfor = Output(new ICacheVictimInfor()) 82*1d8f4dcbSJay// val probeMerge = Input(new ICacheVictimInfor) 83*1d8f4dcbSJay// val probeMergeFix = Output(Bool()) 84*1d8f4dcbSJay 85*1d8f4dcbSJay }) 86*1d8f4dcbSJay 87*1d8f4dcbSJay /** default value for control signals */ 88*1d8f4dcbSJay io.resp := DontCare 89*1d8f4dcbSJay io.mem_acquire.bits := DontCare 90*1d8f4dcbSJay io.mem_grant.ready := true.B 91*1d8f4dcbSJay io.meta_write.bits := DontCare 92*1d8f4dcbSJay io.data_write.bits := DontCare 93*1d8f4dcbSJay 94*1d8f4dcbSJay val s_idle :: s_send_release :: s_send_mem_aquire :: s_wait_mem_grant :: s_write_back :: s_send_grant_ack :: s_wait_resp :: Nil = Enum(7) 95*1d8f4dcbSJay val state = RegInit(s_idle) 96*1d8f4dcbSJay 97*1d8f4dcbSJay /** control logic transformation */ 98*1d8f4dcbSJay //request register 99*1d8f4dcbSJay val req = Reg(new ICacheMissReq) 100*1d8f4dcbSJay val req_idx = req.getVirSetIdx //virtual index 101*1d8f4dcbSJay val req_tag = req.getPhyTag //physical tag 102*1d8f4dcbSJay val req_waymask = req.waymask 103*1d8f4dcbSJay 104*1d8f4dcbSJay// val victim_tag = get_phy_tag(req.release.bits.addr) 105*1d8f4dcbSJay// val victim_idx = req_idx 106*1d8f4dcbSJay 107*1d8f4dcbSJay val (_, _, refill_done, refill_address_inc) = edge.addr_inc(io.mem_grant) 108*1d8f4dcbSJay 109*1d8f4dcbSJay// val needMergeProbe = (io.probeMerge.valid && state =/= s_idle && io.probeMerge.ptag === victim_tag && io.probeMerge.vidx === victim_idx) 110*1d8f4dcbSJay// 111*1d8f4dcbSJay// //change release into a ProbeAck 112*1d8f4dcbSJay// //WARNING: no change to param, default TtoN 113*1d8f4dcbSJay// when(needMergeProbe && state === s_send_release){ 114*1d8f4dcbSJay// io.release.bits.voluntary := false.B 115*1d8f4dcbSJay// io.release.bits.hasData := true.B 116*1d8f4dcbSJay// } 117*1d8f4dcbSJay// 118*1d8f4dcbSJay// io.probeMergeFix := needMergeProbe && state === s_send_release 119*1d8f4dcbSJay 120*1d8f4dcbSJay //cacheline register 121*1d8f4dcbSJay //refullCycles: 8 for 64-bit bus bus and 2 for 256-bit 122*1d8f4dcbSJay val readBeatCnt = Reg(UInt(log2Up(refillCycles).W)) 123*1d8f4dcbSJay val respDataReg = Reg(Vec(refillCycles, UInt(beatBits.W))) 124*1d8f4dcbSJay 125*1d8f4dcbSJay //initial 126*1d8f4dcbSJay io.resp.bits := DontCare 127*1d8f4dcbSJay io.mem_acquire.bits := DontCare 128*1d8f4dcbSJay io.mem_grant.ready := true.B 129*1d8f4dcbSJay io.meta_write.bits := DontCare 130*1d8f4dcbSJay io.data_write.bits := DontCare 131*1d8f4dcbSJay 132*1d8f4dcbSJay 133*1d8f4dcbSJay io.req.ready := (state === s_idle) 134*1d8f4dcbSJay io.mem_acquire.valid := (state === s_send_mem_aquire) //&& !io.flush 135*1d8f4dcbSJay 136*1d8f4dcbSJay val grantack = RegEnable(edge.GrantAck(io.mem_grant.bits), io.mem_grant.fire()) 137*1d8f4dcbSJay val grant_param = Reg(UInt(TLPermissions.bdWidth.W)) 138*1d8f4dcbSJay val is_dirty = RegInit(false.B) 139*1d8f4dcbSJay val is_grant = RegEnable(edge.isRequest(io.mem_grant.bits), io.mem_grant.fire()) 140*1d8f4dcbSJay 141*1d8f4dcbSJay val neddSendAck = RegInit(false.B) 142*1d8f4dcbSJay 143*1d8f4dcbSJay //state change 144*1d8f4dcbSJay switch(state) { 145*1d8f4dcbSJay is(s_idle) { 146*1d8f4dcbSJay when(io.req.fire()) { 147*1d8f4dcbSJay readBeatCnt := 0.U 148*1d8f4dcbSJay state := s_send_mem_aquire 149*1d8f4dcbSJay req := io.req.bits 150*1d8f4dcbSJay } 151*1d8f4dcbSJay } 152*1d8f4dcbSJay 153*1d8f4dcbSJay // memory request 154*1d8f4dcbSJay is(s_send_mem_aquire) { 155*1d8f4dcbSJay when(io.mem_acquire.fire()) { 156*1d8f4dcbSJay state := s_wait_mem_grant 157*1d8f4dcbSJay } 158*1d8f4dcbSJay } 159*1d8f4dcbSJay 160*1d8f4dcbSJay is(s_wait_mem_grant) { 161*1d8f4dcbSJay when(edge.hasData(io.mem_grant.bits)) { 162*1d8f4dcbSJay when(io.mem_grant.fire()) { 163*1d8f4dcbSJay readBeatCnt := readBeatCnt + 1.U 164*1d8f4dcbSJay respDataReg(readBeatCnt) := io.mem_grant.bits.data 165*1d8f4dcbSJay grant_param := io.mem_grant.bits.param 166*1d8f4dcbSJay is_dirty := io.mem_grant.bits.echo.lift(DirtyKey).getOrElse(false.B) 167*1d8f4dcbSJay when(readBeatCnt === (refillCycles - 1).U) { 168*1d8f4dcbSJay assert(refill_done, "refill not done!") 169*1d8f4dcbSJay state := s_write_back 170*1d8f4dcbSJay neddSendAck := edge.isResponse(io.mem_grant.bits) 171*1d8f4dcbSJay } 172*1d8f4dcbSJay } 173*1d8f4dcbSJay } 174*1d8f4dcbSJay } 175*1d8f4dcbSJay 176*1d8f4dcbSJay is(s_write_back) { 177*1d8f4dcbSJay state := Mux(io.meta_write.fire() && io.data_write.fire(), Mux(neddSendAck, s_send_grant_ack, s_wait_resp), s_write_back) 178*1d8f4dcbSJay } 179*1d8f4dcbSJay 180*1d8f4dcbSJay is(s_send_grant_ack) { 181*1d8f4dcbSJay when(io.mem_finish.fire()) { 182*1d8f4dcbSJay state := s_wait_resp 183*1d8f4dcbSJay } 184*1d8f4dcbSJay } 185*1d8f4dcbSJay 186*1d8f4dcbSJay is(s_wait_resp) { 187*1d8f4dcbSJay io.resp.bits.data := respDataReg.asUInt 188*1d8f4dcbSJay when(io.resp.fire()) { 189*1d8f4dcbSJay state := s_idle 190*1d8f4dcbSJay } 191*1d8f4dcbSJay } 192*1d8f4dcbSJay } 193*1d8f4dcbSJay 194*1d8f4dcbSJay /** refill write and meta write */ 195*1d8f4dcbSJay 196*1d8f4dcbSJay /** update coh meta */ 197*1d8f4dcbSJay def missCohGen(param: UInt, dirty: Bool): UInt = { 198*1d8f4dcbSJay MuxLookup(Cat(param, dirty), Nothing, Seq( 199*1d8f4dcbSJay Cat(toB, false.B) -> Branch, 200*1d8f4dcbSJay Cat(toB, true.B) -> Branch, 201*1d8f4dcbSJay Cat(toT, false.B) -> Trunk, 202*1d8f4dcbSJay Cat(toT, true.B) -> Dirty)) 203*1d8f4dcbSJay } 204*1d8f4dcbSJay 205*1d8f4dcbSJay val miss_new_coh = ClientMetadata(missCohGen(grant_param, is_dirty)) 206*1d8f4dcbSJay 207*1d8f4dcbSJay io.meta_write.valid := (state === s_write_back) 208*1d8f4dcbSJay io.meta_write.bits.generate(tag = req_tag, coh = miss_new_coh, idx = req_idx, waymask = req_waymask, bankIdx = req_idx(0)) 209*1d8f4dcbSJay 210*1d8f4dcbSJay io.data_write.valid := (state === s_write_back) 211*1d8f4dcbSJay io.data_write.bits.generate(data = respDataReg.asUInt, idx = req_idx, waymask = req_waymask, bankIdx = req_idx(0)) 212*1d8f4dcbSJay 213*1d8f4dcbSJay// io.release.valid := req.release.valid && (state === s_send_release) 214*1d8f4dcbSJay// io.release.bits := req.release.bits 215*1d8f4dcbSJay// 216*1d8f4dcbSJay// io.victimInfor.valid := state =/= s_idle 217*1d8f4dcbSJay// io.victimInfor.ptag := req_tag 218*1d8f4dcbSJay// io.victimInfor.vidx := req_idx 219*1d8f4dcbSJay 220*1d8f4dcbSJay /** Tilelink request for next level cache/memory */ 221*1d8f4dcbSJay val missCoh = ClientMetadata(Nothing) 222*1d8f4dcbSJay val grow_param = missCoh.onAccess(M_XRD)._2 223*1d8f4dcbSJay val acquireBlock = edge.AcquireBlock( 224*1d8f4dcbSJay fromSource = io.id, 225*1d8f4dcbSJay toAddress = addrAlign(req.paddr, blockBytes, PAddrBits), 226*1d8f4dcbSJay lgSize = (log2Up(cacheParams.blockBytes)).U, 227*1d8f4dcbSJay growPermissions = grow_param 228*1d8f4dcbSJay )._2 229*1d8f4dcbSJay io.mem_acquire.bits := acquireBlock 230*1d8f4dcbSJay // resolve cache alias by L2 231*1d8f4dcbSJay io.mem_acquire.bits.user.lift(AliasKey).foreach(_ := req.vaddr(13, 12)) 232*1d8f4dcbSJay require(nSets <= 256) // icache size should not be more than 128KB 233*1d8f4dcbSJay 234*1d8f4dcbSJay /** Grant ACK */ 235*1d8f4dcbSJay io.mem_finish.valid := (state === s_send_grant_ack) && is_grant 236*1d8f4dcbSJay io.mem_finish.bits := grantack 237*1d8f4dcbSJay 238*1d8f4dcbSJay //resp to ifu 239*1d8f4dcbSJay io.resp.valid := state === s_wait_resp 240*1d8f4dcbSJay 241*1d8f4dcbSJay XSPerfAccumulate( 242*1d8f4dcbSJay "entryPenalty" + Integer.toString(id, 10), 243*1d8f4dcbSJay BoolStopWatch( 244*1d8f4dcbSJay start = io.req.fire(), 245*1d8f4dcbSJay stop = io.resp.valid, 246*1d8f4dcbSJay startHighPriority = true) 247*1d8f4dcbSJay ) 248*1d8f4dcbSJay XSPerfAccumulate("entryReq" + Integer.toString(id, 10), io.req.fire()) 249*1d8f4dcbSJay 250*1d8f4dcbSJay} 251*1d8f4dcbSJay 252*1d8f4dcbSJay 253*1d8f4dcbSJayclass ICacheMissUnit(edge: TLEdgeOut)(implicit p: Parameters) extends ICacheMissUnitModule 254*1d8f4dcbSJay{ 255*1d8f4dcbSJay val io = IO(new Bundle{ 256*1d8f4dcbSJay val req = Vec(2, Flipped(DecoupledIO(new ICacheMissReq))) 257*1d8f4dcbSJay val resp = Vec(2, ValidIO(new ICacheMissResp)) 258*1d8f4dcbSJay 259*1d8f4dcbSJay val mem_acquire = DecoupledIO(new TLBundleA(edge.bundle)) 260*1d8f4dcbSJay val mem_grant = Flipped(DecoupledIO(new TLBundleD(edge.bundle))) 261*1d8f4dcbSJay val mem_finish = DecoupledIO(new TLBundleE(edge.bundle)) 262*1d8f4dcbSJay 263*1d8f4dcbSJay val meta_write = DecoupledIO(new ICacheMetaWriteBundle) 264*1d8f4dcbSJay val data_write = DecoupledIO(new ICacheDataWriteBundle) 265*1d8f4dcbSJay 266*1d8f4dcbSJay// val release = DecoupledIO(new ReleaseReq) 267*1d8f4dcbSJay 268*1d8f4dcbSJay// val victimInfor = Vec(2, Output(new ICacheVictimInfor())) 269*1d8f4dcbSJay// val probeMerge = Flipped(ValidIO(new ICacheVictimInfor)) 270*1d8f4dcbSJay }) 271*1d8f4dcbSJay // assign default values to output signals 272*1d8f4dcbSJay io.mem_grant.ready := false.B 273*1d8f4dcbSJay 274*1d8f4dcbSJay val meta_write_arb = Module(new Arbiter(new ICacheMetaWriteBundle, PortNumber)) 275*1d8f4dcbSJay val refill_arb = Module(new Arbiter(new ICacheDataWriteBundle, PortNumber)) 276*1d8f4dcbSJay //val release_arb = Module(new Arbiter(new ReleaseReq, PortNumber)) 277*1d8f4dcbSJay 278*1d8f4dcbSJay io.mem_grant.ready := true.B 279*1d8f4dcbSJay 280*1d8f4dcbSJay// val probeMergeFix = VecInit(Seq.fill(2)(WireInit(false.B))) 281*1d8f4dcbSJay// 282*1d8f4dcbSJay// val probeMerge = RegInit(0.U.asTypeOf(new ICacheVictimInfor)) 283*1d8f4dcbSJay// when(io.probeMerge.valid){ 284*1d8f4dcbSJay// probeMerge.ptag := io.probeMerge.bits.ptag 285*1d8f4dcbSJay// probeMerge.vidx := io.probeMerge.bits.vidx 286*1d8f4dcbSJay// probeMerge.valid := true.B 287*1d8f4dcbSJay// } 288*1d8f4dcbSJay// 289*1d8f4dcbSJay// when(probeMergeFix.reduce(_||_)){ 290*1d8f4dcbSJay// probeMerge.valid := false.B 291*1d8f4dcbSJay// } 292*1d8f4dcbSJay 293*1d8f4dcbSJay val entries = (0 until 2) map { i => 294*1d8f4dcbSJay val entry = Module(new ICacheMissEntry(edge, i)) 295*1d8f4dcbSJay 296*1d8f4dcbSJay entry.io.id := i.U 297*1d8f4dcbSJay 298*1d8f4dcbSJay // entry req 299*1d8f4dcbSJay entry.io.req.valid := io.req(i).valid 300*1d8f4dcbSJay entry.io.req.bits := io.req(i).bits 301*1d8f4dcbSJay io.req(i).ready := entry.io.req.ready 302*1d8f4dcbSJay 303*1d8f4dcbSJay// io.victimInfor(i) := entry.io.victimInfor 304*1d8f4dcbSJay// entry.io.probeMerge := probeMerge 305*1d8f4dcbSJay// 306*1d8f4dcbSJay// probeMergeFix(i) := entry.io.probeMergeFix 307*1d8f4dcbSJay 308*1d8f4dcbSJay // entry resp 309*1d8f4dcbSJay meta_write_arb.io.in(i) <> entry.io.meta_write 310*1d8f4dcbSJay refill_arb.io.in(i) <> entry.io.data_write 311*1d8f4dcbSJay //release_arb.io.in(i) <> entry.io.release 312*1d8f4dcbSJay 313*1d8f4dcbSJay entry.io.mem_grant.valid := false.B 314*1d8f4dcbSJay entry.io.mem_grant.bits := DontCare 315*1d8f4dcbSJay when (io.mem_grant.bits.source === i.U) { 316*1d8f4dcbSJay entry.io.mem_grant <> io.mem_grant 317*1d8f4dcbSJay } 318*1d8f4dcbSJay 319*1d8f4dcbSJay io.resp(i) <> entry.io.resp 320*1d8f4dcbSJay 321*1d8f4dcbSJay XSPerfAccumulate( 322*1d8f4dcbSJay "entryPenalty" + Integer.toString(i, 10), 323*1d8f4dcbSJay BoolStopWatch( 324*1d8f4dcbSJay start = entry.io.req.fire(), 325*1d8f4dcbSJay stop = entry.io.resp.fire(), 326*1d8f4dcbSJay startHighPriority = true) 327*1d8f4dcbSJay ) 328*1d8f4dcbSJay XSPerfAccumulate("entryReq" + Integer.toString(i, 10), entry.io.req.fire()) 329*1d8f4dcbSJay 330*1d8f4dcbSJay entry 331*1d8f4dcbSJay } 332*1d8f4dcbSJay 333*1d8f4dcbSJay TLArbiter.lowest(edge, io.mem_acquire, entries.map(_.io.mem_acquire):_*) 334*1d8f4dcbSJay TLArbiter.lowest(edge, io.mem_finish, entries.map(_.io.mem_finish):_*) 335*1d8f4dcbSJay 336*1d8f4dcbSJay io.meta_write <> meta_write_arb.io.out 337*1d8f4dcbSJay io.data_write <> refill_arb.io.out 338*1d8f4dcbSJay //io.release <> release_arb.io.out 339*1d8f4dcbSJay 340*1d8f4dcbSJay (0 until nWays).map{ w => 341*1d8f4dcbSJay XSPerfAccumulate("line_0_refill_way_" + Integer.toString(w, 10), entries(0).io.meta_write.valid && OHToUInt(entries(0).io.meta_write.bits.waymask) === w.U) 342*1d8f4dcbSJay XSPerfAccumulate("line_1_refill_way_" + Integer.toString(w, 10), entries(1).io.meta_write.valid && OHToUInt(entries(1).io.meta_write.bits.waymask) === w.U) 343*1d8f4dcbSJay } 344*1d8f4dcbSJay 345*1d8f4dcbSJay} 346*1d8f4dcbSJay 347*1d8f4dcbSJay 348*1d8f4dcbSJay 349