use literalinclude directive to pull source directly from example package

This commit is contained in:
Howard Mao 2019-09-09 22:47:23 -07:00
parent fd5e0024a7
commit 646d7cba4c
5 changed files with 48 additions and 110 deletions

View File

@ -66,50 +66,23 @@ MMIO Peripheral
The easiest way to create a TileLink peripheral is to use the ``TLRegisterRouter``, which abstracts away the details of handling the TileLink protocol and provides a convenient interface for specifying memory-mapped registers.
To create a RegisterRouter-based peripheral, you will need to specify a parameter case class for the configuration settings, a bundle trait with the extra top-level ports, and a module implementation containing the actual RTL.
In this case we use a submodule ``PWMBase`` to actually perform the pulse-width modulation. The ``PWMModule`` class only creates the registers and hooks them
up using ``regmap``.
.. code-block:: scala
case class PWMParams(address: BigInt, beatBytes: Int)
trait PWMTLBundle extends Bundle {
val pwmout = Output(Bool())
}
trait PWMTLModule extends HasRegMap {
val io: PWMTLBundle
implicit val p: Parameters
def params: PWMParams
val w = params.beatBytes * 8
val period = Reg(UInt(w.W))
val duty = Reg(UInt(w.W))
val enable = RegInit(false.B)
// ... Use the registers to drive io.pwmout ...
regmap(
0x00 -> Seq(
RegField(w, period)),
0x04 -> Seq(
RegField(w, duty)),
0x08 -> Seq(
RegField(1, enable)))
}
.. literalinclude:: ../../generators/example/src/main/scala/PWM.scala
:language: scala
:start-after: DOC include start: PWM generic traits
:end-before: DOC include end: PWM generic traits
Once you have these classes, you can construct the final peripheral by extending the ``TLRegisterRouter`` and passing the proper arguments.
The first set of arguments determines where the register router will be placed in the global address map and what information will be put in its device tree entry.
The second set of arguments is the IO bundle constructor, which we create by extending ``TLRegBundle`` with our bundle trait.
The final set of arguments is the module constructor, which we create by extends ``TLRegModule`` with our module trait.
.. code-block:: scala
class PWMTL(c: PWMParams)(implicit p: Parameters)
extends TLRegisterRouter(
c.address, "pwm", Seq("ucbbar,pwm"),
beatBytes = c.beatBytes)(
new TLRegBundle(c, _) with PWMTLBundle)(
new TLRegModule(c, _, _) with PWMTLModule)
.. literalinclude:: ../../generators/example/src/main/scala/PWM.scala
:language: scala
:start-after: DOC include start: PWMTL
:end-before: DOC include end: PWMTL
The full module code can be found in ``generators/example/src/main/scala/PWM.scala``.
@ -121,19 +94,10 @@ In the Rocket Chip cake, there are two kinds of traits: a ``LazyModule`` trait a
The ``LazyModule`` trait runs setup code that must execute before all the hardware gets elaborated.
For a simple memory-mapped peripheral, this just involves connecting the peripheral's TileLink node to the MMIO crossbar.
.. code-block:: scala
trait HasPeripheryPWM { this: BaseSubsystem =>
implicit val p: Parameters
private val address = 0x2000
private val portName = "pwm"
val pwm = LazyModule(new PWMTL(PWMParams(address, pbus.beatBytes)))
pbus.toVariableWidthSlave(Some(portName)) { pwm.node }
}
.. literalinclude:: ../../generators/example/src/main/scala/PWM.scala
:language: scala
:start-after: DOC include start: HasPeripheryPWMTL
:end-before: DOC include end: HasPeripheryPWMTL
Note that the ``PWMTL`` class we created from the register router is itself a ``LazyModule``.
Register routers have a TileLink node simply named "node", which we can hook up to the Rocket Chip bus.
@ -143,30 +107,18 @@ The module implementation trait is where we instantiate our PWM module and conne
Since this module has an extra `pwmout` output, we declare that in this trait, using Chisel's multi-IO functionality.
We then connect the ``PWMTL``'s pwmout to the pwmout we declared.
.. code-block:: scala
trait HasPeripheryPWMModuleImp extends LazyModuleImp {
implicit val p: Parameters
val outer: HasPeripheryPWM
val pwmout = IO(Output(Bool()))
pwmout := outer.pwm.module.io.pwmout
}
.. literalinclude:: ../../generators/example/src/main/scala/PWM.scala
:language: scala
:start-after: DOC include start: HasPeripheryPWMTLModuleImp
:end-before: DOC include end: HasPeripheryPWMTLModuleImp
Now we want to mix our traits into the system as a whole.
This code is from ``generators/example/src/main/scala/Top.scala``.
.. code-block:: scala
class TopWithPWM(implicit p: Parameters) extends Top
with HasPeripheryPWM {
override lazy val module = Module(new TopWithPWMModule(this))
}
class TopWithPWMModule(l: TopWithPWM) extends TopModule(l)
with HasPeripheryPWMModuleImp
.. literalinclude:: ../../generators/example/src/main/scala/Top.scala
:language: scala
:start-after: DOC include start: TopWithPWMTL
:end-before: DOC include end: TopWithPWMTL
Just as we need separate traits for ``LazyModule`` and module implementation, we need two classes to build the system.
The ``Top`` classes already have the basic peripherals included for us, so we will just extend those.
@ -174,52 +126,24 @@ The ``Top`` classes already have the basic peripherals included for us, so we wi
The ``Top`` class includes the pre-elaboration code and also a ``lazy val`` to produce the module implementation (hence ``LazyModule``).
The ``TopModule`` class is the actual RTL that gets synthesized.
Next, we need to add a configuration mixin in ``generators/example/src/main/scala/ConfigMixins.scala`` that tells the ``TestHarness`` to instantiate ``TopWithPWM`` instead of the default ``Top``.
Next, we need to add a configuration mixin in ``generators/example/src/main/scala/ConfigMixins.scala`` that tells the ``TestHarness`` to instantiate ``TopWithPWMTL`` instead of the default ``Top``.
.. code-block:: scala
.. literalinclude:: ../../generators/example/src/main/scala/ConfigMixins.scala
:language: scala
:start-after: DOC include start: WithPWMTop
:end-before: DOC include end: WithPWMTop
class WithPWMTop extends Config((site, here, up) => {
case BuildTop => (p: Parameters) =>
Module(LazyModule(new TopWithPWM()(p)).module)
})
And finally, we create a configuration class in ``generators/example/src/main/scala/Configs.scala`` that uses this mixin.
And finally, we create a configuration class in ``generators/example/src/main/scala/RocketConfigs.scala`` that uses this mixin.
.. code-block:: scala
class PWMRocketConfig extends Config(
new WithPWMTop ++
new WithBootROM ++
new freechips.rocketchip.subsystem.WithNBigCores(1) ++
new freechips.rocketchip.system.BaseConfig)
.. literalinclude:: ../../generators/example/src/main/scala/RocketConfigs.scala
:language: scala
:start-after: DOC include start: PWMRocketConfig
:end-before: DOC include end: PWMRocketConfig
Now we can test that the PWM is working. The test program is in ``tests/pwm.c``.
.. code-block:: c
#define PWM_PERIOD 0x2000
#define PWM_DUTY 0x2008
#define PWM_ENABLE 0x2010
static inline void write_reg(unsigned long addr, unsigned long data)
{
volatile unsigned long *ptr = (volatile unsigned long *) addr;
*ptr = data;
}
static inline unsigned long read_reg(unsigned long addr)
{
volatile unsigned long *ptr = (volatile unsigned long *) addr;
return *ptr;
}
int main(void)
{
write_reg(PWM_PERIOD, 20);
write_reg(PWM_DUTY, 5);
write_reg(PWM_ENABLE, 1);
}
.. literalinclude:: ../../tests/pwm.c
:language: c
This just writes out to the registers we defined earlier.
The base of the module's MMIO region is at 0x2000.

