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