xref: /XiangShan/src/main/scala/xiangshan/backend/regfile/Regfile.scala (revision 708ceed4afe43fb0ea3a52407e46b2794c573634)
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.regfile
18
19import chipsalliance.rocketchip.config.Parameters
20import chisel3._
21import chisel3.experimental.ExtModule
22import chisel3.util._
23import xiangshan._
24
25class RfReadPort(len: Int)(implicit p: Parameters) extends XSBundle {
26  val addr = Input(UInt(PhyRegIdxWidth.W))
27  val data = Output(UInt(len.W))
28  override def cloneType: RfReadPort.this.type =
29    new RfReadPort(len).asInstanceOf[this.type]
30}
31
32class RfWritePort(len: Int)(implicit p: Parameters) extends XSBundle {
33  val wen = Input(Bool())
34  val addr = Input(UInt(PhyRegIdxWidth.W))
35  val data = Input(UInt(len.W))
36  override def cloneType: RfWritePort.this.type =
37    new RfWritePort(len).asInstanceOf[this.type]
38}
39
40class Regfile
41(
42  numReadPorts: Int,
43  numWritePorts: Int,
44  hasZero: Boolean,
45  len: Int
46)(implicit p: Parameters) extends XSModule {
47  val io = IO(new Bundle() {
48    val readPorts = Vec(numReadPorts, new RfReadPort(len))
49    val writePorts = Vec(numWritePorts, new RfWritePort(len))
50    val debug_rports = Vec(32, new RfReadPort(len))
51  })
52
53  println("Regfile: size:" + NRPhyRegs + " read: " + numReadPorts + " write: " + numWritePorts)
54
55  val mem = Reg(Vec(NRPhyRegs, UInt(len.W)))
56  for (r <- io.readPorts) {
57    val rdata = if (hasZero) Mux(r.addr === 0.U, 0.U, mem(r.addr)) else mem(r.addr)
58    r.data := RegNext(rdata)
59  }
60  for (w <- io.writePorts) {
61    when(w.wen) {
62      mem(w.addr) := w.data
63    }
64  }
65
66  for (rport <- io.debug_rports) {
67    val zero_rdata = Mux(rport.addr === 0.U, 0.U, mem(rport.addr))
68    rport.data := (if (hasZero) zero_rdata else mem(rport.addr))
69  }
70}
71
72object Regfile {
73  def apply(
74    numEntries: Int,
75    raddr: Seq[UInt],
76    wen: Seq[Bool],
77    waddr: Seq[UInt],
78    wdata: Seq[UInt],
79    hasZero: Boolean,
80    withReset: Boolean = true,
81    debugRead: Option[Seq[UInt]] = None
82  )(implicit p: Parameters): Seq[UInt] = {
83    val numReadPorts = raddr.length
84    val numWritePorts = wen.length
85    require(wen.length == waddr.length)
86    require(wen.length == wdata.length)
87    val dataBits = wdata.map(_.getWidth).min
88    require(wdata.map(_.getWidth).min == wdata.map(_.getWidth).max, s"dataBits != $dataBits")
89    val regfile = Module(new Regfile(numReadPorts, numWritePorts, hasZero, dataBits))
90    val rdata = regfile.io.readPorts.zip(raddr).map { case (rport, addr) =>
91      rport.addr := addr
92      rport.data
93    }
94    regfile.io.writePorts.zip(wen).zip(waddr).zip(wdata).foreach{ case (((wport, en), addr), data) =>
95      wport.wen := en
96      wport.addr := addr
97      wport.data := data
98    }
99    if (withReset) {
100      val numResetCycles = math.ceil(numEntries / numWritePorts).toInt
101      val resetCounter = RegInit(numResetCycles.U)
102      val resetWaddr = RegInit(VecInit((0 until numWritePorts).map(_.U(log2Up(numEntries + 1).W))))
103      val inReset = resetCounter =/= 0.U
104      when (inReset) {
105        resetCounter := resetCounter - 1.U
106        resetWaddr := VecInit(resetWaddr.map(_ + numWritePorts.U))
107      }
108      when (!inReset) {
109        resetWaddr.map(_ := 0.U)
110      }
111      for ((wport, i) <- regfile.io.writePorts.zipWithIndex) {
112        wport.wen := inReset || wen(i)
113        wport.addr := Mux(inReset, resetWaddr(i), waddr(i))
114        wport.data := wdata(i)
115      }
116    }
117    regfile.io.debug_rports := DontCare
118    val debug_rdata = regfile.io.debug_rports.zip(debugRead.getOrElse(Seq())).map { case (rport, addr) =>
119      rport.addr := addr
120      rport.data
121    }
122    rdata ++ debug_rdata
123  }
124}
125