xref: /XiangShan/src/main/scala/xiangshan/backend/fu/NewCSR/CSRFields.scala (revision 25dc4a827ee27e3ccbaf02e8e5134872cba28fcd)
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 needReset: Boolean = init != null
151
152  def rfn: CSRRfnType = rwType.rfn
153
154  def wfn: CSRWfnType = rwType.wfn
155
156  // Check if reset with a enum value in factory.all
157  protected def resetCheck[T <: EnumType](init: T): Unit = {
158    resetCheckRWType
159    require(this.factory.all.contains(init),
160      s"""
161      | The value ${init.litValue} is NOT in ${factory.all}.
162      | Please check if $init is the enum in the $factory")
163      """.stripMargin
164    )
165  }
166
167  // Check if reset with a enum value in factory.all
168  protected def resetCheck(init: UInt): Unit = {
169    resetCheckRWType
170    require(this.factory.all.exists(_.litValue == init.litValue),
171      s"""
172      |The value ${init.litValue} is not in ${factory.all}.
173      |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.
174      |                                                ^              ^
175      |""".stripMargin
176    )
177  }
178
179  protected def resetCheckRWType: Unit = {
180    rwType match {
181      case ROType(rfn) => require(rfn == null)
182      case _ =>
183    }
184  }
185
186  def withReset[T <: EnumType](init: T): this.type = {
187    resetCheck(init)
188    this.init = init
189    if (!factory.all.exists(_.litValue == ((BigInt(1) << (msb - lsb + 1)) - 1))) {
190      factory.asInstanceOf[CSREnum].addMaxValue
191    }
192    this
193  }
194
195  def withReset(init: UInt): this.type = {
196    resetCheck(init)
197    this.init = this.factory(init)
198    if (!factory.all.exists(_.litValue == ((BigInt(1) << (msb - lsb + 1)) - 1))) {
199      factory.asInstanceOf[CSREnum].addMaxValue
200    }
201    this
202  }
203
204  // Reset using the value not in factory.all
205  def withNonEnumReset(init: UInt): this.type = {
206    resetCheckRWType
207    if (!this.factory.all.exists(_.litValue == init.litValue)) {
208      this.factory.asInstanceOf[CSREnum].addNewValue(init)
209      println(s"[CSR-info] add reset value ${init.litValue} into $this")
210    }
211    if (!factory.all.exists(_.litValue == ((BigInt(1) << (msb - lsb + 1)) - 1))) {
212      factory.asInstanceOf[CSREnum].addMaxValue
213    }
214    this
215  }
216
217  def := (that: UInt): Unit = {
218    this := this.factory(that)
219  }
220
221  def dumpName = {
222    s"${chisel3.reflect.DataMirror.queryNameGuess(this)} ${rwType} [$msb, $lsb] reset($init)"
223  }
224
225  def asBool: Bool = {
226    this.asUInt.asBool
227  }
228
229  private def setRwType(newType: CSRRWType): this.type = {
230    this.rwType = newType
231    this
232  }
233
234  def setRO(rfn: CSRRfnType = null): this.type = {
235    this.setRwType(ROType(rfn))
236  }
237
238  def setRW(): this.type = {
239    this.setRwType(RWType())
240  }
241
242  def setWARL(wfn: CSRWfnType): this.type = {
243    this.setRwType(WARLType(wfn))
244  }
245
246  // override cloneType to make ValidIO etc function return CSREnumType not EnumType
247  override def cloneType: this.type = factory.asInstanceOf[CSREnum].makeType.asInstanceOf[this.type]
248}
249
250class CSREnum extends ChiselEnum {
251  protected def apply(rwType: CSRRWType, init: Data = null)(msb: Int, lsb: Int)(factory: ChiselEnum): CSREnumType = {
252    this.msb = msb
253    this.lsb = lsb
254    new CSREnumType(msb, lsb)(rwType, init)(factory)
255  }
256
257  var msb, lsb: Int = 0
258
259  def makeType: CSREnumType = {
260    new CSREnumType(msb, lsb)(RWType())(this)
261  }
262
263  /**
264   * Used to allow 0.U.asTypeOf(CSREnumInstance) convertion
265   */
266  def addMinValue: Unit = {
267    Value(0.U)
268  }
269
270  /**
271   * A trick to expand the width of Enum to (msb - lsb + 1)
272   */
273  def addMaxValue: Unit = {
274    Value(((BigInt(1) << (msb - lsb + 1)) - 1).U)
275  }
276
277  /**
278   *
279   * @param value: A new value need to add in Enum set
280   * @return this
281   */
282  def addNewValue(value: UInt): this.type = {
283    Value(value)
284    this
285  }
286
287  def isLegal(enum: CSREnumType): Bool = true.B
288
289  println(s"A new CSREnum is created, factory: $this")
290}
291
292trait RWApply { self: CSREnum =>
293  def apply(msb: Int, lsb: Int): CSREnumType = self
294    .apply(RWType())(msb, lsb)(this)
295
296  def apply(bit: Int): CSREnumType = apply(bit, bit)
297}
298
299trait ROApply { self: CSREnum =>
300  def apply(msb: Int, lsb: Int): CSREnumType = self
301    .apply(ROType())(msb, lsb)(this)
302}
303
304trait WARLApply { self: CSREnum =>
305  def apply(msb: Int, lsb: Int, wfn: CSRWfnType, rfn: CSRRfnType): CSREnumType = self
306    .apply(WARLType(wfn, rfn))(msb, lsb)(this)
307
308  def apply(msb: Int, lsb: Int, wfn: CSRWfnType): CSREnumType = self
309    .apply(WARLType(wfn))(msb, lsb)(this)
310}
311
312trait WLRLApply { self: CSREnum =>
313  def apply(msb: Int, lsb: Int, wfn: CSRWfnType, rfn: CSRRfnType): CSREnumType = self
314    .apply(WLRLType(wfn, rfn))(msb, lsb)(this)
315}
316
317trait CSRMacroApply { self: CSREnum =>
318  def RO(msb: Int, lsb: Int, rfn: CSRRfnType): CSREnumType = self
319    .apply(ROType(rfn))(msb, lsb)(this)
320
321  def RO(msb: Int, lsb: Int): CSREnumType = self
322    .apply(ROType())(msb, lsb)(this)
323
324  def RW(msb: Int, lsb: Int, resetVal: Data = null): CSREnumType = self
325    .apply(RWType(), resetVal)(msb, lsb)(this)
326
327  def WARL(msb: Int, lsb: Int, wfn: CSRWfnType, rfn: CSRRfnType): CSREnumType = self
328    .apply(WARLType(wfn, rfn))(msb, lsb)(this)
329
330  def WARL(msb: Int, lsb: Int, wfn: CSRWfnType): CSREnumType = self
331    .apply(WARLType(wfn))(msb, lsb)(this)
332
333  def WLRL(msb: Int, lsb: Int, wfn: CSRWfnType, rfn: CSRRfnType): CSREnumType = self
334    .apply(WLRLType(wfn, rfn))(msb, lsb)(this)
335
336  def RefRO(ref: CSREnumType, msb: Int, lsb: Int, rfn: CSRRfnType): CSREnumType = self
337    .apply(RefROType(Some(ref) ,rfn))(msb, lsb)(ref.factory)
338
339  def RefRO(ref: CSREnumType, msb: Int, lsb: Int): CSREnumType = self
340    .apply(RefROType(Some(ref)))(msb, lsb)(ref.factory)
341
342  def RefWARL(ref: CSREnumType, msb: Int, lsb: Int, wfn: CSRWfnType, rfn: CSRRfnType): CSREnumType = self
343    .apply(RefWARLType(Some(ref), wfn, rfn))(msb, lsb)(ref.factory)
344
345  def RefWARL(ref: CSREnumType, msb: Int, lsb: Int, wfn: CSRWfnType): CSREnumType = self
346    .apply(RefWARLType(Some(ref), wfn))(msb, lsb)(ref.factory)
347}
348
349object CSREnumTypeImplicitCast {
350  implicit def CSREnumTypeToUInt(field: CSREnumType): UInt = {
351    field.asUInt
352  }
353
354  class BoolField(val value: Bool) {
355    def && (field: CSREnumType): Bool = {
356      this.value && field.asBool
357    }
358
359    def || (field: CSREnumType): Bool = {
360      this.value || field.asBool
361    }
362  }
363
364  implicit def BoolToBoolField(bool: Bool): BoolField = new BoolField(bool)
365}
366
367