xref: /XiangShan/src/main/scala/xiangshan/cache/dcache/CtrlUnit.scala (revision 72dab9745cef33532f03ca252d63455645aaab8a)
1*72dab974Scz4e/***************************************************************************************
2*72dab974Scz4e* Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences
3*72dab974Scz4e* Copyright (c) 2020-2021 Peng Cheng Laboratory
4*72dab974Scz4e*
5*72dab974Scz4e* XiangShan is licensed under Mulan PSL v2.
6*72dab974Scz4e* You can use this software according to the terms and conditions of the Mulan PSL v2.
7*72dab974Scz4e* You may obtain a copy of Mulan PSL v2 at:
8*72dab974Scz4e*          http://license.coscl.org.cn/MulanPSL2
9*72dab974Scz4e*
10*72dab974Scz4e* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
11*72dab974Scz4e* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
12*72dab974Scz4e* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
13*72dab974Scz4e*
14*72dab974Scz4e* See the Mulan PSL v2 for more details.
15*72dab974Scz4e***************************************************************************************/
16*72dab974Scz4e
17*72dab974Scz4epackage xiangshan.cache
18*72dab974Scz4e
19*72dab974Scz4eimport org.chipsalliance.cde.config.Parameters
20*72dab974Scz4eimport chisel3._
21*72dab974Scz4eimport chisel3.util._
22*72dab974Scz4eimport freechips.rocketchip.subsystem._
23*72dab974Scz4eimport freechips.rocketchip.diplomacy._
24*72dab974Scz4eimport freechips.rocketchip.regmapper._
25*72dab974Scz4eimport freechips.rocketchip.tilelink._
26*72dab974Scz4eimport freechips.rocketchip.interrupts._
27*72dab974Scz4eimport freechips.rocketchip.util._
28*72dab974Scz4eimport chisel3.experimental.SourceInfo
29*72dab974Scz4eimport xiangshan._
30*72dab974Scz4e
31*72dab974Scz4ecase class L1CacheCtrlParams (
32*72dab974Scz4e  address: AddressSet,
33*72dab974Scz4e  beatBytes: Int = 8,
34*72dab974Scz4e) {
35*72dab974Scz4e  def maxBanks    = 1
36*72dab974Scz4e  def bankBytes   = 128
37*72dab974Scz4e
38*72dab974Scz4e  def regWidth    = 64
39*72dab974Scz4e  def regBytes    = regWidth / 8
40*72dab974Scz4e
41*72dab974Scz4e  def ctrlOffset  = 0x0
42*72dab974Scz4e  def delayOffset = ctrlOffset + regBytes
43*72dab974Scz4e  def maskOffset  = delayOffset + regBytes
44*72dab974Scz4e
45*72dab974Scz4e  def nSignalComps = 2
46*72dab974Scz4e}
47*72dab974Scz4e
48*72dab974Scz4eclass CtrlUnitCtrlBundle(implicit p: Parameters) extends XSBundle with HasDCacheParameters {
49*72dab974Scz4e  val zero0   = UInt((60-DCacheBanks).W)  // padding bits
50*72dab974Scz4e  val bank    = UInt(DCacheBanks.W) // bank enable
51*72dab974Scz4e  val comp    = UInt(1.W)   // components: 1'b0 tag, 1'b1 data
52*72dab974Scz4e  val ede     = Bool()      // error delay enable
53*72dab974Scz4e  val persist = Bool()  // persist inject
54*72dab974Scz4e  val ese     = Bool()      // error signaling enable
55*72dab974Scz4e}
56*72dab974Scz4e
57*72dab974Scz4eclass CtrlUnitSignalingBundle(implicit p: Parameters) extends XSBundle with HasDCacheParameters {
58*72dab974Scz4e  val valid = Bool()
59*72dab974Scz4e  val mask  = UInt(DCacheSRAMRowBits.W)
60*72dab974Scz4e}
61*72dab974Scz4e
62*72dab974Scz4eclass CtrlUnit(params: L1CacheCtrlParams)(implicit p: Parameters) extends LazyModule
63*72dab974Scz4e  with HasDCacheParameters
64*72dab974Scz4e{
65*72dab974Scz4e  val device: SimpleDevice = new SimpleDevice("L1DCacheCtrl", Seq("xiangshan,l1dcache_ctrl"))
66*72dab974Scz4e
67*72dab974Scz4e  val node: TLRegisterNode = TLRegisterNode(
68*72dab974Scz4e    address     = Seq(params.address),
69*72dab974Scz4e    device      = device,
70*72dab974Scz4e    beatBytes   = params.beatBytes,
71*72dab974Scz4e    concurrency = 1,
72*72dab974Scz4e  )
73*72dab974Scz4e
74*72dab974Scz4e  lazy val module = new CtrlUnitImp
75*72dab974Scz4e
76*72dab974Scz4e  class CtrlUnitImp extends LazyModuleImp(this) {
77*72dab974Scz4e    val io_pseudoError = IO(Vec(params.nSignalComps, DecoupledIO(Vec(DCacheBanks, new CtrlUnitSignalingBundle))))
78*72dab974Scz4e
79*72dab974Scz4e    require(params.maxBanks > 0, "At least one bank!")
80*72dab974Scz4e    require(params.maxBanks == 1, "Is it necessary to have more than 1 bank?")
81*72dab974Scz4e    require(params.regWidth == DCacheSRAMRowBits, "regWidth must be equal to DCacheSRAMRowBits!")
82*72dab974Scz4e    val ctrlRegs  = RegInit(VecInit(Seq.fill(1)(0.U(params.regWidth.W))))
83*72dab974Scz4e    val delayRegs = RegInit(VecInit(Seq.fill(1)(0.U(params.regWidth.W))))
84*72dab974Scz4e    val maskRegs  = RegInit(VecInit(Seq.fill(DCacheBanks)(0.U(DCacheSRAMRowBits.W))))
85*72dab974Scz4e    val counterRegs = RegInit(VecInit(Seq.fill(1)(0.U(params.regWidth.W))))
86*72dab974Scz4e
87*72dab974Scz4e    io_pseudoError.zipWithIndex.foreach {
88*72dab974Scz4e      case (inj, i) =>
89*72dab974Scz4e        val ctrlReg = ctrlRegs.head
90*72dab974Scz4e        val ctrlRegBundle = ctrlRegs.head.asTypeOf(new CtrlUnitCtrlBundle)
91*72dab974Scz4e        val delayReg = delayRegs.head
92*72dab974Scz4e        val counterReg = counterRegs.head
93*72dab974Scz4e
94*72dab974Scz4e        require(log2Up(io_pseudoError.length) == ctrlRegBundle.comp.getWidth, "io_pseudoError must equal number of components!")
95*72dab974Scz4e        inj.valid := ctrlRegBundle.ese && (ctrlRegBundle.comp === i.U) && (!ctrlRegBundle.ede || counterReg === 0.U)
96*72dab974Scz4e        inj.bits.zip(ctrlRegBundle.bank.asBools).zip(maskRegs).map {
97*72dab974Scz4e          case ((bankOut, bankEnable), mask) =>
98*72dab974Scz4e            bankOut.valid := bankEnable
99*72dab974Scz4e            bankOut.mask  := mask
100*72dab974Scz4e        }
101*72dab974Scz4e
102*72dab974Scz4e        when (inj.fire) {
103*72dab974Scz4e          val newCtrlReg = WireInit(0.U.asTypeOf(ctrlRegBundle))
104*72dab974Scz4e          newCtrlReg := ctrlRegBundle
105*72dab974Scz4e          newCtrlReg.ese := Mux(ctrlRegBundle.persist, ctrlRegBundle.ese, false.B)
106*72dab974Scz4e
107*72dab974Scz4e          when (newCtrlReg.ese && newCtrlReg.ede) {
108*72dab974Scz4e            counterReg := Mux(newCtrlReg.persist, delayReg, 0.U)
109*72dab974Scz4e          }
110*72dab974Scz4e          ctrlReg := newCtrlReg.asUInt
111*72dab974Scz4e        }
112*72dab974Scz4e    }
113*72dab974Scz4e
114*72dab974Scz4e    ctrlRegs.map(_.asTypeOf(new CtrlUnitCtrlBundle)).zip(counterRegs).zipWithIndex.foreach {
115*72dab974Scz4e      case ((ctl, cnt), i) =>
116*72dab974Scz4e        when (ctl.ese && ctl.ede && cnt =/= 0.U) {
117*72dab974Scz4e          cnt := cnt - 1.U
118*72dab974Scz4e        }
119*72dab974Scz4e    }
120*72dab974Scz4e
121*72dab974Scz4e    def ctrlRegDesc(i: Int) =
122*72dab974Scz4e      RegFieldDesc(
123*72dab974Scz4e        name      = s"control_$i",
124*72dab974Scz4e        desc      = s"Acting control of controller $i",
125*72dab974Scz4e        group     = Some(s"controll_${i}"),
126*72dab974Scz4e        groupDesc = Some(s"Acting control of controller ${i}"),
127*72dab974Scz4e        reset     = Some(0)
128*72dab974Scz4e      )
129*72dab974Scz4e
130*72dab974Scz4e    def delayRegDesc(i: Int) =
131*72dab974Scz4e      RegFieldDesc(
132*72dab974Scz4e        name      = s"delay_$i",
133*72dab974Scz4e        desc      = s"pseudo error delay $i",
134*72dab974Scz4e        group     = Some(s"delay_${i}"),
135*72dab974Scz4e        groupDesc = Some(s"pseudo error delay ${i}"),
136*72dab974Scz4e        reset     = Some(0)
137*72dab974Scz4e      )
138*72dab974Scz4e
139*72dab974Scz4e    def maskRegDesc(i: Int) =
140*72dab974Scz4e      RegFieldDesc(
141*72dab974Scz4e        name      = s"mask_$i",
142*72dab974Scz4e        desc      = s"pseudo error toggle mask$i",
143*72dab974Scz4e        group     = Some(s"mask_${i}"),
144*72dab974Scz4e        groupDesc = Some(s"pseudo error toggle mask ${i}"),
145*72dab974Scz4e        reset     = Some(0)
146*72dab974Scz4e      )
147*72dab974Scz4e
148*72dab974Scz4e    def ctrlRegField(x: UInt, i: Int) = {
149*72dab974Scz4e      RegField(params.regWidth, x, ctrlRegDesc(i))
150*72dab974Scz4e    }
151*72dab974Scz4e
152*72dab974Scz4e    def delayRegField(x: UInt, i: Int) = {
153*72dab974Scz4e      RegField(params.regWidth,
154*72dab974Scz4e        RegReadFn { valid =>
155*72dab974Scz4e          (true.B, x)
156*72dab974Scz4e        },
157*72dab974Scz4e        RegWriteFn { (valid, data) =>
158*72dab974Scz4e          when(valid) { x := data; counterRegs(i) := data }
159*72dab974Scz4e          true.B
160*72dab974Scz4e        },
161*72dab974Scz4e        delayRegDesc(i)
162*72dab974Scz4e      )
163*72dab974Scz4e    }
164*72dab974Scz4e
165*72dab974Scz4e    def maskRegField(x: UInt, i: Int) = {
166*72dab974Scz4e      RegField(params.regWidth, x, maskRegDesc(i))
167*72dab974Scz4e    }
168*72dab974Scz4e
169*72dab974Scz4e    val ctrlRegFields = ctrlRegs.zipWithIndex.map {
170*72dab974Scz4e      case (reg, i) =>
171*72dab974Scz4e        params.ctrlOffset -> Seq(ctrlRegField(reg, i))
172*72dab974Scz4e    }
173*72dab974Scz4e    val delayRegFields = delayRegs.zipWithIndex.map {
174*72dab974Scz4e      case (reg, i) =>
175*72dab974Scz4e        params.delayOffset -> Seq(delayRegField(reg, i))
176*72dab974Scz4e    }
177*72dab974Scz4e    val maskRegFields = maskRegs.zipWithIndex.map {
178*72dab974Scz4e      case (reg, i) =>
179*72dab974Scz4e        (params.maskOffset + 8 * i) -> Seq(maskRegField(reg, i))
180*72dab974Scz4e    }
181*72dab974Scz4e
182*72dab974Scz4e    node.regmap((ctrlRegFields ++ delayRegFields ++ maskRegFields):_*)
183*72dab974Scz4e  }
184*72dab974Scz4e}