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. 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. 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 .. literalinclude:: ../../generators/example/src/main/scala/PWM.scala
:language: scala
case class PWMParams(address: BigInt, beatBytes: Int) :start-after: DOC include start: PWM generic traits
:end-before: DOC include end: PWM generic traits
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)))
}
Once you have these classes, you can construct the final peripheral by extending the ``TLRegisterRouter`` and passing the proper arguments. 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 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 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. The final set of arguments is the module constructor, which we create by extends ``TLRegModule`` with our module trait.
.. code-block:: scala .. literalinclude:: ../../generators/example/src/main/scala/PWM.scala
:language: scala
class PWMTL(c: PWMParams)(implicit p: Parameters) :start-after: DOC include start: PWMTL
extends TLRegisterRouter( :end-before: DOC include end: PWMTL
c.address, "pwm", Seq("ucbbar,pwm"),
beatBytes = c.beatBytes)(
new TLRegBundle(c, _) with PWMTLBundle)(
new TLRegModule(c, _, _) with PWMTLModule)
The full module code can be found in ``generators/example/src/main/scala/PWM.scala``. 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. 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. For a simple memory-mapped peripheral, this just involves connecting the peripheral's TileLink node to the MMIO crossbar.
.. code-block:: scala .. literalinclude:: ../../generators/example/src/main/scala/PWM.scala
:language: scala
trait HasPeripheryPWM { this: BaseSubsystem => :start-after: DOC include start: HasPeripheryPWMTL
implicit val p: Parameters :end-before: DOC include end: HasPeripheryPWMTL
private val address = 0x2000
private val portName = "pwm"
val pwm = LazyModule(new PWMTL(PWMParams(address, pbus.beatBytes)))
pbus.toVariableWidthSlave(Some(portName)) { pwm.node }
}
Note that the ``PWMTL`` class we created from the register router is itself a ``LazyModule``. 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. 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. 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. We then connect the ``PWMTL``'s pwmout to the pwmout we declared.
.. code-block:: scala .. literalinclude:: ../../generators/example/src/main/scala/PWM.scala
:language: scala
trait HasPeripheryPWMModuleImp extends LazyModuleImp { :start-after: DOC include start: HasPeripheryPWMTLModuleImp
implicit val p: Parameters :end-before: DOC include end: HasPeripheryPWMTLModuleImp
val outer: HasPeripheryPWM
val pwmout = IO(Output(Bool()))
pwmout := outer.pwm.module.io.pwmout
}
Now we want to mix our traits into the system as a whole. Now we want to mix our traits into the system as a whole.
This code is from ``generators/example/src/main/scala/Top.scala``. This code is from ``generators/example/src/main/scala/Top.scala``.
.. code-block:: scala .. literalinclude:: ../../generators/example/src/main/scala/Top.scala
:language: scala
class TopWithPWM(implicit p: Parameters) extends Top :start-after: DOC include start: TopWithPWMTL
with HasPeripheryPWM { :end-before: DOC include end: TopWithPWMTL
override lazy val module = Module(new TopWithPWMModule(this))
}
class TopWithPWMModule(l: TopWithPWM) extends TopModule(l)
with HasPeripheryPWMModuleImp
Just as we need separate traits for ``LazyModule`` and module implementation, we need two classes to build the system. 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. 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 ``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. 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) => { And finally, we create a configuration class in ``generators/example/src/main/scala/Configs.scala`` that uses this mixin.
case BuildTop => (p: Parameters) =>
Module(LazyModule(new TopWithPWM()(p)).module)
})
And finally, we create a configuration class in ``generators/example/src/main/scala/RocketConfigs.scala`` that uses this mixin. .. literalinclude:: ../../generators/example/src/main/scala/RocketConfigs.scala
:language: scala
.. code-block:: scala :start-after: DOC include start: PWMRocketConfig
:end-before: DOC include end: PWMRocketConfig
class PWMRocketConfig extends Config(
new WithPWMTop ++
new WithBootROM ++
new freechips.rocketchip.subsystem.WithNBigCores(1) ++
new freechips.rocketchip.system.BaseConfig)
Now we can test that the PWM is working. The test program is in ``tests/pwm.c``. Now we can test that the PWM is working. The test program is in ``tests/pwm.c``.
.. code-block:: c .. literalinclude:: ../../tests/pwm.c
:language: 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);
}
This just writes out to the registers we defined earlier. This just writes out to the registers we defined earlier.
The base of the module's MMIO region is at 0x2000. 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 * Class to specify a top level BOOM and/or Rocket system with PWM
*/ */
// DOC include start: WithPWMTop
class WithPWMTop extends Config((site, here, up) => { class WithPWMTop extends Config((site, here, up) => {
case BuildTop => (clock: Clock, reset: Bool, p: Parameters) => case BuildTop => (clock: Clock, reset: Bool, p: Parameters) =>
Module(LazyModule(new TopWithPWMTL()(p)).module) 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 * 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.tilelink._
import freechips.rocketchip.util.UIntIsOneOf import freechips.rocketchip.util.UIntIsOneOf
// DOC include start: PWM generic traits
case class PWMParams(address: BigInt, beatBytes: Int) case class PWMParams(address: BigInt, beatBytes: Int)
class PWMBase(w: Int) extends Module { class PWMBase(w: Int) extends Module {
@ -64,19 +65,23 @@ trait PWMModule extends HasRegMap {
0x08 -> Seq( 0x08 -> Seq(
RegField(1, enable))) RegField(1, enable)))
} }
// DOC include end: PWM generic traits
// DOC include start: PWMTL
class PWMTL(c: PWMParams)(implicit p: Parameters) class PWMTL(c: PWMParams)(implicit p: Parameters)
extends TLRegisterRouter( extends TLRegisterRouter(
c.address, "pwm", Seq("ucbbar,pwm"), c.address, "pwm", Seq("ucbbar,pwm"),
beatBytes = c.beatBytes)( beatBytes = c.beatBytes)(
new TLRegBundle(c, _) with PWMBundle)( new TLRegBundle(c, _) with PWMBundle)(
new TLRegModule(c, _, _) with PWMModule) new TLRegModule(c, _, _) with PWMModule)
// DOC include end: PWMTL
class PWMAXI4(c: PWMParams)(implicit p: Parameters) class PWMAXI4(c: PWMParams)(implicit p: Parameters)
extends AXI4RegisterRouter(c.address, beatBytes = c.beatBytes)( extends AXI4RegisterRouter(c.address, beatBytes = c.beatBytes)(
new AXI4RegBundle(c, _) with PWMBundle)( new AXI4RegBundle(c, _) with PWMBundle)(
new AXI4RegModule(c, _, _) with PWMModule) new AXI4RegModule(c, _, _) with PWMModule)
// DOC include start: HasPeripheryPWMTL
trait HasPeripheryPWMTL { this: BaseSubsystem => trait HasPeripheryPWMTL { this: BaseSubsystem =>
implicit val p: Parameters implicit val p: Parameters
@ -88,7 +93,9 @@ trait HasPeripheryPWMTL { this: BaseSubsystem =>
pbus.toVariableWidthSlave(Some(portName)) { pwm.node } pbus.toVariableWidthSlave(Some(portName)) { pwm.node }
} }
// DOC include end: HasPeripheryPWMTL
// DOC include start: HasPeripheryPWMTLModuleImp
trait HasPeripheryPWMTLModuleImp extends LazyModuleImp { trait HasPeripheryPWMTLModuleImp extends LazyModuleImp {
implicit val p: Parameters implicit val p: Parameters
val outer: HasPeripheryPWMTL val outer: HasPeripheryPWMTL
@ -97,6 +104,7 @@ trait HasPeripheryPWMTLModuleImp extends LazyModuleImp {
pwmout := outer.pwm.module.io.pwmout pwmout := outer.pwm.module.io.pwmout
} }
// DOC include end: HasPeripheryPWMTLModuleImp
trait HasPeripheryPWMAXI4 { this: BaseSubsystem => trait HasPeripheryPWMAXI4 { this: BaseSubsystem =>
implicit val p: Parameters implicit val p: Parameters

View File

@ -39,12 +39,14 @@ class jtagRocketConfig extends Config(
new freechips.rocketchip.subsystem.WithNBigCores(1) ++ new freechips.rocketchip.subsystem.WithNBigCores(1) ++
new freechips.rocketchip.system.BaseConfig) new freechips.rocketchip.system.BaseConfig)
// DOC include start: PWMRocketConfig
class PWMRocketConfig extends Config( class PWMRocketConfig extends Config(
new WithPWMTop ++ // use top with tilelink-controlled PWM new WithPWMTop ++ // use top with tilelink-controlled PWM
new WithBootROM ++ new WithBootROM ++
new freechips.rocketchip.subsystem.WithInclusiveCache ++ new freechips.rocketchip.subsystem.WithInclusiveCache ++
new freechips.rocketchip.subsystem.WithNBigCores(1) ++ new freechips.rocketchip.subsystem.WithNBigCores(1) ++
new freechips.rocketchip.system.BaseConfig) new freechips.rocketchip.system.BaseConfig)
// DOC include end: PWMRocketConfig
class PWMRAXI4ocketConfig extends Config( class PWMRAXI4ocketConfig extends Config(
new WithPWMAXI4Top ++ // use top with axi4-controlled PWM 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 with DontTouch
//--------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------
// DOC include start: TopWithPWMTL
class TopWithPWMTL(implicit p: Parameters) extends Top class TopWithPWMTL(implicit p: Parameters) extends Top
with HasPeripheryPWMTL { with HasPeripheryPWMTL {
@ -39,6 +40,7 @@ class TopWithPWMTL(implicit p: Parameters) extends Top
class TopWithPWMTLModule(l: TopWithPWMTL) extends TopModule(l) class TopWithPWMTLModule(l: TopWithPWMTL) extends TopModule(l)
with HasPeripheryPWMTLModuleImp with HasPeripheryPWMTLModuleImp
// DOC include end: TopWithPWMTL
//--------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------
class TopWithPWMAXI4(implicit p: Parameters) extends Top class TopWithPWMAXI4(implicit p: Parameters) extends Top