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