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