11f0e2dc7SJiawei Lin/*************************************************************************************** 2e3da8badSTang Haojin* Copyright (c) 2024 Beijing Institute of Open Source Chip (BOSC) 3e3da8badSTang Haojin* Copyright (c) 2020-2024 Institute of Computing Technology, Chinese Academy of Sciences 41f0e2dc7SJiawei Lin* Copyright (c) 2020-2021 Peng Cheng Laboratory 51f0e2dc7SJiawei Lin* 61f0e2dc7SJiawei Lin* XiangShan is licensed under Mulan PSL v2. 71f0e2dc7SJiawei Lin* You can use this software according to the terms and conditions of the Mulan PSL v2. 81f0e2dc7SJiawei Lin* You may obtain a copy of Mulan PSL v2 at: 91f0e2dc7SJiawei Lin* http://license.coscl.org.cn/MulanPSL2 101f0e2dc7SJiawei Lin* 111f0e2dc7SJiawei Lin* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 121f0e2dc7SJiawei Lin* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 131f0e2dc7SJiawei Lin* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 141f0e2dc7SJiawei Lin* 151f0e2dc7SJiawei Lin* See the Mulan PSL v2 for more details. 161f0e2dc7SJiawei Lin***************************************************************************************/ 171f0e2dc7SJiawei Lin 181f0e2dc7SJiawei Linpackage xiangshan.cache 191f0e2dc7SJiawei Lin 208891a219SYinan Xuimport org.chipsalliance.cde.config.Parameters 211f0e2dc7SJiawei Linimport chisel3._ 221f0e2dc7SJiawei Linimport chisel3.util._ 231f0e2dc7SJiawei Linimport freechips.rocketchip.tilelink.{ClientMetadata, TLClientParameters, TLEdgeOut} 24*11269ca7STang Haojinimport utility.{Code, ParallelOR, ReplacementPolicy, XSDebug} 25*11269ca7STang Haojinimport utility.sram.SRAMTemplate 261f0e2dc7SJiawei Lin 271f0e2dc7SJiawei Linimport scala.math.max 281f0e2dc7SJiawei Lin 291f0e2dc7SJiawei Linclass DuplicatedDataArray(implicit p: Parameters) extends AbstractDataArray { 301f0e2dc7SJiawei Lin val singlePort = true 311f0e2dc7SJiawei Lin val readHighPriority = false 321f0e2dc7SJiawei Lin 331f0e2dc7SJiawei Lin def getECCFromEncWord(encWord: UInt) = { 341f0e2dc7SJiawei Lin require(encWord.getWidth == encWordBits) 351f0e2dc7SJiawei Lin encWord(encWordBits - 1, wordBits) 361f0e2dc7SJiawei Lin } 371f0e2dc7SJiawei Lin 381f0e2dc7SJiawei Lin def getECCFromRow(row: UInt) = { 391f0e2dc7SJiawei Lin require(row.getWidth == rowBits) 401f0e2dc7SJiawei Lin VecInit((0 until rowWords).map { w => 411f0e2dc7SJiawei Lin val word = row(wordBits * (w + 1) - 1, wordBits * w) 421f0e2dc7SJiawei Lin getECCFromEncWord(cacheParams.dataCode.encode(word)) 431f0e2dc7SJiawei Lin }) 441f0e2dc7SJiawei Lin } 451f0e2dc7SJiawei Lin 46935edac4STang Haojin val waddr = (io.write.bits.addr >> blockOffBits).asUInt 471f0e2dc7SJiawei Lin val raddrs = io.read.map(r => (r.bits.addr >> blockOffBits).asUInt) 481f0e2dc7SJiawei Lin io.write.ready := (if (readHighPriority) { 491f0e2dc7SJiawei Lin if (singlePort) { 501f0e2dc7SJiawei Lin !VecInit(io.read.map(_.valid)).asUInt.orR 511f0e2dc7SJiawei Lin } else { 521f0e2dc7SJiawei Lin !(Cat(io.read.zipWithIndex.map { case (r, i) => r.valid && raddrs(i) === waddr }).orR) 531f0e2dc7SJiawei Lin } 541f0e2dc7SJiawei Lin } else { 551f0e2dc7SJiawei Lin true.B 561f0e2dc7SJiawei Lin }) 571f0e2dc7SJiawei Lin 581f0e2dc7SJiawei Lin // wrap a data row and a ecc row 591f0e2dc7SJiawei Lin class DataSRAMGroup extends Module { 601f0e2dc7SJiawei Lin val io = IO(new Bundle() { 611f0e2dc7SJiawei Lin val wen, ren = Input(Bool()) 621f0e2dc7SJiawei Lin val waddr, raddr = Input(UInt()) 631f0e2dc7SJiawei Lin val wdata = Input(UInt(rowBits.W)) 641f0e2dc7SJiawei Lin val w_way_en, r_way_en = Input(UInt(nWays.W)) 651f0e2dc7SJiawei Lin val rdata = Output(UInt()) 661f0e2dc7SJiawei Lin }) 671f0e2dc7SJiawei Lin 685adc4829SYanqin Li val r_way_en_reg = RegEnable(io.r_way_en, io.ren) 69e3da8badSTang Haojin val data_array = Seq.fill(nWays) { 701f0e2dc7SJiawei Lin Module(new SRAMTemplate( 711f0e2dc7SJiawei Lin Bits(rowBits.W), 721f0e2dc7SJiawei Lin set = nSets, 731f0e2dc7SJiawei Lin way = 1, 741f0e2dc7SJiawei Lin shouldReset = false, 751f0e2dc7SJiawei Lin holdRead = false, 761f0e2dc7SJiawei Lin singlePort = singlePort 771f0e2dc7SJiawei Lin )) 781f0e2dc7SJiawei Lin } 791f0e2dc7SJiawei Lin 801f0e2dc7SJiawei Lin for (w <- 0 until nWays) { 811f0e2dc7SJiawei Lin val wen = io.wen && io.w_way_en(w) 821f0e2dc7SJiawei Lin data_array(w).io.w.req.valid := wen 831f0e2dc7SJiawei Lin data_array(w).io.w.req.bits.apply( 841f0e2dc7SJiawei Lin setIdx = io.waddr, 851f0e2dc7SJiawei Lin data = io.wdata, 861f0e2dc7SJiawei Lin waymask = 1.U 871f0e2dc7SJiawei Lin ) 881f0e2dc7SJiawei Lin data_array(w).io.r.req.valid := io.ren 891f0e2dc7SJiawei Lin data_array(w).io.r.req.bits.apply(setIdx = io.raddr) 901f0e2dc7SJiawei Lin } 911f0e2dc7SJiawei Lin 921f0e2dc7SJiawei Lin val half = nWays / 2 931f0e2dc7SJiawei Lin val data_read = data_array.map(_.io.r.resp.data(0)) 941f0e2dc7SJiawei Lin val data_left = Mux1H(r_way_en_reg.tail(half), data_read.take(half)) 951f0e2dc7SJiawei Lin val data_right = Mux1H(r_way_en_reg.head(half), data_read.drop(half)) 961f0e2dc7SJiawei Lin 97935edac4STang Haojin val sel_low = r_way_en_reg.tail(half).orR 981f0e2dc7SJiawei Lin val row_data = Mux(sel_low, data_left, data_right) 991f0e2dc7SJiawei Lin 1001f0e2dc7SJiawei Lin io.rdata := row_data 1011f0e2dc7SJiawei Lin } 1021f0e2dc7SJiawei Lin 1031f0e2dc7SJiawei Lin for (j <- 0 until 3) { 1041f0e2dc7SJiawei Lin val raddr = raddrs(j) 1051f0e2dc7SJiawei Lin val rmask = io.read(j).bits.rmask 1061f0e2dc7SJiawei Lin 1071f0e2dc7SJiawei Lin // for single port SRAM, do not allow read and write in the same cycle 1081f0e2dc7SJiawei Lin // for dual port SRAM, raddr === waddr is undefined behavior 1091f0e2dc7SJiawei Lin val rwhazard = if (singlePort) io.write.valid else io.write.valid && waddr === raddr 1101f0e2dc7SJiawei Lin io.read(j).ready := (if (readHighPriority) true.B else !rwhazard) 1111f0e2dc7SJiawei Lin 1121f0e2dc7SJiawei Lin // use way_en to select a way after data read out 113935edac4STang Haojin assert(!(RegNext(io.read(j).fire && PopCount(io.read(j).bits.way_en) > 1.U))) 1145adc4829SYanqin Li val way_en = RegEnable(io.read(j).bits.way_en, io.read(j).fire) 1151f0e2dc7SJiawei Lin 1161f0e2dc7SJiawei Lin val row_error = Wire(Vec(blockRows, Vec(rowWords, Bool()))) 1171f0e2dc7SJiawei Lin for (r <- 0 until blockRows) { 1181f0e2dc7SJiawei Lin val ecc_array = Module(new SRAMTemplate( 1191f0e2dc7SJiawei Lin Vec(rowWords, Bits(eccBits.W)), 1201f0e2dc7SJiawei Lin set = nSets, 1211f0e2dc7SJiawei Lin way = nWays, 1221f0e2dc7SJiawei Lin shouldReset = false, 1231f0e2dc7SJiawei Lin holdRead = false, 1241f0e2dc7SJiawei Lin singlePort = singlePort 1251f0e2dc7SJiawei Lin )) 1261f0e2dc7SJiawei Lin ecc_array.io.w.req.valid := io.write.valid && io.write.bits.wmask(r) 1271f0e2dc7SJiawei Lin ecc_array.io.w.req.bits.apply( 1281f0e2dc7SJiawei Lin setIdx = waddr, 1291f0e2dc7SJiawei Lin data = getECCFromRow(io.write.bits.data(r)), 1301f0e2dc7SJiawei Lin waymask = io.write.bits.way_en 1311f0e2dc7SJiawei Lin ) 1328b33cd30Sklin02 XSDebug(ecc_array.io.w.req.valid, 1338b33cd30Sklin02 p"write in ecc sram ${j.U} row ${r.U}: setIdx=${Hexadecimal(ecc_array.io.w.req.bits.setIdx)} ecc(0)=${Hexadecimal(getECCFromRow(io.write.bits.data(r))(0))} ecc(1)=${Hexadecimal(getECCFromRow(io.write.bits.data(r))(1))} waymask=${Hexadecimal(io.write.bits.way_en)}\n") 1341f0e2dc7SJiawei Lin ecc_array.io.r.req.valid := io.read(j).valid && rmask(r) 1351f0e2dc7SJiawei Lin ecc_array.io.r.req.bits.apply(setIdx = raddr) 1361f0e2dc7SJiawei Lin 1371f0e2dc7SJiawei Lin val dataGroup = Module(new DataSRAMGroup) 1381f0e2dc7SJiawei Lin dataGroup.io.wen := io.write.valid && io.write.bits.wmask(r) 1391f0e2dc7SJiawei Lin dataGroup.io.w_way_en := io.write.bits.way_en 1401f0e2dc7SJiawei Lin dataGroup.io.waddr := waddr 1411f0e2dc7SJiawei Lin dataGroup.io.wdata := io.write.bits.data(r) 1421f0e2dc7SJiawei Lin dataGroup.io.ren := io.read(j).valid && io.read(j).bits.rmask(r) 1431f0e2dc7SJiawei Lin dataGroup.io.r_way_en := io.read(j).bits.way_en 1441f0e2dc7SJiawei Lin dataGroup.io.raddr := raddr 1451f0e2dc7SJiawei Lin 1461f0e2dc7SJiawei Lin val ecc_resp = Wire(Vec(rowWords, Vec(nWays, Bits(eccBits.W)))) 1471f0e2dc7SJiawei Lin for(w <- 0 until nWays){ 1481f0e2dc7SJiawei Lin for(k <- 0 until rowWords){ 1491f0e2dc7SJiawei Lin ecc_resp(k)(w) := ecc_array.io.r.resp.data(w)(k) 1501f0e2dc7SJiawei Lin } 1511f0e2dc7SJiawei Lin } 1521f0e2dc7SJiawei Lin val ecc_resp_chosen = Wire(Vec(rowWords, Bits(eccBits.W))) 1531f0e2dc7SJiawei Lin val data_resp_chosen = Wire(Vec(rowWords, Bits(wordBits.W))) 1541f0e2dc7SJiawei Lin data_resp_chosen := dataGroup.io.rdata.asTypeOf(data_resp_chosen) 1551f0e2dc7SJiawei Lin for (k <- 0 until rowWords) { 1561f0e2dc7SJiawei Lin ecc_resp_chosen(k) := Mux1H(way_en, ecc_resp(k)) 1571f0e2dc7SJiawei Lin } 158e3da8badSTang Haojin io.resp(j)(r) := Cat((0 until rowWords).reverseIterator.map { 1591f0e2dc7SJiawei Lin k => { 1601f0e2dc7SJiawei Lin val data = Cat(ecc_resp_chosen(k), data_resp_chosen(k)) 1611f0e2dc7SJiawei Lin row_error(r)(k) := dcacheParameters.dataCode.decode(data).error && RegNext(rmask(r)) 1621f0e2dc7SJiawei Lin data 1631f0e2dc7SJiawei Lin } 164e3da8badSTang Haojin }.toSeq) 1650184a80eSYanqin Li io.errors(j).bits.report_to_beu := RegNext(io.read(j).fire) && Cat(row_error.flatten).orR 1665adc4829SYanqin Li io.errors(j).bits.paddr := RegEnable(io.read(j).bits.addr, io.read(j).fire) 1671f0e2dc7SJiawei Lin } 1681f0e2dc7SJiawei Lin 1691f0e2dc7SJiawei Lin io.nacks(j) := false.B 1701f0e2dc7SJiawei Lin } 1711f0e2dc7SJiawei Lin} 172