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, LazyModule, LazyModuleImp, TransferSizes} 23*1d8f4dcbSJayimport freechips.rocketchip.tilelink._ 24*1d8f4dcbSJayimport freechips.rocketchip.util.BundleFieldBase 25*1d8f4dcbSJayimport huancun.{AliasField, PreferCacheField, PrefetchField,DirtyField} 26*1d8f4dcbSJayimport xiangshan._ 27*1d8f4dcbSJayimport xiangshan.frontend._ 28*1d8f4dcbSJayimport xiangshan.cache._ 29*1d8f4dcbSJayimport utils._ 30*1d8f4dcbSJayimport xiangshan.cache.mmu.BlockTlbRequestIO 31*1d8f4dcbSJay 32*1d8f4dcbSJaycase class ICacheParameters( 33*1d8f4dcbSJay nSets: Int = 256, 34*1d8f4dcbSJay nWays: Int = 8, 35*1d8f4dcbSJay rowBits: Int = 64, 36*1d8f4dcbSJay nTLBEntries: Int = 32, 37*1d8f4dcbSJay tagECC: Option[String] = None, 38*1d8f4dcbSJay dataECC: Option[String] = None, 39*1d8f4dcbSJay replacer: Option[String] = Some("random"), 40*1d8f4dcbSJay nMissEntries: Int = 2, 41*1d8f4dcbSJay nReleaseEntries: Int = 2, 42*1d8f4dcbSJay nProbeEntries: Int = 2, 43*1d8f4dcbSJay nMMIOs: Int = 1, 44*1d8f4dcbSJay blockBytes: Int = 64 45*1d8f4dcbSJay)extends L1CacheParameters { 46*1d8f4dcbSJay 47*1d8f4dcbSJay val setBytes = nSets * blockBytes 48*1d8f4dcbSJay val aliasBitsOpt = if(setBytes > pageSize) Some(log2Ceil(setBytes / pageSize)) else None 49*1d8f4dcbSJay val reqFields: Seq[BundleFieldBase] = Seq( 50*1d8f4dcbSJay PrefetchField(), 51*1d8f4dcbSJay PreferCacheField() 52*1d8f4dcbSJay ) ++ aliasBitsOpt.map(AliasField) 53*1d8f4dcbSJay val echoFields: Seq[BundleFieldBase] = Seq(DirtyField()) 54*1d8f4dcbSJay def tagCode: Code = Code.fromString(tagECC) 55*1d8f4dcbSJay def dataCode: Code = Code.fromString(dataECC) 56*1d8f4dcbSJay def replacement = ReplacementPolicy.fromString(replacer,nWays,nSets) 57*1d8f4dcbSJay} 58*1d8f4dcbSJay 59*1d8f4dcbSJaytrait HasICacheParameters extends HasL1CacheParameters with HasInstrMMIOConst with HasIFUConst{ 60*1d8f4dcbSJay val cacheParams = icacheParameters 61*1d8f4dcbSJay val dataCodeUnit = 8 62*1d8f4dcbSJay val dataUnitNum = blockBits/dataCodeUnit 63*1d8f4dcbSJay 64*1d8f4dcbSJay def highestIdxBit = log2Ceil(nSets) - 1 65*1d8f4dcbSJay def dataCodeBits = cacheParams.dataCode.width(dataCodeUnit) 66*1d8f4dcbSJay def dataEntryBits = dataCodeBits * dataUnitNum 67*1d8f4dcbSJay 68*1d8f4dcbSJay val ICacheSets = cacheParams.nSets 69*1d8f4dcbSJay val ICacheWays = cacheParams.nWays 70*1d8f4dcbSJay 71*1d8f4dcbSJay val ICacheSameVPAddrLength = 12 72*1d8f4dcbSJay 73*1d8f4dcbSJay val ICacheWordOffset = 0 74*1d8f4dcbSJay val ICacheSetOffset = ICacheWordOffset + log2Up(blockBytes) 75*1d8f4dcbSJay val ICacheAboveIndexOffset = ICacheSetOffset + log2Up(ICacheSets) 76*1d8f4dcbSJay val ICacheTagOffset = ICacheAboveIndexOffset min ICacheSameVPAddrLength 77*1d8f4dcbSJay 78*1d8f4dcbSJay def ProbeKey = 0 79*1d8f4dcbSJay def FetchKey = 1 80*1d8f4dcbSJay def ReleaseKey = 2 81*1d8f4dcbSJay 82*1d8f4dcbSJay def PortNumber = 2 83*1d8f4dcbSJay 84*1d8f4dcbSJay def nMissEntries = cacheParams.nMissEntries 85*1d8f4dcbSJay 86*1d8f4dcbSJay require(isPow2(nMissEntries), s"nMissEntries($nMissEntries) must be pow2") 87*1d8f4dcbSJay require(isPow2(nSets), s"nSets($nSets) must be pow2") 88*1d8f4dcbSJay require(isPow2(nWays), s"nWays($nWays) must be pow2") 89*1d8f4dcbSJay} 90*1d8f4dcbSJay 91*1d8f4dcbSJayabstract class ICacheBundle(implicit p: Parameters) extends XSBundle 92*1d8f4dcbSJay with HasICacheParameters 93*1d8f4dcbSJay 94*1d8f4dcbSJayabstract class ICacheModule(implicit p: Parameters) extends XSModule 95*1d8f4dcbSJay with HasICacheParameters 96*1d8f4dcbSJay 97*1d8f4dcbSJayabstract class ICacheArray(implicit p: Parameters) extends XSModule 98*1d8f4dcbSJay with HasICacheParameters 99*1d8f4dcbSJay 100*1d8f4dcbSJayclass ICacheMetadata(implicit p: Parameters) extends ICacheBundle { 101*1d8f4dcbSJay val coh = new ClientMetadata 102*1d8f4dcbSJay val tag = UInt(tagBits.W) 103*1d8f4dcbSJay} 104*1d8f4dcbSJay 105*1d8f4dcbSJayobject ICacheMetadata { 106*1d8f4dcbSJay def apply(tag: Bits, coh: ClientMetadata)(implicit p: Parameters) = { 107*1d8f4dcbSJay val meta = Wire(new L1Metadata) 108*1d8f4dcbSJay meta.tag := tag 109*1d8f4dcbSJay meta.coh := coh 110*1d8f4dcbSJay meta 111*1d8f4dcbSJay } 112*1d8f4dcbSJay} 113*1d8f4dcbSJay 114*1d8f4dcbSJay 115*1d8f4dcbSJayclass ICacheMetaArray()(implicit p: Parameters) extends ICacheArray 116*1d8f4dcbSJay{ 117*1d8f4dcbSJay def onReset = ICacheMetadata(0.U, ClientMetadata.onReset) 118*1d8f4dcbSJay val metaBits = onReset.getWidth 119*1d8f4dcbSJay val metaEntryBits = cacheParams.tagCode.width(metaBits) 120*1d8f4dcbSJay 121*1d8f4dcbSJay val io=IO{new Bundle{ 122*1d8f4dcbSJay val write = Flipped(DecoupledIO(new ICacheMetaWriteBundle)) 123*1d8f4dcbSJay val read = Flipped(DecoupledIO(new ICacheReadBundle)) 124*1d8f4dcbSJay val readResp = Output(new ICacheMetaRespBundle) 125*1d8f4dcbSJay val fencei = Input(Bool()) 126*1d8f4dcbSJay val cacheOp = Flipped(new DCacheInnerOpIO) // customized cache op port 127*1d8f4dcbSJay }} 128*1d8f4dcbSJay 129*1d8f4dcbSJay io.read.ready := !io.write.valid 130*1d8f4dcbSJay 131*1d8f4dcbSJay val port_0_read_0 = io.read.valid && !io.read.bits.vSetIdx(0)(0) 132*1d8f4dcbSJay val port_0_read_1 = io.read.valid && io.read.bits.vSetIdx(0)(0) 133*1d8f4dcbSJay val port_1_read_1 = io.read.valid && io.read.bits.vSetIdx(1)(0) && io.read.bits.isDoubleLine 134*1d8f4dcbSJay val port_1_read_0 = io.read.valid && !io.read.bits.vSetIdx(1)(0) && io.read.bits.isDoubleLine 135*1d8f4dcbSJay 136*1d8f4dcbSJay val port_0_read_0_reg = RegEnable(next = port_0_read_0, enable = io.read.fire()) 137*1d8f4dcbSJay val port_0_read_1_reg = RegEnable(next = port_0_read_1, enable = io.read.fire()) 138*1d8f4dcbSJay val port_1_read_1_reg = RegEnable(next = port_1_read_1, enable = io.read.fire()) 139*1d8f4dcbSJay val port_1_read_0_reg = RegEnable(next = port_1_read_0, enable = io.read.fire()) 140*1d8f4dcbSJay 141*1d8f4dcbSJay val bank_0_idx = Mux(port_0_read_0, io.read.bits.vSetIdx(0), io.read.bits.vSetIdx(1)) 142*1d8f4dcbSJay val bank_1_idx = Mux(port_0_read_1, io.read.bits.vSetIdx(0), io.read.bits.vSetIdx(1)) 143*1d8f4dcbSJay 144*1d8f4dcbSJay val write_bank_0 = io.write.valid && !io.write.bits.bankIdx 145*1d8f4dcbSJay val write_bank_1 = io.write.valid && io.write.bits.bankIdx 146*1d8f4dcbSJay 147*1d8f4dcbSJay val write_meta_bits = Wire(UInt(metaEntryBits.W)) 148*1d8f4dcbSJay 149*1d8f4dcbSJay val tagArrays = (0 until 2) map { bank => 150*1d8f4dcbSJay val tagArray = Module(new SRAMTemplate( 151*1d8f4dcbSJay UInt(metaEntryBits.W), 152*1d8f4dcbSJay set=nSets/2, 153*1d8f4dcbSJay way=nWays, 154*1d8f4dcbSJay shouldReset = true, 155*1d8f4dcbSJay holdRead = true, 156*1d8f4dcbSJay singlePort = true 157*1d8f4dcbSJay )) 158*1d8f4dcbSJay 159*1d8f4dcbSJay //meta connection 160*1d8f4dcbSJay if(bank == 0) { 161*1d8f4dcbSJay tagArray.io.r.req.valid := port_0_read_0 || port_1_read_0 162*1d8f4dcbSJay tagArray.io.r.req.bits.apply(setIdx=bank_0_idx(highestIdxBit,1)) 163*1d8f4dcbSJay tagArray.io.w.req.valid := write_bank_0 164*1d8f4dcbSJay tagArray.io.w.req.bits.apply(data=write_meta_bits, setIdx=io.write.bits.virIdx(highestIdxBit,1), waymask=io.write.bits.waymask) 165*1d8f4dcbSJay } 166*1d8f4dcbSJay else { 167*1d8f4dcbSJay tagArray.io.r.req.valid := port_0_read_1 || port_1_read_1 168*1d8f4dcbSJay tagArray.io.r.req.bits.apply(setIdx=bank_1_idx(highestIdxBit,1)) 169*1d8f4dcbSJay tagArray.io.w.req.valid := write_bank_1 170*1d8f4dcbSJay tagArray.io.w.req.bits.apply(data=write_meta_bits, setIdx=io.write.bits.virIdx(highestIdxBit,1), waymask=io.write.bits.waymask) 171*1d8f4dcbSJay } 172*1d8f4dcbSJay 173*1d8f4dcbSJay tagArray 174*1d8f4dcbSJay } 175*1d8f4dcbSJay //Parity Decode 176*1d8f4dcbSJay val read_metas = Wire(Vec(2,Vec(nWays,new ICacheMetadata()))) 177*1d8f4dcbSJay for((tagArray,i) <- tagArrays.zipWithIndex){ 178*1d8f4dcbSJay val read_meta_bits = tagArray.io.r.resp.asTypeOf(Vec(nWays,UInt(metaEntryBits.W))) 179*1d8f4dcbSJay val read_meta_decoded = read_meta_bits.map{ way_bits => cacheParams.tagCode.decode(way_bits)} 180*1d8f4dcbSJay val read_meta_wrong = read_meta_decoded.map{ way_bits_decoded => way_bits_decoded.error} 181*1d8f4dcbSJay val read_meta_corrected = VecInit(read_meta_decoded.map{ way_bits_decoded => way_bits_decoded.corrected}) 182*1d8f4dcbSJay read_metas(i) := read_meta_corrected.asTypeOf(Vec(nWays,new ICacheMetadata())) 183*1d8f4dcbSJay (0 until nWays).map{ w => io.readResp.errors(i)(w) := RegNext(io.read.fire()) && read_meta_wrong(w)} 184*1d8f4dcbSJay } 185*1d8f4dcbSJay 186*1d8f4dcbSJay //Parity Encode 187*1d8f4dcbSJay val write = io.write.bits 188*1d8f4dcbSJay write_meta_bits := cacheParams.tagCode.encode(ICacheMetadata(tag = write.phyTag, coh = write.coh).asUInt) 189*1d8f4dcbSJay 190*1d8f4dcbSJay // when(io.write.valid){ 191*1d8f4dcbSJay // printf("[time:%d ] idx:%x ptag:%x waymask:%x coh:%x\n", GTimer().asUInt, write.virIdx, write.phyTag, write.waymask, write.coh.asUInt) 192*1d8f4dcbSJay // } 193*1d8f4dcbSJay 194*1d8f4dcbSJay val readIdxNext = RegEnable(next = io.read.bits.vSetIdx, enable = io.read.fire()) 195*1d8f4dcbSJay val validArray = RegInit(0.U((nSets * nWays).W)) 196*1d8f4dcbSJay val validMetas = VecInit((0 until 2).map{ bank => 197*1d8f4dcbSJay val validMeta = Cat((0 until nWays).map{w => validArray( Cat(readIdxNext(bank), w.U(log2Ceil(nWays).W)) )}.reverse).asUInt 198*1d8f4dcbSJay validMeta 199*1d8f4dcbSJay }) 200*1d8f4dcbSJay 201*1d8f4dcbSJay val wayNum = OHToUInt(io.write.bits.waymask) 202*1d8f4dcbSJay val validPtr = Cat(io.write.bits.virIdx, wayNum) 203*1d8f4dcbSJay when(io.write.valid){ 204*1d8f4dcbSJay validArray := validArray.bitSet(validPtr, true.B) 205*1d8f4dcbSJay } 206*1d8f4dcbSJay 207*1d8f4dcbSJay when(io.fencei){ validArray := 0.U } 208*1d8f4dcbSJay 209*1d8f4dcbSJay io.readResp.metaData <> DontCare 210*1d8f4dcbSJay when(port_0_read_0_reg){ 211*1d8f4dcbSJay io.readResp.metaData(0) := read_metas(0) 212*1d8f4dcbSJay }.elsewhen(port_0_read_1_reg){ 213*1d8f4dcbSJay io.readResp.metaData(0) := read_metas(1) 214*1d8f4dcbSJay } 215*1d8f4dcbSJay 216*1d8f4dcbSJay when(port_1_read_0_reg){ 217*1d8f4dcbSJay io.readResp.metaData(1) := read_metas(0) 218*1d8f4dcbSJay }.elsewhen(port_1_read_1_reg){ 219*1d8f4dcbSJay io.readResp.metaData(1) := read_metas(1) 220*1d8f4dcbSJay } 221*1d8f4dcbSJay 222*1d8f4dcbSJay (io.readResp.valid zip validMetas).map {case (io, reg) => io := reg.asTypeOf(Vec(nWays,Bool()))} 223*1d8f4dcbSJay 224*1d8f4dcbSJay io.write.ready := true.B 225*1d8f4dcbSJay // deal with customized cache op 226*1d8f4dcbSJay require(nWays <= 32) 227*1d8f4dcbSJay io.cacheOp.resp.bits := DontCare 228*1d8f4dcbSJay val cacheOpShouldResp = WireInit(false.B) 229*1d8f4dcbSJay when(io.cacheOp.req.valid){ 230*1d8f4dcbSJay when( 231*1d8f4dcbSJay CacheInstrucion.isReadTag(io.cacheOp.req.bits.opCode) || 232*1d8f4dcbSJay CacheInstrucion.isReadTagECC(io.cacheOp.req.bits.opCode) 233*1d8f4dcbSJay ){ 234*1d8f4dcbSJay for (i <- 0 until 2) { 235*1d8f4dcbSJay tagArrays(i).io.r.req.valid := true.B 236*1d8f4dcbSJay tagArrays(i).io.r.req.bits.apply(setIdx = io.cacheOp.req.bits.index) 237*1d8f4dcbSJay } 238*1d8f4dcbSJay cacheOpShouldResp := true.B 239*1d8f4dcbSJay } 240*1d8f4dcbSJay when(CacheInstrucion.isWriteTag(io.cacheOp.req.bits.opCode)){ 241*1d8f4dcbSJay for (i <- 0 until 2) { 242*1d8f4dcbSJay tagArrays(i).io.w.req.valid := true.B 243*1d8f4dcbSJay tagArrays(i).io.w.req.bits.apply( 244*1d8f4dcbSJay data = io.cacheOp.req.bits.write_tag_low, 245*1d8f4dcbSJay setIdx = io.cacheOp.req.bits.index, 246*1d8f4dcbSJay waymask = UIntToOH(io.cacheOp.req.bits.wayNum(4, 0)) 247*1d8f4dcbSJay ) 248*1d8f4dcbSJay } 249*1d8f4dcbSJay cacheOpShouldResp := true.B 250*1d8f4dcbSJay } 251*1d8f4dcbSJay // TODO 252*1d8f4dcbSJay // when(CacheInstrucion.isWriteTagECC(io.cacheOp.req.bits.opCode)){ 253*1d8f4dcbSJay // for (i <- 0 until readPorts) { 254*1d8f4dcbSJay // array(i).io.ecc_write.valid := true.B 255*1d8f4dcbSJay // array(i).io.ecc_write.bits.idx := io.cacheOp.req.bits.index 256*1d8f4dcbSJay // array(i).io.ecc_write.bits.way_en := UIntToOH(io.cacheOp.req.bits.wayNum(4, 0)) 257*1d8f4dcbSJay // array(i).io.ecc_write.bits.ecc := io.cacheOp.req.bits.write_tag_ecc 258*1d8f4dcbSJay // } 259*1d8f4dcbSJay // cacheOpShouldResp := true.B 260*1d8f4dcbSJay // } 261*1d8f4dcbSJay } 262*1d8f4dcbSJay io.cacheOp.resp.valid := RegNext(io.cacheOp.req.valid && cacheOpShouldResp) 263*1d8f4dcbSJay io.cacheOp.resp.bits.read_tag_low := Mux(io.cacheOp.resp.valid, 264*1d8f4dcbSJay tagArrays(0).io.r.resp.asTypeOf(Vec(nWays, UInt(tagBits.W)))(io.cacheOp.req.bits.wayNum), 265*1d8f4dcbSJay 0.U 266*1d8f4dcbSJay ) 267*1d8f4dcbSJay io.cacheOp.resp.bits.read_tag_ecc := DontCare // TODO 268*1d8f4dcbSJay // TODO: deal with duplicated array 269*1d8f4dcbSJay} 270*1d8f4dcbSJay 271*1d8f4dcbSJay 272*1d8f4dcbSJayclass ICacheDataArray(implicit p: Parameters) extends ICacheArray 273*1d8f4dcbSJay{ 274*1d8f4dcbSJay val io=IO{new Bundle{ 275*1d8f4dcbSJay val write = Flipped(DecoupledIO(new ICacheDataWriteBundle)) 276*1d8f4dcbSJay val read = Flipped(DecoupledIO(new ICacheReadBundle)) 277*1d8f4dcbSJay val readResp = Output(new ICacheDataRespBundle) 278*1d8f4dcbSJay val cacheOp = Flipped(new DCacheInnerOpIO) // customized cache op port 279*1d8f4dcbSJay }} 280*1d8f4dcbSJay 281*1d8f4dcbSJay io.read.ready := !io.write.valid 282*1d8f4dcbSJay 283*1d8f4dcbSJay val port_0_read_0 = io.read.valid && !io.read.bits.vSetIdx(0)(0) 284*1d8f4dcbSJay val port_0_read_1 = io.read.valid && io.read.bits.vSetIdx(0)(0) 285*1d8f4dcbSJay val port_1_read_1 = io.read.valid && io.read.bits.vSetIdx(1)(0) && io.read.bits.isDoubleLine 286*1d8f4dcbSJay val port_1_read_0 = io.read.valid && !io.read.bits.vSetIdx(1)(0) && io.read.bits.isDoubleLine 287*1d8f4dcbSJay 288*1d8f4dcbSJay val port_0_read_1_reg = RegEnable(next = port_0_read_1, enable = io.read.fire()) 289*1d8f4dcbSJay val port_1_read_0_reg = RegEnable(next = port_1_read_0, enable = io.read.fire()) 290*1d8f4dcbSJay 291*1d8f4dcbSJay val bank_0_idx = Mux(port_0_read_0, io.read.bits.vSetIdx(0), io.read.bits.vSetIdx(1)) 292*1d8f4dcbSJay val bank_1_idx = Mux(port_0_read_1, io.read.bits.vSetIdx(0), io.read.bits.vSetIdx(1)) 293*1d8f4dcbSJay 294*1d8f4dcbSJay val write_bank_0 = io.write.valid && !io.write.bits.bankIdx 295*1d8f4dcbSJay val write_bank_1 = io.write.valid && io.write.bits.bankIdx 296*1d8f4dcbSJay 297*1d8f4dcbSJay val write_data_bits = Wire(UInt(dataEntryBits.W)) 298*1d8f4dcbSJay 299*1d8f4dcbSJay val dataArrays = (0 until 2) map { i => 300*1d8f4dcbSJay val dataArray = Module(new SRAMTemplate( 301*1d8f4dcbSJay UInt(dataEntryBits.W), 302*1d8f4dcbSJay set=nSets/2, 303*1d8f4dcbSJay way=nWays, 304*1d8f4dcbSJay shouldReset = true, 305*1d8f4dcbSJay holdRead = true, 306*1d8f4dcbSJay singlePort = true 307*1d8f4dcbSJay )) 308*1d8f4dcbSJay 309*1d8f4dcbSJay if(i == 0) { 310*1d8f4dcbSJay dataArray.io.r.req.valid := port_0_read_0 || port_1_read_0 311*1d8f4dcbSJay dataArray.io.r.req.bits.apply(setIdx=bank_0_idx(highestIdxBit,1)) 312*1d8f4dcbSJay dataArray.io.w.req.valid := write_bank_0 313*1d8f4dcbSJay dataArray.io.w.req.bits.apply(data=write_data_bits, setIdx=io.write.bits.virIdx(highestIdxBit,1), waymask=io.write.bits.waymask) 314*1d8f4dcbSJay } 315*1d8f4dcbSJay else { 316*1d8f4dcbSJay dataArray.io.r.req.valid := port_0_read_1 || port_1_read_1 317*1d8f4dcbSJay dataArray.io.r.req.bits.apply(setIdx=bank_1_idx(highestIdxBit,1)) 318*1d8f4dcbSJay dataArray.io.w.req.valid := write_bank_1 319*1d8f4dcbSJay dataArray.io.w.req.bits.apply(data=write_data_bits, setIdx=io.write.bits.virIdx(highestIdxBit,1), waymask=io.write.bits.waymask) 320*1d8f4dcbSJay } 321*1d8f4dcbSJay 322*1d8f4dcbSJay dataArray 323*1d8f4dcbSJay } 324*1d8f4dcbSJay 325*1d8f4dcbSJay //Parity Decode 326*1d8f4dcbSJay val read_datas = Wire(Vec(2,Vec(nWays,UInt(blockBits.W) ))) 327*1d8f4dcbSJay for((dataArray,i) <- dataArrays.zipWithIndex){ 328*1d8f4dcbSJay val read_data_bits = dataArray.io.r.resp.asTypeOf(Vec(nWays,Vec(dataUnitNum, UInt(dataCodeBits.W)))) 329*1d8f4dcbSJay val read_data_decoded = read_data_bits.map{way_bits => way_bits.map(unit => cacheParams.dataCode.decode(unit))} 330*1d8f4dcbSJay val read_data_wrong = VecInit(read_data_decoded.map{way_bits_decoded => VecInit(way_bits_decoded.map(unit_decoded => unit_decoded.error ))}) 331*1d8f4dcbSJay val read_data_corrected = VecInit(read_data_decoded.map{way_bits_decoded => VecInit(way_bits_decoded.map(unit_decoded => unit_decoded.corrected )).asUInt}) 332*1d8f4dcbSJay read_datas(i) := read_data_corrected.asTypeOf(Vec(nWays,UInt(blockBits.W))) 333*1d8f4dcbSJay (0 until nWays).map{ w => io.readResp.errors(i)(w) := RegNext(io.read.fire()) && read_data_wrong(w).asUInt.orR } 334*1d8f4dcbSJay } 335*1d8f4dcbSJay 336*1d8f4dcbSJay //Parity Encode 337*1d8f4dcbSJay val write = io.write.bits 338*1d8f4dcbSJay val write_data = write.data.asTypeOf(Vec(dataUnitNum, UInt(dataCodeUnit.W))) 339*1d8f4dcbSJay val write_data_encoded = VecInit(write_data.map( unit_bits => cacheParams.dataCode.encode(unit_bits) )) 340*1d8f4dcbSJay write_data_bits := write_data_encoded.asUInt 341*1d8f4dcbSJay 342*1d8f4dcbSJay io.readResp.datas(0) := Mux( port_0_read_1_reg, read_datas(1) , read_datas(0)) 343*1d8f4dcbSJay io.readResp.datas(1) := Mux( port_1_read_0_reg, read_datas(0) , read_datas(1)) 344*1d8f4dcbSJay 345*1d8f4dcbSJay io.write.ready := true.B 346*1d8f4dcbSJay 347*1d8f4dcbSJay // deal with customized cache op 348*1d8f4dcbSJay require(nWays <= 32) 349*1d8f4dcbSJay io.cacheOp.resp.bits := DontCare 350*1d8f4dcbSJay val cacheOpShouldResp = WireInit(false.B) 351*1d8f4dcbSJay when(io.cacheOp.req.valid){ 352*1d8f4dcbSJay when( 353*1d8f4dcbSJay CacheInstrucion.isReadData(io.cacheOp.req.bits.opCode) || 354*1d8f4dcbSJay CacheInstrucion.isReadDataECC(io.cacheOp.req.bits.opCode) 355*1d8f4dcbSJay ){ 356*1d8f4dcbSJay (0 until 2).map(i => { 357*1d8f4dcbSJay dataArrays(i).io.r.req.valid := true.B 358*1d8f4dcbSJay dataArrays(i).io.r.req.bits.apply(setIdx = io.cacheOp.req.bits.index) 359*1d8f4dcbSJay }) 360*1d8f4dcbSJay cacheOpShouldResp := true.B 361*1d8f4dcbSJay } 362*1d8f4dcbSJay when(CacheInstrucion.isWriteData(io.cacheOp.req.bits.opCode)){ 363*1d8f4dcbSJay (0 until 2).map(i => { 364*1d8f4dcbSJay dataArrays(i).io.w.req.valid := io.cacheOp.req.bits.bank_num === i.U 365*1d8f4dcbSJay dataArrays(i).io.w.req.bits.apply( 366*1d8f4dcbSJay data = io.cacheOp.req.bits.write_data_vec.asUInt, 367*1d8f4dcbSJay setIdx = io.cacheOp.req.bits.index, 368*1d8f4dcbSJay waymask = UIntToOH(io.cacheOp.req.bits.wayNum(4, 0)) 369*1d8f4dcbSJay ) 370*1d8f4dcbSJay }) 371*1d8f4dcbSJay cacheOpShouldResp := true.B 372*1d8f4dcbSJay } 373*1d8f4dcbSJay // when(CacheInstrucion.isWriteDataECC(io.cacheOp.req.bits.opCode)){ 374*1d8f4dcbSJay // for (bank_index <- 0 until DCacheBanks) { 375*1d8f4dcbSJay // val ecc_bank = ecc_banks(bank_index) 376*1d8f4dcbSJay // ecc_bank.io.w.req.valid := true.B 377*1d8f4dcbSJay // ecc_bank.io.w.req.bits.apply( 378*1d8f4dcbSJay // setIdx = io.cacheOp.req.bits.index, 379*1d8f4dcbSJay // data = io.cacheOp.req.bits.write_data_ecc, 380*1d8f4dcbSJay // waymask = UIntToOH(io.cacheOp.req.bits.wayNum(4, 0)) 381*1d8f4dcbSJay // ) 382*1d8f4dcbSJay // } 383*1d8f4dcbSJay // cacheOpShouldResp := true.B 384*1d8f4dcbSJay // } 385*1d8f4dcbSJay } 386*1d8f4dcbSJay io.cacheOp.resp.valid := RegNext(io.cacheOp.req.valid && cacheOpShouldResp) 387*1d8f4dcbSJay val dataresp = Mux(io.cacheOp.req.bits.bank_num(0).asBool, 388*1d8f4dcbSJay dataArrays(0).io.r.resp.data.asTypeOf(Vec(nWays, UInt(blockBits.W))), 389*1d8f4dcbSJay dataArrays(1).io.r.resp.data.asTypeOf(Vec(nWays, UInt(blockBits.W))) 390*1d8f4dcbSJay ) 391*1d8f4dcbSJay 392*1d8f4dcbSJay val numICacheLineWords = blockBits / 64 393*1d8f4dcbSJay require(blockBits >= 64 && isPow2(blockBits)) 394*1d8f4dcbSJay for (wordIndex <- 0 until numICacheLineWords) { 395*1d8f4dcbSJay io.cacheOp.resp.bits.read_data_vec(wordIndex) := dataresp(io.cacheOp.req.bits.wayNum(4, 0))(64*(wordIndex+1)-1, 64*wordIndex) 396*1d8f4dcbSJay } 397*1d8f4dcbSJay // io.cacheOp.resp.bits.read_data_ecc := Mux(io.cacheOp.resp.valid, 398*1d8f4dcbSJay // bank_result(io.cacheOp.req.bits.bank_num).ecc, 399*1d8f4dcbSJay // 0.U 400*1d8f4dcbSJay // ) 401*1d8f4dcbSJay} 402*1d8f4dcbSJay 403*1d8f4dcbSJay 404*1d8f4dcbSJayclass ICacheIO(implicit p: Parameters) extends ICacheBundle 405*1d8f4dcbSJay{ 406*1d8f4dcbSJay val fencei = Input(Bool()) 407*1d8f4dcbSJay val stop = Input(Bool()) 408*1d8f4dcbSJay val csr = new L1CacheToCsrIO 409*1d8f4dcbSJay val fetch = Vec(PortNumber, new ICacheMainPipeBundle) 410*1d8f4dcbSJay val pmp = Vec(PortNumber, new ICachePMPBundle) 411*1d8f4dcbSJay val itlb = Vec(PortNumber, new BlockTlbRequestIO) 412*1d8f4dcbSJay val perfInfo = Output(new ICachePerfInfo) 413*1d8f4dcbSJay} 414*1d8f4dcbSJay 415*1d8f4dcbSJayclass ICache()(implicit p: Parameters) extends LazyModule with HasICacheParameters { 416*1d8f4dcbSJay 417*1d8f4dcbSJay val clientParameters = TLMasterPortParameters.v1( 418*1d8f4dcbSJay Seq(TLMasterParameters.v1( 419*1d8f4dcbSJay name = "icache", 420*1d8f4dcbSJay sourceId = IdRange(0, cacheParams.nMissEntries + cacheParams.nReleaseEntries), 421*1d8f4dcbSJay supportsProbe = TransferSizes(blockBytes) 422*1d8f4dcbSJay )), 423*1d8f4dcbSJay requestFields = cacheParams.reqFields, 424*1d8f4dcbSJay echoFields = cacheParams.echoFields 425*1d8f4dcbSJay ) 426*1d8f4dcbSJay 427*1d8f4dcbSJay val clientNode = TLClientNode(Seq(clientParameters)) 428*1d8f4dcbSJay 429*1d8f4dcbSJay lazy val module = new ICacheImp(this) 430*1d8f4dcbSJay} 431*1d8f4dcbSJay 432*1d8f4dcbSJayclass ICacheImp(outer: ICache) extends LazyModuleImp(outer) with HasICacheParameters { 433*1d8f4dcbSJay val io = IO(new ICacheIO) 434*1d8f4dcbSJay 435*1d8f4dcbSJay val (bus, edge) = outer.clientNode.out.head 436*1d8f4dcbSJay 437*1d8f4dcbSJay val metaArray = Module(new ICacheMetaArray) 438*1d8f4dcbSJay val dataArray = Module(new ICacheDataArray) 439*1d8f4dcbSJay val mainpipe = Module(new ICacheMainPipe) 440*1d8f4dcbSJay val missUnit = Module(new ICacheMissUnit(edge)) 441*1d8f4dcbSJay val releaseUnit = Module(new ReleaseUnit(edge)) 442*1d8f4dcbSJay val probe = Module(new ICacheProbe) 443*1d8f4dcbSJay val probeQueue = Module(new ICacheProbeQueue(edge)) 444*1d8f4dcbSJay 445*1d8f4dcbSJay 446*1d8f4dcbSJay val meta_read_arb = Module(new Arbiter(new ICacheReadBundle, 2)) 447*1d8f4dcbSJay val data_read_arb = Module(new Arbiter(new ICacheReadBundle, 2)) 448*1d8f4dcbSJay val meta_write_arb = Module(new Arbiter(new ICacheMetaWriteBundle(), 2 + 1)) 449*1d8f4dcbSJay val release_arb = Module(new Arbiter(new ReleaseReq, 2)) 450*1d8f4dcbSJay 451*1d8f4dcbSJay meta_read_arb.io.in(ProbeKey) <> probe.io.meta_read 452*1d8f4dcbSJay meta_read_arb.io.in(FetchKey) <> mainpipe.io.metaArray.toIMeta 453*1d8f4dcbSJay metaArray.io.read <> meta_read_arb.io.out 454*1d8f4dcbSJay probe.io.meta_response <> metaArray.io.readResp 455*1d8f4dcbSJay mainpipe.io.metaArray.fromIMeta <> metaArray.io.readResp 456*1d8f4dcbSJay 457*1d8f4dcbSJay data_read_arb.io.in(ProbeKey) <> probe.io.data_read 458*1d8f4dcbSJay data_read_arb.io.in(FetchKey) <> mainpipe.io.dataArray.toIData 459*1d8f4dcbSJay dataArray.io.read <> data_read_arb.io.out 460*1d8f4dcbSJay probe.io.data_response <> dataArray.io.readResp 461*1d8f4dcbSJay mainpipe.io.dataArray.fromIData <> dataArray.io.readResp 462*1d8f4dcbSJay 463*1d8f4dcbSJay mainpipe.io.respStall := io.stop 464*1d8f4dcbSJay io.perfInfo := mainpipe.io.perfInfo 465*1d8f4dcbSJay 466*1d8f4dcbSJay meta_write_arb.io.in(FetchKey) <> missUnit.io.meta_write 467*1d8f4dcbSJay meta_write_arb.io.in(ProbeKey) <> probe.io.meta_write 468*1d8f4dcbSJay meta_write_arb.io.in(ReleaseKey) <> releaseUnit.io.release_meta_write 469*1d8f4dcbSJay 470*1d8f4dcbSJay metaArray.io.write <> meta_write_arb.io.out 471*1d8f4dcbSJay dataArray.io.write <> missUnit.io.data_write 472*1d8f4dcbSJay 473*1d8f4dcbSJay 474*1d8f4dcbSJay release_arb.io.in(1) <> probe.io.release_req 475*1d8f4dcbSJay release_arb.io.in(0) <> mainpipe.io.toReleaseUnit(0)//probe.io.release_req 476*1d8f4dcbSJay 477*1d8f4dcbSJay io.itlb <> mainpipe.io.itlb 478*1d8f4dcbSJay io.pmp <> mainpipe.io.pmp 479*1d8f4dcbSJay for(i <- 0 until PortNumber){ 480*1d8f4dcbSJay io.fetch(i).resp <> mainpipe.io.fetch(i).resp 481*1d8f4dcbSJay 482*1d8f4dcbSJay missUnit.io.req(i) <> mainpipe.io.mshr(i).toMSHR 483*1d8f4dcbSJay mainpipe.io.mshr(i).fromMSHR <> missUnit.io.resp(i) 484*1d8f4dcbSJay 485*1d8f4dcbSJay } 486*1d8f4dcbSJay 487*1d8f4dcbSJay bus.b.ready := false.B 488*1d8f4dcbSJay bus.c.valid := false.B 489*1d8f4dcbSJay bus.c.bits := DontCare 490*1d8f4dcbSJay bus.e.valid := false.B 491*1d8f4dcbSJay bus.e.bits := DontCare 492*1d8f4dcbSJay 493*1d8f4dcbSJay metaArray.io.fencei := io.fencei 494*1d8f4dcbSJay bus.a <> missUnit.io.mem_acquire 495*1d8f4dcbSJay bus.e <> missUnit.io.mem_finish 496*1d8f4dcbSJay 497*1d8f4dcbSJay releaseUnit.io.req(0) <> release_arb.io.out 498*1d8f4dcbSJay releaseUnit.io.req(1) <> mainpipe.io.toReleaseUnit(1) 499*1d8f4dcbSJay bus.c <> releaseUnit.io.mem_release 500*1d8f4dcbSJay 501*1d8f4dcbSJay // connect bus d 502*1d8f4dcbSJay missUnit.io.mem_grant.valid := false.B 503*1d8f4dcbSJay missUnit.io.mem_grant.bits := DontCare 504*1d8f4dcbSJay 505*1d8f4dcbSJay releaseUnit.io.mem_grant.valid := false.B 506*1d8f4dcbSJay releaseUnit.io.mem_grant.bits := DontCare 507*1d8f4dcbSJay 508*1d8f4dcbSJay //Probe through bus b 509*1d8f4dcbSJay probeQueue.io.mem_probe <> bus.b 510*1d8f4dcbSJay probe.io.req <> probeQueue.io.pipe_req 511*1d8f4dcbSJay 512*1d8f4dcbSJay val hasVictim = VecInit(Seq( 513*1d8f4dcbSJay mainpipe.io.victimInfor.s1(0).valid, 514*1d8f4dcbSJay mainpipe.io.victimInfor.s1(1).valid, 515*1d8f4dcbSJay mainpipe.io.victimInfor.s2(0).valid, 516*1d8f4dcbSJay mainpipe.io.victimInfor.s2(1).valid 517*1d8f4dcbSJay )) 518*1d8f4dcbSJay 519*1d8f4dcbSJay val victimSetSeq = Seq( 520*1d8f4dcbSJay mainpipe.io.victimInfor.s1(0).vidx, 521*1d8f4dcbSJay mainpipe.io.victimInfor.s1(1).vidx, 522*1d8f4dcbSJay mainpipe.io.victimInfor.s2(0).vidx, 523*1d8f4dcbSJay mainpipe.io.victimInfor.s2(1).vidx 524*1d8f4dcbSJay ) 525*1d8f4dcbSJay 526*1d8f4dcbSJay val victimTagSeq = Seq( 527*1d8f4dcbSJay mainpipe.io.victimInfor.s1(0).ptag, 528*1d8f4dcbSJay mainpipe.io.victimInfor.s1(1).ptag, 529*1d8f4dcbSJay mainpipe.io.victimInfor.s2(0).ptag, 530*1d8f4dcbSJay mainpipe.io.victimInfor.s2(1).ptag 531*1d8f4dcbSJay ) 532*1d8f4dcbSJay 533*1d8f4dcbSJay val probeReqValid = probe.io.req.valid 534*1d8f4dcbSJay val probeReqPtag = get_phy_tag(probe.io.req.bits.addr) 535*1d8f4dcbSJay val probeReqVidx = get_idx(probe.io.req.bits.vaddr) 536*1d8f4dcbSJay 537*1d8f4dcbSJay //send to probe state machine and cancel the probe 538*1d8f4dcbSJay val probe_need_merge = VecInit(hasVictim.zip(victimSetSeq).zip(victimTagSeq).map{case((valid, idx), tag) => valid && probeReqValid && idx === probeReqVidx && tag === probeReqPtag}).reduce(_||_) 539*1d8f4dcbSJay probe.io.probe_should_merge := RegNext(probe_need_merge) 540*1d8f4dcbSJay 541*1d8f4dcbSJay val hasMiss = VecInit(Seq( 542*1d8f4dcbSJay mainpipe.io.setInfor.s1(0).valid, 543*1d8f4dcbSJay mainpipe.io.setInfor.s1(1).valid, 544*1d8f4dcbSJay mainpipe.io.setInfor.s2(0).valid, 545*1d8f4dcbSJay mainpipe.io.setInfor.s2(1).valid 546*1d8f4dcbSJay )) 547*1d8f4dcbSJay 548*1d8f4dcbSJay val missSetSeq = Seq( 549*1d8f4dcbSJay mainpipe.io.setInfor.s1(0).vidx, 550*1d8f4dcbSJay mainpipe.io.setInfor.s1(1).vidx, 551*1d8f4dcbSJay mainpipe.io.setInfor.s2(0).vidx, 552*1d8f4dcbSJay mainpipe.io.setInfor.s2(1).vidx 553*1d8f4dcbSJay ) 554*1d8f4dcbSJay 555*1d8f4dcbSJay val fetchReq = io.fetch.map(_.req) 556*1d8f4dcbSJay val fetchShouldBlock = VecInit(fetchReq.map(req => VecInit(hasMiss.zip(missSetSeq).map{case(valid, idx)=> valid && idx === req.bits.vsetIdx}).reduce(_||_))) 557*1d8f4dcbSJay 558*1d8f4dcbSJay (0 until PortNumber).map{i => 559*1d8f4dcbSJay mainpipe.io.fetch(i).req.valid := io.fetch(i).req.valid && !fetchShouldBlock(i) 560*1d8f4dcbSJay io.fetch(i).req.ready := mainpipe.io.fetch(i).req.ready && !fetchShouldBlock(i) 561*1d8f4dcbSJay mainpipe.io.fetch(i).req.bits := io.fetch(i).req.bits 562*1d8f4dcbSJay } 563*1d8f4dcbSJay 564*1d8f4dcbSJay 565*1d8f4dcbSJay //raise a flag to inform the MissUnit you have a merged Probe 566*1d8f4dcbSJay releaseUnit.io.probeMerge.valid := probe_need_merge 567*1d8f4dcbSJay releaseUnit.io.probeMerge.bits.valid := DontCare 568*1d8f4dcbSJay releaseUnit.io.probeMerge.bits.ptag := probeReqPtag 569*1d8f4dcbSJay releaseUnit.io.probeMerge.bits.vidx := probeReqVidx 570*1d8f4dcbSJay 571*1d8f4dcbSJay // in L1ICache, we only expect GrantData and ReleaseAck 572*1d8f4dcbSJay bus.d.ready := false.B 573*1d8f4dcbSJay when ( bus.d.bits.opcode === TLMessages.GrantData) { 574*1d8f4dcbSJay missUnit.io.mem_grant <> bus.d 575*1d8f4dcbSJay } .elsewhen (bus.d.bits.opcode === TLMessages.ReleaseAck) { 576*1d8f4dcbSJay releaseUnit.io.mem_grant <> bus.d 577*1d8f4dcbSJay } .otherwise { 578*1d8f4dcbSJay assert (!bus.d.fire()) 579*1d8f4dcbSJay } 580*1d8f4dcbSJay 581*1d8f4dcbSJay val perfinfo = IO(new Bundle(){ 582*1d8f4dcbSJay val perfEvents = Output(new PerfEventsBundle(2)) 583*1d8f4dcbSJay }) 584*1d8f4dcbSJay val perfEvents = Seq( 585*1d8f4dcbSJay ("icache_miss_cnt ", false.B ), 586*1d8f4dcbSJay ("icache_miss_penty ", BoolStopWatch(start = false.B, stop = false.B || false.B, startHighPriority = true) ), 587*1d8f4dcbSJay ) 588*1d8f4dcbSJay 589*1d8f4dcbSJay // Customized csr cache op support 590*1d8f4dcbSJay val cacheOpDecoder = Module(new CSRCacheOpDecoder("icache", CacheInstrucion.COP_ID_ICACHE)) 591*1d8f4dcbSJay cacheOpDecoder.io.csr <> io.csr 592*1d8f4dcbSJay dataArray.io.cacheOp.req := cacheOpDecoder.io.cache.req 593*1d8f4dcbSJay metaArray.io.cacheOp.req := cacheOpDecoder.io.cache.req 594*1d8f4dcbSJay cacheOpDecoder.io.cache.resp.valid := 595*1d8f4dcbSJay dataArray.io.cacheOp.resp.valid || 596*1d8f4dcbSJay metaArray.io.cacheOp.resp.valid 597*1d8f4dcbSJay cacheOpDecoder.io.cache.resp.bits := Mux1H(List( 598*1d8f4dcbSJay dataArray.io.cacheOp.resp.valid -> dataArray.io.cacheOp.resp.bits, 599*1d8f4dcbSJay metaArray.io.cacheOp.resp.valid -> metaArray.io.cacheOp.resp.bits, 600*1d8f4dcbSJay )) 601*1d8f4dcbSJay assert(!((dataArray.io.cacheOp.resp.valid +& metaArray.io.cacheOp.resp.valid) > 1.U)) 602*1d8f4dcbSJay 603*1d8f4dcbSJay}