xref: /XiangShan/src/main/scala/xiangshan/backend/fu/NewCSR/CSRFields.scala (revision b03c55a5df5dc8793cb44b42dd60141566e57e78)
1package xiangshan.backend.fu.NewCSR
2
3import chisel3._
4import chisel3.util.Fill
5import xiangshan.backend.fu.NewCSR.CSRFunc._
6
7import scala.language.implicitConversions
8
9abstract class CSRRWType {
10  val wfn: CSRWfnType
11  var rfn: CSRRfnType
12  val ref: Option[CSREnumType] = None
13
14  def isRO: Boolean = this.isInstanceOf[ROType] || this.isInstanceOf[RefROType]
15
16  def isRW: Boolean = this.isInstanceOf[RWType] || this.isInstanceOf[RefRWType]
17
18  def isWARL: Boolean = this.isInstanceOf[WARLType] || this.isInstanceOf[RefWARLType]
19
20  def isWLRL: Boolean = this.isInstanceOf[WLRLType] || this.isInstanceOf[RefWLRLType]
21
22  def isRef: Boolean = this.isInstanceOf[RefROType] || this.isInstanceOf[RefRWType] || this.isInstanceOf[RefWARLType] ||
23    this.isInstanceOf[RefWLRLType]
24
25  override def toString: String = {
26    val typeString = this match {
27      case WARLType(_, _) => "WARL"
28      case ROType(_)      => "RO"
29      case WLRLType(_, _) => "WLRL"
30      case RWType()       => "RW"
31    }
32    typeString + (if (isRef) " Ref" else "")
33  }
34}
35
36case class WARLType(
37  override val wfn: CSRWfnType,
38  override var rfn: CSRRfnType = null,
39) extends CSRRWType
40
41case class ROType(
42  override var rfn: CSRRfnType = null,
43) extends CSRRWType {
44  override final val wfn: CSRWfnType = wNoEffect
45  var isHardWired = false
46  var hardWiredValue = 0.U
47
48  def setHardWired(value: UInt): Unit = {
49    this.isHardWired = true
50    this.hardWiredValue = value
51  }
52}
53
54case class WLRLType(
55  override val wfn: CSRWfnType,
56  override var rfn: CSRRfnType,
57) extends CSRRWType
58
59case class RWType() extends CSRRWType {
60  override final val wfn: CSRWfnType = wNoFilter
61  override final var rfn: CSRRfnType = null
62}
63
64trait CheckRef { self: CSRRWType =>
65  require(ref.nonEmpty)
66}
67
68case class RefWARLType(
69  override val ref: Option[CSREnumType],
70  override val wfn: CSRWfnType,
71  override var rfn: CSRRfnType = null,
72) extends CSRRWType with CheckRef
73
74case class RefROType(
75  override val ref: Option[CSREnumType],
76  override var rfn: CSRRfnType = null,
77) extends CSRRWType with CheckRef {
78  override final val wfn: CSRWfnType = wNoEffect
79}
80
81case class RefWLRLType(
82  override val ref: Option[CSREnumType],
83  override val wfn: CSRWfnType,
84  override var rfn: CSRRfnType,
85) extends CSRRWType with CheckRef
86
87case class RefRWType(
88  override val ref: Option[CSREnumType],
89) extends CSRRWType with CheckRef {
90  override final val wfn: CSRWfnType = wNoFilter
91  override final var rfn: CSRRfnType = null
92}
93
94object CSRFunc {
95  type CSRWfnType = (UInt, UInt, Seq[Data]) => UInt
96
97  def wNoFilter: CSRWfnType =
98    (newV: UInt, oldV: UInt, _: Seq[Data]) => newV
99
100  def wNoEffectWhen(keepCond: UInt => Bool): CSRWfnType =
101    (newV: UInt, oldV: UInt, _: Seq[Data]) => {
102      Mux(keepCond(newV), oldV, newV)
103    }
104
105  def wNoEffect: CSRWfnType =
106    (_: UInt, oldV: UInt, _: Seq[Data]) => { oldV }
107
108  type CSRRfnType = (UInt, Seq[Data]) => UInt
109
110  def rNoFilter: CSRRfnType = null
111
112  def rWithFilter(rFilter: (UInt, Seq[Data]) => UInt): CSRRfnType =
113    (oriV: UInt, seq: Seq[Data]) => rFilter(oriV, seq)
114
115  def rFixValue(value: UInt): CSRRfnType = {
116    (_, _) => value
117  }
118}
119
120class CSREnumType(
121  val msb: Int,
122  val lsb: Int,
123)(
124  var rwType: CSRRWType,
125  var init: Data = null
126)(
127  override val factory: ChiselEnum
128) extends EnumType(factory) {
129
130  if (factory.all.isEmpty) {
131    factory.asInstanceOf[CSREnum].addMinValue
132  }
133
134  if (this.init != null && !factory.all.exists(_.litValue == this.init.litValue)) {
135    factory.asInstanceOf[CSREnum].addNewValue(init.asUInt)
136  }
137
138  if (!factory.all.exists(_.litValue == ((BigInt(1) << (msb - lsb + 1)) - 1))) {
139    factory.asInstanceOf[CSREnum].addMaxValue
140  }
141
142  if (msb - lsb + 1 > this.getWidth)
143    println(
144      s"[CSRInfo] $this: " +
145      s"the setting range($msb, $lsb) of bitfield is widen than EnumType's width(${this.getWidth}), " +
146      s"the higher bits will be optimized"
147    )
148
149  def isRef = this.rwType.isRef
150
151  def isRO = this.rwType.isRO
152
153  def isRW = this.rwType.isRW
154
155  def isWARL = this.rwType.isWARL
156
157  def isHardWired = this.isRO && this.rwType.asInstanceOf[ROType].isHardWired
158
159  def getHardWireValue: UInt = this.rwType.asInstanceOf[ROType].hardWiredValue
160
161  // Check if the write data is legal that can update the regfield.
162  // Also check if the write field is not Read Only.
163  def isLegal: Bool = this.factory.asInstanceOf[CSREnum].isLegal(this) && (!this.isRO).B
164
165  def isLegal(dmode: Bool): Bool = this.factory.asInstanceOf[CSREnum].isLegal(this, dmode) && (!this.isRO).B
166
167  // make the illegal wdata legalize
168  def legalize: CSREnumType = this.factory.asInstanceOf[CSREnum].legalize(this)
169
170  def legalize(dmode: Bool): CSREnumType = this.factory.asInstanceOf[CSREnum].legalize(this, dmode)
171
172  def needReset: Boolean = init != null
173
174  def rfn: CSRRfnType = rwType.rfn
175
176  def wfn: CSRWfnType = rwType.wfn
177
178  // Check if reset with a enum value in factory.all
179  protected def resetCheck[T <: EnumType](init: T): Unit = {
180    resetCheckRWType
181    require(this.factory.all.contains(init),
182      s"""
183      | The value ${init.litValue} is NOT in ${factory.all}.
184      | Please check if $init is the enum in the $factory")
185      """.stripMargin
186    )
187  }
188
189  // Check if reset with a enum value in factory.all
190  protected def resetCheck(init: UInt): Unit = {
191    resetCheckRWType
192    require(this.factory.all.exists(_.litValue == init.litValue),
193      s"""
194      |The value ${init.litValue} is not in ${factory.all}.
195      |Please add reset value as the tail of (msb,lsb, HERE) or (bit, HERE), If you need reset field with the value NOT in enum set.
196      |                                                ^              ^
197      |""".stripMargin
198    )
199  }
200
201  protected def resetCheckRWType: Unit = {
202    rwType match {
203      case ROType(rfn) => require(rfn == null)
204      case _ =>
205    }
206  }
207
208  def withReset[T <: EnumType](init: T): this.type = {
209    resetCheck(init)
210    this.init = init
211    if (!factory.all.exists(_.litValue == ((BigInt(1) << (msb - lsb + 1)) - 1))) {
212      factory.asInstanceOf[CSREnum].addMaxValue
213    }
214    this
215  }
216
217  def withReset(init: UInt): this.type = {
218    resetCheck(init)
219    this.init = this.factory(init)
220    if (!factory.all.exists(_.litValue == ((BigInt(1) << (msb - lsb + 1)) - 1))) {
221      factory.asInstanceOf[CSREnum].addMaxValue
222    }
223    this
224  }
225
226  // Reset using the value not in factory.all
227  def withNonEnumReset(init: UInt): this.type = {
228    resetCheckRWType
229    if (!this.factory.all.exists(_.litValue == init.litValue)) {
230      this.factory.asInstanceOf[CSREnum].addNewValue(init)
231      println(s"[CSR-info] add reset value ${init.litValue} into $this")
232    }
233    if (!factory.all.exists(_.litValue == ((BigInt(1) << (msb - lsb + 1)) - 1))) {
234      factory.asInstanceOf[CSREnum].addMaxValue
235    }
236    this
237  }
238
239  def := (that: UInt): Unit = {
240    suppressEnumCastWarning {
241      this := this.factory(that)
242    }
243  }
244
245  def dumpName = {
246    s"${chisel3.reflect.DataMirror.queryNameGuess(this)} ${rwType} [$msb, $lsb] reset($init)"
247  }
248
249  def asBool: Bool = {
250    this.asUInt.asBool
251  }
252
253  private def setRwType(newType: CSRRWType): this.type = {
254    this.rwType = newType
255    this
256  }
257
258  def setRO(rfn: CSRRfnType = null): this.type = {
259    this.setRwType(ROType(rfn))
260  }
261
262  def setHardWired(value: UInt): this.type = {
263    require(this.isRO)
264    this.rwType.asInstanceOf[ROType].setHardWired(value)
265    this
266  }
267
268  def setRW(): this.type = {
269    this.setRwType(RWType())
270  }
271
272  def setWARL(wfn: CSRWfnType): this.type = {
273    this.setRwType(WARLType(wfn))
274  }
275
276  def ||(that: Bool): Bool = {
277    require(this.getWidth == 1, s"Only 1 bit field can use operator ||. The width of left operand is ${this.getWidth}")
278    this.asBool || that
279  }
280
281  def ||(that: CSREnumType): Bool = {
282    require(this.getWidth == 1, s"Only 1 bit field can use operator ||. The width of left operand is ${this.getWidth}")
283    require(that.getWidth == 1, s"Only 1 bit field can use operator ||. The width of right operand is ${that.getWidth}")
284    this.asBool || that.asBool
285  }
286
287  def &&(that: Bool): Bool = {
288    require(this.getWidth == 1, s"Only 1 bit field can use operator &&. The width of left operand is ${this.getWidth}")
289    this.asBool && that
290  }
291
292  def &&(that: CSREnumType): Bool = {
293    require(this.getWidth == 1, s"Only 1 bit field can use operator &&. The width of left operand is ${this.getWidth}")
294    require(that.getWidth == 1, s"Only 1 bit field can use operator &&. The width of right operand is ${that.getWidth}")
295    this.asBool && that.asBool
296  }
297
298  def unary_! : Bool = {
299    require(this.getWidth == 1, s"Only 1 bit field can use operator &&. The width of left operand is ${this.getWidth}")
300    !this.asBool
301  }
302
303  def & (that: UInt): UInt = {
304    require(this.getWidth == that.getWidth || !that.widthKnown)
305    this.asUInt & that
306  }
307
308  def &> (that: Bool): UInt = {
309    this.asUInt & Fill(this.getWidth, that)
310  }
311
312  def |> (that: Bool): UInt = {
313    this.asUInt | Fill(this.getWidth, that)
314  }
315
316  // override cloneType to make ValidIO etc function return CSREnumType not EnumType
317  override def cloneType: this.type = factory.asInstanceOf[CSREnum].makeType.asInstanceOf[this.type].setRwType(this.rwType)
318}
319
320class CSREnum extends ChiselEnum {
321  protected def apply(rwType: CSRRWType)(msb: Int, lsb: Int)(factory: ChiselEnum): CSREnumType = {
322    this.msb = msb
323    this.lsb = lsb
324    new CSREnumType(msb, lsb)(rwType, null)(factory)
325  }
326
327  var msb, lsb: Int = 0
328
329  def makeType: CSREnumType = {
330    new CSREnumType(msb, lsb)(RWType())(this)
331  }
332
333  /**
334   * Used to allow 0.U.asTypeOf(CSREnumInstance) convertion
335   */
336  def addMinValue: Unit = {
337    Value(0.U)
338  }
339
340  /**
341   * A trick to expand the width of Enum to (msb - lsb + 1)
342   */
343  def addMaxValue: Unit = {
344    Value(((BigInt(1) << (msb - lsb + 1)) - 1).U)
345  }
346
347  /**
348   *
349   * @param value: A new value need to add in Enum set
350   * @return this
351   */
352  def addNewValue(value: UInt): this.type = {
353    Value(value)
354    this
355  }
356
357  def isLegal(enumeration: CSREnumType): Bool = true.B
358
359  def isLegal(enumeration: CSREnumType, dmode: Bool): Bool = true.B
360
361  def legalize(enumeration: CSREnumType): CSREnumType = makeType
362
363  def legalize(enumeration: CSREnumType, dmode: Bool): CSREnumType = makeType
364
365  println(s"A new CSREnum is created, factory: $this")
366}
367
368trait RWApply { self: CSREnum =>
369  def apply(msb: Int, lsb: Int): CSREnumType = self
370    .apply(RWType())(msb, lsb)(this)
371
372  def apply(bit: Int): CSREnumType = apply(bit, bit)
373}
374
375trait ROApply { self: CSREnum =>
376  def apply(msb: Int, lsb: Int): CSREnumType = self
377    .apply(ROType())(msb, lsb)(this)
378}
379
380trait WARLApply { self: CSREnum =>
381  def apply(msb: Int, lsb: Int, wfn: CSRWfnType, rfn: CSRRfnType): CSREnumType = self
382    .apply(WARLType(wfn, rfn))(msb, lsb)(this)
383
384  def apply(msb: Int, lsb: Int, wfn: CSRWfnType): CSREnumType = self
385    .apply(WARLType(wfn))(msb, lsb)(this)
386
387  def apply(bit: Int, wfn: CSRWfnType): CSREnumType = apply(bit, bit, wfn)
388}
389
390trait WLRLApply { self: CSREnum =>
391  def apply(msb: Int, lsb: Int, wfn: CSRWfnType, rfn: CSRRfnType): CSREnumType = self
392    .apply(WLRLType(wfn, rfn))(msb, lsb)(this)
393}
394
395trait CSRMacroApply { self: CSREnum =>
396  def RO(msb: Int, lsb: Int, rfn: CSRRfnType): CSREnumType = self
397    .apply(ROType(rfn))(msb, lsb)(this)
398
399  def RW(msb: Int, lsb: Int): CSREnumType = self
400    .apply(RWType())(msb, lsb)(this)
401
402  def WARL(msb: Int, lsb: Int, wfn: CSRWfnType, rfn: CSRRfnType): CSREnumType = self
403    .apply(WARLType(wfn, rfn))(msb, lsb)(this)
404
405  def WLRL(msb: Int, lsb: Int, wfn: CSRWfnType, rfn: CSRRfnType): CSREnumType = self
406    .apply(WLRLType(wfn, rfn))(msb, lsb)(this)
407
408  def RefRO(ref: CSREnumType, msb: Int, lsb: Int, rfn: CSRRfnType): CSREnumType = self
409    .apply(RefROType(Some(ref) ,rfn))(msb, lsb)(ref.factory)
410
411  def RefRO(ref: CSREnumType, msb: Int, lsb: Int): CSREnumType = self
412    .apply(RefROType(Some(ref)))(msb, lsb)(ref.factory)
413
414  def RefWARL(ref: CSREnumType, msb: Int, lsb: Int, wfn: CSRWfnType, rfn: CSRRfnType): CSREnumType = self
415    .apply(RefWARLType(Some(ref), wfn, rfn))(msb, lsb)(ref.factory)
416
417  def RefWARL(ref: CSREnumType, msb: Int, lsb: Int, wfn: CSRWfnType): CSREnumType = self
418    .apply(RefWARLType(Some(ref), wfn))(msb, lsb)(ref.factory)
419}
420
421object CSREnumTypeImplicitCast {
422  class BoolField(val value: Bool) {
423    def && (field: CSREnumType): Bool = {
424      this.value && field.asBool
425    }
426
427    def || (field: CSREnumType): Bool = {
428      this.value || field.asBool
429    }
430
431    def &<(that: UInt): UInt = {
432      require(that.widthKnown, "The width of the right operand should be known when using &< operator")
433      Fill(that.getWidth, this.value) & that
434    }
435
436    def &<(that: CSREnumType): UInt = {
437      this &< that.asUInt
438    }
439
440    def |<(that: UInt): UInt = {
441      require(that.widthKnown, "The width of the right operand should be known when using |< operator")
442      Fill(that.getWidth, this.value) | that
443    }
444
445    def |<(that: CSREnumType): UInt = {
446      this |< that.asUInt
447    }
448  }
449
450  implicit def BoolToBoolField(bool: Bool): BoolField = new BoolField(bool)
451}
452
453