xref: /XiangShan/src/main/scala/xiangshan/backend/regcache/RegCacheDataModule.scala (revision 6639e9a467468f4e1b05a25a5de4500772aedeb1)
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.backend.regcache
18
19import org.chipsalliance.cde.config.Parameters
20import chisel3._
21import chisel3.util._
22import xiangshan._
23import utils._
24import xiangshan.backend.BackendParams
25
26class RCReadPort(dataWidth: Int, addrWidth: Int) extends Bundle {
27  val ren  = Input(Bool())
28  val addr = Input(UInt(addrWidth.W))
29  val data = Output(UInt(dataWidth.W))
30}
31
32class RCWritePort(dataWidth: Int, addrWidth: Int, tagWidth: Int, debugEn: Boolean) extends Bundle {
33  val wen  = Input(Bool())
34  val addr = Input(UInt(addrWidth.W))
35  val data = Input(UInt(dataWidth.W))
36  val tag  = OptionWrapper(debugEn, Input(UInt(tagWidth.W)))
37}
38
39class RegCacheDataModule
40(
41  name: String,
42  numEntries: Int,
43  numReadPorts: Int,
44  numWritePorts: Int,
45  dataWidth: Int,
46  addrWidth: Int,
47  tagWidth: Int,
48)(implicit p: Parameters) extends XSModule {
49  val io = IO(new Bundle() {
50    val readPorts = Vec(numReadPorts, new RCReadPort(dataWidth, addrWidth))
51    val writePorts = Vec(numWritePorts, new RCWritePort(dataWidth, addrWidth, tagWidth, backendParams.debugEn))
52    val validInfo = Vec(numEntries, Output(Bool()))
53  })
54
55  println(s"[RegCache] $name: size: $numEntries, read: $numReadPorts, write: $numWritePorts")
56
57  val v   = RegInit(VecInit(Seq.fill(numEntries)(false.B)))
58  val mem = Reg(Vec(numEntries, UInt(dataWidth.W)))
59  val tag = OptionWrapper(backendParams.debugEn, Reg(Vec(numEntries, UInt(tagWidth.W))))
60
61  for ((r, i) <- io.readPorts.zipWithIndex) {
62    r.data := mem(r.addr)
63    when (r.ren) {
64      assert(v(r.addr), s"$name readPorts $i read a invalid entry")
65    }
66  }
67
68  val writePorts = io.writePorts
69  for (i <- writePorts.indices) {
70    if (i < writePorts.size-1) {
71      val hasSameWrite = writePorts.drop(i + 1).map(w => w.wen && w.addr === writePorts(i).addr && writePorts(i).wen).reduce(_ || _)
72      assert(!hasSameWrite, s"$name has two or more writePorts writing the same entry")
73    }
74  }
75  for (i <- mem.indices) {
76    val wenOH = VecInit(io.writePorts.map(w => w.wen && w.addr === i.U))
77    val wData = Mux1H(wenOH, io.writePorts.map(_.data))
78    when (wenOH.asUInt.orR) {
79      v(i)   := true.B
80      mem(i) := wData
81    }
82    if (backendParams.debugEn) {
83      val wTag = Mux1H(wenOH, io.writePorts.map(_.tag.get))
84      when (wenOH.asUInt.orR) {
85        tag.get(i) := wTag
86      }
87    }
88  }
89
90  io.validInfo := v
91}
92