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.regcache 18 19import org.chipsalliance.cde.config.Parameters 20import chisel3._ 21import chisel3.util._ 22import xiangshan._ 23import utils._ 24import xiangshan.backend.BackendParams 25 26class RCReadPort(dataWidth: Int, addrWidth: Int) extends Bundle { 27 val ren = Input(Bool()) 28 val addr = Input(UInt(addrWidth.W)) 29 val data = Output(UInt(dataWidth.W)) 30} 31 32class RCWritePort(dataWidth: Int, addrWidth: Int, tagWidth: Int, debugEn: Boolean) extends Bundle { 33 val wen = Input(Bool()) 34 val addr = Input(UInt(addrWidth.W)) 35 val data = Input(UInt(dataWidth.W)) 36 val tag = OptionWrapper(debugEn, Input(UInt(tagWidth.W))) 37} 38 39class RegCacheDataModule 40( 41 name: String, 42 numEntries: Int, 43 numReadPorts: Int, 44 numWritePorts: Int, 45 dataWidth: Int, 46 addrWidth: Int, 47 tagWidth: Int, 48)(implicit p: Parameters) extends XSModule { 49 val io = IO(new Bundle() { 50 val readPorts = Vec(numReadPorts, new RCReadPort(dataWidth, addrWidth)) 51 val writePorts = Vec(numWritePorts, new RCWritePort(dataWidth, addrWidth, tagWidth, backendParams.debugEn)) 52 val validInfo = Vec(numEntries, Output(Bool())) 53 }) 54 55 println(s"[RegCache] $name: size: $numEntries, read: $numReadPorts, write: $numWritePorts") 56 57 val v = RegInit(VecInit(Seq.fill(numEntries)(false.B))) 58 val mem = Reg(Vec(numEntries, UInt(dataWidth.W))) 59 val tag = OptionWrapper(backendParams.debugEn, Reg(Vec(numEntries, UInt(tagWidth.W)))) 60 61 for ((r, i) <- io.readPorts.zipWithIndex) { 62 r.data := mem(r.addr) 63 when (r.ren) { 64 assert(v(r.addr), s"$name readPorts $i read a invalid entry") 65 } 66 } 67 68 val writePorts = io.writePorts 69 for (i <- writePorts.indices) { 70 if (i < writePorts.size-1) { 71 val hasSameWrite = writePorts.drop(i + 1).map(w => w.wen && w.addr === writePorts(i).addr && writePorts(i).wen).reduce(_ || _) 72 assert(!hasSameWrite, s"$name has two or more writePorts writing the same entry") 73 } 74 } 75 for (i <- mem.indices) { 76 val wenOH = VecInit(io.writePorts.map(w => w.wen && w.addr === i.U)) 77 val wData = Mux1H(wenOH, io.writePorts.map(_.data)) 78 when (wenOH.asUInt.orR) { 79 v(i) := true.B 80 mem(i) := wData 81 } 82 if (backendParams.debugEn) { 83 val wTag = Mux1H(wenOH, io.writePorts.map(_.tag.get)) 84 when (wenOH.asUInt.orR) { 85 tag.get(i) := wTag 86 } 87 } 88 } 89 90 io.validInfo := v 91} 92