xref: /XiangShan/src/main/scala/xiangshan/backend/regfile/Regfile.scala (revision 16a511c2061bd1e18bf14940333486b30a10637f)
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.util._
22import xiangshan._
23
24class RfReadPort(dataWidth: Int, addrWidth: Int)(implicit p: Parameters) extends XSBundle {
25  val addr = Input(UInt(addrWidth.W))
26  val data = Output(UInt(dataWidth.W))
27}
28
29class RfWritePort(dataWidth: Int, addrWidth: Int)(implicit p: Parameters) extends XSBundle {
30  val wen = Input(Bool())
31  val addr = Input(UInt(addrWidth.W))
32  val data = Input(UInt(dataWidth.W))
33}
34
35class Regfile
36(
37  name: String,
38  numReadPorts: Int,
39  numWritePorts: Int,
40  hasZero: Boolean,
41  len: Int,
42  width: Int,
43)(implicit p: Parameters) extends XSModule {
44  val io = IO(new Bundle() {
45    val readPorts = Vec(numReadPorts, new RfReadPort(len, width))
46    val writePorts = Vec(numWritePorts, new RfWritePort(len, width))
47    val debug_rports = Vec(64, new RfReadPort(len, width))
48  })
49
50  println(name + ": size:" + NRPhyRegs + " read: " + numReadPorts + " write: " + numWritePorts)
51
52  val mem = Reg(Vec(NRPhyRegs, UInt(len.W)))
53  for (r <- io.readPorts) {
54    val rdata = if (hasZero) Mux(r.addr === 0.U, 0.U, mem(r.addr)) else mem(r.addr)
55    r.data := rdata
56  }
57  for (w <- io.writePorts) {
58    when(w.wen) {
59      mem(w.addr) := w.data
60    }
61  }
62
63  for (rport <- io.debug_rports) {
64    val zero_rdata = Mux(rport.addr === 0.U, 0.U, mem(rport.addr))
65    rport.data := (if (hasZero) zero_rdata else mem(rport.addr))
66  }
67}
68
69object Regfile {
70  def apply(
71    name         : String,
72    numEntries   : Int,
73    raddr        : Seq[UInt],
74    wen          : Seq[Bool],
75    waddr        : Seq[UInt],
76    wdata        : Seq[UInt],
77    hasZero      : Boolean,
78    withReset    : Boolean = false,
79    debugReadAddr: Option[Seq[UInt]] = None,
80  )(implicit p: Parameters): Seq[UInt] = {
81    val numReadPorts = raddr.length
82    val numWritePorts = wen.length
83    require(wen.length == waddr.length)
84    require(wen.length == wdata.length)
85    val dataBits = wdata.map(_.getWidth).min
86    require(wdata.map(_.getWidth).min == wdata.map(_.getWidth).max, s"dataBits != $dataBits")
87    val addrBits = waddr.map(_.getWidth).min
88    require(waddr.map(_.getWidth).min == waddr.map(_.getWidth).max, s"addrBits != $addrBits")
89
90    val regfile = Module(new Regfile(name, numReadPorts, numWritePorts, hasZero, dataBits, addrBits))
91    val rdata = regfile.io.readPorts.zip(raddr).map { case (rport, addr) =>
92      rport.addr := addr
93      rport.data
94    }
95
96    regfile.io.writePorts.zip(wen).zip(waddr).zip(wdata).foreach{ case (((wport, en), addr), data) =>
97      wport.wen := en
98      wport.addr := addr
99      wport.data := data
100    }
101    if (withReset) {
102      val numResetCycles = math.ceil(numEntries / numWritePorts).toInt
103      val resetCounter = RegInit(numResetCycles.U)
104      val resetWaddr = RegInit(VecInit((0 until numWritePorts).map(_.U(log2Up(numEntries + 1).W))))
105      val inReset = resetCounter =/= 0.U
106      when (inReset) {
107        resetCounter := resetCounter - 1.U
108        resetWaddr := VecInit(resetWaddr.map(_ + numWritePorts.U))
109      }
110      when (!inReset) {
111        resetWaddr.map(_ := 0.U)
112      }
113      for ((wport, i) <- regfile.io.writePorts.zipWithIndex) {
114        wport.wen := inReset || wen(i)
115        wport.addr := Mux(inReset, resetWaddr(i), waddr(i))
116        wport.data := wdata(i)
117      }
118    }
119    regfile.io.debug_rports := DontCare
120    val debug_rdata = regfile.io.debug_rports.zip(debugReadAddr.getOrElse(Seq())).map { case (rport, addr) =>
121      rport.addr := addr
122      rport.data
123    }
124    rdata ++ debug_rdata
125  }
126}
127
128object IntRegFile {
129  def apply(
130    name         : String,
131    numEntries   : Int,
132    raddr        : Seq[UInt],
133    wen          : Seq[Bool],
134    waddr        : Seq[UInt],
135    wdata        : Seq[UInt],
136    withReset    : Boolean = false,
137    debugReadAddr: Option[Seq[UInt]] = None,
138  )(implicit p: Parameters): Seq[UInt] = {
139    Regfile(
140      name, numEntries, raddr, wen, waddr, wdata,
141      hasZero = true, withReset, debugReadAddr)
142  }
143}
144
145object VfRegFile {
146  def apply(
147    name         : String,
148    numEntries   : Int,
149    splitNum     : Int,
150    raddr        : Seq[UInt],
151    wen          : Seq[Seq[Bool]],
152    waddr        : Seq[UInt],
153    wdata        : Seq[UInt],
154    withReset    : Boolean = false,
155    debugReadAddr: Option[Seq[UInt]] = None,
156  )(implicit p: Parameters) : Seq[UInt] = {
157    require(splitNum >= 1, "splitNum should be no less than 1")
158    require(splitNum == wen.length, "splitNum should be equal to length of wen vec")
159    if (splitNum == 1) {
160      Regfile(name, numEntries, raddr, wen.head, waddr, wdata,
161        hasZero = false, withReset, debugReadAddr)
162    } else {
163      val dataWidth = 64
164      val numReadPorts = raddr.length + debugReadAddr.getOrElse(Seq()).length
165      require(splitNum > 1 && wdata.head.getWidth == dataWidth * splitNum)
166      val wdataVec = Wire(Vec(splitNum, Vec(wdata.length, UInt(dataWidth.W))))
167      var rdataVec = Wire(Vec(splitNum, Vec(numReadPorts, UInt(dataWidth.W))))
168      for (i <- 0 until splitNum) {
169        wdataVec(i) := wdata.map(_((i + 1) * dataWidth - 1, i * dataWidth))
170        rdataVec(i) := Regfile(name+s"Part${i}", numEntries, raddr, wen(i), waddr, wdataVec(i),
171          hasZero = false, withReset, debugReadAddr)
172      }
173      val rdata = Wire(Vec(numReadPorts, UInt(wdata.head.getWidth.W)))
174      for (i <- 0 until rdata.length) {
175        rdata(i) := Cat(rdataVec.map(_(i)).reverse)
176      }
177      rdata
178    }
179  }
180}
181