xref: /XiangShan/src/main/scala/xiangshan/backend/fu/NewCSR/CSRBundle.scala (revision e3da8bad334fc71ba0d72f0607e2e93245ddaece)
1039cdc35SXuan Hupackage xiangshan.backend.fu.NewCSR
2039cdc35SXuan Hu
3039cdc35SXuan Huimport chisel3._
4039cdc35SXuan Huimport chisel3.experimental.SourceInfo
51d192ad8SXuan Huimport chisel3.util.{Cat, Fill}
6237d4cfdSXuan Huimport chisel3.experimental.BundleLiterals._
7039cdc35SXuan Hu
8039cdc35SXuan Huimport scala.language.experimental.macros
9039cdc35SXuan Hu
10039cdc35SXuan Hu
11039cdc35SXuan Huabstract class CSRBundle extends Bundle {
12039cdc35SXuan Hu  val len: Int = 64
13039cdc35SXuan Hu
14237d4cfdSXuan Hu  var eventFields: Set[CSREnumType] = Set()
15237d4cfdSXuan Hu
16039cdc35SXuan Hu  override def do_asUInt(implicit sourceInfo: SourceInfo): UInt = {
1738e7849bSXuan Hu    // sorted from msb to lsb
1838e7849bSXuan Hu    val fields = this.getFields.sortWith((l, r) => l.lsb > r.lsb)
19039cdc35SXuan Hu    var paddedFields: Seq[Data] = Seq()
20039cdc35SXuan Hu    var lsb = len
21039cdc35SXuan Hu
22039cdc35SXuan Hu    for (field <- fields) {
23039cdc35SXuan Hu      val diffWidth = lsb - field.lsb - field.getWidth
24039cdc35SXuan Hu      if (diffWidth > 0)
25039cdc35SXuan Hu        paddedFields :+= 0.U((diffWidth).W)
26039cdc35SXuan Hu      paddedFields :+= field
27039cdc35SXuan Hu      lsb = field.lsb
28039cdc35SXuan Hu    }
29039cdc35SXuan Hu
30039cdc35SXuan Hu    if (fields.last.lsb > 0) {
31039cdc35SXuan Hu      paddedFields :+= 0.U(fields.last.lsb.W)
32039cdc35SXuan Hu    }
33039cdc35SXuan Hu
34039cdc35SXuan Hu    Cat(paddedFields.map(x => x.asUInt))
35039cdc35SXuan Hu  }
36039cdc35SXuan Hu
37039cdc35SXuan Hu  def := (that: UInt): Unit = {
38039cdc35SXuan Hu    val fields = this.getFields
39039cdc35SXuan Hu
409a28ebd4SXuan Hu    suppressEnumCastWarning {
41039cdc35SXuan Hu      for (field <- fields) {
42039cdc35SXuan Hu        field := field.factory.apply(that(field.lsb + field.getWidth - 1, field.lsb))
43039cdc35SXuan Hu      }
44039cdc35SXuan Hu    }
459a28ebd4SXuan Hu  }
46039cdc35SXuan Hu
47039cdc35SXuan Hu  @inline
48039cdc35SXuan Hu  def init: this.type = {
49039cdc35SXuan Hu    val init = Wire(this)
509a28ebd4SXuan Hu    suppressEnumCastWarning {
51039cdc35SXuan Hu      init.elements.foreach { case (str, field: CSREnumType) =>
5201cdded8SXuan Hu        field := (if (field.init != null) field.factory(field.init.asUInt) else field.factory(0.U))
53039cdc35SXuan Hu      }
549a28ebd4SXuan Hu    }
55039cdc35SXuan Hu    init.asInstanceOf[this.type]
56039cdc35SXuan Hu  }
57039cdc35SXuan Hu
58039cdc35SXuan Hu  /**
59039cdc35SXuan Hu   * filtered read connection
60039cdc35SXuan Hu   *
61039cdc35SXuan Hu   * CSRBundle will be filtered by CSRFields' read filter function.
62039cdc35SXuan Hu   */
63039cdc35SXuan Hu  def :|= [T <: CSRBundle](that: T): Unit = {
64039cdc35SXuan Hu    if (this.getClass != that.getClass) {
65039cdc35SXuan Hu      throw MonoConnectException(s"Type miss match! (sink :|= source) " +
66039cdc35SXuan Hu        s"sink type: ${this.getClass}, " +
67039cdc35SXuan Hu        s"source type: ${that.getClass}")
68039cdc35SXuan Hu    }
69039cdc35SXuan Hu
70039cdc35SXuan Hu    for ((sink: CSREnumType, source: CSREnumType)  <- this.getFields.zip(that.getFields)) {
71039cdc35SXuan Hu      if (sink.rfn == null)
72039cdc35SXuan Hu        sink := source // .factory.apply(sink.rfn(source.asUInt, Seq()))
73039cdc35SXuan Hu      else
74039cdc35SXuan Hu        sink := sink.factory(sink.rfn(source.asUInt, Seq()))
75039cdc35SXuan Hu    }
76039cdc35SXuan Hu  }
77039cdc35SXuan Hu
78039cdc35SXuan Hu  def getFields: Seq[CSREnumType] = this.getElements.map(_.asInstanceOf[CSREnumType])
79039cdc35SXuan Hu
80039cdc35SXuan Hu  def needReset: Boolean = this.getFields.exists(_.needReset)
81237d4cfdSXuan Hu
82237d4cfdSXuan Hu  // used by event bundle to filter the fields need to update
83237d4cfdSXuan Hu  def addInEvent(fieldFns: (this.type => CSREnumType)*): this.type = {
84237d4cfdSXuan Hu    this.eventFields ++= fieldFns.map(fn => fn(this))
85237d4cfdSXuan Hu    this
86237d4cfdSXuan Hu  }
87237d4cfdSXuan Hu
88237d4cfdSXuan Hu  override def cloneType: CSRBundle.this.type = {
89237d4cfdSXuan Hu    val ret = super.cloneType
90237d4cfdSXuan Hu    //
91237d4cfdSXuan Hu    (ret.getFields zip this.getFields).foreach { case (l, r) =>
92237d4cfdSXuan Hu      if (this.eventFields.contains(r)) {
93237d4cfdSXuan Hu        ret.eventFields += l
94237d4cfdSXuan Hu      }
95237d4cfdSXuan Hu    }
96237d4cfdSXuan Hu    ret
97237d4cfdSXuan Hu  }
981d192ad8SXuan Hu
991d192ad8SXuan Hu  def & (that: CSRBundle): UInt = {
1001d192ad8SXuan Hu    this.asUInt & that.asUInt
1011d192ad8SXuan Hu  }
1021d192ad8SXuan Hu
1031d192ad8SXuan Hu  def & (that: UInt): UInt = {
1041d192ad8SXuan Hu    require(this.asUInt.getWidth == that.getWidth,
1051d192ad8SXuan Hu      s"The width between left $this(${this.getWidth}) and right $that(${that.getWidth}) should be equal.")
1061d192ad8SXuan Hu    this.asUInt & that
1071d192ad8SXuan Hu  }
1081d192ad8SXuan Hu
1091d192ad8SXuan Hu  def | (that: CSRBundle): UInt = {
1101d192ad8SXuan Hu    this.asUInt | that.asUInt
1111d192ad8SXuan Hu  }
1121d192ad8SXuan Hu
1131d192ad8SXuan Hu  def | (that: UInt): UInt = {
1141d192ad8SXuan Hu    require(this.getWidth == that.getWidth)
1151d192ad8SXuan Hu    this.asUInt | that
1161d192ad8SXuan Hu  }
1171d192ad8SXuan Hu
1181d192ad8SXuan Hu  def unary_~ : UInt = {
1191d192ad8SXuan Hu    (~this.asUInt).asUInt
1201d192ad8SXuan Hu  }
1211d192ad8SXuan Hu
1221d192ad8SXuan Hu  def apply(num: Int) : CSREnumType = {
1231d192ad8SXuan Hu    this.getFields.find(x => x.lsb == num && x.msb == num).get
1241d192ad8SXuan Hu  }
1251d192ad8SXuan Hu
1261d192ad8SXuan Hu  def apply(str: String) : CSREnumType = {
1271d192ad8SXuan Hu    elements(str).asInstanceOf[CSREnumType]
1281d192ad8SXuan Hu  }
1291d192ad8SXuan Hu}
1301d192ad8SXuan Hu
1311d192ad8SXuan Huobject CSRBundleImplicitCast {
1321d192ad8SXuan Hu  class UIntField(val value: UInt) {
1331d192ad8SXuan Hu    def &[T <: CSRBundle] (field: T): UInt = {
1341d192ad8SXuan Hu      this.value & field.asUInt
1351d192ad8SXuan Hu    }
1361d192ad8SXuan Hu
1371d192ad8SXuan Hu    def |[T <: CSRBundle] (field: T): UInt = {
1381d192ad8SXuan Hu      this.value | field.asUInt
1391d192ad8SXuan Hu    }
1401d192ad8SXuan Hu
1411d192ad8SXuan Hu    def &>(that: Bool): UInt = {
1421d192ad8SXuan Hu      require(value.widthKnown, "The width of the left operand should be known when using >& operator")
1431d192ad8SXuan Hu      this.value & Fill(value.getWidth, that)
1441d192ad8SXuan Hu    }
1451d192ad8SXuan Hu
1461d192ad8SXuan Hu    def |>(that: Bool): UInt = {
1471d192ad8SXuan Hu      require(value.widthKnown, "The width of the left operand should be known when using >| operator")
1481d192ad8SXuan Hu      this.value | Fill(value.getWidth, that)
1491d192ad8SXuan Hu    }
1501d192ad8SXuan Hu  }
1511d192ad8SXuan Hu
152*e3da8badSTang Haojin  import scala.language.implicitConversions
1531d192ad8SXuan Hu  implicit def UIntToUIntField(uint: UInt): UIntField = new UIntField(uint)
1541d192ad8SXuan Hu}
1551d192ad8SXuan Hu
1561d192ad8SXuan Huobject ChiselRecordForField {
1571d192ad8SXuan Hu  implicit class AddRecordSpecifyFields[T <: Record](val x: T) {
1581d192ad8SXuan Hu    def specifyField(elemFns: (T => Unit)*): Unit = {
1591d192ad8SXuan Hu      elemFns.foreach(_.apply(x))
1601d192ad8SXuan Hu    }
1611d192ad8SXuan Hu  }
162039cdc35SXuan Hu}
163