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}