1*86102875Ssinsanction/*************************************************************************************** 2*86102875Ssinsanction* Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences 3*86102875Ssinsanction* Copyright (c) 2020-2021 Peng Cheng Laboratory 4*86102875Ssinsanction* 5*86102875Ssinsanction* XiangShan is licensed under Mulan PSL v2. 6*86102875Ssinsanction* You can use this software according to the terms and conditions of the Mulan PSL v2. 7*86102875Ssinsanction* You may obtain a copy of Mulan PSL v2 at: 8*86102875Ssinsanction* http://license.coscl.org.cn/MulanPSL2 9*86102875Ssinsanction* 10*86102875Ssinsanction* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 11*86102875Ssinsanction* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 12*86102875Ssinsanction* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 13*86102875Ssinsanction* 14*86102875Ssinsanction* See the Mulan PSL v2 for more details. 15*86102875Ssinsanction***************************************************************************************/ 16*86102875Ssinsanction 17*86102875Ssinsanctionpackage xiangshan.backend.regcache 18*86102875Ssinsanction 19*86102875Ssinsanctionimport org.chipsalliance.cde.config.Parameters 20*86102875Ssinsanctionimport chisel3._ 21*86102875Ssinsanctionimport chisel3.util._ 22*86102875Ssinsanctionimport xiangshan._ 23*86102875Ssinsanctionimport utils._ 24*86102875Ssinsanctionimport xiangshan.backend.BackendParams 25*86102875Ssinsanction 26*86102875Ssinsanctionclass RCReadPort(dataWidth: Int, addrWidth: Int) extends Bundle { 27*86102875Ssinsanction val ren = Input(Bool()) 28*86102875Ssinsanction val addr = Input(UInt(addrWidth.W)) 29*86102875Ssinsanction val data = Output(UInt(dataWidth.W)) 30*86102875Ssinsanction} 31*86102875Ssinsanction 32*86102875Ssinsanctionclass RCWritePort(dataWidth: Int, addrWidth: Int, tagWidth: Int, debugEn: Boolean) extends Bundle { 33*86102875Ssinsanction val wen = Input(Bool()) 34*86102875Ssinsanction val addr = Input(UInt(addrWidth.W)) 35*86102875Ssinsanction val data = Input(UInt(dataWidth.W)) 36*86102875Ssinsanction val tag = OptionWrapper(debugEn, Input(UInt(tagWidth.W))) 37*86102875Ssinsanction} 38*86102875Ssinsanction 39*86102875Ssinsanctionclass RegCacheDataModule 40*86102875Ssinsanction( 41*86102875Ssinsanction name: String, 42*86102875Ssinsanction numEntries: Int, 43*86102875Ssinsanction numReadPorts: Int, 44*86102875Ssinsanction numWritePorts: Int, 45*86102875Ssinsanction dataWidth: Int, 46*86102875Ssinsanction addrWidth: Int, 47*86102875Ssinsanction tagWidth: Int, 48*86102875Ssinsanction)(implicit p: Parameters) extends XSModule { 49*86102875Ssinsanction val io = IO(new Bundle() { 50*86102875Ssinsanction val readPorts = Vec(numReadPorts, new RCReadPort(dataWidth, addrWidth)) 51*86102875Ssinsanction val writePorts = Vec(numWritePorts, new RCWritePort(dataWidth, addrWidth, tagWidth, backendParams.debugEn)) 52*86102875Ssinsanction val validInfo = Vec(numEntries, Output(Bool())) 53*86102875Ssinsanction }) 54*86102875Ssinsanction 55*86102875Ssinsanction println(s"[RegCache] $name: size: $numEntries, read: $numReadPorts, write: $numWritePorts") 56*86102875Ssinsanction 57*86102875Ssinsanction val v = RegInit(VecInit(Seq.fill(numEntries)(false.B))) 58*86102875Ssinsanction val mem = Reg(Vec(numEntries, UInt(dataWidth.W))) 59*86102875Ssinsanction val tag = OptionWrapper(backendParams.debugEn, Reg(Vec(numEntries, UInt(tagWidth.W)))) 60*86102875Ssinsanction 61*86102875Ssinsanction for ((r, i) <- io.readPorts.zipWithIndex) { 62*86102875Ssinsanction r.data := mem(r.addr) 63*86102875Ssinsanction when (r.ren) { 64*86102875Ssinsanction assert(v(r.addr), s"$name readPorts $i read a invalid entry") 65*86102875Ssinsanction } 66*86102875Ssinsanction } 67*86102875Ssinsanction 68*86102875Ssinsanction val writePorts = io.writePorts 69*86102875Ssinsanction for (i <- writePorts.indices) { 70*86102875Ssinsanction if (i < writePorts.size-1) { 71*86102875Ssinsanction val hasSameWrite = writePorts.drop(i + 1).map(w => w.wen && w.addr === writePorts(i).addr && writePorts(i).wen).reduce(_ || _) 72*86102875Ssinsanction assert(!hasSameWrite, s"$name has two or more writePorts writing the same entry") 73*86102875Ssinsanction } 74*86102875Ssinsanction } 75*86102875Ssinsanction for (i <- mem.indices) { 76*86102875Ssinsanction val wenOH = VecInit(io.writePorts.map(w => w.wen && w.addr === i.U)) 77*86102875Ssinsanction val wData = Mux1H(wenOH, io.writePorts.map(_.data)) 78*86102875Ssinsanction when (wenOH.asUInt.orR) { 79*86102875Ssinsanction v(i) := true.B 80*86102875Ssinsanction mem(i) := wData 81*86102875Ssinsanction } 82*86102875Ssinsanction if (backendParams.debugEn) { 83*86102875Ssinsanction val wTag = Mux1H(wenOH, io.writePorts.map(_.tag.get)) 84*86102875Ssinsanction when (wenOH.asUInt.orR) { 85*86102875Ssinsanction tag.get(i) := wTag 86*86102875Ssinsanction } 87*86102875Ssinsanction } 88*86102875Ssinsanction } 89*86102875Ssinsanction 90*86102875Ssinsanction io.validInfo := v 91*86102875Ssinsanction} 92