xref: /XiangShan/src/main/scala/xiangshan/backend/fu/NewCSR/CSRBundle.scala (revision e3da8bad334fc71ba0d72f0607e2e93245ddaece)
1package xiangshan.backend.fu.NewCSR
2
3import chisel3._
4import chisel3.experimental.SourceInfo
5import chisel3.util.{Cat, Fill}
6import chisel3.experimental.BundleLiterals._
7
8import scala.language.experimental.macros
9
10
11abstract class CSRBundle extends Bundle {
12  val len: Int = 64
13
14  var eventFields: Set[CSREnumType] = Set()
15
16  override def do_asUInt(implicit sourceInfo: SourceInfo): UInt = {
17    // sorted from msb to lsb
18    val fields = this.getFields.sortWith((l, r) => l.lsb > r.lsb)
19    var paddedFields: Seq[Data] = Seq()
20    var lsb = len
21
22    for (field <- fields) {
23      val diffWidth = lsb - field.lsb - field.getWidth
24      if (diffWidth > 0)
25        paddedFields :+= 0.U((diffWidth).W)
26      paddedFields :+= field
27      lsb = field.lsb
28    }
29
30    if (fields.last.lsb > 0) {
31      paddedFields :+= 0.U(fields.last.lsb.W)
32    }
33
34    Cat(paddedFields.map(x => x.asUInt))
35  }
36
37  def := (that: UInt): Unit = {
38    val fields = this.getFields
39
40    suppressEnumCastWarning {
41      for (field <- fields) {
42        field := field.factory.apply(that(field.lsb + field.getWidth - 1, field.lsb))
43      }
44    }
45  }
46
47  @inline
48  def init: this.type = {
49    val init = Wire(this)
50    suppressEnumCastWarning {
51      init.elements.foreach { case (str, field: CSREnumType) =>
52        field := (if (field.init != null) field.factory(field.init.asUInt) else field.factory(0.U))
53      }
54    }
55    init.asInstanceOf[this.type]
56  }
57
58  /**
59   * filtered read connection
60   *
61   * CSRBundle will be filtered by CSRFields' read filter function.
62   */
63  def :|= [T <: CSRBundle](that: T): Unit = {
64    if (this.getClass != that.getClass) {
65      throw MonoConnectException(s"Type miss match! (sink :|= source) " +
66        s"sink type: ${this.getClass}, " +
67        s"source type: ${that.getClass}")
68    }
69
70    for ((sink: CSREnumType, source: CSREnumType)  <- this.getFields.zip(that.getFields)) {
71      if (sink.rfn == null)
72        sink := source // .factory.apply(sink.rfn(source.asUInt, Seq()))
73      else
74        sink := sink.factory(sink.rfn(source.asUInt, Seq()))
75    }
76  }
77
78  def getFields: Seq[CSREnumType] = this.getElements.map(_.asInstanceOf[CSREnumType])
79
80  def needReset: Boolean = this.getFields.exists(_.needReset)
81
82  // used by event bundle to filter the fields need to update
83  def addInEvent(fieldFns: (this.type => CSREnumType)*): this.type = {
84    this.eventFields ++= fieldFns.map(fn => fn(this))
85    this
86  }
87
88  override def cloneType: CSRBundle.this.type = {
89    val ret = super.cloneType
90    //
91    (ret.getFields zip this.getFields).foreach { case (l, r) =>
92      if (this.eventFields.contains(r)) {
93        ret.eventFields += l
94      }
95    }
96    ret
97  }
98
99  def & (that: CSRBundle): UInt = {
100    this.asUInt & that.asUInt
101  }
102
103  def & (that: UInt): UInt = {
104    require(this.asUInt.getWidth == that.getWidth,
105      s"The width between left $this(${this.getWidth}) and right $that(${that.getWidth}) should be equal.")
106    this.asUInt & that
107  }
108
109  def | (that: CSRBundle): UInt = {
110    this.asUInt | that.asUInt
111  }
112
113  def | (that: UInt): UInt = {
114    require(this.getWidth == that.getWidth)
115    this.asUInt | that
116  }
117
118  def unary_~ : UInt = {
119    (~this.asUInt).asUInt
120  }
121
122  def apply(num: Int) : CSREnumType = {
123    this.getFields.find(x => x.lsb == num && x.msb == num).get
124  }
125
126  def apply(str: String) : CSREnumType = {
127    elements(str).asInstanceOf[CSREnumType]
128  }
129}
130
131object CSRBundleImplicitCast {
132  class UIntField(val value: UInt) {
133    def &[T <: CSRBundle] (field: T): UInt = {
134      this.value & field.asUInt
135    }
136
137    def |[T <: CSRBundle] (field: T): UInt = {
138      this.value | field.asUInt
139    }
140
141    def &>(that: Bool): UInt = {
142      require(value.widthKnown, "The width of the left operand should be known when using >& operator")
143      this.value & Fill(value.getWidth, that)
144    }
145
146    def |>(that: Bool): UInt = {
147      require(value.widthKnown, "The width of the left operand should be known when using >| operator")
148      this.value | Fill(value.getWidth, that)
149    }
150  }
151
152  import scala.language.implicitConversions
153  implicit def UIntToUIntField(uint: UInt): UIntField = new UIntField(uint)
154}
155
156object ChiselRecordForField {
157  implicit class AddRecordSpecifyFields[T <: Record](val x: T) {
158    def specifyField(elemFns: (T => Unit)*): Unit = {
159      elemFns.foreach(_.apply(x))
160    }
161  }
162}
163