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 = io.write.valid && !io.write.bits.bankIdx 310 val write_bank_1 = 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 = 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.apply( 381 data = io.cacheOp.req.bits.write_data_vec.asUInt, 382 setIdx = io.cacheOp.req.bits.index, 383 waymask = UIntToOH(io.cacheOp.req.bits.wayNum(4, 0)) 384 ) 385 }) 386 cacheOpShouldResp := true.B 387 } 388 // when(CacheInstrucion.isWriteDataECC(io.cacheOp.req.bits.opCode)){ 389 // for (bank_index <- 0 until DCacheBanks) { 390 // val ecc_bank = ecc_banks(bank_index) 391 // ecc_bank.io.w.req.valid := true.B 392 // ecc_bank.io.w.req.bits.apply( 393 // setIdx = io.cacheOp.req.bits.index, 394 // data = io.cacheOp.req.bits.write_data_ecc, 395 // waymask = UIntToOH(io.cacheOp.req.bits.wayNum(4, 0)) 396 // ) 397 // } 398 // cacheOpShouldResp := true.B 399 // } 400 } 401 io.cacheOp.resp.valid := RegNext(io.cacheOp.req.valid && cacheOpShouldResp) 402 val dataresp = Mux(io.cacheOp.req.bits.bank_num(0).asBool, 403 dataArrays(0).io.r.resp.data.asTypeOf(Vec(nWays, UInt(blockBits.W))), 404 dataArrays(1).io.r.resp.data.asTypeOf(Vec(nWays, UInt(blockBits.W))) 405 ) 406 407 val numICacheLineWords = blockBits / 64 408 require(blockBits >= 64 && isPow2(blockBits)) 409 for (wordIndex <- 0 until numICacheLineWords) { 410 io.cacheOp.resp.bits.read_data_vec(wordIndex) := dataresp(io.cacheOp.req.bits.wayNum(4, 0))(64*(wordIndex+1)-1, 64*wordIndex) 411 } 412 // io.cacheOp.resp.bits.read_data_ecc := Mux(io.cacheOp.resp.valid, 413 // bank_result(io.cacheOp.req.bits.bank_num).ecc, 414 // 0.U 415 // ) 416} 417 418 419class ICacheIO(implicit p: Parameters) extends ICacheBundle 420{ 421 val fencei = Input(Bool()) 422 val stop = Input(Bool()) 423 val csr = new L1CacheToCsrIO 424 val fetch = Vec(PortNumber, new ICacheMainPipeBundle) 425 val pmp = Vec(PortNumber, new ICachePMPBundle) 426 val itlb = Vec(PortNumber, new BlockTlbRequestIO) 427 val perfInfo = Output(new ICachePerfInfo) 428} 429 430class ICache()(implicit p: Parameters) extends LazyModule with HasICacheParameters { 431 432 val clientParameters = TLMasterPortParameters.v1( 433 Seq(TLMasterParameters.v1( 434 name = "icache", 435 sourceId = IdRange(0, cacheParams.nMissEntries + cacheParams.nReleaseEntries), 436 supportsProbe = TransferSizes(blockBytes) 437 )), 438 requestFields = cacheParams.reqFields, 439 echoFields = cacheParams.echoFields 440 ) 441 442 val clientNode = TLClientNode(Seq(clientParameters)) 443 444 lazy val module = new ICacheImp(this) 445} 446 447class ICacheImp(outer: ICache) extends LazyModuleImp(outer) with HasICacheParameters { 448 val io = IO(new ICacheIO) 449 450 val (bus, edge) = outer.clientNode.out.head 451 452 val metaArray = Module(new ICacheMetaArray) 453 val dataArray = Module(new ICacheDataArray) 454 val mainPipe = Module(new ICacheMainPipe) 455 val missUnit = Module(new ICacheMissUnit(edge)) 456 val releaseUnit = Module(new ReleaseUnit(edge)) 457 val replacePipe = Module(new ReplacePipe) 458 val probeQueue = Module(new ICacheProbeQueue(edge)) 459 460 val meta_read_arb = Module(new Arbiter(new ICacheReadBundle, 2)) 461 val data_read_arb = Module(new Arbiter(new ICacheReadBundle, 2)) 462 val meta_write_arb = Module(new Arbiter(new ICacheMetaWriteBundle(), 2 )) 463 val replace_req_arb = Module(new Arbiter(new ReplacePipeReq, 2)) 464 465 meta_read_arb.io.in(ReplacePipeKey) <> replacePipe.io.meta_read 466 meta_read_arb.io.in(mainPipeKey) <> mainPipe.io.metaArray.toIMeta 467 metaArray.io.read <> meta_read_arb.io.out 468 replacePipe.io.meta_response <> metaArray.io.readResp 469 mainPipe.io.metaArray.fromIMeta <> metaArray.io.readResp 470 471 data_read_arb.io.in(ReplacePipeKey) <> replacePipe.io.data_read 472 data_read_arb.io.in(mainPipeKey) <> mainPipe.io.dataArray.toIData 473 dataArray.io.read <> data_read_arb.io.out 474 replacePipe.io.data_response <> dataArray.io.readResp 475 mainPipe.io.dataArray.fromIData <> dataArray.io.readResp 476 477 mainPipe.io.respStall := io.stop 478 io.perfInfo := mainPipe.io.perfInfo 479 480 meta_write_arb.io.in(ReplacePipeKey) <> replacePipe.io.meta_write 481 meta_write_arb.io.in(mainPipeKey) <> missUnit.io.meta_write 482 483 metaArray.io.write <> meta_write_arb.io.out 484 dataArray.io.write <> missUnit.io.data_write 485 486 io.itlb <> mainPipe.io.itlb 487 io.pmp <> mainPipe.io.pmp 488 for(i <- 0 until PortNumber){ 489 io.fetch(i).resp <> mainPipe.io.fetch(i).resp 490 491 missUnit.io.req(i) <> mainPipe.io.mshr(i).toMSHR 492 mainPipe.io.mshr(i).fromMSHR <> missUnit.io.resp(i) 493 494 } 495 496 bus.b.ready := false.B 497 bus.c.valid := false.B 498 bus.c.bits := DontCare 499 bus.e.valid := false.B 500 bus.e.bits := DontCare 501 502 metaArray.io.fencei := io.fencei 503 bus.a <> missUnit.io.mem_acquire 504 bus.e <> missUnit.io.mem_finish 505 506 releaseUnit.io.req(0) <> replacePipe.io.release_req 507 releaseUnit.io.req(1) <> DontCare//mainPipe.io.toReleaseUnit(1) 508 bus.c <> releaseUnit.io.mem_release 509 510 // connect bus d 511 missUnit.io.mem_grant.valid := false.B 512 missUnit.io.mem_grant.bits := DontCare 513 514 releaseUnit.io.mem_grant.valid := false.B 515 releaseUnit.io.mem_grant.bits := DontCare 516 517 //Probe through bus b 518 probeQueue.io.mem_probe <> bus.b 519 520 replace_req_arb.io.in(ReplacePipeKey) <> probeQueue.io.pipe_req 521 replace_req_arb.io.in(mainPipeKey) <> missUnit.io.release_req 522 replacePipe.io.pipe_req <> replace_req_arb.io.out 523 524 missUnit.io.release_resp <> replacePipe.io.pipe_resp 525 526 /** Block set-conflict request */ 527 val probeReqValid = probeQueue.io.pipe_req.valid 528 val probeReqVidx = probeQueue.io.pipe_req.bits.vidx 529 530 val hasVictim = VecInit(missUnit.io.victimInfor.map(_.valid)) 531 val victimSetSeq = VecInit(missUnit.io.victimInfor.map(_.vidx)) 532 533 val probeShouldBlock = VecInit(hasVictim.zip(victimSetSeq).map{case(valid, idx) => valid && probeReqValid && idx === probeReqVidx }).reduce(_||_) 534 535 when(probeShouldBlock){ 536 probeQueue.io.pipe_req.ready := false.B 537 } 538 539 val releaseReqValid = missUnit.io.release_req.valid 540 val releaseReqVidx = missUnit.io.release_req.bits.vidx 541 542 val hasConflict = VecInit(Seq( 543 replacePipe.io.status.r1_set.valid, 544 replacePipe.io.status.r2_set.valid 545 )) 546 547 val conflictIdx = VecInit(Seq( 548 replacePipe.io.status.r1_set.bits, 549 replacePipe.io.status.r2_set.bits 550 )) 551 552 val releaseShouldBlock = VecInit(hasConflict.zip(conflictIdx).map{case(valid, idx) => valid && releaseReqValid && idx === releaseReqVidx }).reduce(_||_) 553 554 when(releaseShouldBlock){ 555 missUnit.io.release_req.ready := false.B 556 } 557 558 559 (0 until PortNumber).map{i => 560 mainPipe.io.fetch(i).req.valid := io.fetch(i).req.valid //&& !fetchShouldBlock(i) 561 io.fetch(i).req.ready := mainPipe.io.fetch(i).req.ready //&& !fetchShouldBlock(i) 562 mainPipe.io.fetch(i).req.bits := io.fetch(i).req.bits 563 } 564 565 // in L1ICache, we only expect GrantData and ReleaseAck 566 bus.d.ready := false.B 567 when ( bus.d.bits.opcode === TLMessages.GrantData) { 568 missUnit.io.mem_grant <> bus.d 569 } .elsewhen (bus.d.bits.opcode === TLMessages.ReleaseAck) { 570 releaseUnit.io.mem_grant <> bus.d 571 } .otherwise { 572 assert (!bus.d.fire()) 573 } 574 575 val perfinfo = IO(new Bundle(){ 576 val perfEvents = Output(new PerfEventsBundle(2)) 577 }) 578 val perfEvents = Seq( 579 ("icache_miss_cnt ", false.B ), 580 ("icache_miss_penty ", BoolStopWatch(start = false.B, stop = false.B || false.B, startHighPriority = true) ), 581 ) 582 583 // Customized csr cache op support 584 val cacheOpDecoder = Module(new CSRCacheOpDecoder("icache", CacheInstrucion.COP_ID_ICACHE)) 585 cacheOpDecoder.io.csr <> io.csr 586 dataArray.io.cacheOp.req := cacheOpDecoder.io.cache.req 587 metaArray.io.cacheOp.req := cacheOpDecoder.io.cache.req 588 cacheOpDecoder.io.cache.resp.valid := 589 dataArray.io.cacheOp.resp.valid || 590 metaArray.io.cacheOp.resp.valid 591 cacheOpDecoder.io.cache.resp.bits := Mux1H(List( 592 dataArray.io.cacheOp.resp.valid -> dataArray.io.cacheOp.resp.bits, 593 metaArray.io.cacheOp.resp.valid -> metaArray.io.cacheOp.resp.bits, 594 )) 595 assert(!((dataArray.io.cacheOp.resp.valid +& metaArray.io.cacheOp.resp.valid) > 1.U)) 596 597}