xref: /XiangShan/src/main/scala/xiangshan/frontend/icache/WayLookup.scala (revision 91946104573e5d0a8312a4a5c4410074bb4e1e10)
1b92f8445Sssszwic/***************************************************************************************
2b92f8445Sssszwic  * Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences
3b92f8445Sssszwic  * Copyright (c) 2020-2021 Peng Cheng Laboratory
4b92f8445Sssszwic  *
5b92f8445Sssszwic  * XiangShan is licensed under Mulan PSL v2.
6b92f8445Sssszwic  * You can use this software according to the terms and conditions of the Mulan PSL v2.
7b92f8445Sssszwic  * You may obtain a copy of Mulan PSL v2 at:
8b92f8445Sssszwic  *          http://license.coscl.org.cn/MulanPSL2
9b92f8445Sssszwic  *
10b92f8445Sssszwic  * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
11b92f8445Sssszwic  * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
12b92f8445Sssszwic  * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
13b92f8445Sssszwic  *
14b92f8445Sssszwic  * See the Mulan PSL v2 for more details.
15b92f8445Sssszwic  ***************************************************************************************/
16b92f8445Sssszwic
17b92f8445Sssszwicpackage xiangshan.frontend.icache
18b92f8445Sssszwic
19b92f8445Sssszwicimport org.chipsalliance.cde.config.Parameters
20b92f8445Sssszwicimport chisel3._
21b92f8445Sssszwicimport chisel3.util._
22b92f8445Sssszwicimport utility._
23b92f8445Sssszwic
24*91946104Sxu_zh/* WayLookupEntry is for internal storage, while WayLookupInfo is for interface
25*91946104Sxu_zh * Notes:
26*91946104Sxu_zh *   1. there must be a flush (caused by guest page fault) after excp_tlb_gpf === true.B,
27*91946104Sxu_zh *      so, we need only the first excp_tlb_gpf and the corresponding gpaddr.
28*91946104Sxu_zh *      to save area, we separate those signals from WayLookupEntry and store only once.
29*91946104Sxu_zh */
30*91946104Sxu_zhclass WayLookupEntry(implicit p: Parameters) extends ICacheBundle {
31*91946104Sxu_zh  val vSetIdx      : Vec[UInt] = Vec(PortNumber, UInt(idxBits.W))
32*91946104Sxu_zh  val waymask      : Vec[UInt] = Vec(PortNumber, UInt(nWays.W))
33*91946104Sxu_zh  val ptag         : Vec[UInt] = Vec(PortNumber, UInt(tagBits.W))
34*91946104Sxu_zh  val excp_tlb_af  : Vec[Bool] = Vec(PortNumber, Bool())
35*91946104Sxu_zh  val excp_tlb_pf  : Vec[Bool] = Vec(PortNumber, Bool())
36*91946104Sxu_zh  val meta_errors  : Vec[Bool] = Vec(PortNumber, Bool())
37*91946104Sxu_zh}
38*91946104Sxu_zh
39*91946104Sxu_zhclass WayLookupGPFEntry(implicit p: Parameters) extends ICacheBundle {
40*91946104Sxu_zh  val excp_tlb_gpf : Vec[Bool] = Vec(PortNumber, Bool())
41*91946104Sxu_zh  val gpaddr       : UInt      = UInt(GPAddrBits.W)
42*91946104Sxu_zh
43*91946104Sxu_zh  def hasGPF: Bool = excp_tlb_gpf.asUInt.orR
44*91946104Sxu_zh}
45*91946104Sxu_zh
46b92f8445Sssszwicclass WayLookupInfo(implicit p: Parameters) extends ICacheBundle {
47*91946104Sxu_zh  val entry = new WayLookupEntry
48*91946104Sxu_zh  val gpf   = new WayLookupGPFEntry
49*91946104Sxu_zh
50*91946104Sxu_zh  // for compatibility
51*91946104Sxu_zh  def vSetIdx      : Vec[UInt] = entry.vSetIdx
52*91946104Sxu_zh  def waymask      : Vec[UInt] = entry.waymask
53*91946104Sxu_zh  def ptag         : Vec[UInt] = entry.ptag
54*91946104Sxu_zh  def excp_tlb_af  : Vec[Bool] = entry.excp_tlb_af
55*91946104Sxu_zh  def excp_tlb_pf  : Vec[Bool] = entry.excp_tlb_pf
56*91946104Sxu_zh  def meta_errors  : Vec[Bool] = entry.meta_errors
57*91946104Sxu_zh  def excp_tlb_gpf : Vec[Bool] = gpf.excp_tlb_gpf
58*91946104Sxu_zh  def gpaddr       : UInt      = gpf.gpaddr
59b92f8445Sssszwic}
60b92f8445Sssszwic
61b92f8445Sssszwic
62b92f8445Sssszwic// class WayLookupRead(implicit p: Parameters) extends ICacheBundle {
63b92f8445Sssszwic//   val vSetIdx     = Vec(PortNumber, UInt(idxBits.W))
64b92f8445Sssszwic//   val waymask     = Vec(PortNumber, UInt(nWays.W))
65b92f8445Sssszwic//   val ptag        = Vec(PortNumber, UInt(tagBits.W))
66b92f8445Sssszwic//   val excp_tlb_af = Vec(PortNumber, Bool())
67b92f8445Sssszwic//   val excp_tlb_pf = Vec(PortNumber, Bool())
68b92f8445Sssszwic// }
69b92f8445Sssszwic
70b92f8445Sssszwic// class WayLookupWrite(implicit p: Parameters) extends ICacheBundle {
71b92f8445Sssszwic//   val vSetIdx       = Vec(PortNumber, UInt(idxBits.W))
72b92f8445Sssszwic//   val ptag          = Vec(PortNumber, UInt(tagBits.W))
73b92f8445Sssszwic//   val waymask       = Vec(PortNumber, UInt(nWays.W))
74b92f8445Sssszwic//   val excp_tlb_af   = Vec(PortNumber, Bool())
75b92f8445Sssszwic//   val excp_tlb_pf   = Vec(PortNumber, Bool())
76b92f8445Sssszwic// }
77b92f8445Sssszwic
78b92f8445Sssszwicclass WayLookupInterface(implicit p: Parameters) extends ICacheBundle {
79b92f8445Sssszwic  val flush   = Input(Bool())
80b92f8445Sssszwic  val read    = DecoupledIO(new WayLookupInfo)
81b92f8445Sssszwic  val write   = Flipped(DecoupledIO(new WayLookupInfo))
82b92f8445Sssszwic  val update  = Flipped(ValidIO(new ICacheMissResp))
83b92f8445Sssszwic}
84b92f8445Sssszwic
85b92f8445Sssszwicclass WayLookup(implicit p: Parameters) extends ICacheModule {
86*91946104Sxu_zh  val io: WayLookupInterface = IO(new WayLookupInterface)
87b92f8445Sssszwic
88b92f8445Sssszwic  class WayLookupPtr(implicit p: Parameters) extends CircularQueuePtr[WayLookupPtr](nWayLookupSize)
89*91946104Sxu_zh  private object WayLookupPtr {
90b92f8445Sssszwic    def apply(f: Bool, v: UInt)(implicit p: Parameters): WayLookupPtr = {
91b92f8445Sssszwic      val ptr = Wire(new WayLookupPtr)
92b92f8445Sssszwic      ptr.flag := f
93b92f8445Sssszwic      ptr.value := v
94b92f8445Sssszwic      ptr
95b92f8445Sssszwic    }
96b92f8445Sssszwic  }
97b92f8445Sssszwic
98*91946104Sxu_zh  private val entries  = RegInit(VecInit(Seq.fill(nWayLookupSize)(0.U.asTypeOf(new WayLookupEntry))))
99*91946104Sxu_zh  private val readPtr  = RegInit(WayLookupPtr(false.B, 0.U))
100*91946104Sxu_zh  private val writePtr = RegInit(WayLookupPtr(false.B, 0.U))
101b92f8445Sssszwic
102*91946104Sxu_zh  private val empty = readPtr === writePtr
103*91946104Sxu_zh  private val full  = (readPtr.value === writePtr.value) && (readPtr.flag ^ writePtr.flag)
104b92f8445Sssszwic
105b92f8445Sssszwic  when(io.flush) {
106b92f8445Sssszwic    writePtr.value := 0.U
107b92f8445Sssszwic    writePtr.flag  := false.B
108b92f8445Sssszwic  }.elsewhen(io.write.fire) {
109b92f8445Sssszwic    writePtr := writePtr + 1.U
110b92f8445Sssszwic  }
111b92f8445Sssszwic
112b92f8445Sssszwic  when(io.flush) {
113b92f8445Sssszwic    readPtr.value := 0.U
114b92f8445Sssszwic    readPtr.flag  := false.B
115b92f8445Sssszwic  }.elsewhen(io.read.fire) {
116b92f8445Sssszwic    readPtr := readPtr + 1.U
117b92f8445Sssszwic  }
118b92f8445Sssszwic
119*91946104Sxu_zh  private val gpf_entry = RegInit(0.U.asTypeOf(new WayLookupGPFEntry))
120*91946104Sxu_zh  private val gpfPtr    = RegInit(WayLookupPtr(false.B, 0.U))
121*91946104Sxu_zh
122*91946104Sxu_zh  when(io.flush) {
123*91946104Sxu_zh    // we don't need to reset gpfPtr, since the valid is actually gpf_entries.excp_tlb_gpf
124*91946104Sxu_zh    gpf_entry := 0.U.asTypeOf(new WayLookupGPFEntry)
125*91946104Sxu_zh  }
126*91946104Sxu_zh
127b92f8445Sssszwic  /**
128b92f8445Sssszwic    ******************************************************************************
129b92f8445Sssszwic    * update
130b92f8445Sssszwic    ******************************************************************************
131b92f8445Sssszwic    */
132*91946104Sxu_zh  private val hits = Wire(Vec(nWayLookupSize, Bool()))
133b92f8445Sssszwic  entries.zip(hits).foreach{ case(entry, hit) =>
134b92f8445Sssszwic    val hit_vec = Wire(Vec(PortNumber, Bool()))
135b92f8445Sssszwic    (0 until PortNumber).foreach { i =>
136b92f8445Sssszwic      val vset_same = (io.update.bits.vSetIdx === entry.vSetIdx(i)) && !io.update.bits.corrupt && io.update.valid
137b92f8445Sssszwic      val ptag_same = getPhyTagFromBlk(io.update.bits.blkPaddr) === entry.ptag(i)
138b92f8445Sssszwic      val way_same = io.update.bits.waymask === entry.waymask(i)
139b92f8445Sssszwic      when(vset_same) {
140b92f8445Sssszwic        when(ptag_same) {
141b92f8445Sssszwic          // miss -> hit
142b92f8445Sssszwic          entry.waymask(i) := io.update.bits.waymask
143b92f8445Sssszwic          // also clear previously found errors since data/metaArray is refilled
144b92f8445Sssszwic          entry.meta_errors(i) := false.B
145b92f8445Sssszwic        }.elsewhen(way_same) {
146b92f8445Sssszwic          // data is overwritten: hit -> miss
147b92f8445Sssszwic          entry.waymask(i) := 0.U
148b92f8445Sssszwic          // do not clear previously found errors since way_same might be unreliable when error occurs
149b92f8445Sssszwic        }
150b92f8445Sssszwic      }
151b92f8445Sssszwic      hit_vec(i) := vset_same && (ptag_same || way_same)
152b92f8445Sssszwic    }
153b92f8445Sssszwic    hit := hit_vec.reduce(_||_)
154b92f8445Sssszwic  }
155b92f8445Sssszwic
156b92f8445Sssszwic  /**
157b92f8445Sssszwic    ******************************************************************************
158b92f8445Sssszwic    * read
159b92f8445Sssszwic    ******************************************************************************
160b92f8445Sssszwic    */
161b92f8445Sssszwic  io.read.valid := !empty || io.write.valid
162*91946104Sxu_zh  when (empty && io.write.valid) {  // bypass
163*91946104Sxu_zh    io.read.bits := io.write.bits
164*91946104Sxu_zh  }.otherwise {
165*91946104Sxu_zh    io.read.bits.entry := entries(readPtr.value)
166*91946104Sxu_zh    io.read.bits.gpf   := Mux(readPtr === gpfPtr, gpf_entry, 0.U.asTypeOf(new WayLookupGPFEntry))
167*91946104Sxu_zh  }
168b92f8445Sssszwic
169b92f8445Sssszwic  /**
170b92f8445Sssszwic    ******************************************************************************
171b92f8445Sssszwic    * write
172b92f8445Sssszwic    ******************************************************************************
173b92f8445Sssszwic    */
174b92f8445Sssszwic  io.write.ready := !full
175b92f8445Sssszwic  when(io.write.fire) {
176*91946104Sxu_zh    entries(writePtr.value) := io.write.bits.entry
177*91946104Sxu_zh    // save gpf iff no gpf is already saved
178*91946104Sxu_zh    when(!gpf_entry.hasGPF && io.write.bits.gpf.hasGPF) {
179*91946104Sxu_zh      gpf_entry := io.write.bits.gpf
180*91946104Sxu_zh      gpfPtr := writePtr
181*91946104Sxu_zh    }
182b92f8445Sssszwic  }
183b92f8445Sssszwic}
184