1c6d43980SLemover/*************************************************************************************** 2c6d43980SLemover* Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences 3f320e0f0SYinan Xu* Copyright (c) 2020-2021 Peng Cheng Laboratory 4c6d43980SLemover* 5c6d43980SLemover* XiangShan is licensed under Mulan PSL v2. 6c6d43980SLemover* You can use this software according to the terms and conditions of the Mulan PSL v2. 7c6d43980SLemover* You may obtain a copy of Mulan PSL v2 at: 8c6d43980SLemover* http://license.coscl.org.cn/MulanPSL2 9c6d43980SLemover* 10c6d43980SLemover* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 11c6d43980SLemover* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 12c6d43980SLemover* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 13c6d43980SLemover* 14c6d43980SLemover* See the Mulan PSL v2 for more details. 15c6d43980SLemover***************************************************************************************/ 16c6d43980SLemover 170f22ee7cSWilliam Wangpackage xiangshan.mem 180f22ee7cSWilliam Wang 190f22ee7cSWilliam Wangimport chisel3._ 200f22ee7cSWilliam Wangimport chisel3.util._ 210f22ee7cSWilliam Wangimport xiangshan._ 220f22ee7cSWilliam Wangimport utils._ 230f22ee7cSWilliam Wangimport xiangshan.cache._ 240f22ee7cSWilliam Wang 252225d46eSJiawei Linclass MaskedSyncDataModuleTemplate[T <: Data]( 26*39f2ec76SWilliam Wang gen: T, 27*39f2ec76SWilliam Wang numEntries: Int, 28*39f2ec76SWilliam Wang numRead: Int, 29*39f2ec76SWilliam Wang numWrite: Int, 30*39f2ec76SWilliam Wang numMRead: Int = 0, 31*39f2ec76SWilliam Wang numMWrite: Int = 0 322225d46eSJiawei Lin) extends Module { 330f22ee7cSWilliam Wang val io = IO(new Bundle { 340f22ee7cSWilliam Wang // address indexed sync read 350f22ee7cSWilliam Wang val raddr = Input(Vec(numRead, UInt(log2Up(numEntries).W))) 360f22ee7cSWilliam Wang val rdata = Output(Vec(numRead, gen)) 370f22ee7cSWilliam Wang // masked sync read (1H) 380f22ee7cSWilliam Wang val mrmask = Input(Vec(numMRead, Vec(numEntries, Bool()))) 390f22ee7cSWilliam Wang val mrdata = Output(Vec(numMRead, gen)) 400f22ee7cSWilliam Wang // address indexed write 410f22ee7cSWilliam Wang val wen = Input(Vec(numWrite, Bool())) 420f22ee7cSWilliam Wang val waddr = Input(Vec(numWrite, UInt(log2Up(numEntries).W))) 430f22ee7cSWilliam Wang val wdata = Input(Vec(numWrite, gen)) 440f22ee7cSWilliam Wang // masked write 450f22ee7cSWilliam Wang val mwmask = Input(Vec(numMWrite, Vec(numEntries, Bool()))) 460f22ee7cSWilliam Wang val mwdata = Input(Vec(numMWrite, gen)) 470f22ee7cSWilliam Wang }) 480f22ee7cSWilliam Wang 490f22ee7cSWilliam Wang val data = Reg(Vec(numEntries, gen)) 500f22ee7cSWilliam Wang 510f22ee7cSWilliam Wang // read ports 520f22ee7cSWilliam Wang for (i <- 0 until numRead) { 530f22ee7cSWilliam Wang io.rdata(i) := data(RegNext(io.raddr(i))) 540f22ee7cSWilliam Wang } 550f22ee7cSWilliam Wang 560f22ee7cSWilliam Wang // masked read ports 570f22ee7cSWilliam Wang for (i <- 0 until numMRead) { 580f22ee7cSWilliam Wang io.mrdata(i) := Mux1H(RegNext(io.mrmask(i)), data) 590f22ee7cSWilliam Wang } 600f22ee7cSWilliam Wang 610f22ee7cSWilliam Wang // write ports (with priorities) 620f22ee7cSWilliam Wang for (i <- 0 until numWrite) { 630f22ee7cSWilliam Wang when (io.wen(i)) { 640f22ee7cSWilliam Wang data(io.waddr(i)) := io.wdata(i) 650f22ee7cSWilliam Wang } 660f22ee7cSWilliam Wang } 670f22ee7cSWilliam Wang 680f22ee7cSWilliam Wang // masked write 690f22ee7cSWilliam Wang for (j <- 0 until numEntries) { 700f22ee7cSWilliam Wang val wen = VecInit((0 until numMWrite).map(i => io.mwmask(i)(j))).asUInt.orR 710f22ee7cSWilliam Wang when (wen) { 720f22ee7cSWilliam Wang data(j) := VecInit((0 until numMWrite).map(i => { 730f22ee7cSWilliam Wang Mux(io.mwmask(i)(j), io.mwdata(i), 0.U).asUInt 740f22ee7cSWilliam Wang })).reduce(_ | _) 750f22ee7cSWilliam Wang } 760f22ee7cSWilliam Wang } 770f22ee7cSWilliam Wang 780f22ee7cSWilliam Wang // DataModuleTemplate should not be used when there're any write conflicts 790f22ee7cSWilliam Wang for (i <- 0 until numWrite) { 800f22ee7cSWilliam Wang for (j <- i+1 until numWrite) { 810f22ee7cSWilliam Wang assert(!(io.wen(i) && io.wen(j) && io.waddr(i) === io.waddr(j))) 820f22ee7cSWilliam Wang } 830f22ee7cSWilliam Wang } 840f22ee7cSWilliam Wang} 85*39f2ec76SWilliam Wang 86*39f2ec76SWilliam Wangclass MaskedBankedSyncDataModuleTemplate[T <: Data]( 87*39f2ec76SWilliam Wang gen: T, 88*39f2ec76SWilliam Wang numEntries: Int, 89*39f2ec76SWilliam Wang numRead: Int, 90*39f2ec76SWilliam Wang numWrite: Int, 91*39f2ec76SWilliam Wang numMRead: Int = 0, 92*39f2ec76SWilliam Wang numMWrite: Int = 0, 93*39f2ec76SWilliam Wang numWBanks: Int = 2 94*39f2ec76SWilliam Wang) extends Module { 95*39f2ec76SWilliam Wang val io = IO(new Bundle { 96*39f2ec76SWilliam Wang // address indexed sync read 97*39f2ec76SWilliam Wang val raddr = Input(Vec(numRead, UInt(log2Up(numEntries).W))) 98*39f2ec76SWilliam Wang val rdata = Output(Vec(numRead, gen)) 99*39f2ec76SWilliam Wang // masked sync read (1H) 100*39f2ec76SWilliam Wang val mrmask = Input(Vec(numMRead, Vec(numEntries, Bool()))) 101*39f2ec76SWilliam Wang val mrdata = Output(Vec(numMRead, gen)) 102*39f2ec76SWilliam Wang // address indexed write 103*39f2ec76SWilliam Wang val wen = Input(Vec(numWrite, Bool())) 104*39f2ec76SWilliam Wang val waddr = Input(Vec(numWrite, UInt(log2Up(numEntries).W))) 105*39f2ec76SWilliam Wang val wdata = Input(Vec(numWrite, gen)) 106*39f2ec76SWilliam Wang // masked write 107*39f2ec76SWilliam Wang val mwmask = Input(Vec(numMWrite, Vec(numEntries, Bool()))) 108*39f2ec76SWilliam Wang val mwdata = Input(Vec(numMWrite, gen)) 109*39f2ec76SWilliam Wang }) 110*39f2ec76SWilliam Wang 111*39f2ec76SWilliam Wang require(isPow2(numWBanks)) 112*39f2ec76SWilliam Wang require(numWBanks >= 2) 113*39f2ec76SWilliam Wang 114*39f2ec76SWilliam Wang val numEntryPerBank = numEntries / numWBanks 115*39f2ec76SWilliam Wang 116*39f2ec76SWilliam Wang val data = Reg(Vec(numEntries, gen)) 117*39f2ec76SWilliam Wang 118*39f2ec76SWilliam Wang // read ports 119*39f2ec76SWilliam Wang for (i <- 0 until numRead) { 120*39f2ec76SWilliam Wang val raddr_dec = RegNext(UIntToOH(io.raddr(i))) 121*39f2ec76SWilliam Wang io.rdata(i) := Mux1H(raddr_dec, data) 122*39f2ec76SWilliam Wang } 123*39f2ec76SWilliam Wang 124*39f2ec76SWilliam Wang // masked read ports 125*39f2ec76SWilliam Wang for (i <- 0 until numMRead) { 126*39f2ec76SWilliam Wang io.mrdata(i) := Mux1H(RegNext(io.mrmask(i)), data) 127*39f2ec76SWilliam Wang } 128*39f2ec76SWilliam Wang 129*39f2ec76SWilliam Wang val waddr_dec = io.waddr.map(a => UIntToOH(a)) 130*39f2ec76SWilliam Wang 131*39f2ec76SWilliam Wang def selectBankMask(in: UInt, bank: Int): UInt = { 132*39f2ec76SWilliam Wang in((bank + 1) * numEntryPerBank - 1, bank * numEntryPerBank) 133*39f2ec76SWilliam Wang } 134*39f2ec76SWilliam Wang 135*39f2ec76SWilliam Wang for (bank <- 0 until numWBanks) { 136*39f2ec76SWilliam Wang // write ports 137*39f2ec76SWilliam Wang // s0: write to bank level buffer 138*39f2ec76SWilliam Wang val s0_bank_waddr_dec = waddr_dec.map(a => selectBankMask(a, bank)) 139*39f2ec76SWilliam Wang val s0_bank_write_en = io.wen.zip(s0_bank_waddr_dec).map(w => w._1 && w._2.orR) 140*39f2ec76SWilliam Wang s0_bank_waddr_dec.zipWithIndex.map(a => 141*39f2ec76SWilliam Wang a._1.suggestName("s0_bank_waddr_dec" + bank + "_" + a._2) 142*39f2ec76SWilliam Wang ) 143*39f2ec76SWilliam Wang s0_bank_write_en.zipWithIndex.map(a => 144*39f2ec76SWilliam Wang a._1.suggestName("s0_bank_write_en" + bank + "_" + a._2) 145*39f2ec76SWilliam Wang ) 146*39f2ec76SWilliam Wang // s1: write data to entries 147*39f2ec76SWilliam Wang val s1_bank_waddr_dec = s0_bank_waddr_dec.zip(s0_bank_write_en).map(w => RegEnable(w._1, w._2)) 148*39f2ec76SWilliam Wang val s1_bank_wen = RegNext(VecInit(s0_bank_write_en)) 149*39f2ec76SWilliam Wang val s1_wdata = io.wdata.zip(s0_bank_write_en).map(w => RegEnable(w._1, w._2)) 150*39f2ec76SWilliam Wang s1_bank_waddr_dec.zipWithIndex.map(a => 151*39f2ec76SWilliam Wang a._1.suggestName("s1_bank_waddr_dec" + bank + "_" + a._2) 152*39f2ec76SWilliam Wang ) 153*39f2ec76SWilliam Wang s1_bank_wen.zipWithIndex.map(a => 154*39f2ec76SWilliam Wang a._1.suggestName("s1_bank_wen" + bank + "_" + a._2) 155*39f2ec76SWilliam Wang ) 156*39f2ec76SWilliam Wang s1_wdata.zipWithIndex.map(a => 157*39f2ec76SWilliam Wang a._1.suggestName("s1_wdata" + bank + "_" + a._2) 158*39f2ec76SWilliam Wang ) 159*39f2ec76SWilliam Wang // masked write ports 160*39f2ec76SWilliam Wang // s0: write to bank level buffer 161*39f2ec76SWilliam Wang val s0_bank_mwmask = io.mwmask.map(a => selectBankMask(a.asUInt, bank)) 162*39f2ec76SWilliam Wang val s0_bank_mwrite_en = s0_bank_mwmask.map(w => w.orR) 163*39f2ec76SWilliam Wang s0_bank_mwmask.zipWithIndex.map(a => 164*39f2ec76SWilliam Wang a._1.suggestName("s0_bank_mwmask" + bank + "_" + a._2) 165*39f2ec76SWilliam Wang ) 166*39f2ec76SWilliam Wang s0_bank_mwrite_en.zipWithIndex.map(a => 167*39f2ec76SWilliam Wang a._1.suggestName("s0_bank_mwrite_en" + bank + "_" + a._2) 168*39f2ec76SWilliam Wang ) 169*39f2ec76SWilliam Wang // s1: write data to entries 170*39f2ec76SWilliam Wang val s1_bank_mwmask = s0_bank_mwmask.map(a => RegNext(a)) 171*39f2ec76SWilliam Wang val s1_mwdata = io.mwdata.zip(s0_bank_mwrite_en).map(w => RegEnable(w._1, w._2)) 172*39f2ec76SWilliam Wang s1_bank_mwmask.zipWithIndex.map(a => 173*39f2ec76SWilliam Wang a._1.suggestName("s1_bank_mwmask" + bank + "_" + a._2) 174*39f2ec76SWilliam Wang ) 175*39f2ec76SWilliam Wang s1_mwdata.zipWithIndex.map(a => 176*39f2ec76SWilliam Wang a._1.suggestName("s1_mwdata" + bank + "_" + a._2) 177*39f2ec76SWilliam Wang ) 178*39f2ec76SWilliam Wang 179*39f2ec76SWilliam Wang // entry write 180*39f2ec76SWilliam Wang for (entry <- 0 until numEntryPerBank) { 181*39f2ec76SWilliam Wang // write ports 182*39f2ec76SWilliam Wang val s1_entry_write_en_vec = s1_bank_wen.zip(s1_bank_waddr_dec).map(w => w._1 && w._2(entry)) 183*39f2ec76SWilliam Wang val s1_entry_write_en = VecInit(s1_entry_write_en_vec).asUInt.orR 184*39f2ec76SWilliam Wang val s1_entry_write_data = Mux1H(s1_entry_write_en_vec, s1_wdata) 185*39f2ec76SWilliam Wang // masked write ports 186*39f2ec76SWilliam Wang val s1_bank_mwrite_en_vec = s1_bank_mwmask.map(_(entry)) 187*39f2ec76SWilliam Wang val s1_bank_mwrite_en = VecInit(s1_bank_mwrite_en_vec).asUInt.orR 188*39f2ec76SWilliam Wang val s1_bank_mwrite_data = Mux1H(s1_bank_mwrite_en_vec, s1_mwdata) 189*39f2ec76SWilliam Wang when (s1_entry_write_en || s1_bank_mwrite_en) { 190*39f2ec76SWilliam Wang data(bank * numEntryPerBank + entry) := Mux1H( 191*39f2ec76SWilliam Wang Seq(s1_entry_write_en, s1_bank_mwrite_en), 192*39f2ec76SWilliam Wang Seq(s1_entry_write_data, s1_bank_mwrite_data) 193*39f2ec76SWilliam Wang ) 194*39f2ec76SWilliam Wang } 195*39f2ec76SWilliam Wang s1_entry_write_en_vec.zipWithIndex.map(a => 196*39f2ec76SWilliam Wang a._1.suggestName("s1_entry_write_en_vec" + bank + "_" + entry + "_" + a._2) 197*39f2ec76SWilliam Wang ) 198*39f2ec76SWilliam Wang s1_bank_mwrite_en_vec.zipWithIndex.map(a => 199*39f2ec76SWilliam Wang a._1.suggestName("s1_bank_mwrite_en_vec" + bank + "_" + entry + "_" + a._2) 200*39f2ec76SWilliam Wang ) 201*39f2ec76SWilliam Wang s1_entry_write_en.suggestName("s1_entry_write_en" + bank + "_" + entry) 202*39f2ec76SWilliam Wang s1_entry_write_data.suggestName("s1_entry_write_data" + bank + "_" + entry) 203*39f2ec76SWilliam Wang s1_bank_mwrite_en.suggestName("s1_bank_mwrite_en" + bank + "_" + entry) 204*39f2ec76SWilliam Wang s1_bank_mwrite_data.suggestName("s1_bank_mwrite_data" + bank + "_" + entry) 205*39f2ec76SWilliam Wang } 206*39f2ec76SWilliam Wang } 207*39f2ec76SWilliam Wang} 208