1
0

regmapper: refactor how json is emitted

This commit is contained in:
Henry Cook 2018-03-11 18:06:35 -07:00 committed by Megan Wachs
parent ea89259dd4
commit 59d5e61366
3 changed files with 54 additions and 41 deletions

View File

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

View File

@ -5,6 +5,10 @@ package freechips.rocketchip.regmapper
import Chisel._ import Chisel._
import chisel3.util.{ReadyValidIO} 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} import freechips.rocketchip.util.{SimpleRegIO}
// This information is not used internally by the regmap(...) function. // 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]) case class RegField(width: Int, read: RegReadFn, write: RegWriteFn, desc: Option[RegFieldDesc])
{ {
require (width > 0, s"RegField width must be > 0, not $width") require (width > 0, s"RegField width must be > 0, not $width")
def pipelined = !read.combinational || !write.combinational def pipelined = !read.combinational || !write.combinational
def readOnly = this.copy(write = (), desc = this.desc.map(_.copy(access = RegFieldAccessType.R))) 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 object RegField

View File

@ -10,9 +10,6 @@ import freechips.rocketchip.interrupts._
import freechips.rocketchip.util.{HeterogeneousBag, ElaborationArtefacts} import freechips.rocketchip.util.{HeterogeneousBag, ElaborationArtefacts}
import scala.math.{min,max} import scala.math.{min,max}
import org.json4s.JsonDSL._
import org.json4s.jackson.JsonMethods.{pretty, render}
case class TLRegisterNode( case class TLRegisterNode(
address: Seq[AddressSet], address: Seq[AddressSet],
device: Device, device: Device,
@ -85,47 +82,15 @@ case class TLRegisterNode(
bundleIn.e.ready := Bool(true) bundleIn.e.ready := Bool(true)
// Dump out the register map for documentation purposes. // Dump out the register map for documentation purposes.
val regDescs = mapping.flatMap { case (offset, seq) => val base = address.head.base
var currentBitOffset = 0 val baseHex = s"0x${base.toInt.toHexString}"
seq.zipWithIndex.map { case (f, i) => { val name = s"deviceAt${baseHex}" //TODO: It would be better to name this other than "Device at ...."
val tmp = (f.desc.map{ _.name}.getOrElse(s"unnamedRegField${offset.toHexString}_${currentBitOffset}") -> ( val json = RegMappingAnnotation.serialize(base, name, mapping:_*)
("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)
))
var suffix = 0 var suffix = 0
while( ElaborationArtefacts.contains(s"${base}.${suffix}.regmap.json")){ while( ElaborationArtefacts.contains(s"${baseHex}.${suffix}.regmap.json")){
suffix = suffix + 1 suffix = suffix + 1
} }
ElaborationArtefacts.add(s"${base}.${suffix}.regmap.json", pretty(render(json))) ElaborationArtefacts.add(s"${baseHex}.${suffix}.regmap.json", json)
} }
} }