From 2f239f2a9a0ad63792ded3349e650246d1c41bc4 Mon Sep 17 00:00:00 2001 From: Megan Wachs Date: Fri, 9 Mar 2018 11:29:17 -0800 Subject: [PATCH] RegFieldDesc: Add more features to support more IP-XACT like descriptions & emit them in the JSON --- src/main/scala/regmapper/RegField.scala | 41 ++++++++++++++------ src/main/scala/tilelink/RegisterRouter.scala | 21 +++++----- 2 files changed, 42 insertions(+), 20 deletions(-) diff --git a/src/main/scala/regmapper/RegField.scala b/src/main/scala/regmapper/RegField.scala index b814732b..91c69e52 100644 --- a/src/main/scala/regmapper/RegField.scala +++ b/src/main/scala/regmapper/RegField.scala @@ -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 diff --git a/src/main/scala/tilelink/RegisterRouter.scala b/src/main/scala/tilelink/RegisterRouter.scala index c4b4d42c..ed764c67 100644 --- a/src/main/scala/tilelink/RegisterRouter.scala +++ b/src/main/scala/tilelink/RegisterRouter.scala @@ -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) ~