Merge pull request #1184 from freechipsproject/regfield_json
TLRegMapper: emit a JSON file describing the register fields
This commit is contained in:
commit
6f70d25ef9
@ -15,6 +15,7 @@ lazy val commonSettings = Seq(
|
|||||||
traceLevel := 15,
|
traceLevel := 15,
|
||||||
scalacOptions ++= Seq("-deprecation","-unchecked"),
|
scalacOptions ++= Seq("-deprecation","-unchecked"),
|
||||||
libraryDependencies ++= Seq("org.scala-lang" % "scala-reflect" % scalaVersion.value),
|
libraryDependencies ++= Seq("org.scala-lang" % "scala-reflect" % scalaVersion.value),
|
||||||
|
libraryDependencies ++= Seq("org.json4s" %% "json4s-jackson" % "3.5.0"),
|
||||||
addCompilerPlugin("org.scalamacros" % "paradise" % "2.1.0" cross CrossVersion.full)
|
addCompilerPlugin("org.scalamacros" % "paradise" % "2.1.0" cross CrossVersion.full)
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -44,3 +45,4 @@ val chipSettings = Seq(
|
|||||||
s"make -C $makeDir -j $jobs $target".!
|
s"make -C $makeDir -j $jobs $target".!
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -83,9 +83,9 @@ class CoreplexLocalInterrupter(params: ClintParams)(implicit p: Parameters) exte
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
node.regmap(
|
node.regmap(
|
||||||
0 -> RegFieldGroup ("msip", Some("MSIP Bits"), ipi.zipWithIndex.map{ case (r, i) => RegField(ipiWidth, r, RegFieldDesc(s"msip_$i", "MSIP bit for Hart $i", reset=Some(0)))}),
|
0 -> RegFieldGroup ("msip", Some("MSIP Bits"), ipi.zipWithIndex.map{ case (r, i) => RegField(ipiWidth, r, RegFieldDesc(s"msip_$i", s"MSIP bit for Hart $i", reset=Some(0)))}),
|
||||||
timecmpOffset(0) -> timecmp.zipWithIndex.flatMap{ case (t, i) =>
|
timecmpOffset(0) -> timecmp.zipWithIndex.flatMap{ case (t, i) =>
|
||||||
RegFieldGroup(s"mtimecmp_$i", Some(s"MTIMECMP for hart $i"), RegField.bytes(t, Some(RegFieldDesc("mtimecmp_$i", "", reset=None))))},
|
RegFieldGroup(s"mtimecmp_$i", Some(s"MTIMECMP for hart $i"), RegField.bytes(t, Some(RegFieldDesc(s"mtimecmp_$i", "", reset=None))))},
|
||||||
timeOffset -> RegFieldGroup("mtime", Some("Timer Register"), RegField.bytes(time, Some(RegFieldDesc("mtime", "", reset=Some(0)))))
|
timeOffset -> RegFieldGroup("mtime", Some("Timer Register"), RegField.bytes(time, Some(RegFieldDesc("mtime", "", reset=Some(0)))))
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -179,8 +179,8 @@ class TLPLIC(params: PLICParams)(implicit p: Parameters) extends LazyModule
|
|||||||
|
|
||||||
|
|
||||||
val enableRegFields = enables.zipWithIndex.map { case (e, i) =>
|
val enableRegFields = enables.zipWithIndex.map { case (e, i) =>
|
||||||
PLICConsts.enableBase(i) -> RegFieldGroup("enable", Some("Enable bits for each interrupt source. 1 bit for each interrupt source."),
|
PLICConsts.enableBase(i) -> RegFieldGroup(s"enables_${i}", Some(s"Enable bits for each interrupt source for target $i. 1 bit for each interrupt source."),
|
||||||
e.map(b => RegField(1, b, RegFieldDesc(s"enable_$i", "Enable interrupt and claim for source $i", reset=None))))
|
e.zipWithIndex.map{case (b, j) => RegField(1, b, RegFieldDesc(s"enable_${i}_${j}", s"Enable interrupt for source $j for target $i.", reset=None))})
|
||||||
}
|
}
|
||||||
|
|
||||||
// When a hart reads a claim/complete register, then the
|
// When a hart reads a claim/complete register, then the
|
||||||
@ -232,8 +232,9 @@ class TLPLIC(params: PLICParams)(implicit p: Parameters) extends LazyModule
|
|||||||
completer(i) := valid && enables(i)(completerDev)
|
completer(i) := valid && enables(i)(completerDev)
|
||||||
Bool(true)
|
Bool(true)
|
||||||
},
|
},
|
||||||
Some(RegFieldDesc(s"claim_complete_$i", ("Claim/Complete register for Target $i. Reading this register returns the claimed interrupt number and makes it no longer pending." +
|
Some(RegFieldDesc(s"claim_complete_$i",
|
||||||
"Writing the interrupt number back completes the interrupt."),
|
s"Claim/Complete register for Target $i. Reading this register returns the claimed interrupt number and makes it no longer pending." +
|
||||||
|
s"Writing the interrupt number back completes the interrupt.",
|
||||||
reset = None,
|
reset = None,
|
||||||
access = RegFieldAccessType.RWSPECIAL))
|
access = RegFieldAccessType.RWSPECIAL))
|
||||||
)
|
)
|
||||||
|
@ -164,7 +164,7 @@ object RegField
|
|||||||
val valids = Wire(init = Vec.fill(numBytes) { Bool(false) })
|
val valids = Wire(init = Vec.fill(numBytes) { Bool(false) })
|
||||||
when (valids.reduce(_ || _)) { reg := newBytes.asUInt }
|
when (valids.reduce(_ || _)) { reg := newBytes.asUInt }
|
||||||
Seq.tabulate(numBytes) { i =>
|
Seq.tabulate(numBytes) { i =>
|
||||||
val newDesc = desc.map {d => d.copy(name = d.name + s"[${i*8-1}:${i*8}]")}
|
val newDesc = desc.map {d => d.copy(name = d.name + s"[${(i+1)*8-1}:${i*8}]")}
|
||||||
RegField(8, oldBytes(i),
|
RegField(8, oldBytes(i),
|
||||||
RegWriteFn((valid, data) => {
|
RegWriteFn((valid, data) => {
|
||||||
valids(i) := valid
|
valids(i) := valid
|
||||||
|
@ -7,9 +7,12 @@ import freechips.rocketchip.config.Parameters
|
|||||||
import freechips.rocketchip.diplomacy._
|
import freechips.rocketchip.diplomacy._
|
||||||
import freechips.rocketchip.regmapper._
|
import freechips.rocketchip.regmapper._
|
||||||
import freechips.rocketchip.interrupts._
|
import freechips.rocketchip.interrupts._
|
||||||
import freechips.rocketchip.util.HeterogeneousBag
|
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,
|
||||||
@ -80,6 +83,35 @@ case class TLRegisterNode(
|
|||||||
bundleIn.b.valid := Bool(false)
|
bundleIn.b.valid := Bool(false)
|
||||||
bundleIn.c.ready := Bool(true)
|
bundleIn.c.ready := Bool(true)
|
||||||
bundleIn.e.ready := Bool(true)
|
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${i}") -> (
|
||||||
|
("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})
|
||||||
|
))
|
||||||
|
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)
|
||||||
|
))
|
||||||
|
ElaborationArtefacts.add(s"${base}.regmap.json", pretty(render(json)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user