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