Awesome
DUH component export to Scala
Installation
npm i duh-scala
Exporting a blackbox wrapper and attach
method
This is a scala LazyModule
that has diplomatic nodes corresponding to the bus
interfaces of the duh component.
duh-export-scala <mycomp>.json5 -o <output-dir>
Exporting a RegisterRouter
duh-export-regmap
will export a RegisterRouter
corresponding the the
memoryMap
s in a duh component. A RegisterRouter
is an abstract Scala
description of memory-mapped registers that is generic to any bus interface.
Concrete implementations for TileLink and AXI4 are included in the generated
Scala.
duh-export-regmap <mycomp>.json5 -o <output-dir>
Exporting a monitor wrapper and attach
method
This is a special kind of chisel Module
that can be attached to diplomatic
edges corresponding to the monitor's bus interface type.
duh-export-monitor <mycomp>.json5 -o <output-dir>
Blackbox wrapper API
This section describes the API of the blackbox wrapper generated by
duh-export-scala
. The hierarchy of the output modules is looks like
top: N${name}Top
└── imp: L${name}
└── blackbox: ${name}
The reason for having two layers of wrapping is to separate the purely
combinational wrapper logic from the sequential logic. The inner L${name}
module only contains combinational wrapper logic while the outer N${name}Top
module contains sequential logic
The L${name}
module contains the node declarations, blackbox instantiation,
and connections between node bundles and blackbox ports. There is also an
extraResources
method that is called when the DTS data structure is
constructed. The fields returned by this method are included in the entry
corresponding the component in the DTS.
class L${name}Base(c: ${name}Params)(implicit p: Parameters) extends LazyModule {
// device declaration
val device = new SimpleDevice("${name}", Seq("sifive,${name}-${version}")) {
...
}
// extra fields to include in the entry of this device in the DTS
def extraResources(resources: ResourceBindings) = Map[String, Seq[ResourceValue]]()
// node declarations
val axiNode = ...
val apbNode = ...
...
// blackbox instantiation and wiring
lazy val module = new L${name}BaseImp
}
The corresponding user class that extends L${name}Base
looks like
class L${name}(c: ${name}Params)(implicit p: Parameters) extends L${name}Base(c)(p)
{
// User code here
}
To add another integer field called data-width
and string field called name
you would add the following code into the user L${name}
class.
override def extraResources(resources: ResourceBindings) =
Map("data-width" -> Seq(ResourceInt(dataWidth)),
"name" -> Seq(ResourceString(name)))
The result should look like
class L${name}(c: ${name}Params)(implicit p: Parameters) extends L${name}Base(c)(p)
{
override def extraResources(resources: ResourceBindings) =
Map("data-width" -> Seq(ResourceInt(dataWidth)),
"name" -> Seq(ResourceString(name)))
}
The N${name}
module contains methods to instantate TileLink adapters for the
nodes. It also contains a method called userOM
that is called when the object
model of the component is constructed. The object returned by userOM
is
included with the base object model. This can be overrided to include arbitrary
information in the object model and defaults to empty. The value returned by
this method should be an instance of a case class
which is why it returns
Product with Serializable
.
class N${name}TopBase(val c: N${name}TopParams)(implicit p: Parameters) extends SimpleLazyModule
with BindingScope {
// userOM method
def userOM: Product with Serializable = Nil
// adapter methods
def getaxilNodeTLAdapter(): TLInwardNode = ...
def getahblNodeTLAdapter(): TLInwardNode = ...
...
}
The corresponding user class that extends N${name}Base
looks like
class N${name}Top(c: N${name}TopParams)(implicit p: Parameters) extends N${name}TopBase(c)(p)
{
// User code here
}
To add the following fields to the OMDevice
of the component
foo: "foo",
foobar: {
foo: "foo",
bar: "bar"
}
add the following code to the user N${name}
by defining the following case class
case class MyOM(foo: String, foobar: Map[String, String])
and add the following code to N${name}
override def userOM = new MyOM("foo", Map("foo" -> "foo", "bar" -> "bar"))
The result should look like
class N${name}Top(c: N${name}TopParams)(implicit p: Parameters) extends N${name}TopBase(c)(p)
{
override def userOM = new MyOM("foo", Map("foo" -> "foo", "bar" -> "bar"))
}
And the output object model should look like
{
"foo" : {
"foo" : "foo",
"bar" : "bar"
},
"memoryRegions" : [ ... ],
"interrupts" : [ ... ],
"_types" : [ "OM${name}", "OMDevice", "OMComponent", "OMCompoundType" ]
}
Testing
npm test
License
Apache 2.0 LICENSE.