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