xref: /XiangShan/src/main/scala/xiangshan/frontend/WrBypass.scala (revision 76e02f07106d3571a66ce9e5e5b533e097828cde)
1569b279fSLingrui98/***************************************************************************************
2569b279fSLingrui98* Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences
3569b279fSLingrui98* Copyright (c) 2020-2021 Peng Cheng Laboratory
4569b279fSLingrui98*
5569b279fSLingrui98* XiangShan is licensed under Mulan PSL v2.
6569b279fSLingrui98* You can use this software according to the terms and conditions of the Mulan PSL v2.
7569b279fSLingrui98* You may obtain a copy of Mulan PSL v2 at:
8569b279fSLingrui98*          http://license.coscl.org.cn/MulanPSL2
9569b279fSLingrui98*
10569b279fSLingrui98* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
11569b279fSLingrui98* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
12569b279fSLingrui98* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
13569b279fSLingrui98*
14569b279fSLingrui98* See the Mulan PSL v2 for more details.
15569b279fSLingrui98***************************************************************************************/
16569b279fSLingrui98package xiangshan.frontend
17569b279fSLingrui98
18569b279fSLingrui98import chipsalliance.rocketchip.config.Parameters
19569b279fSLingrui98import chisel3._
20569b279fSLingrui98import chisel3.util._
21569b279fSLingrui98import xiangshan._
22569b279fSLingrui98import utils._
23569b279fSLingrui98import chisel3.experimental.chiselName
24*76e02f07SLingrui98import xiangshan.cache.mmu.CAMTemplate
25569b279fSLingrui98
26569b279fSLingrui98class WrBypass[T <: Data](gen: T, val numEntries: Int, val idxWidth: Int,
27569b279fSLingrui98  val numWays: Int = 1, val tagWidth: Int = 0)(implicit p: Parameters) extends XSModule {
28569b279fSLingrui98  require(numEntries >= 0)
29569b279fSLingrui98  require(idxWidth > 0)
30569b279fSLingrui98  require(numWays >= 1)
31569b279fSLingrui98  require(tagWidth >= 0)
32569b279fSLingrui98  def hasTag = tagWidth > 0
33569b279fSLingrui98  def multipleWays = numWays > 1
34569b279fSLingrui98  val io = IO(new Bundle {
35569b279fSLingrui98    val wen = Input(Bool())
36569b279fSLingrui98    val write_idx = Input(UInt(idxWidth.W))
37569b279fSLingrui98    val write_tag = if (hasTag) Some(Input(UInt(tagWidth.W))) else None
38569b279fSLingrui98    val write_data = Input(Vec(numWays, gen))
39569b279fSLingrui98    val write_way_mask = if (multipleWays) Some(Input(Vec(numWays, Bool()))) else None
40569b279fSLingrui98
41569b279fSLingrui98    val hit = Output(Bool())
42569b279fSLingrui98    val hit_data = Vec(numWays, Valid(gen))
43569b279fSLingrui98  })
44569b279fSLingrui98
45569b279fSLingrui98  class WrBypassPtr extends CircularQueuePtr[WrBypassPtr](numEntries){
46569b279fSLingrui98    override def cloneType = (new WrBypassPtr).asInstanceOf[this.type]
47569b279fSLingrui98  }
48569b279fSLingrui98
49*76e02f07SLingrui98  class Idx_Tag extends Bundle {
50*76e02f07SLingrui98    val idx = UInt(idxWidth.W)
51*76e02f07SLingrui98    val tag = if (hasTag) Some(UInt(tagWidth.W)) else None
52*76e02f07SLingrui98    def apply(idx: UInt, tag: UInt) = {
53*76e02f07SLingrui98      this.idx := idx
54*76e02f07SLingrui98      this.tag.map(_ := tag)
55*76e02f07SLingrui98    }
56*76e02f07SLingrui98  }
57*76e02f07SLingrui98  val idx_tag_cam = Module(new CAMTemplate(new Idx_Tag, numEntries, 1))
58*76e02f07SLingrui98  val data_mem = Mem(numEntries, Vec(numWays, gen))
59569b279fSLingrui98
60569b279fSLingrui98  val valids = RegInit(0.U.asTypeOf(Vec(numEntries, Vec(numWays, Bool()))))
61569b279fSLingrui98
62569b279fSLingrui98  val enq_ptr = RegInit(0.U.asTypeOf(new WrBypassPtr))
63569b279fSLingrui98  val enq_idx = enq_ptr.value
64569b279fSLingrui98
65*76e02f07SLingrui98  idx_tag_cam.io.r.req(0)(io.write_idx, io.write_tag.getOrElse(0.U))
66*76e02f07SLingrui98  val hits_oh = idx_tag_cam.io.r.resp(0)
67*76e02f07SLingrui98  val hit_idx = OHToUInt(hits_oh)
68*76e02f07SLingrui98  val hit = hits_oh.reduce(_||_)
69569b279fSLingrui98
70569b279fSLingrui98  io.hit := hit
71569b279fSLingrui98  for (i <- 0 until numWays) {
72*76e02f07SLingrui98    io.hit_data(i).valid := Mux1H(hits_oh, valids)(i)
73*76e02f07SLingrui98    io.hit_data(i).bits  := data_mem.read(hit_idx)(i)
74569b279fSLingrui98  }
75569b279fSLingrui98
76*76e02f07SLingrui98  val full_mask = Fill(numWays, 1.U(1.W)).asTypeOf(Vec(numWays, Bool()))
77*76e02f07SLingrui98  val update_way_mask = io.write_way_mask.getOrElse(full_mask)
78*76e02f07SLingrui98
79*76e02f07SLingrui98  // write data on every request
80*76e02f07SLingrui98  when (io.wen) {
81*76e02f07SLingrui98    val data_write_idx = Mux(hit, hit_idx, enq_idx)
82*76e02f07SLingrui98    data_mem.write(data_write_idx, io.write_data, update_way_mask)
83*76e02f07SLingrui98  }
84*76e02f07SLingrui98
85*76e02f07SLingrui98  // update valids
86569b279fSLingrui98  for (i <- 0 until numWays) {
87569b279fSLingrui98    when (io.wen) {
88569b279fSLingrui98      when (hit) {
89*76e02f07SLingrui98        when (update_way_mask(i)) {
90569b279fSLingrui98          valids(hit_idx)(i) := true.B
91569b279fSLingrui98        }
92569b279fSLingrui98      }.otherwise {
93569b279fSLingrui98        valids(enq_idx)(i) := false.B
94*76e02f07SLingrui98        when (update_way_mask(i)) {
95569b279fSLingrui98          valids(enq_idx)(i) := true.B
96*76e02f07SLingrui98        }
97569b279fSLingrui98      }
98569b279fSLingrui98    }
99569b279fSLingrui98  }
100569b279fSLingrui98
101*76e02f07SLingrui98  val enq_en = io.wen && !hit
102*76e02f07SLingrui98  idx_tag_cam.io.w.valid := enq_en
103*76e02f07SLingrui98  idx_tag_cam.io.w.bits.index := enq_idx
104*76e02f07SLingrui98  idx_tag_cam.io.w.bits.data(io.write_idx, io.write_tag.getOrElse(0.U))
105*76e02f07SLingrui98  enq_ptr := enq_ptr + enq_en
106569b279fSLingrui98
107569b279fSLingrui98  XSPerfAccumulate("wrbypass_hit",  io.wen &&  hit)
108569b279fSLingrui98  XSPerfAccumulate("wrbypass_miss", io.wen && !hit)
109569b279fSLingrui98
110569b279fSLingrui98  XSDebug(io.wen && hit,  p"wrbypass hit entry #${hit_idx}, idx ${io.write_idx}" +
111569b279fSLingrui98    p"tag ${io.write_tag.getOrElse(0.U)}data ${io.write_data}\n")
112569b279fSLingrui98  XSDebug(io.wen && !hit, p"wrbypass enq entry #${enq_idx}, idx ${io.write_idx}" +
113569b279fSLingrui98    p"tag ${io.write_tag.getOrElse(0.U)}data ${io.write_data}\n")
114569b279fSLingrui98}