RegFieldDesc: Add more features to support more IP-XACT like descriptions & emit them in the JSON
This commit is contained in:
parent
e07b37c7ad
commit
2f239f2a9a
@ -7,7 +7,6 @@ import chisel3.util.{ReadyValidIO}
|
||||
|
||||
import freechips.rocketchip.util.{SimpleRegIO}
|
||||
|
||||
|
||||
// This information is not used internally by the regmap(...) function.
|
||||
// However, the author of a RegField may be the best person to provide this
|
||||
// information which is likely to be needed by downstream SW and Documentation
|
||||
@ -15,26 +14,47 @@ import freechips.rocketchip.util.{SimpleRegIO}
|
||||
|
||||
object RegFieldAccessType extends scala.Enumeration {
|
||||
type RegFieldAccessType = Value
|
||||
val R, W, RW, RSPECIAL, WSPECIAL, RWSPECIAL, OTHER = Value
|
||||
val R, W, RW = Value
|
||||
}
|
||||
import RegFieldAccessType._
|
||||
|
||||
object RegFieldWrType extends scala.Enumeration {
|
||||
type RegFieldWrType = Value
|
||||
val ONE_TO_CLEAR, ONE_TO_SET, ONE_TO_TOGGLE, ZERO_TO_CLEAR,
|
||||
ZERO_TO_SET, ZERO_TO_TOGGLE, CLEAR, SET, MODIFY = Value
|
||||
}
|
||||
import RegFieldWrType._
|
||||
|
||||
object RegFieldRdAction extends scala.Enumeration {
|
||||
type RegFieldRdAction = Value
|
||||
val CLEAR, SET, MODIFY = Value
|
||||
}
|
||||
import RegFieldRdAction._
|
||||
|
||||
case class RegFieldDesc (
|
||||
name: String,
|
||||
desc: String,
|
||||
group: Option[String] = None,
|
||||
groupDesc: Option[String] = None,
|
||||
access: RegFieldAccessType = RegFieldAccessType.RW,
|
||||
wrType: Option[RegFieldWrType] = None,
|
||||
rdAction: Option[RegFieldRdAction] = None,
|
||||
volatile: Boolean = false,
|
||||
// TODO: testable?
|
||||
reset: Option[BigInt] = None,
|
||||
enumerations: Map[BigInt, (String, String)] = Map()
|
||||
){
|
||||
}
|
||||
|
||||
// Our descriptions are in terms of RegFields only, which is somewhat unusual for
|
||||
// developers who are used to things being defined as bitfields within registers.
|
||||
// The "Group" allows a string & (optional) description to be added which describes the conceptual "Group"
|
||||
// the RegField belongs to. This can be used by downstream flows as they see fit to
|
||||
// present the information.
|
||||
object RegFieldDescReserved {
|
||||
def apply(): RegFieldDesc = RegFieldDesc("reserved", "", access=RegFieldAccessType.R, reset=Some(0))
|
||||
}
|
||||
|
||||
// Our descriptions are in terms of RegFields only, which is somewhat
|
||||
// unusual for developers who are used to things being defined as bitfields
|
||||
// within registers. The "Group" allows a string & (optional) description
|
||||
// to be added which describes the conceptual "Group" the RegField belongs to.
|
||||
// This can be used by downstream flows as they see fit to present the information.
|
||||
|
||||
object RegFieldGroup {
|
||||
def apply (name: String, desc: Option[String], regs: Seq[RegField], descFirstOnly: Boolean = true): Seq[RegField] = {
|
||||
@ -125,8 +145,7 @@ object RegField
|
||||
// Byte address => sequence of bitfields, lowest index => lowest address
|
||||
type Map = (Int, Seq[RegField])
|
||||
|
||||
def apply(n: Int) : RegField = apply(n, (), (),
|
||||
Some(RegFieldDesc("reserved", "", access = RegFieldAccessType.R, reset = Some(0))))
|
||||
def apply(n: Int) : RegField = apply(n, (), (), Some(RegFieldDescReserved()))
|
||||
|
||||
def apply(n: Int, r: RegReadFn, w: RegWriteFn) : RegField = apply(n, r, w, None)
|
||||
def apply(n: Int, r: RegReadFn, w: RegWriteFn, desc: RegFieldDesc) : RegField = apply(n, r, w, Some(desc))
|
||||
@ -142,7 +161,7 @@ object RegField
|
||||
// Setting takes priority over clearing.
|
||||
def w1ToClear(n: Int, reg: UInt, set: UInt, desc: Option[RegFieldDesc] = None): RegField =
|
||||
RegField(n, reg, RegWriteFn((valid, data) => { reg := ~(~reg | Mux(valid, data, UInt(0))) | set; Bool(true) }),
|
||||
desc.map{_.copy(access = RegFieldAccessType.RWSPECIAL)})
|
||||
desc.map{_.copy(access = RegFieldAccessType.RW, wrType=Some(RegFieldWrType.ONE_TO_CLEAR), volatile = true)})
|
||||
|
||||
// This RegField wraps an explicit register
|
||||
// (e.g. Black-Boxed Register) to create a R/W register.
|
||||
@ -151,7 +170,7 @@ object RegField
|
||||
bb.en := valid
|
||||
bb.d := data
|
||||
Bool(true)
|
||||
}), desc.map{_.copy(access = RegFieldAccessType.RW)})
|
||||
}), desc)
|
||||
|
||||
// Create byte-sized read-write RegFields out of a large UInt register.
|
||||
// It is updated when any of the bytes are written. Because the RegFields
|
||||
|
@ -89,15 +89,18 @@ case class TLRegisterNode(
|
||||
var currentBitOffset = 0
|
||||
seq.zipWithIndex.map { case (f, i) => {
|
||||
val tmp = (f.desc.map{ _.name}.getOrElse(s"unnamedRegField${offset.toHexString}_${currentBitOffset}") -> (
|
||||
("byteOffset" -> s"0x${offset.toHexString}") ~
|
||||
("bitOffset" -> currentBitOffset) ~
|
||||
("bitWidth" -> f.width) ~
|
||||
("name" -> f.desc.map(_.name)) ~
|
||||
("description" -> f.desc.map{d => if (d.desc == "") None else Some(d.desc)}) ~
|
||||
("resetValue" -> f.desc.map{_.reset}) ~
|
||||
("group" -> f.desc.map{_.group}) ~
|
||||
("groupDesc" -> f.desc.map{_.groupDesc}) ~
|
||||
("accessType" -> f.desc.map {d => d.access.toString}) ~
|
||||
("byteOffset" -> s"0x${offset.toHexString}") ~
|
||||
("bitOffset" -> currentBitOffset) ~
|
||||
("bitWidth" -> f.width) ~
|
||||
("name" -> f.desc.map(_.name)) ~
|
||||
("description" -> f.desc.map{d => if (d.desc == "") None else Some(d.desc)}) ~
|
||||
("resetValue" -> f.desc.map{_.reset}) ~
|
||||
("group" -> f.desc.map{_.group}) ~
|
||||
("groupDesc" -> f.desc.map{_.groupDesc}) ~
|
||||
("accessType" -> f.desc.map {d => d.access.toString}) ~
|
||||
("writeType" -> f.desc.map {d => d.wrType.map(_.toString)}) ~
|
||||
("readAction" -> f.desc.map {d => d.rdAction.map(_.toString)}) ~
|
||||
("volatile" -> f.desc.map {d => if (d.volatile) Some(true) else None}) ~
|
||||
("enumerations" -> f.desc.map {d =>
|
||||
Option(d.enumerations.map { case (key, (name, desc)) =>
|
||||
(("value" -> key) ~
|
||||
|
Loading…
Reference in New Issue
Block a user