merge the different ExampleTop subclasses into the example package
This commit is contained in:
66
README.md
66
README.md
@@ -83,21 +83,16 @@ By passing the +blkdev argument on the simulator command line, you can allow
|
|||||||
the RTL simulation to read and write from a file. Take a look at tests/blkdev.c
|
the RTL simulation to read and write from a file. Take a look at tests/blkdev.c
|
||||||
for an example of how Rocket can program the block device controller.
|
for an example of how Rocket can program the block device controller.
|
||||||
|
|
||||||
## Creating your own project
|
## Adding an MMIO peripheral
|
||||||
|
|
||||||
To create your own project, you should create your own scala package.
|
You can RocketChip to create your own memory-mapped IO device and add it into
|
||||||
Let's use the PWM package as an example. First you create a directory
|
the SoC design. The easiest way to create a TileLink peripheral is to use the
|
||||||
under src/main/scala that has the same name as your package.
|
TLRegisterRouter, which abstracts away the details of handling the TileLink
|
||||||
|
protocol and provides a convenient interface for specifying memory-mapped
|
||||||
mkdir src/main/scala/pwm
|
registers. To create a RegisterRouter-based peripheral, you will need to
|
||||||
|
specify a parameter case class for the configuration settings, a bundle trait
|
||||||
Now let's add a peripheral device to the new SoC. The easiest way to create a
|
with the extra top-level ports, and a module implementation containing the
|
||||||
TileLink peripheral is to use the TLRegisterRouter, which abstracts away the
|
actual RTL.
|
||||||
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.
|
|
||||||
|
|
||||||
case class PWMParams(address: BigInt, beatBytes: Int)
|
case class PWMParams(address: BigInt, beatBytes: Int)
|
||||||
|
|
||||||
@@ -142,7 +137,7 @@ module trait.
|
|||||||
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/pwm/PWM.scala.
|
The full module code with comments can be found in src/main/scala/example/PWM.scala.
|
||||||
|
|
||||||
After creating the module, we need to hook it up to our SoC. Rocketchip
|
After creating the module, we need to hook it up to our SoC. Rocketchip
|
||||||
accomplishes this using the [cake pattern](http://www.cakesolutions.net/teamblogs/2011/12/19/cake-pattern-in-depth).
|
accomplishes this using the [cake pattern](http://www.cakesolutions.net/teamblogs/2011/12/19/cake-pattern-in-depth).
|
||||||
@@ -186,7 +181,7 @@ functionality. We then connect the PWMTL's pwmout to the pwmout we declared.
|
|||||||
}
|
}
|
||||||
|
|
||||||
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/pwm/Top.scala.
|
src/main/scala/example/Top.scala.
|
||||||
|
|
||||||
class ExampleTopWithPWM(q: Parameters) extends ExampleTop(q)
|
class ExampleTopWithPWM(q: Parameters) extends ExampleTop(q)
|
||||||
with PeripheryPWM {
|
with PeripheryPWM {
|
||||||
@@ -198,38 +193,23 @@ src/main/scala/pwm/Top.scala.
|
|||||||
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 from the example
|
need two classes to build the system. The ExampleTop classes already have the
|
||||||
package already have the basic peripherals included for us, so we will just
|
basic peripherals included for us, so we will just extend those.
|
||||||
extend those.
|
|
||||||
|
|
||||||
The ExampleTop class includes the pre-elaboration code and also a lazy val to
|
The ExampleTop class includes the pre-elaboration code and also a lazy val to
|
||||||
produce the module implementation (hence LazyModule). The ExampleTopModule
|
produce the module implementation (hence LazyModule). The ExampleTopModule
|
||||||
class is the actual RTL that gets synthesized.
|
class is the actual RTL that gets synthesized.
|
||||||
|
|
||||||
Now we have the RTL for the chip, but we need a test harness to simulate it.
|
Finally, we need to add a configuration class in
|
||||||
|
src/main/scala/example/Configs.scala that tells the TestHarness to instantiate
|
||||||
|
ExampleTopWithPWM instead of the default ExampleTop.
|
||||||
|
|
||||||
class TestHarness(q: Parameters) extends example.TestHarness()(q) {
|
class WithPWM extends Config((site, here, up) => {
|
||||||
override def buildTop(p: Parameters) =
|
case BuildTop => (p: Parameters) =>
|
||||||
LazyModule(new ExampleTopWithPWM(p))
|
Module(LazyModule(new ExampleTopWithPWM()(p)).module)
|
||||||
}
|
})
|
||||||
|
|
||||||
We just extend the TestHarness from the example package, which already has
|
class PWMConfig extends Config(new WithPWM ++ new BaseExampleConfig)
|
||||||
the extra RTL to simulate the memory system and tethered serial port.
|
|
||||||
It provides us the hook function `buildTop` which we can override to build
|
|
||||||
our ExampleTopWithPWM instead of the regular ExampleTop.
|
|
||||||
|
|
||||||
We also need to create a Generator object, which gets called as the entry
|
|
||||||
point for elaboration.
|
|
||||||
|
|
||||||
object Generator extends GeneratorApp {
|
|
||||||
generateFirrtl
|
|
||||||
}
|
|
||||||
|
|
||||||
Finally, we need to add a configuration class in src/main/scala/pwm/Configs.scala.
|
|
||||||
This defines all the settings in the Parameters object. We aren't adding any
|
|
||||||
new parameters, so we can just extend the default configuration.
|
|
||||||
|
|
||||||
class PWMTLConfig extends Config(new example.DefaultExampleConfig)
|
|
||||||
|
|
||||||
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
|
||||||
|
|
||||||
@@ -265,8 +245,8 @@ Compiling this program with make produces a `pwm.riscv` executable.
|
|||||||
Now with all of that done, we can go ahead and run our simulation.
|
Now with all of that done, we can go ahead and run our simulation.
|
||||||
|
|
||||||
cd verisim
|
cd verisim
|
||||||
make PROJECT=pwm CONFIG=PWMTLConfig
|
make PROJECT=pwm CONFIG=PWMConfig
|
||||||
./simulator-pwm-PWMTLConfig ../tests/pwm.riscv
|
./simulator-pwm-PWMConfig ../tests/pwm.riscv
|
||||||
|
|
||||||
## Adding a DMA port
|
## Adding a DMA port
|
||||||
|
|
||||||
|
|||||||
@@ -1,21 +0,0 @@
|
|||||||
package blkdev
|
|
||||||
|
|
||||||
import config.{Parameters, Config}
|
|
||||||
import example.DefaultExampleConfig
|
|
||||||
import testchipip.{WithBlockDevice, WithNBlockDeviceTrackers}
|
|
||||||
|
|
||||||
class WithSimBlockDevice extends Config((site, here, up) => {
|
|
||||||
case UseSimBlockDevice => true
|
|
||||||
})
|
|
||||||
|
|
||||||
class WithBlockDeviceModel extends Config((site, here, up) => {
|
|
||||||
case UseSimBlockDevice => false
|
|
||||||
})
|
|
||||||
|
|
||||||
class BlockDeviceConfig extends Config(
|
|
||||||
new WithSimBlockDevice ++
|
|
||||||
new WithBlockDevice ++
|
|
||||||
new DefaultExampleConfig)
|
|
||||||
|
|
||||||
class WithTwoTrackers extends WithNBlockDeviceTrackers(2)
|
|
||||||
class WithFourTrackers extends WithNBlockDeviceTrackers(4)
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
package blkdev
|
|
||||||
|
|
||||||
import diplomacy.LazyModule
|
|
||||||
import chisel3._
|
|
||||||
import config.{Parameters, Field}
|
|
||||||
import testchipip.GeneratorApp
|
|
||||||
import example._
|
|
||||||
|
|
||||||
case object UseSimBlockDevice extends Field[Boolean]
|
|
||||||
|
|
||||||
class TestHarness(implicit p: Parameters) extends Module {
|
|
||||||
val io = IO(new Bundle {
|
|
||||||
val success = Output(Bool())
|
|
||||||
})
|
|
||||||
|
|
||||||
val dut = Module(LazyModule(new ExampleTopWithBlockDevice).module)
|
|
||||||
dut.connectSimAXIMem()
|
|
||||||
if (p(UseSimBlockDevice))
|
|
||||||
dut.connectSimBlockDevice()
|
|
||||||
else
|
|
||||||
dut.connectBlockDeviceModel()
|
|
||||||
io.success := dut.connectSimSerial()
|
|
||||||
}
|
|
||||||
|
|
||||||
object Generator extends GeneratorApp {
|
|
||||||
generateFirrtl
|
|
||||||
}
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
package blkdev
|
|
||||||
|
|
||||||
import chisel3._
|
|
||||||
import config.Parameters
|
|
||||||
import testchipip._
|
|
||||||
import example._
|
|
||||||
|
|
||||||
class ExampleTopWithBlockDevice(implicit p: Parameters) extends ExampleTop
|
|
||||||
with HasPeripheryBlockDevice {
|
|
||||||
override lazy val module = new ExampleTopWithBlockDeviceModule(this)
|
|
||||||
}
|
|
||||||
|
|
||||||
class ExampleTopWithBlockDeviceModule(l: ExampleTopWithBlockDevice)
|
|
||||||
extends ExampleTopModule(l)
|
|
||||||
with HasPeripheryBlockDeviceModuleImp
|
|
||||||
@@ -1,14 +1,56 @@
|
|||||||
package example
|
package example
|
||||||
|
|
||||||
|
import chisel3._
|
||||||
import config.{Parameters, Config}
|
import config.{Parameters, Config}
|
||||||
import testchipip.WithSerialAdapter
|
import diplomacy.LazyModule
|
||||||
import coreplex.WithRoccExample
|
import coreplex.WithRoccExample
|
||||||
import rocketchip.WithoutTLMonitors
|
import rocketchip.WithoutTLMonitors
|
||||||
|
import testchipip._
|
||||||
|
|
||||||
class DefaultExampleConfig extends Config(
|
class WithExampleTop extends Config((site, here, up) => {
|
||||||
|
case BuildTop => (p: Parameters) =>
|
||||||
|
Module(LazyModule(new ExampleTop()(p)).module)
|
||||||
|
})
|
||||||
|
|
||||||
|
class WithPWM extends Config((site, here, up) => {
|
||||||
|
case BuildTop => (p: Parameters) =>
|
||||||
|
Module(LazyModule(new ExampleTopWithPWM()(p)).module)
|
||||||
|
})
|
||||||
|
|
||||||
|
class WithBlockDeviceModel extends Config((site, here, up) => {
|
||||||
|
case BuildTop => (p: Parameters) => {
|
||||||
|
val top = Module(LazyModule(new ExampleTopWithBlockDevice()(p)).module)
|
||||||
|
top.connectBlockDeviceModel()
|
||||||
|
top
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
class WithSimBlockDevice extends Config((site, here, up) => {
|
||||||
|
case BuildTop => (p: Parameters) => {
|
||||||
|
val top = Module(LazyModule(new ExampleTopWithBlockDevice()(p)).module)
|
||||||
|
top.connectSimBlockDevice()
|
||||||
|
top
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
class BaseExampleConfig extends Config(
|
||||||
new WithoutTLMonitors ++
|
new WithoutTLMonitors ++
|
||||||
new WithSerialAdapter ++
|
new WithSerialAdapter ++
|
||||||
new rocketchip.DefaultConfig)
|
new rocketchip.DefaultConfig)
|
||||||
|
|
||||||
|
class DefaultExampleConfig extends Config(
|
||||||
|
new WithExampleTop ++ new BaseExampleConfig)
|
||||||
|
|
||||||
class RoccExampleConfig extends Config(
|
class RoccExampleConfig extends Config(
|
||||||
new WithRoccExample ++ new DefaultExampleConfig)
|
new WithRoccExample ++ new DefaultExampleConfig)
|
||||||
|
|
||||||
|
class PWMConfig extends Config(new WithPWM ++ new BaseExampleConfig)
|
||||||
|
|
||||||
|
class SimBlockDeviceConfig extends Config(
|
||||||
|
new WithBlockDevice ++ new WithSimBlockDevice ++ new BaseExampleConfig)
|
||||||
|
|
||||||
|
class BlockDeviceModelConfig extends Config(
|
||||||
|
new WithBlockDevice ++ new WithBlockDeviceModel ++ new BaseExampleConfig)
|
||||||
|
|
||||||
|
class WithTwoTrackers extends WithNBlockDeviceTrackers(2)
|
||||||
|
class WithFourTrackers extends WithNBlockDeviceTrackers(4)
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
package pwm
|
package example
|
||||||
|
|
||||||
import chisel3._
|
import chisel3._
|
||||||
import chisel3.util._
|
import chisel3.util._
|
||||||
@@ -4,16 +4,16 @@ import diplomacy.LazyModule
|
|||||||
import rocketchip._
|
import rocketchip._
|
||||||
import testchipip._
|
import testchipip._
|
||||||
import chisel3._
|
import chisel3._
|
||||||
import config.Parameters
|
import config.{Field, Parameters}
|
||||||
|
|
||||||
|
case object BuildTop extends Field[Parameters => ExampleTopModule[ExampleTop]]
|
||||||
|
|
||||||
class TestHarness(implicit val p: Parameters) extends Module {
|
class TestHarness(implicit val p: Parameters) extends Module {
|
||||||
val io = IO(new Bundle {
|
val io = IO(new Bundle {
|
||||||
val success = Output(Bool())
|
val success = Output(Bool())
|
||||||
})
|
})
|
||||||
|
|
||||||
def buildTop(p: Parameters): ExampleTop = LazyModule(new ExampleTop()(p))
|
val dut = p(BuildTop)(p)
|
||||||
|
|
||||||
val dut = Module(buildTop(p).module)
|
|
||||||
dut.connectSimAXIMem()
|
dut.connectSimAXIMem()
|
||||||
io.success := dut.connectSimSerial()
|
io.success := dut.connectSimSerial()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,3 +24,20 @@ class ExampleTopModule[+L <: ExampleTop](l: L) extends BaseSystemModule(l)
|
|||||||
with HasRocketPlexMasterModuleImp
|
with HasRocketPlexMasterModuleImp
|
||||||
with HasNoDebugModuleImp
|
with HasNoDebugModuleImp
|
||||||
with HasPeripherySerialModuleImp
|
with HasPeripherySerialModuleImp
|
||||||
|
|
||||||
|
class ExampleTopWithPWM(implicit p: Parameters) extends ExampleTop
|
||||||
|
with HasPeripheryPWM {
|
||||||
|
override lazy val module = new ExampleTopWithPWMModule(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
class ExampleTopWithPWMModule(l: ExampleTopWithPWM)
|
||||||
|
extends ExampleTopModule(l) with HasPeripheryPWMModuleImp
|
||||||
|
|
||||||
|
class ExampleTopWithBlockDevice(implicit p: Parameters) extends ExampleTop
|
||||||
|
with HasPeripheryBlockDevice {
|
||||||
|
override lazy val module = new ExampleTopWithBlockDeviceModule(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
class ExampleTopWithBlockDeviceModule(l: ExampleTopWithBlockDevice)
|
||||||
|
extends ExampleTopModule(l)
|
||||||
|
with HasPeripheryBlockDeviceModuleImp
|
||||||
|
|||||||
@@ -1,8 +0,0 @@
|
|||||||
package pwm
|
|
||||||
|
|
||||||
import config.{Parameters, Config}
|
|
||||||
import testchipip.WithSerialAdapter
|
|
||||||
import uncore.tilelink.ClientUncachedTileLinkIO
|
|
||||||
import chisel3._
|
|
||||||
|
|
||||||
class PWMConfig extends Config(new example.DefaultExampleConfig)
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
package pwm
|
|
||||||
|
|
||||||
import config.Parameters
|
|
||||||
import diplomacy.LazyModule
|
|
||||||
import testchipip.GeneratorApp
|
|
||||||
|
|
||||||
class TestHarness(q: Parameters) extends example.TestHarness()(q) {
|
|
||||||
override def buildTop(p: Parameters) =
|
|
||||||
LazyModule(new ExampleTopWithPWM()(p))
|
|
||||||
}
|
|
||||||
|
|
||||||
object Generator extends GeneratorApp {
|
|
||||||
generateFirrtl
|
|
||||||
}
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
package pwm
|
|
||||||
|
|
||||||
import chisel3._
|
|
||||||
import example._
|
|
||||||
import config.Parameters
|
|
||||||
|
|
||||||
class ExampleTopWithPWM(implicit p: Parameters) extends ExampleTop
|
|
||||||
with HasPeripheryPWM {
|
|
||||||
override lazy val module = new ExampleTopWithPWMModule(this)
|
|
||||||
}
|
|
||||||
|
|
||||||
class ExampleTopWithPWMModule(l: ExampleTopWithPWM)
|
|
||||||
extends ExampleTopModule(l) with HasPeripheryPWMModuleImp
|
|
||||||
Reference in New Issue
Block a user