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 25import freechips.rocketchip.util.SeqBoolBitwiseOps 26 27class RCTagTableReadPort(addrWidth: Int, tagWidth: Int)(implicit p: Parameters) extends XSBundle { 28 val ren = Input(Bool()) 29 val tag = Input(UInt(tagWidth.W)) 30 val valid = Output(Bool()) 31 val addr = Output(UInt(addrWidth.W)) 32} 33 34class RCTagTableWritePort(addrWidth: Int, tagWidth: Int)(implicit p: Parameters) extends XSBundle { 35 val wen = Input(Bool()) 36 val addr = Input(UInt(addrWidth.W)) 37 val tag = Input(UInt(tagWidth.W)) 38 val loadDependency = Vec(LoadPipelineWidth, Input(UInt(LoadDependencyWidth.W))) 39} 40 41class RegCacheTagModule 42( 43 name: String, 44 numEntries: Int, 45 numReadPorts: Int, 46 numWritePorts: Int, 47 addrWidth: Int, 48 tagWidth: Int, 49)(implicit p: Parameters) extends XSModule { 50 val io = IO(new Bundle() { 51 val readPorts = Vec(numReadPorts, new RCTagTableReadPort(addrWidth, tagWidth)) 52 val writePorts = Vec(numWritePorts, new RCTagTableWritePort(addrWidth, tagWidth)) 53 54 val cancelVec = Vec(numEntries, Input(Bool())) 55 56 val validVec = Vec(numEntries, Output(Bool())) 57 val tagVec = Vec(numEntries, Output(UInt(tagWidth.W))) 58 val loadDependencyVec = Vec(numEntries, Vec(LoadPipelineWidth, Output(UInt(LoadDependencyWidth.W)))) 59 }) 60 61 println(s"[RegCacheTagModule] $name: size: $numEntries, read: $numReadPorts, write: $numWritePorts") 62 63 val v = RegInit(VecInit(Seq.fill(numEntries)(false.B))) 64 val tag = Reg(Vec(numEntries, UInt(tagWidth.W))) 65 val loadDependency = Reg(Vec(numEntries, Vec(LoadPipelineWidth, UInt(LoadDependencyWidth.W)))) 66 67 for ((r, i) <- io.readPorts.zipWithIndex) { 68 val matchOH = v.zip(tag).map(x => x._1 && x._2 === r.tag) 69 r.valid := Mux(r.ren, matchOH.orR, false.B) 70 r.addr := OHToUInt(matchOH) 71 when (r.ren) { 72 assert(PopCount(matchOH) <= 1.U, s"$name readPorts $i has more than 1 matched entry") 73 } 74 } 75 76 val writePorts = io.writePorts 77 for (i <- writePorts.indices) { 78 if (i < writePorts.size-1) { 79 val hasSameWrite = writePorts.drop(i + 1).map(w => w.wen && w.addr === writePorts(i).addr && writePorts(i).wen).reduce(_ || _) 80 assert(!hasSameWrite, s"$name has two or more writePorts writing the same entry") 81 } 82 } 83 84 for (i <- tag.indices) { 85 val wenOH = VecInit(io.writePorts.map(w => w.wen && w.addr === i.U)) 86 val wTag = Mux1H(wenOH, io.writePorts.map(_.tag)) 87 val wLoadDependency = Mux1H(wenOH, io.writePorts.map(_.loadDependency)) 88 89 when (wenOH.asUInt.orR) { 90 v(i) := true.B 91 tag(i) := wTag 92 loadDependency(i) := wLoadDependency 93 } 94 .elsewhen (io.cancelVec(i)) { 95 v(i) := false.B 96 } 97 .elsewhen (loadDependency(i).map(x => x.orR).reduce(_ || _)) { 98 loadDependency(i) := loadDependency(i).map(l => l << 1) 99 } 100 } 101 102 io.validVec := v 103 io.tagVec := tag 104 io.loadDependencyVec := loadDependency 105} 106