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