xref: /XiangShan/src/main/scala/xiangshan/frontend/icache/WayLookup.scala (revision b92f84459b67a53e82d79920469d5fd6d21aad5e)
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 org.chipsalliance.cde.config.Parameters
20import chisel3._
21import chisel3.util._
22import difftest._
23import freechips.rocketchip.tilelink._
24import utils._
25import xiangshan.cache.mmu._
26import xiangshan.frontend._
27import xiangshan.backend.fu.{PMPReqBundle, PMPRespBundle}
28import huancun.PreferCacheKey
29import xiangshan.XSCoreParamsKey
30import utility._
31
32class WayLookupInfo(implicit p: Parameters) extends ICacheBundle {
33  val vSetIdx       = Vec(PortNumber, UInt(idxBits.W))
34  val waymask       = Vec(PortNumber, UInt(nWays.W))
35  val ptag          = Vec(PortNumber, UInt(tagBits.W))
36  val gpaddr        = Vec(PortNumber, UInt(GPAddrBits.W))
37  val excp_tlb_af   = Vec(PortNumber, Bool())
38  val excp_tlb_pf   = Vec(PortNumber, Bool())
39  val excp_tlb_gpf  = Vec(PortNumber, Bool())
40  val meta_errors   = Vec(PortNumber, Bool())
41}
42
43
44// class WayLookupRead(implicit p: Parameters) extends ICacheBundle {
45//   val vSetIdx     = Vec(PortNumber, UInt(idxBits.W))
46//   val waymask     = Vec(PortNumber, UInt(nWays.W))
47//   val ptag        = Vec(PortNumber, UInt(tagBits.W))
48//   val excp_tlb_af = Vec(PortNumber, Bool())
49//   val excp_tlb_pf = Vec(PortNumber, Bool())
50// }
51
52// class WayLookupWrite(implicit p: Parameters) extends ICacheBundle {
53//   val vSetIdx       = Vec(PortNumber, UInt(idxBits.W))
54//   val ptag          = Vec(PortNumber, UInt(tagBits.W))
55//   val waymask       = Vec(PortNumber, UInt(nWays.W))
56//   val excp_tlb_af   = Vec(PortNumber, Bool())
57//   val excp_tlb_pf   = Vec(PortNumber, Bool())
58// }
59
60class WayLookupInterface(implicit p: Parameters) extends ICacheBundle {
61  val flush   = Input(Bool())
62  val read    = DecoupledIO(new WayLookupInfo)
63  val write   = Flipped(DecoupledIO(new WayLookupInfo))
64  val update  = Flipped(ValidIO(new ICacheMissResp))
65}
66
67class WayLookup(implicit p: Parameters) extends ICacheModule {
68  val io = IO(new WayLookupInterface)
69
70  class WayLookupPtr(implicit p: Parameters) extends CircularQueuePtr[WayLookupPtr](nWayLookupSize)
71  object WayLookupPtr {
72    def apply(f: Bool, v: UInt)(implicit p: Parameters): WayLookupPtr = {
73      val ptr = Wire(new WayLookupPtr)
74      ptr.flag := f
75      ptr.value := v
76      ptr
77    }
78  }
79
80  val entries         = RegInit(VecInit(Seq.fill(nWayLookupSize)(0.U.asTypeOf((new WayLookupInfo).cloneType))))
81  val readPtr         = RegInit(WayLookupPtr(false.B, 0.U))
82  val writePtr        = RegInit(WayLookupPtr(false.B, 0.U))
83
84  val empty = readPtr === writePtr
85  val full  = (readPtr.value === writePtr.value) && (readPtr.flag ^ writePtr.flag)
86
87  when(io.flush) {
88    writePtr.value  := 0.U
89    writePtr.flag   := false.B
90  }.elsewhen(io.write.fire) {
91    writePtr := writePtr + 1.U
92  }
93
94  when(io.flush) {
95    readPtr.value  := 0.U
96    readPtr.flag   := false.B
97  }.elsewhen(io.read.fire) {
98    readPtr := readPtr + 1.U
99  }
100
101  /**
102    ******************************************************************************
103    * update
104    ******************************************************************************
105    */
106  val hits = Wire(Vec(nWayLookupSize, Bool()))
107  entries.zip(hits).foreach{case(entry, hit) =>
108    val hit_vec = Wire(Vec(PortNumber, Bool()))
109    (0 until PortNumber).foreach { i =>
110      val vset_same = (io.update.bits.vSetIdx === entry.vSetIdx(i)) && !io.update.bits.corrupt && io.update.valid
111      val ptag_same = getPhyTagFromBlk(io.update.bits.blkPaddr) === entry.ptag(i)
112      val way_same = io.update.bits.waymask === entry.waymask(i)
113      when(vset_same) {
114        when(ptag_same) {
115          // miss -> hit
116          entry.waymask(i) := io.update.bits.waymask
117          // also clear previously found errors since data/metaArray is refilled
118          entry.meta_errors(i) := false.B
119        }.elsewhen(way_same) {
120          // data is overwritten: hit -> miss
121          entry.waymask(i) := 0.U
122          // do not clear previously found errors since way_same might be unreliable when error occurs
123        }
124      }
125      hit_vec(i) := vset_same && (ptag_same || way_same)
126    }
127    hit := hit_vec.reduce(_||_)
128  }
129
130  /**
131    ******************************************************************************
132    * read
133    ******************************************************************************
134    */
135  val bypass = empty && io.write.valid
136  io.read.valid             := !empty || io.write.valid
137  io.read.bits              := Mux(bypass, io.write.bits, entries(readPtr.value))
138
139  /**
140    ******************************************************************************
141    * write
142    ******************************************************************************
143    */
144  io.write.ready := !full
145  when(io.write.fire) {
146    entries(writePtr.value) := io.write.bits
147  }
148}
149