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