xref: /XiangShan/src/main/scala/xiangshan/frontend/WrBypass.scala (revision 569b279f195dc0ad7c83f0513d51b94afa3311ba)
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
24
25class WrBypass[T <: Data](gen: T, val numEntries: Int, val idxWidth: Int,
26  val numWays: Int = 1, val tagWidth: Int = 0)(implicit p: Parameters) extends XSModule {
27  require(numEntries >= 0)
28  require(idxWidth > 0)
29  require(numWays >= 1)
30  require(tagWidth >= 0)
31  def hasTag = tagWidth > 0
32  def multipleWays = numWays > 1
33  val io = IO(new Bundle {
34    val wen = Input(Bool())
35    val write_idx = Input(UInt(idxWidth.W))
36    val write_tag = if (hasTag) Some(Input(UInt(tagWidth.W))) else None
37    val write_data = Input(Vec(numWays, gen))
38    val write_way_mask = if (multipleWays) Some(Input(Vec(numWays, Bool()))) else None
39
40    val hit = Output(Bool())
41    val hit_data = Vec(numWays, Valid(gen))
42  })
43
44  class WrBypassPtr extends CircularQueuePtr[WrBypassPtr](numEntries){
45    override def cloneType = (new WrBypassPtr).asInstanceOf[this.type]
46  }
47
48
49
50  val tags = RegInit(0.U.asTypeOf((Vec(numEntries, UInt(tagWidth.W)))))
51  val idxes = RegInit(0.U.asTypeOf((Vec(numEntries, UInt(idxWidth.W)))))
52  val datas = RegInit(0.U.asTypeOf(Vec(numEntries, Vec(numWays, gen))))
53  val valids = RegInit(0.U.asTypeOf(Vec(numEntries, Vec(numWays, Bool()))))
54
55  val enq_ptr = RegInit(0.U.asTypeOf(new WrBypassPtr))
56  val enq_idx = enq_ptr.value
57
58  val hits = VecInit((0 until numEntries).map {i =>
59    idxes(i) === io.write_idx &&
60    tags(i) === io.write_tag.getOrElse(0.U)
61  })
62  val hit = hits.reduce(_||_)
63  val hit_idx = ParallelPriorityEncoder(hits)
64
65  io.hit := hit
66  for (i <- 0 until numWays) {
67    io.hit_data(i).valid := valids(hit_idx)(i)
68    io.hit_data(i).bits  := datas(hit_idx)(i)
69  }
70
71  for (i <- 0 until numWays) {
72    when (io.wen) {
73      val full_mask = Fill(numWays, 1.U(1.W)).asTypeOf(Vec(numWays, Bool()))
74      val update_this_way = io.write_way_mask.getOrElse(full_mask)(i)
75      when (hit) {
76        when (update_this_way) {
77          datas(hit_idx)(i) := io.write_data(i)
78          valids(hit_idx)(i) := true.B
79        }
80      }.otherwise {
81        valids(enq_idx)(i) := false.B
82        when (update_this_way) {
83          valids(enq_idx)(i) := true.B
84          datas(enq_idx)(i) := io.write_data(i)
85        }
86      }
87    }
88
89  }
90
91  when (io.wen && !hit) {
92    idxes(enq_idx) := io.write_idx
93    tags(enq_idx) := io.write_tag.getOrElse(0.U)
94    enq_ptr := enq_ptr + 1.U
95  }
96
97  XSPerfAccumulate("wrbypass_hit",  io.wen &&  hit)
98  XSPerfAccumulate("wrbypass_miss", io.wen && !hit)
99
100  XSDebug(io.wen && hit,  p"wrbypass hit entry #${hit_idx}, idx ${io.write_idx}" +
101    p"tag ${io.write_tag.getOrElse(0.U)}data ${io.write_data}\n")
102  XSDebug(io.wen && !hit, p"wrbypass enq entry #${enq_idx}, idx ${io.write_idx}" +
103    p"tag ${io.write_tag.getOrElse(0.U)}data ${io.write_data}\n")
104}