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 for (field <- fields) { 41 field := field.factory.apply(that(field.lsb + field.getWidth - 1, field.lsb)) 42 } 43 } 44 45 @inline 46 def init: this.type = { 47 val init = Wire(this) 48 init.elements.foreach { case (str, field: CSREnumType) => 49 field := (if (field.init != null) field.factory(field.init.asUInt) else field.factory(0.U)) 50 } 51 init.asInstanceOf[this.type] 52 } 53 54 /** 55 * filtered read connection 56 * 57 * CSRBundle will be filtered by CSRFields' read filter function. 58 */ 59 def :|= [T <: CSRBundle](that: T): Unit = { 60 if (this.getClass != that.getClass) { 61 throw MonoConnectException(s"Type miss match! (sink :|= source) " + 62 s"sink type: ${this.getClass}, " + 63 s"source type: ${that.getClass}") 64 } 65 66 for ((sink: CSREnumType, source: CSREnumType) <- this.getFields.zip(that.getFields)) { 67 if (sink.rfn == null) 68 sink := source // .factory.apply(sink.rfn(source.asUInt, Seq())) 69 else 70 sink := sink.factory(sink.rfn(source.asUInt, Seq())) 71 } 72 } 73 74 def getFields: Seq[CSREnumType] = this.getElements.map(_.asInstanceOf[CSREnumType]) 75 76 def needReset: Boolean = this.getFields.exists(_.needReset) 77 78 // used by event bundle to filter the fields need to update 79 def addInEvent(fieldFns: (this.type => CSREnumType)*): this.type = { 80 this.eventFields ++= fieldFns.map(fn => fn(this)) 81 this 82 } 83 84 override def cloneType: CSRBundle.this.type = { 85 val ret = super.cloneType 86 // 87 (ret.getFields zip this.getFields).foreach { case (l, r) => 88 if (this.eventFields.contains(r)) { 89 ret.eventFields += l 90 } 91 } 92 ret 93 } 94 95 def & (that: CSRBundle): UInt = { 96 this.asUInt & that.asUInt 97 } 98 99 def & (that: UInt): UInt = { 100 require(this.asUInt.getWidth == that.getWidth, 101 s"The width between left $this(${this.getWidth}) and right $that(${that.getWidth}) should be equal.") 102 this.asUInt & that 103 } 104 105 def | (that: CSRBundle): UInt = { 106 this.asUInt | that.asUInt 107 } 108 109 def | (that: UInt): UInt = { 110 require(this.getWidth == that.getWidth) 111 this.asUInt | that 112 } 113 114 def unary_~ : UInt = { 115 (~this.asUInt).asUInt 116 } 117 118 def apply(num: Int) : CSREnumType = { 119 this.getFields.find(x => x.lsb == num && x.msb == num).get 120 } 121 122 def apply(str: String) : CSREnumType = { 123 elements(str).asInstanceOf[CSREnumType] 124 } 125} 126 127object CSRBundleImplicitCast { 128 class UIntField(val value: UInt) { 129 def &[T <: CSRBundle] (field: T): UInt = { 130 this.value & field.asUInt 131 } 132 133 def |[T <: CSRBundle] (field: T): UInt = { 134 this.value | field.asUInt 135 } 136 137 def &>(that: Bool): UInt = { 138 require(value.widthKnown, "The width of the left operand should be known when using >& operator") 139 this.value & Fill(value.getWidth, that) 140 } 141 142 def |>(that: Bool): UInt = { 143 require(value.widthKnown, "The width of the left operand should be known when using >| operator") 144 this.value | Fill(value.getWidth, that) 145 } 146 } 147 148 implicit def UIntToUIntField(uint: UInt): UIntField = new UIntField(uint) 149} 150 151object ChiselRecordForField { 152 implicit class AddRecordSpecifyFields[T <: Record](val x: T) { 153 def specifyField(elemFns: (T => Unit)*): Unit = { 154 elemFns.foreach(_.apply(x)) 155 } 156 } 157} 158