xref: /XiangShan/src/main/scala/xiangshan/backend/regfile/Regfile.scala (revision c0be7f3326dfca5bea51a5a98f3c07e847728c49)
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._
23import xiangshan.backend.datapath.DataConfig.{DataConfig, FpData, FpRegSrcDataSet, IntData, IntRegSrcDataSet, VecData, VecRegSrcDataSet, VfRegSrcDataSet}
24
25class RfReadPort(dataWidth: Int, addrWidth: Int) extends Bundle {
26  val addr = Input(UInt(addrWidth.W))
27  val data = Output(UInt(dataWidth.W))
28}
29
30class RfWritePort(dataWidth: Int, addrWidth: Int) extends Bundle {
31  val wen = Input(Bool())
32  val addr = Input(UInt(addrWidth.W))
33  val data = Input(UInt(dataWidth.W))
34}
35
36class RfReadPortWithConfig(val rfReadDataCfg: DataConfig, addrWidth: Int) extends Bundle {
37  val addr: UInt = Input(UInt(addrWidth.W))
38  val data: UInt = Output(UInt(rfReadDataCfg.dataWidth.W))
39  val srcType: UInt = Input(UInt(3.W))
40
41  def readInt: Boolean = IntRegSrcDataSet.contains(rfReadDataCfg)
42  def readFp : Boolean = FpRegSrcDataSet .contains(rfReadDataCfg)
43  def readVec: Boolean = VecRegSrcDataSet.contains(rfReadDataCfg)
44  def readVf : Boolean = VfRegSrcDataSet .contains(rfReadDataCfg)
45}
46
47class RfWritePortWithConfig(val rfWriteDataCfg: DataConfig, addrWidth: Int) extends Bundle {
48  val wen = Input(Bool())
49  val addr = Input(UInt(addrWidth.W))
50  val data = Input(UInt(rfWriteDataCfg.dataWidth.W))
51  val intWen = Input(Bool())
52  val fpWen = Input(Bool())
53  val vecWen = Input(Bool())
54  def writeInt: Boolean = rfWriteDataCfg.isInstanceOf[IntData]
55  def writeFp : Boolean = rfWriteDataCfg.isInstanceOf[FpData]
56  def writeVec: Boolean = rfWriteDataCfg.isInstanceOf[VecData]
57}
58
59class Regfile
60(
61  name: String,
62  numPregs: Int,
63  numReadPorts: Int,
64  numWritePorts: Int,
65  hasZero: Boolean,
66  len: Int,
67  width: Int,
68) extends Module {
69  val io = IO(new Bundle() {
70    val readPorts = Vec(numReadPorts, new RfReadPort(len, width))
71    val writePorts = Vec(numWritePorts, new RfWritePort(len, width))
72    val debug_rports = Vec(65, new RfReadPort(len, width))
73  })
74
75  println(name + ": size:" + numPregs + " read: " + numReadPorts + " write: " + numWritePorts)
76
77  val mem = Reg(Vec(numPregs, UInt(len.W)))
78  for (r <- io.readPorts) {
79    val rdata = if (hasZero) Mux(r.addr === 0.U, 0.U, mem(r.addr)) else mem(r.addr)
80    r.data := RegNext(rdata)
81  }
82  for (w <- io.writePorts) {
83    when(w.wen) {
84      mem(w.addr) := w.data
85    }
86  }
87
88  for (rport <- io.debug_rports) {
89    val zero_rdata = Mux(rport.addr === 0.U, 0.U, mem(rport.addr))
90    rport.data := (if (hasZero) zero_rdata else mem(rport.addr))
91  }
92}
93
94object Regfile {
95  // non-return version
96  def apply(
97    name         : String,
98    numEntries   : Int,
99    raddr        : Seq[UInt],
100    rdata        : Vec[UInt],
101    wen          : Seq[Bool],
102    waddr        : Seq[UInt],
103    wdata        : Seq[UInt],
104    hasZero      : Boolean,
105    withReset    : Boolean = false,
106    debugReadAddr: Option[Seq[UInt]],
107    debugReadData: Option[Vec[UInt]],
108  )(implicit p: Parameters): Unit = {
109    val numReadPorts = raddr.length
110    val numWritePorts = wen.length
111    require(wen.length == waddr.length)
112    require(wen.length == wdata.length)
113    val dataBits = wdata.map(_.getWidth).min
114    require(wdata.map(_.getWidth).min == wdata.map(_.getWidth).max, s"dataBits != $dataBits")
115    val addrBits = waddr.map(_.getWidth).min
116    require(waddr.map(_.getWidth).min == waddr.map(_.getWidth).max, s"addrBits != $addrBits")
117
118    val regfile = Module(new Regfile(name, numEntries, numReadPorts, numWritePorts, hasZero, dataBits, addrBits))
119    rdata := regfile.io.readPorts.zip(raddr).map { case (rport, addr) =>
120      rport.addr := addr
121      rport.data
122    }
123
124    regfile.io.writePorts.zip(wen).zip(waddr).zip(wdata).foreach{ case (((wport, en), addr), data) =>
125      wport.wen := en
126      wport.addr := addr
127      wport.data := data
128    }
129    if (withReset) {
130      val numResetCycles = math.ceil(numEntries / numWritePorts).toInt
131      val resetCounter = RegInit(numResetCycles.U)
132      val resetWaddr = RegInit(VecInit((0 until numWritePorts).map(_.U(log2Up(numEntries + 1).W))))
133      val inReset = resetCounter =/= 0.U
134      when (inReset) {
135        resetCounter := resetCounter - 1.U
136        resetWaddr := VecInit(resetWaddr.map(_ + numWritePorts.U))
137      }
138      when (!inReset) {
139        resetWaddr.map(_ := 0.U)
140      }
141      for ((wport, i) <- regfile.io.writePorts.zipWithIndex) {
142        wport.wen := inReset || wen(i)
143        wport.addr := Mux(inReset, resetWaddr(i), waddr(i))
144        wport.data := wdata(i)
145      }
146    }
147
148    require(debugReadAddr.nonEmpty == debugReadData.nonEmpty, "Both debug addr and data bundles should be empty or not")
149    regfile.io.debug_rports := DontCare
150    if (debugReadAddr.nonEmpty && debugReadData.nonEmpty) {
151      debugReadData.get := VecInit(regfile.io.debug_rports.zip(debugReadAddr.get).map { case (rport, addr) =>
152        rport.addr := addr
153        rport.data
154      })
155    }
156  }
157}
158
159object IntRegFile {
160  // non-return version
161  def apply(
162    name         : String,
163    numEntries   : Int,
164    raddr        : Seq[UInt],
165    rdata        : Vec[UInt],
166    wen          : Seq[Bool],
167    waddr        : Seq[UInt],
168    wdata        : Seq[UInt],
169    debugReadAddr: Option[Seq[UInt]],
170    debugReadData: Option[Vec[UInt]],
171    withReset    : Boolean = false,
172  )(implicit p: Parameters): Unit = {
173    Regfile(
174      name, numEntries, raddr, rdata, wen, waddr, wdata,
175      hasZero = true, withReset, debugReadAddr, debugReadData)
176  }
177}
178
179object VfRegFile {
180  // non-return version
181  def apply(
182    name         : String,
183    numEntries   : Int,
184    splitNum     : Int,
185    raddr        : Seq[UInt],
186    rdata        : Vec[UInt],
187    wen          : Seq[Seq[Bool]],
188    waddr        : Seq[UInt],
189    wdata        : Seq[UInt],
190    debugReadAddr: Option[Seq[UInt]],
191    debugReadData: Option[Vec[UInt]],
192    withReset    : Boolean = false,
193  )(implicit p: Parameters): Unit = {
194    require(splitNum >= 1, "splitNum should be no less than 1")
195    require(splitNum == wen.length, "splitNum should be equal to length of wen vec")
196    if (splitNum == 1) {
197      Regfile(
198        name, numEntries, raddr, rdata, wen.head, waddr, wdata,
199        hasZero = false, withReset, debugReadAddr, debugReadData)
200    } else {
201      val dataWidth = 64
202      val numReadPorts = raddr.length
203      require(splitNum > 1 && wdata.head.getWidth == dataWidth * splitNum)
204      val wdataVec = Wire(Vec(splitNum, Vec(wdata.length, UInt(dataWidth.W))))
205      val rdataVec = Wire(Vec(splitNum, Vec(raddr.length, UInt(dataWidth.W))))
206      val debugRDataVec: Option[Vec[Vec[UInt]]] = debugReadData.map(x => Wire(Vec(splitNum, Vec(x.length, UInt(dataWidth.W)))))
207      for (i <- 0 until splitNum) {
208        wdataVec(i) := wdata.map(_ ((i + 1) * dataWidth - 1, i * dataWidth))
209        Regfile(
210          name + s"Part${i}", numEntries, raddr, rdataVec(i), wen(i), waddr, wdataVec(i),
211          hasZero = false, withReset, debugReadAddr, debugRDataVec.map(_(i))
212        )
213      }
214      for (i <- 0 until rdata.length) {
215        rdata(i) := Cat(rdataVec.map(_ (i)).reverse)
216      }
217      if (debugReadData.nonEmpty) {
218        for (i <- 0 until debugReadData.get.length) {
219          debugReadData.get(i) := Cat(debugRDataVec.get.map(_ (i)).reverse)
220        }
221      }
222    }
223  }
224}