xref: /XiangShan/src/main/scala/xiangshan/cache/dcache/CtrlUnit.scala (revision 94aa21c6009c2f39c5c5dae9c87260c78887efcc)
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}