1
0

RegFieldDesc: Add more features to support more IP-XACT like descriptions & emit them in the JSON

This commit is contained in:
Megan Wachs 2018-03-09 11:29:17 -08:00
parent e07b37c7ad
commit 2f239f2a9a
2 changed files with 42 additions and 20 deletions

View File

@ -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

View File

@ -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) ~