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