xref: /XiangShan/src/main/scala/xiangshan/frontend/icache/WayLookup.scala (revision b92f84459b67a53e82d79920469d5fd6d21aad5e)
1*b92f8445Sssszwic/***************************************************************************************
2*b92f8445Sssszwic  * Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences
3*b92f8445Sssszwic  * Copyright (c) 2020-2021 Peng Cheng Laboratory
4*b92f8445Sssszwic  *
5*b92f8445Sssszwic  * XiangShan is licensed under Mulan PSL v2.
6*b92f8445Sssszwic  * You can use this software according to the terms and conditions of the Mulan PSL v2.
7*b92f8445Sssszwic  * You may obtain a copy of Mulan PSL v2 at:
8*b92f8445Sssszwic  *          http://license.coscl.org.cn/MulanPSL2
9*b92f8445Sssszwic  *
10*b92f8445Sssszwic  * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
11*b92f8445Sssszwic  * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
12*b92f8445Sssszwic  * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
13*b92f8445Sssszwic  *
14*b92f8445Sssszwic  * See the Mulan PSL v2 for more details.
15*b92f8445Sssszwic  ***************************************************************************************/
16*b92f8445Sssszwic
17*b92f8445Sssszwicpackage xiangshan.frontend.icache
18*b92f8445Sssszwic
19*b92f8445Sssszwicimport org.chipsalliance.cde.config.Parameters
20*b92f8445Sssszwicimport chisel3._
21*b92f8445Sssszwicimport chisel3.util._
22*b92f8445Sssszwicimport difftest._
23*b92f8445Sssszwicimport freechips.rocketchip.tilelink._
24*b92f8445Sssszwicimport utils._
25*b92f8445Sssszwicimport xiangshan.cache.mmu._
26*b92f8445Sssszwicimport xiangshan.frontend._
27*b92f8445Sssszwicimport xiangshan.backend.fu.{PMPReqBundle, PMPRespBundle}
28*b92f8445Sssszwicimport huancun.PreferCacheKey
29*b92f8445Sssszwicimport xiangshan.XSCoreParamsKey
30*b92f8445Sssszwicimport utility._
31*b92f8445Sssszwic
32*b92f8445Sssszwicclass WayLookupInfo(implicit p: Parameters) extends ICacheBundle {
33*b92f8445Sssszwic  val vSetIdx       = Vec(PortNumber, UInt(idxBits.W))
34*b92f8445Sssszwic  val waymask       = Vec(PortNumber, UInt(nWays.W))
35*b92f8445Sssszwic  val ptag          = Vec(PortNumber, UInt(tagBits.W))
36*b92f8445Sssszwic  val gpaddr        = Vec(PortNumber, UInt(GPAddrBits.W))
37*b92f8445Sssszwic  val excp_tlb_af   = Vec(PortNumber, Bool())
38*b92f8445Sssszwic  val excp_tlb_pf   = Vec(PortNumber, Bool())
39*b92f8445Sssszwic  val excp_tlb_gpf  = Vec(PortNumber, Bool())
40*b92f8445Sssszwic  val meta_errors   = Vec(PortNumber, Bool())
41*b92f8445Sssszwic}
42*b92f8445Sssszwic
43*b92f8445Sssszwic
44*b92f8445Sssszwic// class WayLookupRead(implicit p: Parameters) extends ICacheBundle {
45*b92f8445Sssszwic//   val vSetIdx     = Vec(PortNumber, UInt(idxBits.W))
46*b92f8445Sssszwic//   val waymask     = Vec(PortNumber, UInt(nWays.W))
47*b92f8445Sssszwic//   val ptag        = Vec(PortNumber, UInt(tagBits.W))
48*b92f8445Sssszwic//   val excp_tlb_af = Vec(PortNumber, Bool())
49*b92f8445Sssszwic//   val excp_tlb_pf = Vec(PortNumber, Bool())
50*b92f8445Sssszwic// }
51*b92f8445Sssszwic
52*b92f8445Sssszwic// class WayLookupWrite(implicit p: Parameters) extends ICacheBundle {
53*b92f8445Sssszwic//   val vSetIdx       = Vec(PortNumber, UInt(idxBits.W))
54*b92f8445Sssszwic//   val ptag          = Vec(PortNumber, UInt(tagBits.W))
55*b92f8445Sssszwic//   val waymask       = Vec(PortNumber, UInt(nWays.W))
56*b92f8445Sssszwic//   val excp_tlb_af   = Vec(PortNumber, Bool())
57*b92f8445Sssszwic//   val excp_tlb_pf   = Vec(PortNumber, Bool())
58*b92f8445Sssszwic// }
59*b92f8445Sssszwic
60*b92f8445Sssszwicclass WayLookupInterface(implicit p: Parameters) extends ICacheBundle {
61*b92f8445Sssszwic  val flush   = Input(Bool())
62*b92f8445Sssszwic  val read    = DecoupledIO(new WayLookupInfo)
63*b92f8445Sssszwic  val write   = Flipped(DecoupledIO(new WayLookupInfo))
64*b92f8445Sssszwic  val update  = Flipped(ValidIO(new ICacheMissResp))
65*b92f8445Sssszwic}
66*b92f8445Sssszwic
67*b92f8445Sssszwicclass WayLookup(implicit p: Parameters) extends ICacheModule {
68*b92f8445Sssszwic  val io = IO(new WayLookupInterface)
69*b92f8445Sssszwic
70*b92f8445Sssszwic  class WayLookupPtr(implicit p: Parameters) extends CircularQueuePtr[WayLookupPtr](nWayLookupSize)
71*b92f8445Sssszwic  object WayLookupPtr {
72*b92f8445Sssszwic    def apply(f: Bool, v: UInt)(implicit p: Parameters): WayLookupPtr = {
73*b92f8445Sssszwic      val ptr = Wire(new WayLookupPtr)
74*b92f8445Sssszwic      ptr.flag := f
75*b92f8445Sssszwic      ptr.value := v
76*b92f8445Sssszwic      ptr
77*b92f8445Sssszwic    }
78*b92f8445Sssszwic  }
79*b92f8445Sssszwic
80*b92f8445Sssszwic  val entries         = RegInit(VecInit(Seq.fill(nWayLookupSize)(0.U.asTypeOf((new WayLookupInfo).cloneType))))
81*b92f8445Sssszwic  val readPtr         = RegInit(WayLookupPtr(false.B, 0.U))
82*b92f8445Sssszwic  val writePtr        = RegInit(WayLookupPtr(false.B, 0.U))
83*b92f8445Sssszwic
84*b92f8445Sssszwic  val empty = readPtr === writePtr
85*b92f8445Sssszwic  val full  = (readPtr.value === writePtr.value) && (readPtr.flag ^ writePtr.flag)
86*b92f8445Sssszwic
87*b92f8445Sssszwic  when(io.flush) {
88*b92f8445Sssszwic    writePtr.value  := 0.U
89*b92f8445Sssszwic    writePtr.flag   := false.B
90*b92f8445Sssszwic  }.elsewhen(io.write.fire) {
91*b92f8445Sssszwic    writePtr := writePtr + 1.U
92*b92f8445Sssszwic  }
93*b92f8445Sssszwic
94*b92f8445Sssszwic  when(io.flush) {
95*b92f8445Sssszwic    readPtr.value  := 0.U
96*b92f8445Sssszwic    readPtr.flag   := false.B
97*b92f8445Sssszwic  }.elsewhen(io.read.fire) {
98*b92f8445Sssszwic    readPtr := readPtr + 1.U
99*b92f8445Sssszwic  }
100*b92f8445Sssszwic
101*b92f8445Sssszwic  /**
102*b92f8445Sssszwic    ******************************************************************************
103*b92f8445Sssszwic    * update
104*b92f8445Sssszwic    ******************************************************************************
105*b92f8445Sssszwic    */
106*b92f8445Sssszwic  val hits = Wire(Vec(nWayLookupSize, Bool()))
107*b92f8445Sssszwic  entries.zip(hits).foreach{case(entry, hit) =>
108*b92f8445Sssszwic    val hit_vec = Wire(Vec(PortNumber, Bool()))
109*b92f8445Sssszwic    (0 until PortNumber).foreach { i =>
110*b92f8445Sssszwic      val vset_same = (io.update.bits.vSetIdx === entry.vSetIdx(i)) && !io.update.bits.corrupt && io.update.valid
111*b92f8445Sssszwic      val ptag_same = getPhyTagFromBlk(io.update.bits.blkPaddr) === entry.ptag(i)
112*b92f8445Sssszwic      val way_same = io.update.bits.waymask === entry.waymask(i)
113*b92f8445Sssszwic      when(vset_same) {
114*b92f8445Sssszwic        when(ptag_same) {
115*b92f8445Sssszwic          // miss -> hit
116*b92f8445Sssszwic          entry.waymask(i) := io.update.bits.waymask
117*b92f8445Sssszwic          // also clear previously found errors since data/metaArray is refilled
118*b92f8445Sssszwic          entry.meta_errors(i) := false.B
119*b92f8445Sssszwic        }.elsewhen(way_same) {
120*b92f8445Sssszwic          // data is overwritten: hit -> miss
121*b92f8445Sssszwic          entry.waymask(i) := 0.U
122*b92f8445Sssszwic          // do not clear previously found errors since way_same might be unreliable when error occurs
123*b92f8445Sssszwic        }
124*b92f8445Sssszwic      }
125*b92f8445Sssszwic      hit_vec(i) := vset_same && (ptag_same || way_same)
126*b92f8445Sssszwic    }
127*b92f8445Sssszwic    hit := hit_vec.reduce(_||_)
128*b92f8445Sssszwic  }
129*b92f8445Sssszwic
130*b92f8445Sssszwic  /**
131*b92f8445Sssszwic    ******************************************************************************
132*b92f8445Sssszwic    * read
133*b92f8445Sssszwic    ******************************************************************************
134*b92f8445Sssszwic    */
135*b92f8445Sssszwic  val bypass = empty && io.write.valid
136*b92f8445Sssszwic  io.read.valid             := !empty || io.write.valid
137*b92f8445Sssszwic  io.read.bits              := Mux(bypass, io.write.bits, entries(readPtr.value))
138*b92f8445Sssszwic
139*b92f8445Sssszwic  /**
140*b92f8445Sssszwic    ******************************************************************************
141*b92f8445Sssszwic    * write
142*b92f8445Sssszwic    ******************************************************************************
143*b92f8445Sssszwic    */
144*b92f8445Sssszwic  io.write.ready := !full
145*b92f8445Sssszwic  when(io.write.fire) {
146*b92f8445Sssszwic    entries(writePtr.value) := io.write.bits
147*b92f8445Sssszwic  }
148*b92f8445Sssszwic}
149