use literalinclude directive to pull source directly from example package
This commit is contained in:
parent
fd5e0024a7
commit
646d7cba4c
|
@ -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.
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue