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.cache 18 19import org.chipsalliance.cde.config.Parameters 20import chisel3._ 21import chisel3.util._ 22import freechips.rocketchip.subsystem._ 23import freechips.rocketchip.diplomacy._ 24import freechips.rocketchip.regmapper._ 25import freechips.rocketchip.tilelink._ 26import freechips.rocketchip.interrupts._ 27import freechips.rocketchip.util._ 28import chisel3.experimental.SourceInfo 29import xiangshan._ 30 31case class L1CacheCtrlParams ( 32 address: AddressSet, 33 beatBytes: Int = 8, 34) { 35 def maxBanks = 1 36 def bankBytes = 128 37 38 def regWidth = 64 39 def regBytes = regWidth / 8 40 41 def ctrlOffset = 0x0 42 def delayOffset = ctrlOffset + regBytes 43 def maskOffset = delayOffset + regBytes 44 45 def nSignalComps = 2 46} 47 48class CtrlUnitCtrlBundle(implicit p: Parameters) extends XSBundle with HasDCacheParameters { 49 val zero0 = UInt((60-DCacheBanks).W) // padding bits 50 val bank = UInt(DCacheBanks.W) // bank enable 51 val comp = UInt(1.W) // components: 1'b0 tag, 1'b1 data 52 val ede = Bool() // error delay enable 53 val persist = Bool() // persist inject 54 val ese = Bool() // error signaling enable 55} 56 57class CtrlUnitSignalingBundle(implicit p: Parameters) extends XSBundle with HasDCacheParameters { 58 val valid = Bool() 59 val mask = UInt(DCacheSRAMRowBits.W) 60} 61 62class CtrlUnit(params: L1CacheCtrlParams)(implicit p: Parameters) extends LazyModule 63 with HasDCacheParameters 64{ 65 val device: SimpleDevice = new SimpleDevice("L1DCacheCtrl", Seq("xiangshan,l1dcache_ctrl")) 66 67 val node: TLRegisterNode = TLRegisterNode( 68 address = Seq(params.address), 69 device = device, 70 beatBytes = params.beatBytes, 71 concurrency = 1, 72 ) 73 74 lazy val module = new CtrlUnitImp 75 76 class CtrlUnitImp extends LazyModuleImp(this) { 77 val io_pseudoError = IO(Vec(params.nSignalComps, DecoupledIO(Vec(DCacheBanks, new CtrlUnitSignalingBundle)))) 78 79 require(params.maxBanks > 0, "At least one bank!") 80 require(params.maxBanks == 1, "Is it necessary to have more than 1 bank?") 81 require(params.regWidth == DCacheSRAMRowBits, "regWidth must be equal to DCacheSRAMRowBits!") 82 val ctrlRegs = RegInit(VecInit(Seq.fill(1)(0.U(params.regWidth.W)))) 83 val delayRegs = RegInit(VecInit(Seq.fill(1)(0.U(params.regWidth.W)))) 84 val maskRegs = RegInit(VecInit(Seq.fill(DCacheBanks)(0.U(DCacheSRAMRowBits.W)))) 85 val counterRegs = RegInit(VecInit(Seq.fill(1)(0.U(params.regWidth.W)))) 86 87 io_pseudoError.zipWithIndex.foreach { 88 case (inj, i) => 89 val ctrlReg = ctrlRegs.head 90 val ctrlRegBundle = ctrlRegs.head.asTypeOf(new CtrlUnitCtrlBundle) 91 val delayReg = delayRegs.head 92 val counterReg = counterRegs.head 93 94 require(log2Up(io_pseudoError.length) == ctrlRegBundle.comp.getWidth, "io_pseudoError must equal number of components!") 95 inj.valid := ctrlRegBundle.ese && (ctrlRegBundle.comp === i.U) && (!ctrlRegBundle.ede || counterReg === 0.U) 96 inj.bits.zip(ctrlRegBundle.bank.asBools).zip(maskRegs).map { 97 case ((bankOut, bankEnable), mask) => 98 bankOut.valid := bankEnable 99 bankOut.mask := mask 100 } 101 102 when (inj.fire) { 103 val newCtrlReg = WireInit(0.U.asTypeOf(ctrlRegBundle)) 104 newCtrlReg := ctrlRegBundle 105 newCtrlReg.ese := Mux(ctrlRegBundle.persist, ctrlRegBundle.ese, false.B) 106 107 when (newCtrlReg.ese && newCtrlReg.ede) { 108 counterReg := Mux(newCtrlReg.persist, delayReg, 0.U) 109 } 110 ctrlReg := newCtrlReg.asUInt 111 } 112 } 113 114 ctrlRegs.map(_.asTypeOf(new CtrlUnitCtrlBundle)).zip(counterRegs).zipWithIndex.foreach { 115 case ((ctl, cnt), i) => 116 when (ctl.ese && ctl.ede && cnt =/= 0.U) { 117 cnt := cnt - 1.U 118 } 119 } 120 121 def ctrlRegDesc(i: Int) = 122 RegFieldDesc( 123 name = s"control_$i", 124 desc = s"Acting control of controller $i", 125 group = Some(s"controll_${i}"), 126 groupDesc = Some(s"Acting control of controller ${i}"), 127 reset = Some(0) 128 ) 129 130 def delayRegDesc(i: Int) = 131 RegFieldDesc( 132 name = s"delay_$i", 133 desc = s"pseudo error delay $i", 134 group = Some(s"delay_${i}"), 135 groupDesc = Some(s"pseudo error delay ${i}"), 136 reset = Some(0) 137 ) 138 139 def maskRegDesc(i: Int) = 140 RegFieldDesc( 141 name = s"mask_$i", 142 desc = s"pseudo error toggle mask$i", 143 group = Some(s"mask_${i}"), 144 groupDesc = Some(s"pseudo error toggle mask ${i}"), 145 reset = Some(0) 146 ) 147 148 def ctrlRegField(x: UInt, i: Int) = { 149 RegField(params.regWidth, x, ctrlRegDesc(i)) 150 } 151 152 def delayRegField(x: UInt, i: Int) = { 153 RegField(params.regWidth, 154 RegReadFn { valid => 155 (true.B, x) 156 }, 157 RegWriteFn { (valid, data) => 158 when(valid) { x := data; counterRegs(i) := data } 159 true.B 160 }, 161 delayRegDesc(i) 162 ) 163 } 164 165 def maskRegField(x: UInt, i: Int) = { 166 RegField(params.regWidth, x, maskRegDesc(i)) 167 } 168 169 val ctrlRegFields = ctrlRegs.zipWithIndex.map { 170 case (reg, i) => 171 params.ctrlOffset -> Seq(ctrlRegField(reg, i)) 172 } 173 val delayRegFields = delayRegs.zipWithIndex.map { 174 case (reg, i) => 175 params.delayOffset -> Seq(delayRegField(reg, i)) 176 } 177 val maskRegFields = maskRegs.zipWithIndex.map { 178 case (reg, i) => 179 (params.maskOffset + 8 * i) -> Seq(maskRegField(reg, i)) 180 } 181 182 node.regmap((ctrlRegFields ++ delayRegFields ++ maskRegFields):_*) 183 } 184}