View File

@ -70,10 +70,12 @@ class WithDTMTop extends Config((site, here, up) => {
/**
* Class to specify a top level BOOM and/or Rocket system with PWM
*/
// DOC include start: WithPWMTop
class WithPWMTop extends Config((site, here, up) => {
case BuildTop => (clock: Clock, reset: Bool, p: Parameters) =>
Module(LazyModule(new TopWithPWMTL()(p)).module)
})
// DOC include end: WithPWMTop
/**
* Class to specify a top level BOOM and/or Rocket system with a PWM AXI4

View File

@ -10,6 +10,7 @@ import freechips.rocketchip.regmapper.{HasRegMap, RegField}
import freechips.rocketchip.tilelink._
import freechips.rocketchip.util.UIntIsOneOf
// DOC include start: PWM generic traits
case class PWMParams(address: BigInt, beatBytes: Int)
class PWMBase(w: Int) extends Module {
@ -64,19 +65,23 @@ trait PWMModule extends HasRegMap {
0x08 -> Seq(
RegField(1, enable)))
}
// DOC include end: PWM generic traits
// DOC include start: PWMTL
class PWMTL(c: PWMParams)(implicit p: Parameters)
extends TLRegisterRouter(
c.address, "pwm", Seq("ucbbar,pwm"),
beatBytes = c.beatBytes)(
new TLRegBundle(c, _) with PWMBundle)(
new TLRegModule(c, _, _) with PWMModule)
// DOC include end: PWMTL
class PWMAXI4(c: PWMParams)(implicit p: Parameters)
extends AXI4RegisterRouter(c.address, beatBytes = c.beatBytes)(
new AXI4RegBundle(c, _) with PWMBundle)(
new AXI4RegModule(c, _, _) with PWMModule)
// DOC include start: HasPeripheryPWMTL
trait HasPeripheryPWMTL { this: BaseSubsystem =>
implicit val p: Parameters
@ -88,7 +93,9 @@ trait HasPeripheryPWMTL { this: BaseSubsystem =>
pbus.toVariableWidthSlave(Some(portName)) { pwm.node }
}
// DOC include end: HasPeripheryPWMTL
// DOC include start: HasPeripheryPWMTLModuleImp
trait HasPeripheryPWMTLModuleImp extends LazyModuleImp {
implicit val p: Parameters
val outer: HasPeripheryPWMTL
@ -97,6 +104,7 @@ trait HasPeripheryPWMTLModuleImp extends LazyModuleImp {
pwmout := outer.pwm.module.io.pwmout
}
// DOC include end: HasPeripheryPWMTLModuleImp
trait HasPeripheryPWMAXI4 { this: BaseSubsystem =>
implicit val p: Parameters

View File

@ -39,12 +39,14 @@ class jtagRocketConfig extends Config(
new freechips.rocketchip.subsystem.WithNBigCores(1) ++
new freechips.rocketchip.system.BaseConfig)
// DOC include start: PWMRocketConfig
class PWMRocketConfig extends Config(
new WithPWMTop ++ // use top with tilelink-controlled PWM
new WithBootROM ++
new freechips.rocketchip.subsystem.WithInclusiveCache ++
new freechips.rocketchip.subsystem.WithNBigCores(1) ++
new freechips.rocketchip.system.BaseConfig)
// DOC include end: PWMRocketConfig
class PWMRAXI4ocketConfig extends Config(
new WithPWMAXI4Top ++ // use top with axi4-controlled PWM

View File

@ -30,6 +30,7 @@ class TopModule[+L <: Top](l: L) extends SystemModule(l)
with DontTouch
//---------------------------------------------------------------------------------------------------------
// DOC include start: TopWithPWMTL
class TopWithPWMTL(implicit p: Parameters) extends Top
with HasPeripheryPWMTL {
@ -39,6 +40,7 @@ class TopWithPWMTL(implicit p: Parameters) extends Top
class TopWithPWMTLModule(l: TopWithPWMTL) extends TopModule(l)
with HasPeripheryPWMTLModuleImp
// DOC include end: TopWithPWMTL
//---------------------------------------------------------------------------------------------------------
class TopWithPWMAXI4(implicit p: Parameters) extends Top