From 59d5e613668d090b094c4f1b38a36abb7cb1e1ca Mon Sep 17 00:00:00 2001 From: Henry Cook Date: Sun, 11 Mar 2018 18:06:35 -0700 Subject: [PATCH] regmapper: refactor how json is emitted --- src/main/scala/regmapper/Annotation.scala | 23 ++++++++++ src/main/scala/regmapper/RegField.scala | 25 +++++++++++ src/main/scala/tilelink/RegisterRouter.scala | 47 +++----------------- 3 files changed, 54 insertions(+), 41 deletions(-) create mode 100644 src/main/scala/regmapper/Annotation.scala diff --git a/src/main/scala/regmapper/Annotation.scala b/src/main/scala/regmapper/Annotation.scala new file mode 100644 index 00000000..20ff902b --- /dev/null +++ b/src/main/scala/regmapper/Annotation.scala @@ -0,0 +1,23 @@ +// See LICENSE.SiFive for license details. + +package freechips.rocketchip.regmapper + +import org.json4s.JsonDSL._ +import org.json4s.jackson.JsonMethods.{pretty, render} + +object RegMappingAnnotation { + def serialize(base: BigInt, name: String, mapping: RegField.Map*): String = { + val regDescs = mapping.flatMap { case (byte, seq) => + seq.map(_.width).scanLeft(0)(_ + _).zip(seq).map { case (bit, f) => + val anonName = s"unnamedRegField${byte.toHexString}_${bit}" + (f.desc.map{ _.name}.getOrElse(anonName)) -> f.toJson(byte, bit) + } + } + + pretty(render( + ("peripheral" -> ( + ("displayName" -> name) ~ + ("baseAddress" -> s"0x${base.toInt.toHexString}") ~ + ("regfields" -> regDescs))))) + } +} diff --git a/src/main/scala/regmapper/RegField.scala b/src/main/scala/regmapper/RegField.scala index f620a178..b5a47332 100644 --- a/src/main/scala/regmapper/RegField.scala +++ b/src/main/scala/regmapper/RegField.scala @@ -5,6 +5,10 @@ package freechips.rocketchip.regmapper import Chisel._ import chisel3.util.{ReadyValidIO} +import org.json4s.JsonDSL._ +import org.json4s.JsonAST.JValue +import org.json4s.jackson.JsonMethods.{pretty, render} + import freechips.rocketchip.util.{SimpleRegIO} // This information is not used internally by the regmap(...) function. @@ -136,8 +140,29 @@ object RegWriteFn case class RegField(width: Int, read: RegReadFn, write: RegWriteFn, desc: Option[RegFieldDesc]) { require (width > 0, s"RegField width must be > 0, not $width") + def pipelined = !read.combinational || !write.combinational + def readOnly = this.copy(write = (), desc = this.desc.map(_.copy(access = RegFieldAccessType.R))) + + def toJson(byteOffset: Int, bitOffset: Int): JValue = { + ( ("byteOffset" -> s"0x${byteOffset.toHexString}") ~ + ("bitOffset" -> bitOffset) ~ + ("bitWidth" -> width) ~ + ("name" -> desc.map(_.name)) ~ + ("description" -> desc.map{ d=> if (d.desc == "") None else Some(d.desc)}) ~ + ("resetValue" -> desc.map{_.reset}) ~ + ("group" -> desc.map{_.group}) ~ + ("groupDesc" -> desc.map{_.groupDesc}) ~ + ("accessType" -> desc.map {d => d.access.toString}) ~ + ("writeType" -> desc.map {d => d.wrType.map(_.toString)}) ~ + ("readAction" -> desc.map {d => d.rdAction.map(_.toString)}) ~ + ("volatile" -> desc.map {d => if (d.volatile) Some(true) else None}) ~ + ("enumerations" -> desc.map {d => + Option(d.enumerations.map { case (key, (name, edesc)) => + (("value" -> key) ~ ("name" -> name) ~ ("description" -> edesc)) + }).filter(_.nonEmpty)}) ) + } } object RegField diff --git a/src/main/scala/tilelink/RegisterRouter.scala b/src/main/scala/tilelink/RegisterRouter.scala index ed764c67..fb74591e 100644 --- a/src/main/scala/tilelink/RegisterRouter.scala +++ b/src/main/scala/tilelink/RegisterRouter.scala @@ -10,9 +10,6 @@ import freechips.rocketchip.interrupts._ import freechips.rocketchip.util.{HeterogeneousBag, ElaborationArtefacts} import scala.math.{min,max} -import org.json4s.JsonDSL._ -import org.json4s.jackson.JsonMethods.{pretty, render} - case class TLRegisterNode( address: Seq[AddressSet], device: Device, @@ -85,47 +82,15 @@ case class TLRegisterNode( bundleIn.e.ready := Bool(true) // Dump out the register map for documentation purposes. - val regDescs = mapping.flatMap { case (offset, seq) => - 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}) ~ - ("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) ~ - ("name" -> name) ~ - ("description" -> desc)) - }).filter(_.nonEmpty)}) - )) - currentBitOffset = currentBitOffset + f.width - tmp - }} - } - - //TODO: It would be better to name this other than "Device at ...." - val base = s"0x${address.head.base.toInt.toHexString}" - val json = ("peripheral" -> ( - ("displayName" -> s"deviceAt${base}") ~ - ("baseAddress" -> base) ~ - ("regfields" -> regDescs) - )) - + val base = address.head.base + val baseHex = s"0x${base.toInt.toHexString}" + val name = s"deviceAt${baseHex}" //TODO: It would be better to name this other than "Device at ...." + val json = RegMappingAnnotation.serialize(base, name, mapping:_*) var suffix = 0 - while( ElaborationArtefacts.contains(s"${base}.${suffix}.regmap.json")){ + while( ElaborationArtefacts.contains(s"${baseHex}.${suffix}.regmap.json")){ suffix = suffix + 1 } - ElaborationArtefacts.add(s"${base}.${suffix}.regmap.json", pretty(render(json))) + ElaborationArtefacts.add(s"${baseHex}.${suffix}.regmap.json", json) } }