xref: /XiangShan/src/main/scala/xiangshan/backend/fu/NewCSR/CSRFields.scala (revision d0b87b97186a00ef60cb096970feb89c69d18ff2)
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    suppressEnumCastWarning {
230      this := this.factory(that)
231    }
232  }
233
234  def dumpName = {
235    s"${chisel3.reflect.DataMirror.queryNameGuess(this)} ${rwType} [$msb, $lsb] reset($init)"
236  }
237
238  def asBool: Bool = {
239    this.asUInt.asBool
240  }
241
242  private def setRwType(newType: CSRRWType): this.type = {
243    this.rwType = newType
244    this
245  }
246
247  def setRO(rfn: CSRRfnType = null): this.type = {
248    this.setRwType(ROType(rfn))
249  }
250
251  def setRW(): this.type = {
252    this.setRwType(RWType())
253  }
254
255  def setWARL(wfn: CSRWfnType): this.type = {
256    this.setRwType(WARLType(wfn))
257  }
258
259  def ||(that: Bool): Bool = {
260    require(this.getWidth == 1, s"Only 1 bit field can use operator ||. The width of left operand is ${this.getWidth}")
261    this.asBool || that
262  }
263
264  def ||(that: CSREnumType): Bool = {
265    require(this.getWidth == 1, s"Only 1 bit field can use operator ||. The width of left operand is ${this.getWidth}")
266    require(that.getWidth == 1, s"Only 1 bit field can use operator ||. The width of right operand is ${that.getWidth}")
267    this.asBool || that.asBool
268  }
269
270  def &&(that: Bool): Bool = {
271    require(this.getWidth == 1, s"Only 1 bit field can use operator &&. The width of left operand is ${this.getWidth}")
272    this.asBool && that
273  }
274
275  def &&(that: CSREnumType): Bool = {
276    require(this.getWidth == 1, s"Only 1 bit field can use operator &&. The width of left operand is ${this.getWidth}")
277    require(that.getWidth == 1, s"Only 1 bit field can use operator &&. The width of right operand is ${that.getWidth}")
278    this.asBool && that.asBool
279  }
280
281  def unary_! : Bool = {
282    require(this.getWidth == 1, s"Only 1 bit field can use operator &&. The width of left operand is ${this.getWidth}")
283    !this.asBool
284  }
285
286  def & (that: UInt): UInt = {
287    require(this.getWidth == that.getWidth || !that.widthKnown)
288    this.asUInt & that
289  }
290
291  def &> (that: Bool): UInt = {
292    this.asUInt & Fill(this.getWidth, that)
293  }
294
295  def |> (that: Bool): UInt = {
296    this.asUInt | Fill(this.getWidth, that)
297  }
298
299  // override cloneType to make ValidIO etc function return CSREnumType not EnumType
300  override def cloneType: this.type = factory.asInstanceOf[CSREnum].makeType.asInstanceOf[this.type].setRwType(this.rwType)
301}
302
303class CSREnum extends ChiselEnum {
304  protected def apply(rwType: CSRRWType)(msb: Int, lsb: Int)(factory: ChiselEnum): CSREnumType = {
305    this.msb = msb
306    this.lsb = lsb
307    new CSREnumType(msb, lsb)(rwType, null)(factory)
308  }
309
310  var msb, lsb: Int = 0
311
312  def makeType: CSREnumType = {
313    new CSREnumType(msb, lsb)(RWType())(this)
314  }
315
316  /**
317   * Used to allow 0.U.asTypeOf(CSREnumInstance) convertion
318   */
319  def addMinValue: Unit = {
320    Value(0.U)
321  }
322
323  /**
324   * A trick to expand the width of Enum to (msb - lsb + 1)
325   */
326  def addMaxValue: Unit = {
327    Value(((BigInt(1) << (msb - lsb + 1)) - 1).U)
328  }
329
330  /**
331   *
332   * @param value: A new value need to add in Enum set
333   * @return this
334   */
335  def addNewValue(value: UInt): this.type = {
336    Value(value)
337    this
338  }
339
340  def isLegal(enum: CSREnumType): Bool = true.B
341
342  def isLegal(enum: CSREnumType, dmode: Bool): Bool = true.B
343
344  def legalize(enum: CSREnumType): CSREnumType = makeType
345
346  def legalize(enum: CSREnumType, dmode: Bool): CSREnumType = makeType
347
348  println(s"A new CSREnum is created, factory: $this")
349}
350
351trait RWApply { self: CSREnum =>
352  def apply(msb: Int, lsb: Int): CSREnumType = self
353    .apply(RWType())(msb, lsb)(this)
354
355  def apply(bit: Int): CSREnumType = apply(bit, bit)
356}
357
358trait ROApply { self: CSREnum =>
359  def apply(msb: Int, lsb: Int): CSREnumType = self
360    .apply(ROType())(msb, lsb)(this)
361}
362
363trait WARLApply { self: CSREnum =>
364  def apply(msb: Int, lsb: Int, wfn: CSRWfnType, rfn: CSRRfnType): CSREnumType = self
365    .apply(WARLType(wfn, rfn))(msb, lsb)(this)
366
367  def apply(msb: Int, lsb: Int, wfn: CSRWfnType): CSREnumType = self
368    .apply(WARLType(wfn))(msb, lsb)(this)
369
370  def apply(bit: Int, wfn: CSRWfnType): CSREnumType = apply(bit, bit, wfn)
371}
372
373trait WLRLApply { self: CSREnum =>
374  def apply(msb: Int, lsb: Int, wfn: CSRWfnType, rfn: CSRRfnType): CSREnumType = self
375    .apply(WLRLType(wfn, rfn))(msb, lsb)(this)
376}
377
378trait CSRMacroApply { self: CSREnum =>
379  def RO(msb: Int, lsb: Int, rfn: CSRRfnType): CSREnumType = self
380    .apply(ROType(rfn))(msb, lsb)(this)
381
382  def RW(msb: Int, lsb: Int): CSREnumType = self
383    .apply(RWType())(msb, lsb)(this)
384
385  def WARL(msb: Int, lsb: Int, wfn: CSRWfnType, rfn: CSRRfnType): CSREnumType = self
386    .apply(WARLType(wfn, rfn))(msb, lsb)(this)
387
388  def WLRL(msb: Int, lsb: Int, wfn: CSRWfnType, rfn: CSRRfnType): CSREnumType = self
389    .apply(WLRLType(wfn, rfn))(msb, lsb)(this)
390
391  def RefRO(ref: CSREnumType, msb: Int, lsb: Int, rfn: CSRRfnType): CSREnumType = self
392    .apply(RefROType(Some(ref) ,rfn))(msb, lsb)(ref.factory)
393
394  def RefRO(ref: CSREnumType, msb: Int, lsb: Int): CSREnumType = self
395    .apply(RefROType(Some(ref)))(msb, lsb)(ref.factory)
396
397  def RefWARL(ref: CSREnumType, msb: Int, lsb: Int, wfn: CSRWfnType, rfn: CSRRfnType): CSREnumType = self
398    .apply(RefWARLType(Some(ref), wfn, rfn))(msb, lsb)(ref.factory)
399
400  def RefWARL(ref: CSREnumType, msb: Int, lsb: Int, wfn: CSRWfnType): CSREnumType = self
401    .apply(RefWARLType(Some(ref), wfn))(msb, lsb)(ref.factory)
402}
403
404object CSREnumTypeImplicitCast {
405  class BoolField(val value: Bool) {
406    def && (field: CSREnumType): Bool = {
407      this.value && field.asBool
408    }
409
410    def || (field: CSREnumType): Bool = {
411      this.value || field.asBool
412    }
413
414    def &<(that: UInt): UInt = {
415      require(that.widthKnown, "The width of the right operand should be known when using &< operator")
416      Fill(that.getWidth, this.value) & that
417    }
418
419    def &<(that: CSREnumType): UInt = {
420      this &< that.asUInt
421    }
422
423    def |<(that: UInt): UInt = {
424      require(that.widthKnown, "The width of the right operand should be known when using |< operator")
425      Fill(that.getWidth, this.value) | that
426    }
427
428    def |<(that: CSREnumType): UInt = {
429      this |< that.asUInt
430    }
431  }
432
433  implicit def BoolToBoolField(bool: Bool): BoolField = new BoolField(bool)
434}
435
436