xref: /XiangShan/src/main/scala/xiangshan/frontend/WrBypass.scala (revision 7a2fc509e2d355879c4db3dc3f17a6ccacd3d09e)
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***************************************************************************************/
16package xiangshan.frontend
17
18import chipsalliance.rocketchip.config.Parameters
19import chisel3._
20import chisel3.util._
21import xiangshan._
22import utils._
23import chisel3.experimental.chiselName
24import xiangshan.cache.mmu.CAMTemplate
25
26class WrBypass[T <: Data](gen: T, val numEntries: Int, val idxWidth: Int,
27  val numWays: Int = 1, val tagWidth: Int = 0)(implicit p: Parameters) extends XSModule {
28  require(numEntries >= 0)
29  require(idxWidth > 0)
30  require(numWays >= 1)
31  require(tagWidth >= 0)
32  def hasTag = tagWidth > 0
33  def multipleWays = numWays > 1
34  val io = IO(new Bundle {
35    val wen = Input(Bool())
36    val write_idx = Input(UInt(idxWidth.W))
37    val write_tag = if (hasTag) Some(Input(UInt(tagWidth.W))) else None
38    val write_data = Input(Vec(numWays, gen))
39    val write_way_mask = if (multipleWays) Some(Input(Vec(numWays, Bool()))) else None
40
41    val hit = Output(Bool())
42    val hit_data = Vec(numWays, Valid(gen))
43  })
44
45  class WrBypassPtr extends CircularQueuePtr[WrBypassPtr](numEntries){
46  }
47
48  class Idx_Tag extends Bundle {
49    val idx = UInt(idxWidth.W)
50    val tag = if (hasTag) Some(UInt(tagWidth.W)) else None
51    def apply(idx: UInt, tag: UInt) = {
52      this.idx := idx
53      this.tag.map(_ := tag)
54    }
55  }
56  val idx_tag_cam = Module(new CAMTemplate(new Idx_Tag, numEntries, 1))
57  val data_mem = Mem(numEntries, Vec(numWays, gen))
58
59  val valids = RegInit(0.U.asTypeOf(Vec(numEntries, Vec(numWays, Bool()))))
60
61  val enq_ptr = RegInit(0.U.asTypeOf(new WrBypassPtr))
62  val enq_idx = enq_ptr.value
63
64  idx_tag_cam.io.r.req(0)(io.write_idx, io.write_tag.getOrElse(0.U))
65  val hits_oh = idx_tag_cam.io.r.resp(0)
66  val hit_idx = OHToUInt(hits_oh)
67  val hit = hits_oh.reduce(_||_)
68
69  io.hit := hit
70  for (i <- 0 until numWays) {
71    io.hit_data(i).valid := Mux1H(hits_oh, valids)(i)
72    io.hit_data(i).bits  := data_mem.read(hit_idx)(i)
73  }
74
75  val full_mask = Fill(numWays, 1.U(1.W)).asTypeOf(Vec(numWays, Bool()))
76  val update_way_mask = io.write_way_mask.getOrElse(full_mask)
77
78  // write data on every request
79  when (io.wen) {
80    val data_write_idx = Mux(hit, hit_idx, enq_idx)
81    data_mem.write(data_write_idx, io.write_data, update_way_mask)
82  }
83
84  // update valids
85  for (i <- 0 until numWays) {
86    when (io.wen) {
87      when (hit) {
88        when (update_way_mask(i)) {
89          valids(hit_idx)(i) := true.B
90        }
91      }.otherwise {
92        valids(enq_idx)(i) := false.B
93        when (update_way_mask(i)) {
94          valids(enq_idx)(i) := true.B
95        }
96      }
97    }
98  }
99
100  val enq_en = io.wen && !hit
101  idx_tag_cam.io.w.valid := enq_en
102  idx_tag_cam.io.w.bits.index := enq_idx
103  idx_tag_cam.io.w.bits.data(io.write_idx, io.write_tag.getOrElse(0.U))
104  enq_ptr := enq_ptr + enq_en
105
106  XSPerfAccumulate("wrbypass_hit",  io.wen &&  hit)
107  XSPerfAccumulate("wrbypass_miss", io.wen && !hit)
108
109  XSDebug(io.wen && hit,  p"wrbypass hit entry #${hit_idx}, idx ${io.write_idx}" +
110    p"tag ${io.write_tag.getOrElse(0.U)}data ${io.write_data}\n")
111  XSDebug(io.wen && !hit, p"wrbypass enq entry #${enq_idx}, idx ${io.write_idx}" +
112    p"tag ${io.write_tag.getOrElse(0.U)}data ${io.write_data}\n")
113}
114