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