xref: /XiangShan/src/main/scala/xiangshan/frontend/icache/ICache.scala (revision a4e57ea3a91431261d57a58df4810c0d9f0366ef)
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 L1CacheInnerOpIO) // 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 L1CacheInnerOpIO) // customized cache op port
294  }}
295
296  io.read.ready := !io.write.valid
297
298  val port_0_read_0 = io.read.valid  && !io.read.bits.vSetIdx(0)(0)
299  val port_0_read_1 = io.read.valid  &&  io.read.bits.vSetIdx(0)(0)
300  val port_1_read_1  = io.read.valid &&  io.read.bits.vSetIdx(1)(0) && io.read.bits.isDoubleLine
301  val port_1_read_0  = io.read.valid && !io.read.bits.vSetIdx(1)(0) && io.read.bits.isDoubleLine
302
303  val port_0_read_1_reg = RegEnable(next = port_0_read_1, enable = io.read.fire())
304  val port_1_read_0_reg = RegEnable(next = port_1_read_0, enable = io.read.fire())
305
306  val bank_0_idx = Mux(port_0_read_0, io.read.bits.vSetIdx(0), io.read.bits.vSetIdx(1))
307  val bank_1_idx = Mux(port_0_read_1, io.read.bits.vSetIdx(0), io.read.bits.vSetIdx(1))
308
309  val write_bank_0 = WireInit(io.write.valid && !io.write.bits.bankIdx)
310  val write_bank_1 = WireInit(io.write.valid &&  io.write.bits.bankIdx)
311
312  val write_data_bits = Wire(UInt(dataEntryBits.W))
313
314  val dataArrays = (0 until 2) map { i =>
315    val dataArray = Module(new SRAMTemplate(
316      UInt(dataEntryBits.W),
317      set=nSets/2,
318      way=nWays,
319      shouldReset = true,
320      holdRead = true,
321      singlePort = true
322    ))
323
324    if(i == 0) {
325      dataArray.io.r.req.valid := port_0_read_0 || port_1_read_0
326      dataArray.io.r.req.bits.apply(setIdx=bank_0_idx(highestIdxBit,1))
327      dataArray.io.w.req.valid := write_bank_0
328      dataArray.io.w.req.bits.apply(data=write_data_bits, setIdx=io.write.bits.virIdx(highestIdxBit,1), waymask=io.write.bits.waymask)
329    }
330    else {
331      dataArray.io.r.req.valid := port_0_read_1 || port_1_read_1
332      dataArray.io.r.req.bits.apply(setIdx=bank_1_idx(highestIdxBit,1))
333      dataArray.io.w.req.valid := write_bank_1
334      dataArray.io.w.req.bits.apply(data=write_data_bits, setIdx=io.write.bits.virIdx(highestIdxBit,1), waymask=io.write.bits.waymask)
335    }
336
337    dataArray
338  }
339
340  //Parity Decode
341  val read_datas = Wire(Vec(2,Vec(nWays,UInt(blockBits.W) )))
342  for((dataArray,i) <- dataArrays.zipWithIndex){
343    val read_data_bits = dataArray.io.r.resp.asTypeOf(Vec(nWays,Vec(dataUnitNum, UInt(dataCodeBits.W))))
344    val read_data_decoded = read_data_bits.map{way_bits => way_bits.map(unit =>  cacheParams.dataCode.decode(unit))}
345    val read_data_wrong    = VecInit(read_data_decoded.map{way_bits_decoded => VecInit(way_bits_decoded.map(unit_decoded =>  unit_decoded.error ))})
346    val read_data_corrected = VecInit(read_data_decoded.map{way_bits_decoded => VecInit(way_bits_decoded.map(unit_decoded =>  unit_decoded.corrected )).asUInt})
347    read_datas(i) := read_data_corrected.asTypeOf(Vec(nWays,UInt(blockBits.W)))
348    (0 until nWays).map{ w => io.readResp.errors(i)(w) := RegNext(io.read.fire()) && read_data_wrong(w).asUInt.orR }
349  }
350
351  //Parity Encode
352  val write = io.write.bits
353  val write_data = WireInit(write.data.asTypeOf(Vec(dataUnitNum, UInt(dataCodeUnit.W))))
354  val write_data_encoded = VecInit(write_data.map( unit_bits => cacheParams.dataCode.encode(unit_bits) ))
355  write_data_bits := write_data_encoded.asUInt
356
357  io.readResp.datas(0) := Mux( port_0_read_1_reg, read_datas(1) , read_datas(0))
358  io.readResp.datas(1) := Mux( port_1_read_0_reg, read_datas(0) , read_datas(1))
359
360  io.write.ready := true.B
361
362  // deal with customized cache op
363  require(nWays <= 32)
364  io.cacheOp.resp.bits := DontCare
365  val cacheOpShouldResp = WireInit(false.B)
366  when(io.cacheOp.req.valid){
367    when(
368      CacheInstrucion.isReadData(io.cacheOp.req.bits.opCode) ||
369      CacheInstrucion.isReadDataECC(io.cacheOp.req.bits.opCode)
370    ){
371      (0 until 2).map(i => {
372        dataArrays(i).io.r.req.valid := true.B
373        dataArrays(i).io.r.req.bits.apply(setIdx = io.cacheOp.req.bits.index)
374      })
375      cacheOpShouldResp := true.B
376    }
377    when(CacheInstrucion.isWriteData(io.cacheOp.req.bits.opCode)){
378      (0 until 2).map(i => {
379        dataArrays(i).io.w.req.valid := io.cacheOp.req.bits.bank_num === i.U
380        dataArrays(i).io.w.req.bits.setIdx := io.cacheOp.req.bits.index
381        dataArrays(i).io.w.req.bits.waymask match {
382          case Some(waymask) => waymask := UIntToOH(io.cacheOp.req.bits.wayNum(4, 0))
383          case None =>
384        }
385      })
386      write_data := io.cacheOp.req.bits.write_data_vec.asTypeOf(write_data.cloneType)
387      cacheOpShouldResp := true.B
388    }
389  }
390  io.cacheOp.resp.valid := RegNext(io.cacheOp.req.valid && cacheOpShouldResp)
391  val dataresp = Mux(io.cacheOp.req.bits.bank_num(0).asBool,
392    read_datas(1),
393    read_datas(0)
394  )
395
396  val numICacheLineWords = blockBits / 64
397  require(blockBits >= 64 && isPow2(blockBits))
398  for (wordIndex <- 0 until numICacheLineWords) {
399    io.cacheOp.resp.bits.read_data_vec(wordIndex) := dataresp(io.cacheOp.req.bits.wayNum(4, 0))(64*(wordIndex+1)-1, 64*wordIndex)
400  }
401  // io.cacheOp.resp.bits.read_data_ecc := Mux(io.cacheOp.resp.valid,
402    // bank_result(io.cacheOp.req.bits.bank_num).ecc,
403    // 0.U
404  // )
405}
406
407
408class ICacheIO(implicit p: Parameters) extends ICacheBundle
409{
410  val fencei      = Input(Bool())
411  val stop        = Input(Bool())
412  val csr         = new L1CacheToCsrIO
413  val fetch       = Vec(PortNumber, new ICacheMainPipeBundle)
414  val pmp         = Vec(PortNumber, new ICachePMPBundle)
415  val itlb        = Vec(PortNumber, new BlockTlbRequestIO)
416  val perfInfo = Output(new ICachePerfInfo)
417}
418
419class ICache()(implicit p: Parameters) extends LazyModule with HasICacheParameters {
420
421  val clientParameters = TLMasterPortParameters.v1(
422    Seq(TLMasterParameters.v1(
423      name = "icache",
424      sourceId = IdRange(0, cacheParams.nMissEntries + cacheParams.nReleaseEntries),
425      supportsProbe = TransferSizes(blockBytes)
426    )),
427    requestFields = cacheParams.reqFields,
428    echoFields = cacheParams.echoFields
429  )
430
431  val clientNode = TLClientNode(Seq(clientParameters))
432
433  lazy val module = new ICacheImp(this)
434}
435
436class ICacheImp(outer: ICache) extends LazyModuleImp(outer) with HasICacheParameters with HasPerfEvents {
437  val io = IO(new ICacheIO)
438
439  val (bus, edge) = outer.clientNode.out.head
440
441  val metaArray      = Module(new ICacheMetaArray)
442  val dataArray      = Module(new ICacheDataArray)
443  val mainPipe       = Module(new ICacheMainPipe)
444  val missUnit      = Module(new ICacheMissUnit(edge))
445  val releaseUnit    = Module(new ReleaseUnit(edge))
446  val replacePipe     = Module(new ReplacePipe)
447  val probeQueue     = Module(new ICacheProbeQueue(edge))
448
449  val meta_read_arb   = Module(new Arbiter(new ICacheReadBundle,  2))
450  val data_read_arb   = Module(new Arbiter(new ICacheReadBundle,  2))
451  val meta_write_arb  = Module(new Arbiter(new ICacheMetaWriteBundle(),  2 ))
452  val replace_req_arb     = Module(new Arbiter(new ReplacePipeReq, 2))
453
454  meta_read_arb.io.in(ReplacePipeKey)   <> replacePipe.io.meta_read
455  meta_read_arb.io.in(mainPipeKey)      <> mainPipe.io.metaArray.toIMeta
456  metaArray.io.read                     <> meta_read_arb.io.out
457  replacePipe.io.meta_response          <> metaArray.io.readResp
458  mainPipe.io.metaArray.fromIMeta       <> metaArray.io.readResp
459
460  data_read_arb.io.in(ReplacePipeKey) <> replacePipe.io.data_read
461  data_read_arb.io.in(mainPipeKey)    <> mainPipe.io.dataArray.toIData
462  dataArray.io.read                   <> data_read_arb.io.out
463  replacePipe.io.data_response        <> dataArray.io.readResp
464  mainPipe.io.dataArray.fromIData     <> dataArray.io.readResp
465
466  mainPipe.io.respStall := io.stop
467  io.perfInfo := mainPipe.io.perfInfo
468
469  meta_write_arb.io.in(ReplacePipeKey)  <> replacePipe.io.meta_write
470  meta_write_arb.io.in(mainPipeKey)     <> missUnit.io.meta_write
471
472  metaArray.io.write <> meta_write_arb.io.out
473  dataArray.io.write <> missUnit.io.data_write
474
475  io.itlb           <>    mainPipe.io.itlb
476  io.pmp            <>    mainPipe.io.pmp
477  for(i <- 0 until PortNumber){
478    io.fetch(i).resp     <>    mainPipe.io.fetch(i).resp
479
480    missUnit.io.req(i)           <>   mainPipe.io.mshr(i).toMSHR
481    mainPipe.io.mshr(i).fromMSHR <>   missUnit.io.resp(i)
482
483  }
484
485  bus.b.ready := false.B
486  bus.c.valid := false.B
487  bus.c.bits  := DontCare
488  bus.e.valid := false.B
489  bus.e.bits  := DontCare
490
491  metaArray.io.fencei := io.fencei
492  bus.a <> missUnit.io.mem_acquire
493  bus.e <> missUnit.io.mem_finish
494
495  releaseUnit.io.req(0)  <>  replacePipe.io.release_req
496  releaseUnit.io.req(1)  <>  DontCare//mainPipe.io.toReleaseUnit(1)
497  bus.c <> releaseUnit.io.mem_release
498
499  // connect bus d
500  missUnit.io.mem_grant.valid := false.B
501  missUnit.io.mem_grant.bits  := DontCare
502
503  releaseUnit.io.mem_grant.valid := false.B
504  releaseUnit.io.mem_grant.bits  := DontCare
505
506  //Probe through bus b
507  probeQueue.io.mem_probe    <> bus.b
508
509
510  /** Block set-conflict request */
511 val probeReqValid = probeQueue.io.pipe_req.valid
512 val probeReqVidx  = probeQueue.io.pipe_req.bits.vidx
513
514  val hasVictim = VecInit(missUnit.io.victimInfor.map(_.valid))
515  val victimSetSeq = VecInit(missUnit.io.victimInfor.map(_.vidx))
516
517  val probeShouldBlock = VecInit(hasVictim.zip(victimSetSeq).map{case(valid, idx) =>  valid && probeReqValid && idx === probeReqVidx }).reduce(_||_)
518
519 val releaseReqValid = missUnit.io.release_req.valid
520 val releaseReqVidx  = missUnit.io.release_req.bits.vidx
521
522  val hasConflict = VecInit(Seq(
523        replacePipe.io.status.r1_set.valid,
524        replacePipe.io.status.r2_set.valid
525  ))
526
527  val conflictIdx = VecInit(Seq(
528        replacePipe.io.status.r1_set.bits,
529        replacePipe.io.status.r2_set.bits
530  ))
531
532  val releaseShouldBlock = VecInit(hasConflict.zip(conflictIdx).map{case(valid, idx) =>  valid && releaseReqValid && idx === releaseReqVidx }).reduce(_||_)
533
534  replace_req_arb.io.in(ReplacePipeKey) <> probeQueue.io.pipe_req
535  replace_req_arb.io.in(ReplacePipeKey).valid := probeQueue.io.pipe_req.valid && !probeShouldBlock
536  replace_req_arb.io.in(mainPipeKey)   <> missUnit.io.release_req
537  replace_req_arb.io.in(mainPipeKey).valid := missUnit.io.release_req.valid && !releaseShouldBlock
538  replacePipe.io.pipe_req               <> replace_req_arb.io.out
539
540  when(releaseShouldBlock){
541    missUnit.io.release_req.ready := false.B
542  }
543
544  when(probeShouldBlock){
545    probeQueue.io.pipe_req.ready := false.B
546  }
547
548
549  missUnit.io.release_resp <> replacePipe.io.pipe_resp
550
551
552  (0 until PortNumber).map{i =>
553      mainPipe.io.fetch(i).req.valid := io.fetch(i).req.valid //&& !fetchShouldBlock(i)
554      io.fetch(i).req.ready          :=  mainPipe.io.fetch(i).req.ready //&& !fetchShouldBlock(i)
555      mainPipe.io.fetch(i).req.bits  := io.fetch(i).req.bits
556  }
557
558  // in L1ICache, we only expect GrantData and ReleaseAck
559  bus.d.ready := false.B
560  when ( bus.d.bits.opcode === TLMessages.GrantData) {
561    missUnit.io.mem_grant <> bus.d
562  } .elsewhen (bus.d.bits.opcode === TLMessages.ReleaseAck) {
563    releaseUnit.io.mem_grant <> bus.d
564  } .otherwise {
565    assert (!bus.d.fire())
566  }
567
568  val perfEvents = Seq(
569    ("icache_miss_cnt  ", false.B),
570    ("icache_miss_penty", BoolStopWatch(start = false.B, stop = false.B || false.B, startHighPriority = true)),
571  )
572  generatePerfEvent()
573
574  // Customized csr cache op support
575  val cacheOpDecoder = Module(new CSRCacheOpDecoder("icache", CacheInstrucion.COP_ID_ICACHE))
576  cacheOpDecoder.io.csr <> io.csr
577  dataArray.io.cacheOp.req := cacheOpDecoder.io.cache.req
578  metaArray.io.cacheOp.req := cacheOpDecoder.io.cache.req
579  cacheOpDecoder.io.cache.resp.valid :=
580    dataArray.io.cacheOp.resp.valid ||
581    metaArray.io.cacheOp.resp.valid
582  cacheOpDecoder.io.cache.resp.bits := Mux1H(List(
583    dataArray.io.cacheOp.resp.valid -> dataArray.io.cacheOp.resp.bits,
584    metaArray.io.cacheOp.resp.valid -> metaArray.io.cacheOp.resp.bits,
585  ))
586  // TODO
587  cacheOpDecoder.io.error := DontCare
588  cacheOpDecoder.io.error.ecc_error.valid := false.B
589  assert(!((dataArray.io.cacheOp.resp.valid +& metaArray.io.cacheOp.resp.valid) > 1.U))
590
591}