xref: /XiangShan/src/main/scala/xiangshan/frontend/icache/ICache.scala (revision d6477c69bc3348d63058f8f4cebbf80cad7ca1e0)
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}