Add syntax highlighting to README.md
This commit is contained in:
20
README.md
20
README.md
@@ -119,6 +119,7 @@ specify a parameter case class for the configuration settings, a bundle trait
|
|||||||
with the extra top-level ports, and a module implementation containing the
|
with the extra top-level ports, and a module implementation containing the
|
||||||
actual RTL.
|
actual RTL.
|
||||||
|
|
||||||
|
```scala
|
||||||
case class PWMParams(address: BigInt, beatBytes: Int)
|
case class PWMParams(address: BigInt, beatBytes: Int)
|
||||||
|
|
||||||
trait PWMTLBundle extends Bundle {
|
trait PWMTLBundle extends Bundle {
|
||||||
@@ -145,6 +146,7 @@ actual RTL.
|
|||||||
0x08 -> Seq(
|
0x08 -> Seq(
|
||||||
RegField(1, enable)))
|
RegField(1, enable)))
|
||||||
}
|
}
|
||||||
|
```
|
||||||
|
|
||||||
Once you have these classes, you can construct the final peripheral by
|
Once you have these classes, you can construct the final peripheral by
|
||||||
extending the TLRegisterRouter and passing the proper arguments. The first
|
extending the TLRegisterRouter and passing the proper arguments. The first
|
||||||
@@ -155,12 +157,14 @@ by extending TLRegBundle with our bundle trait. The final set of arguments
|
|||||||
is the module constructor, which we create by extends TLRegModule with our
|
is the module constructor, which we create by extends TLRegModule with our
|
||||||
module trait.
|
module trait.
|
||||||
|
|
||||||
|
```scala
|
||||||
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 PWMTLBundle)(
|
new TLRegBundle(c, _) with PWMTLBundle)(
|
||||||
new TLRegModule(c, _, _) with PWMTLModule)
|
new TLRegModule(c, _, _) with PWMTLModule)
|
||||||
|
```
|
||||||
|
|
||||||
The full module code with comments can be found in src/main/scala/example/PWM.scala.
|
The full module code with comments can be found in src/main/scala/example/PWM.scala.
|
||||||
|
|
||||||
@@ -174,6 +178,7 @@ The LazyModule trait runs setup code that must execute before all the hardware
|
|||||||
gets elaborated. For a simple memory-mapped peripheral, this just involves
|
gets elaborated. For a simple memory-mapped peripheral, this just involves
|
||||||
connecting the peripheral's TileLink node to the MMIO crossbar.
|
connecting the peripheral's TileLink node to the MMIO crossbar.
|
||||||
|
|
||||||
|
```scala
|
||||||
trait HasPeripheryPWM extends HasSystemNetworks {
|
trait HasPeripheryPWM extends HasSystemNetworks {
|
||||||
implicit val p: Parameters
|
implicit val p: Parameters
|
||||||
|
|
||||||
@@ -185,6 +190,7 @@ connecting the peripheral's TileLink node to the MMIO crossbar.
|
|||||||
pwm.node := TLFragmenter(
|
pwm.node := TLFragmenter(
|
||||||
peripheryBusConfig.beatBytes, cacheBlockBytes)(peripheryBus.node)
|
peripheryBusConfig.beatBytes, cacheBlockBytes)(peripheryBus.node)
|
||||||
}
|
}
|
||||||
|
```
|
||||||
|
|
||||||
Note that the PWMTL class we created from the register router is itself a
|
Note that the PWMTL class we created from the register router is itself a
|
||||||
LazyModule. Register routers have a TileLike node simply named "node", which
|
LazyModule. Register routers have a TileLike node simply named "node", which
|
||||||
@@ -196,6 +202,7 @@ connect it to the rest of the SoC. Since this module has an extra `pwmout`
|
|||||||
output, we declare that in this trait, using Chisel's multi-IO
|
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.
|
functionality. We then connect the PWMTL's pwmout to the pwmout we declared.
|
||||||
|
|
||||||
|
```scala
|
||||||
trait HasPeripheryPWMModuleImp extends LazyMultiIOModuleImp {
|
trait HasPeripheryPWMModuleImp extends LazyMultiIOModuleImp {
|
||||||
implicit val p: Parameters
|
implicit val p: Parameters
|
||||||
val outer: HasPeripheryPWM
|
val outer: HasPeripheryPWM
|
||||||
@@ -204,10 +211,12 @@ functionality. We then connect the PWMTL's pwmout to the pwmout we declared.
|
|||||||
|
|
||||||
pwmout := outer.pwm.module.io.pwmout
|
pwmout := outer.pwm.module.io.pwmout
|
||||||
}
|
}
|
||||||
|
```
|
||||||
|
|
||||||
Now we want to mix our traits into the system as a whole. This code is from
|
Now we want to mix our traits into the system as a whole. This code is from
|
||||||
src/main/scala/example/Top.scala.
|
src/main/scala/example/Top.scala.
|
||||||
|
|
||||||
|
```scala
|
||||||
class ExampleTopWithPWM(q: Parameters) extends ExampleTop(q)
|
class ExampleTopWithPWM(q: Parameters) extends ExampleTop(q)
|
||||||
with PeripheryPWM {
|
with PeripheryPWM {
|
||||||
override lazy val module = Module(
|
override lazy val module = Module(
|
||||||
@@ -216,6 +225,7 @@ src/main/scala/example/Top.scala.
|
|||||||
|
|
||||||
class ExampleTopWithPWMModule(l: ExampleTopWithPWM)
|
class ExampleTopWithPWMModule(l: ExampleTopWithPWM)
|
||||||
extends ExampleTopModule(l) with HasPeripheryPWMModuleImp
|
extends ExampleTopModule(l) with HasPeripheryPWMModuleImp
|
||||||
|
```
|
||||||
|
|
||||||
Just as we need separate traits for LazyModule and module implementation, we
|
Just as we need separate traits for LazyModule and module implementation, we
|
||||||
need two classes to build the system. The ExampleTop classes already have the
|
need two classes to build the system. The ExampleTop classes already have the
|
||||||
@@ -229,15 +239,18 @@ Finally, we need to add a configuration class in
|
|||||||
src/main/scala/example/Configs.scala that tells the TestHarness to instantiate
|
src/main/scala/example/Configs.scala that tells the TestHarness to instantiate
|
||||||
ExampleTopWithPWM instead of the default ExampleTop.
|
ExampleTopWithPWM instead of the default ExampleTop.
|
||||||
|
|
||||||
|
```scala
|
||||||
class WithPWM extends Config((site, here, up) => {
|
class WithPWM extends Config((site, here, up) => {
|
||||||
case BuildTop => (p: Parameters) =>
|
case BuildTop => (p: Parameters) =>
|
||||||
Module(LazyModule(new ExampleTopWithPWM()(p)).module)
|
Module(LazyModule(new ExampleTopWithPWM()(p)).module)
|
||||||
})
|
})
|
||||||
|
|
||||||
class PWMConfig extends Config(new WithPWM ++ new BaseExampleConfig)
|
class PWMConfig extends Config(new WithPWM ++ new BaseExampleConfig)
|
||||||
|
```
|
||||||
|
|
||||||
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
|
||||||
|
|
||||||
|
```c
|
||||||
#define PWM_PERIOD 0x2000
|
#define PWM_PERIOD 0x2000
|
||||||
#define PWM_DUTY 0x2008
|
#define PWM_DUTY 0x2008
|
||||||
#define PWM_ENABLE 0x2010
|
#define PWM_ENABLE 0x2010
|
||||||
@@ -260,6 +273,7 @@ Now we can test that the PWM is working. The test program is in tests/pwm.c
|
|||||||
write_reg(PWM_DUTY, 5);
|
write_reg(PWM_DUTY, 5);
|
||||||
write_reg(PWM_ENABLE, 1);
|
write_reg(PWM_ENABLE, 1);
|
||||||
}
|
}
|
||||||
|
```
|
||||||
|
|
||||||
This just writes out to the registers we defined earlier. The base of the
|
This just writes out to the registers we defined earlier. The base of the
|
||||||
module's MMIO region is at 0x2000. This will be printed out in the address
|
module's MMIO region is at 0x2000. This will be printed out in the address
|
||||||
@@ -280,6 +294,7 @@ peripheral through MMIO. However, for IO devices (like a disk or network
|
|||||||
driver), we may want to have the device write directly to the coherent
|
driver), we may want to have the device write directly to the coherent
|
||||||
memory system instead. To add a device like that, you would do the following.
|
memory system instead. To add a device like that, you would do the following.
|
||||||
|
|
||||||
|
```scala
|
||||||
class DMADevice(implicit p: Parameters) extends LazyModule {
|
class DMADevice(implicit p: Parameters) extends LazyModule {
|
||||||
val node = TLClientNode(TLClientParameters(
|
val node = TLClientNode(TLClientParameters(
|
||||||
name = "dma-device", sourceId = IdRange(0, 1)))
|
name = "dma-device", sourceId = IdRange(0, 1)))
|
||||||
@@ -308,6 +323,7 @@ memory system instead. To add a device like that, you would do the following.
|
|||||||
val ext = IO(new ExtBundle)
|
val ext = IO(new ExtBundle)
|
||||||
ext <> outer.dma.module.io.ext
|
ext <> outer.dma.module.io.ext
|
||||||
}
|
}
|
||||||
|
```
|
||||||
|
|
||||||
The `ExtBundle` contains the signals we connect off-chip that we get data from.
|
The `ExtBundle` contains the signals we connect off-chip that we get data from.
|
||||||
The DMADevice also has a Tilelink client port that we connect into the L1-L2
|
The DMADevice also has a Tilelink client port that we connect into the L1-L2
|
||||||
@@ -339,6 +355,7 @@ the accelerator can use to distinguish different instructions from each other.
|
|||||||
RoCC accelerators are lazy modules that extend the LazyRoCC class.
|
RoCC accelerators are lazy modules that extend the LazyRoCC class.
|
||||||
Their implementation should extends the LazyRoCCModule class.
|
Their implementation should extends the LazyRoCCModule class.
|
||||||
|
|
||||||
|
```scala
|
||||||
class CustomAccelerator(implicit p: Parameters) extends LazyRoCC {
|
class CustomAccelerator(implicit p: Parameters) extends LazyRoCC {
|
||||||
override lazy val module = new CustomAcceleratorModule(this)
|
override lazy val module = new CustomAcceleratorModule(this)
|
||||||
}
|
}
|
||||||
@@ -359,6 +376,7 @@ Their implementation should extends the LazyRoCCModule class.
|
|||||||
// rs2 - the value of source register 2
|
// rs2 - the value of source register 2
|
||||||
...
|
...
|
||||||
}
|
}
|
||||||
|
```
|
||||||
|
|
||||||
The LazyRoCC class contains two TLOutputNode instances, `atlNode` and `tlNode`.
|
The LazyRoCC class contains two TLOutputNode instances, `atlNode` and `tlNode`.
|
||||||
The former connects into a tile-local arbiter along with the backside of the
|
The former connects into a tile-local arbiter along with the backside of the
|
||||||
@@ -384,6 +402,7 @@ accelerator, and `generator` which specifies how to build the accelerator itself
|
|||||||
For instance, if we wanted to add the previously defined accelerator and
|
For instance, if we wanted to add the previously defined accelerator and
|
||||||
route custom0 and custom1 instructions to it, we could do the following.
|
route custom0 and custom1 instructions to it, we could do the following.
|
||||||
|
|
||||||
|
```scala
|
||||||
class WithCustomAccelerator extends Config((site, here, up) => {
|
class WithCustomAccelerator extends Config((site, here, up) => {
|
||||||
case RocketTilesKey => up(RocketTilesKey, site).map { r =>
|
case RocketTilesKey => up(RocketTilesKey, site).map { r =>
|
||||||
r.copy(rocc = Seq(
|
r.copy(rocc = Seq(
|
||||||
@@ -395,6 +414,7 @@ route custom0 and custom1 instructions to it, we could do the following.
|
|||||||
|
|
||||||
class CustomAcceleratorConfig extends Config(
|
class CustomAcceleratorConfig extends Config(
|
||||||
new WithCustomAccelerator ++ new BaseConfig)
|
new WithCustomAccelerator ++ new BaseConfig)
|
||||||
|
```
|
||||||
|
|
||||||
## Adding a submodule
|
## Adding a submodule
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user