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