From 757eb763dacf46de0a280b5a4a8a8d5e67d63b41 Mon Sep 17 00:00:00 2001 From: Jerry Zhao Date: Thu, 16 Jan 2020 13:53:11 -0800 Subject: [PATCH] Refactor how Configs parameterize the Top and TestHarnesses --- .circleci/defaults.sh | 2 +- docs/Chipyard-Basics/index.rst | 1 + docs/Customization/Adding-An-Accelerator.rst | 261 ------------------ docs/Customization/Custom-Chisel.rst | 38 +++ docs/Customization/DMA-Devices.rst | 35 +++ .../Incorporating-Verilog-Blocks.rst | 51 +--- docs/Customization/Keys-Traits-Configs.rst | 95 +++++++ docs/Customization/MMIO-Peripherals.rst | 133 +++++++++ docs/Customization/RoCC-Accelerators.rst | 69 +++++ docs/Customization/RoCC-or-MMIO.rst | 27 ++ docs/Customization/index.rst | 31 ++- docs/Generators/Gemmini.rst | 2 +- docs/Generators/SHA3.rst | 2 +- docs/Generators/SiFive-Generators.rst | 10 +- docs/Makefile | 4 +- docs/Quick-Start.rst | 2 +- .../src/main/resources/vsrc/GCDMMIOBlackBox.v | 4 +- .../example/src/main/scala/BoomConfigs.scala | 45 ++- .../example/src/main/scala/ConfigMixins.scala | 134 ++++----- generators/example/src/main/scala/GCD.scala | 207 ++++++++++++++ .../src/main/scala/GCDMMIOBlackBox.scala | 98 ------- .../src/main/scala/HeteroConfigs.scala | 44 ++- .../example/src/main/scala/InitZero.scala | 16 +- generators/example/src/main/scala/PWM.scala | 134 --------- .../src/main/scala/RocketConfigs.scala | 112 +++++--- .../example/src/main/scala/TestHarness.scala | 54 +--- generators/example/src/main/scala/Top.scala | 108 ++------ .../src/main/scala/BridgeBinders.scala | 10 +- .../src/main/scala/TargetConfigs.scala | 8 +- .../firechip/src/main/scala/Targets.scala | 21 +- generators/icenet | 2 +- generators/testchipip | 2 +- sims/firesim | 2 +- variables.mk | 3 +- 34 files changed, 919 insertions(+), 848 deletions(-) delete mode 100644 docs/Customization/Adding-An-Accelerator.rst create mode 100644 docs/Customization/Custom-Chisel.rst create mode 100644 docs/Customization/DMA-Devices.rst create mode 100644 docs/Customization/Keys-Traits-Configs.rst create mode 100644 docs/Customization/MMIO-Peripherals.rst create mode 100644 docs/Customization/RoCC-Accelerators.rst create mode 100644 docs/Customization/RoCC-or-MMIO.rst create mode 100644 generators/example/src/main/scala/GCD.scala delete mode 100644 generators/example/src/main/scala/GCDMMIOBlackBox.scala delete mode 100644 generators/example/src/main/scala/PWM.scala diff --git a/.circleci/defaults.sh b/.circleci/defaults.sh index 87a761d933..c5838a486c 100755 --- a/.circleci/defaults.sh +++ b/.circleci/defaults.sh @@ -45,7 +45,7 @@ mapping["example"]="SUB_PROJECT=example" mapping["boomrocketexample"]="SUB_PROJECT=example CONFIG=LargeBoomAndRocketConfig" mapping["boom"]="SUB_PROJECT=example CONFIG=SmallBoomConfig" mapping["rocketchip"]="SUB_PROJECT=rocketchip" -mapping["blockdevrocketchip"]="SUB_PROJECT=example CONFIG=SimBlockDeviceRocketConfig TOP=TopWithBlockDevice" +mapping["blockdevrocketchip"]="SUB_PROJECT=example CONFIG=SimBlockDeviceRocketConfig" mapping["hwacha"]="SUB_PROJECT=example CONFIG=HwachaRocketConfig" mapping["gemmini"]="SUB_PROJECT=example CONFIG=GemminiRocketConfig" mapping["tracegen"]="SUB_PROJECT=tracegen CONFIG=NonBlockingTraceGenL2Config" diff --git a/docs/Chipyard-Basics/index.rst b/docs/Chipyard-Basics/index.rst index 28a0870030..9a306c4f3d 100644 --- a/docs/Chipyard-Basics/index.rst +++ b/docs/Chipyard-Basics/index.rst @@ -16,6 +16,7 @@ Hit next to get started! :caption: Chipyard Basics: Chipyard-Components + Development-Ecosystem Configs-Parameters-Mixins Initial-Repo-Setup diff --git a/docs/Customization/Adding-An-Accelerator.rst b/docs/Customization/Adding-An-Accelerator.rst deleted file mode 100644 index 3c0ea4eb55..0000000000 --- a/docs/Customization/Adding-An-Accelerator.rst +++ /dev/null @@ -1,261 +0,0 @@ -.. _adding-an-accelerator: - -Adding an Accelerator/Device -=============================== - -Accelerators or custom IO devices can be added to your SoC in several ways: - -* MMIO Peripheral (a.k.a TileLink-Attached Accelerator) -* Tightly-Coupled RoCC Accelerator - -These approaches differ in the method of the communication between the processor and the custom block. - -With the TileLink-Attached approach, the processor communicates with MMIO peripherals through memory-mapped registers. - -In contrast, the processor communicates with a RoCC accelerators through a custom protocol and custom non-standard ISA instructions reserved in the RISC-V ISA encoding space. -Each core can have up to four accelerators that are controlled by custom instructions and share resources with the CPU. -RoCC coprocessor instructions have the following form. - -.. code-block:: none - - customX rd, rs1, rs2, funct - -The X will be a number 0-3, and determines the opcode of the instruction, which controls which accelerator an instruction will be routed to. -The ``rd``, ``rs1``, and ``rs2`` fields are the register numbers of the destination register and two source registers. -The ``funct`` field is a 7-bit integer that the accelerator can use to distinguish different instructions from each other. - -Note that communication through a RoCC interface requires a custom software toolchain, whereas MMIO peripherals can use that standard toolchain with appropriate driver support. - -Integrating into the Generator Build System -------------------------------------------- - -While developing, you want to include Chisel code in a submodule so that it can be shared by different projects. -To add a submodule to the Chipyard framework, make sure that your project is organized as follows. - -.. code-block:: none - - yourproject/ - build.sbt - src/main/scala/ - YourFile.scala - -Put this in a git repository and make it accessible. -Then add it as a submodule to under the following directory hierarchy: ``generators/yourproject``. - -.. code-block:: shell - - cd generators/ - git submodule add https://git-repository.com/yourproject.git - -Then add ``yourproject`` to the Chipyard top-level build.sbt file. - -.. code-block:: scala - - lazy val yourproject = (project in file("generators/yourproject")).settings(commonSettings).dependsOn(rocketchip) - -You can then import the classes defined in the submodule in a new project if -you add it as a dependency. For instance, if you want to use this code in -the ``example`` project, change the final line in build.sbt to the following. - -.. code-block:: scala - - lazy val example = (project in file(".")).settings(commonSettings).dependsOn(testchipip, yourproject) - -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``. - -.. 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. - -.. 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``. - -After creating the module, we need to hook it up to our SoC. -Rocket Chip accomplishes this using the cake pattern. -This basically involves placing code inside traits. -In the Rocket Chip cake, there are two kinds of traits: a ``LazyModule`` trait and a module implementation trait. - -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. - -.. 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. -This will automatically add address map and device tree entries for the peripheral. - -The module implementation trait is where we instantiate our PWM module and 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 functionality. -We then connect the ``PWMTL``'s pwmout to the pwmout we declared. - -.. 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``. - -.. 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. - -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 ``TopWithPWMTL`` instead of the default ``Top``. - -.. literalinclude:: ../../generators/example/src/main/scala/ConfigMixins.scala - :language: scala - :start-after: DOC include start: WithPWMTop - :end-before: DOC include end: WithPWMTop - -And finally, we create a configuration class in ``generators/example/src/main/scala/Configs.scala`` that uses this mixin. - -.. 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``. - -.. 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. -This will be printed out in the address map portion when you generated the verilog code. - -Compiling this program with make produces a ``pwm.riscv`` executable. - -Now with all of that done, we can go ahead and run our simulation. - -.. code-block:: shell - - cd sims/verilator - make CONFIG=PWMRocketConfig TOP=TopWithPWMTL - ./simulator-example-PWMRocketConfig ../../tests/pwm.riscv - -Adding a RoCC Accelerator ----------------------------- - -RoCC accelerators are lazy modules that extend the ``LazyRoCC`` class. -Their implementation should extends the ``LazyRoCCModule`` class. - -.. code-block:: scala - - class CustomAccelerator(opcodes: OpcodeSet) - (implicit p: Parameters) extends LazyRoCC(opcodes) { - override lazy val module = new CustomAcceleratorModule(this) - } - - class CustomAcceleratorModule(outer: CustomAccelerator) - extends LazyRoCCModuleImp(outer) { - val cmd = Queue(io.cmd) - // The parts of the command are as follows - // inst - the parts of the instruction itself - // opcode - // rd - destination register number - // rs1 - first source register number - // rs2 - second source register number - // funct - // xd - is the destination register being used? - // xs1 - is the first source register being used? - // xs2 - is the second source register being used? - // rs1 - the value of source register 1 - // rs2 - the value of source register 2 - ... - } - - -The ``opcodes`` parameter for ``LazyRoCC`` is the set of custom opcodes that will map to this accelerator. -More on this in the next subsection. - -The ``LazyRoCC`` class contains two TLOutputNode instances, ``atlNode`` and ``tlNode``. -The former connects into a tile-local arbiter along with the backside of the L1 instruction cache. -The latter connects directly to the L1-L2 crossbar. -The corresponding Tilelink ports in the module implementation's IO bundle are ``atl`` and ``tl``, respectively. - -The other interfaces available to the accelerator are ``mem``, which provides access to the L1 cache; -``ptw`` which provides access to the page-table walker; -the ``busy`` signal, which indicates when the accelerator is still handling an instruction; -and the ``interrupt`` signal, which can be used to interrupt the CPU. - -Look at the examples in ``generators/rocket-chip/src/main/scala/tile/LazyRocc.scala`` for detailed information on the different IOs. - -Adding RoCC accelerator to Config -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -RoCC accelerators can be added to a core by overriding the ``BuildRoCC`` parameter in the configuration. -This takes a sequence of functions producing ``LazyRoCC`` objects, one for each accelerator you wish to add. - -For instance, if we wanted to add the previously defined accelerator and route custom0 and custom1 instructions to it, we could do the following. - -.. code-block:: scala - - class WithCustomAccelerator extends Config((site, here, up) => { - case BuildRoCC => Seq((p: Parameters) => LazyModule( - new CustomAccelerator(OpcodeSet.custom0 | OpcodeSet.custom1)(p))) - }) - - class CustomAcceleratorConfig extends Config( - new WithCustomAccelerator ++ new RocketConfig) - -To add RoCC instructions in your program, use the RoCC C macros provided in ``tests/rocc.h``. You can find examples in the files ``tests/accum.c`` and ``charcount.c``. - -Adding a DMA port -------------------- - -For IO devices or accelerators (like a disk or network driver), instead of -having the CPU poll data from the device, we may want to have the device write -directly to the coherent memory system instead. For example, here is a device -that writes zeros to the memory at a configured address. - -.. literalinclude:: ../../generators/example/src/main/scala/InitZero.scala - :language: scala - -.. literalinclude:: ../../generators/example/src/main/scala/Top.scala - :language: scala - :start-after: DOC include start: TopWithInitZero - :end-before: DOC include end: TopWithInitZero - -We use ``TLHelper.makeClientNode`` to create a TileLink client node for us. -We then connect the client node to the memory system through the front bus (fbus). -For more info on creating TileLink client nodes, take a look at :ref:`Client Node`. - -Once we've created our top-level module including the DMA widget, we can create a configuration for it as we did before. - -.. literalinclude:: ../../generators/example/src/main/scala/ConfigMixins.scala - :language: scala - :start-after: DOC include start: WithInitZero - :end-before: DOC include end: WithInitZero - -.. literalinclude:: ../../generators/example/src/main/scala/RocketConfigs.scala - :language: scala - :start-after: DOC include start: InitZeroRocketConfig - :end-before: DOC include end: InitZeroRocketConfig - - diff --git a/docs/Customization/Custom-Chisel.rst b/docs/Customization/Custom-Chisel.rst new file mode 100644 index 0000000000..d568f27b2b --- /dev/null +++ b/docs/Customization/Custom-Chisel.rst @@ -0,0 +1,38 @@ +.. _custom_chisel: + +Integrating into the Generator Build System +=========================================== + +While developing, you want to include Chisel code in a submodule so that it can be shared by different projects. +To add a submodule to the Chipyard framework, make sure that your project is organized as follows. + +.. code-block:: none + + yourproject/ + build.sbt + src/main/scala/ + YourFile.scala + +Put this in a git repository and make it accessible. +Then add it as a submodule to under the following directory hierarchy: ``generators/yourproject``. + +.. code-block:: shell + + cd generators/ + git submodule add https://git-repository.com/yourproject.git + +Then add ``yourproject`` to the Chipyard top-level build.sbt file. + +.. code-block:: scala + + lazy val yourproject = (project in file("generators/yourproject")).settings(commonSettings).dependsOn(rocketchip) + +You can then import the classes defined in the submodule in a new project if +you add it as a dependency. For instance, if you want to use this code in +the ``example`` project, change the final line in build.sbt to the following. + +.. code-block:: scala + + lazy val example = (project in file(".")).settings(commonSettings).dependsOn(testchipip, yourproject) + + diff --git a/docs/Customization/DMA-Devices.rst b/docs/Customization/DMA-Devices.rst new file mode 100644 index 0000000000..cbee29e7b3 --- /dev/null +++ b/docs/Customization/DMA-Devices.rst @@ -0,0 +1,35 @@ +.. _dma-devices: + +Adding a DMA Device +=================== + +For IO devices or accelerators (like a disk or network driver), instead of +having the CPU poll data from the device, we may want to have the device write +directly to the coherent memory system instead. For example, here is a device +that writes zeros to the memory at a configured address. + +.. literalinclude:: ../../generators/example/src/main/scala/InitZero.scala + :language: scala + +.. literalinclude:: ../../generators/example/src/main/scala/Top.scala + :language: scala + :start-after: DOC include start: Top + :end-before: DOC include end: Top + +We use ``TLHelper.makeClientNode`` to create a TileLink client node for us. +We then connect the client node to the memory system through the front bus (fbus). +For more info on creating TileLink client nodes, take a look at :ref:`Client Node`. + +Once we've created our top-level module including the DMA widget, we can create a configuration for it as we did before. + +.. literalinclude:: ../../generators/example/src/main/scala/ConfigMixins.scala + :language: scala + :start-after: DOC include start: WithInitZero + :end-before: DOC include end: WithInitZero + +.. literalinclude:: ../../generators/example/src/main/scala/RocketConfigs.scala + :language: scala + :start-after: DOC include start: InitZeroRocketConfig + :end-before: DOC include end: InitZeroRocketConfig + + diff --git a/docs/Customization/Incorporating-Verilog-Blocks.rst b/docs/Customization/Incorporating-Verilog-Blocks.rst index 64f064f815..48f0c6e36b 100644 --- a/docs/Customization/Incorporating-Verilog-Blocks.rst +++ b/docs/Customization/Incorporating-Verilog-Blocks.rst @@ -8,8 +8,7 @@ design flows. Fortunately, both Chisel and Chipyard provide extensive support for Verilog integration. Here, we will examine the process of incorporating an MMIO peripheral -(similar to the PWM example from the previous section) that uses a -Verilog implementation of Greatest Common Denominator (GCD) +that uses a Verilog implementation of Greatest Common Denominator (GCD) algorithm. There are a few steps to adding a Verilog peripheral: * Adding a Verilog resource file to the project @@ -58,7 +57,7 @@ and Verilog sources follow the prescribed directory layout. build.sbt src/main/ scala/ - GCDMMIOBlackBox.scala + GCD.scala resources/ vsrc/ GCDMMIOBlackBox.v @@ -89,7 +88,7 @@ as the bitwidth of the GCD calculation does in this example. **Chisel BlackBox Definition** -.. literalinclude:: ../../generators/example/src/main/scala/GCDMMIOBlackBox.scala +.. literalinclude:: ../../generators/example/src/main/scala/GCD.scala :language: scala :start-after: DOC include start: GCD blackbox :end-before: DOC include end: GCD blackbox @@ -102,54 +101,32 @@ diplomatic memory mapping on the system bus, we still have to integrate the peripheral at the Chisel level by mixing peripheral-specific traits into a ``TLRegisterRouter``. The ``params`` member and ``HasRegMap`` base trait should look familiar from the -previous memory-mapped PWM device example. +previous memory-mapped GCD device example. -.. literalinclude:: ../../generators/example/src/main/scala/GCDMMIOBlackBox.scala +.. literalinclude:: ../../generators/example/src/main/scala/GCD.scala :language: scala :start-after: DOC include start: GCD instance regmap :end-before: DOC include end: GCD instance regmap -Advanced Features of RegField Entries -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -One significant difference from the PWM example is in the peripheral's -memory map. ``RegField`` exposes polymorphic ``r`` and ``w`` methods -that allow read- and write-only memory-mapped registers to be -interfaced to hardware in multiple ways. - -* ``RegField.r(2, status)`` is used to create a 2-bit, read-only register that captures the current value of the ``status`` signal when read. -* ``RegField.r(params.width, gcd)`` "connects" the decoupled handshaking interface ``gcd`` to a read-only memory-mapped register. When this register is read via MMIO, the ``ready`` signal is asserted. This is in turn connected to ``output_ready`` on the Verilog blackbox through the glue logic. -* ``RegField.w(params.width, x)`` exposes a plain register (much like those in the PWM example) via MMIO, but makes it write-only. -* ``RegField.w(params.width, y)`` associates the decoupled interface signal ``y`` with a write-only memory-mapped register, causing ``y.valid`` to be asserted when the register is written. - -Since the ready/valid signals of ``y`` are connected to the -``input_ready`` and ``input_valid`` signals of the blackbox, -respectively, this register map and glue logic has the effect of -triggering the GCD algorithm when ``y`` is written. Therefore, the -algorithm is set up by first writing ``x`` and then performing a -triggering write to ``y``. Polling can be used for status checks. - -Defining a Chip with a GCD Peripheral +Defining a Chip with a BlackBox --------------------------------------- -As with the PWM example, a few more pieces are needed to tie the system together. - -**Composing traits into a complete cake pattern peripheral** +Since we've parameterized the GCD instantiation to choose between the +Chisel and the verilog module, creating a config is easy. -.. literalinclude:: ../../generators/example/src/main/scala/GCDMMIOBlackBox.scala +.. literalinclude:: ../../generators/example/src/main/scala/RocketConfigs.scala :language: scala - :start-after: DOC include start: GCD cake - :end-before: DOC include end: GCD cake + :start-after: DOC include start: GCDAXI4BlackBoxRocketConfig + :end-before: DOC include end: GCDAXI4BlackBoxRocketConfig -Note the differences arising due to the fact that this peripheral has -no top-level IO. To build a complete system, a new ``Top`` and new -``Config`` objects are added in a manner exactly analogous to the PWM -example. +You can play with the parameterization of the mixin to choose a TL/AXI4, BlackBox/Chisel +version of the GCD. Software Testing ---------------- -The GCD module has a slightly more complex interface, so polling is +The GCD module has a more complex interface, so polling is used to check the status of the device before each triggering read or write. diff --git a/docs/Customization/Keys-Traits-Configs.rst b/docs/Customization/Keys-Traits-Configs.rst new file mode 100644 index 0000000000..4a51896dab --- /dev/null +++ b/docs/Customization/Keys-Traits-Configs.rst @@ -0,0 +1,95 @@ +.. _keys-traits-configs: + +Keys, Traits, and Configs +========================= + +You have probably seen snippets of Chisel referencing Keys, Traits, and Configs by this point. +This section aims to elucidate the interactions between these Chisel/Scala components, and provide +best practices for how these should be used to create a parameterized design and configure it. + +We will continue to use the GCD example. + +Keys +---- + +Keys specify some parameter which controls some custom widget. Keys should typically be implemented as **Option types**, with a default value of ``None`` that means no change in the system. In other words, the default behavior when the user does not explicitly set the key should be a no-op. + +Keys should be defined and documented in sub-projects, since they generally deal with some specific block, and not system-level integration. (We make an exception for the example GCD widget). + +.. literalinclude:: ../../generators/example/src/main/scala/GCD.scala + :language: scala + :start-after: DOC include start: GCD key + :end-before: DOC include end: GCD key + +The object within a key is typically a ``case class XXXParams``, which defines a set of parameters which some block accepts. For example, the GCD widget's ``GCDParams`` parameterizes its address, operand widths, whether the widget should be connected by Tilelink or AXI4, and whether the widget should use the blackbox-verilog implementation, or the Chisel implementation + + +.. literalinclude:: ../../generators/example/src/main/scala/GCD.scala + :language: scala + :start-after: DOC include start: GCD params + :end-before: DOC include end: GCD params + +Accessing the value stored in the key is easy in Chisel, as long as the ``implicit p: Parameters`` object is being passed through to the relevant module. For example, ``p(GCDKey).get.address`` returns the address field of ``GCDParams``. Note this only works if ``GCDKey`` was not set to ``None``, so your Chisel should check for that case! + +Traits +------ + +Typically, most custom blocks will need to modify the behavior of some pre-existing block. For example, the GCD widget needs the Top module to instantiate and connect the widget via Tilelink, generate a top-level ``gcd_busy`` port, and connect that to the module as well. Traits let us do this without modifying the existing code for the ``Top``, and enables compartmentalization of code for different custom blcoks. + +Top-level traits specify that the Top has been parameterized to read some custom Key and optionally instantiate and connect a widget defined by that Key. Traits **should not** mandate the instantiation of custom logic. In other words, traits should be written with ``CanHave`` semantics, where the default behavior when the Key is unset is a no-op. + +Top-level traits should be defined and documented in subprojects, alongside their corresponding Keys. The traits should then be added to the Top being used by Chipyard. + +Below we see the traits for the GCD example. The Lazy trait connects the GCD module to the Diplomacy graph, while the Implementation trait causes the Top to instantiate an additional port and concretely connect it to the GCD module. + +.. literalinclude:: ../../generators/example/src/main/scala/GCD.scala + :language: scala + :start-after: DOC include start: GCD lazy trait + :end-before: DOC include end: GCD imp trait + +These traits are added to the default ``Top`` in Chipyard. + +.. literalinclude:: ../../generators/example/src/main/scala/Top.scala + :language: scala + :start-after: DOC include start: Top + :end-before: DOC include end: Top + +Mixins +------ + +Mixins set the keys to a non-default value. Together, the collection of Mixins which define a configuration generate the values for all the keys used by the generator. + +For example, the ``WithGCDMixin`` is parameterized by the type of GCD widget you want to instantiate. When this mixin is added to a config, the ``GCDKey`` is set to a instance of ``GCDParams``, informing the previously mentioned traits to instantiate and connect the GCD widget appropriately. + +.. literalinclude:: ../../generators/example/src/main/scala/ConfigMixins.scala + :language: scala + :start-after: DOC include start: GCD mixin + :end-before: DOC include end: GCD mixin + +We can use this mixin when composing our configs. + +.. literalinclude:: ../../generators/example/src/main/scala/RocketConfigs.scala + :language: scala + :start-after: DOC include start: GCDTLRocketConfig + :end-before: DOC include end: GCDTLRocketConfig + + +BuildTop +-------- + +The ``BuildTop`` key is special, because sometimes, we need to instantiate TestHarness modules to interface with a custom widget. The ``BuildTop`` key provides a function which can call some method of the Top to instantiate these TestHarness modules. Since the ``BuildTop`` key is called from the TestHarness, these modules will appear in the TestHarness. The config system also lets the ``BuildTop`` key look recursively into previous definitions of itself. This enables composability of the Top configurations. + +For example, conside a config that contains the mixins ``WithGPIO ++ WithTSI``. We need to both instantiate the TSI serial adapter, and tie off the GPIO pins. + +.. literalinclude:: ../../generators/example/src/main/scala/ConfigMixins.scala + :language: scala + :start-after: DOC include start: tsi mixin + :end-before: DOC include end: tsi mixin + + +.. literalinclude:: ../../generators/example/src/main/scala/ConfigMixins.scala + :language: scala + :start-after: DOC include start: gpio mixin + :end-before: DOC include end: gpio mixin + +The leftmost mixin is ``WithGPIO``, so at elaboration time, the ``BuildTop`` key is set according to that mixin. This mixin looks up the previously set value of ``BuildTop`` by ``up(BuildTop, site)`` and calls that function to get the Top that would return. In this configuration, the previous ``BuildTop`` is set by ``WithTSI``. Thus after complete evaluation, the TSI ports are connected by the ``BuildTop`` function defined in ``WithTSI``, and the GPIO ports are connected by the ``BuildTop`` function defined in ``WithGPIO``. diff --git a/docs/Customization/MMIO-Peripherals.rst b/docs/Customization/MMIO-Peripherals.rst new file mode 100644 index 0000000000..3add986ee2 --- /dev/null +++ b/docs/Customization/MMIO-Peripherals.rst @@ -0,0 +1,133 @@ +.. _mmio-accelerators: + +MMIO Peripherals +================== + +The easiest way to create a MMIO peripheral is to use the ``TLRegisterRouter`` or ``AXI4RegisterRouter`` widgets, which abstracts away the details of handling the interconnect protocols and provides a convenient interface for specifying memory-mapped registers. Since Chipyard and Rocketchip SoCs primarily use Tilelink as the on-chip interconnect protocol, this section will primarily focus on designing Tilelink-based peripherals. However, see ``generators/example/src/main/scala/GCD.scala`` for how an example AXI4 based peripheral is defined and connected to the Tilelink graph through converters. + +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. + +For this example, we will show how to connect a MMIO peripheral which computes the GCD. +The full code can be found in ``generators/example/src/main/scala/GCD.scala``. + +In this case we use a submodule ``GCDMMIOChiselModule`` to actually perform the GCD. The ``GCDModule`` class only creates the registers and hooks them up using ``regmap``. + +.. literalinclude:: ../../generators/example/src/main/scala/GCD.scala + :language: scala + :start-after: DOC include start: GCD chisel + :end-before: DOC include end: GCD chisel + +.. literalinclude:: ../../generators/example/src/main/scala/GCD.scala + :language: scala + :start-after: DOC include start: GCD instance regmap + :end-before: DOC include end: GCD instance regmap + +Advanced Features of RegField Entries +------------------------------------- + +``RegField`` exposes polymorphic ``r`` and ``w`` methods +that allow read- and write-only memory-mapped registers to be +interfaced to hardware in multiple ways. + +* ``RegField.r(2, status)`` is used to create a 2-bit, read-only register that captures the current value of the ``status`` signal when read. +* ``RegField.r(params.width, gcd)`` "connects" the decoupled handshaking interface ``gcd`` to a read-only memory-mapped register. When this register is read via MMIO, the ``ready`` signal is asserted. This is in turn connected to ``output_ready`` on the GCD module through the glue logic. +* ``RegField.w(params.width, x)`` exposes a plain register via MMIO, but makes it write-only. +* ``RegField.w(params.width, y)`` associates the decoupled interface signal ``y`` with a write-only memory-mapped register, causing ``y.valid`` to be asserted when the register is written. + +Since the ready/valid signals of ``y`` are connected to the +``input_ready`` and ``input_valid`` signals of the GCD module, +respectively, this register map and glue logic has the effect of +triggering the GCD algorithm when ``y`` is written. Therefore, the +algorithm is set up by first writing ``x`` and then performing a +triggering write to ``y``. Polling can be used for status checks. + + +Connecting by TileLink +---------------------- + +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. +Notice how we can create an analagous AXI4 version of our peripheral. + +.. literalinclude:: ../../generators/example/src/main/scala/GCD.scala + :language: scala + :start-after: DOC include start: GCD router + :end-before: DOC include end: GCD router + + + +Top-level Traits +---------------- + +After creating the module, we need to hook it up to our SoC. +Rocket Chip accomplishes this using the cake pattern. +This basically involves placing code inside traits. +In the Rocket Chip cake, there are two kinds of traits: a ``LazyModule`` trait and a module implementation trait. + +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. + +.. literalinclude:: ../../generators/example/src/main/scala/GCD.scala + :language: scala + :start-after: DOC include start: GCD lazy trait + :end-before: DOC include end: GCD lazy trait + +Note that the ``GCDTL`` 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. +This will automatically add address map and device tree entries for the peripheral. +Also observe how we have to place additional AXI4 buffers and converters for the AXI4 version of this peripheral. + +For peripherals which instantiate a concrete module, or which need to be connected to concrete IOs or wires, a matching concrete trait is necessary. We will make our GCD example output a ``gcd_busy`` signal as a top-level port to demonstrate. In the concrete module implementation trait, we instantiate the top level IO (a concrete object) and wire it to the IO of our lazy module. + + +.. literalinclude:: ../../generators/example/src/main/scala/GCD.scala + :language: scala + :start-after: DOC include start: GCD imp trait + :end-before: DOC include end: GCD imp trait + +Constructing the Top and Config +------------------------------- + +Now we want to mix our traits into the system as a whole. +This code is from ``generators/example/src/main/scala/Top.scala``. + +.. literalinclude:: ../../generators/example/src/main/scala/Top.scala + :language: scala + :start-after: DOC include start: Top + :end-before: DOC include end: Top + +Just as we need separate traits for ``LazyModule`` and module implementation, we need two classes to build the system. +The ``Top`` class contains the set of traits which parameterize and define the ``Top``. Typically these traits will optionally add IOs or peripherals to the ``Top``. +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. + +And finally, we create a configuration class in ``generators/example/src/main/scala/Configs.scala`` that uses this mixin. + +.. literalinclude:: ../../generators/example/src/main/scala/RocketConfigs.scala + :language: scala + :start-after: DOC include start: GCDTLRocketConfig + :end-before: DOC include end: GCDTLRocketConfig + +Testing +------- + +Now we can test that the GCD is working. The test program is in ``tests/gcd.c``. + +.. literalinclude:: ../../tests/gcd.c + :language: c + +This just writes out to the registers we defined earlier. +The base of the module's MMIO region is at 0x2000 by default. +This will be printed out in the address map portion when you generated the verilog code. + +Compiling this program with ``make`` produces a ``gcd.riscv`` executable. + +Now with all of that done, we can go ahead and run our simulation. + +.. code-block:: shell + + cd sims/verilator + make CONFIG=GCDTLRocketConfig + ./simulator-example-GCDTLRocketConfig ../../tests/gcd.riscv diff --git a/docs/Customization/RoCC-Accelerators.rst b/docs/Customization/RoCC-Accelerators.rst new file mode 100644 index 0000000000..c150bf3425 --- /dev/null +++ b/docs/Customization/RoCC-Accelerators.rst @@ -0,0 +1,69 @@ +.. _rocc-accelerators: + +Adding a RoCC Accelerator +---------------------------- + +RoCC accelerators are lazy modules that extend the ``LazyRoCC`` class. +Their implementation should extends the ``LazyRoCCModule`` class. + +.. code-block:: scala + + class CustomAccelerator(opcodes: OpcodeSet) + (implicit p: Parameters) extends LazyRoCC(opcodes) { + override lazy val module = new CustomAcceleratorModule(this) + } + + class CustomAcceleratorModule(outer: CustomAccelerator) + extends LazyRoCCModuleImp(outer) { + val cmd = Queue(io.cmd) + // The parts of the command are as follows + // inst - the parts of the instruction itself + // opcode + // rd - destination register number + // rs1 - first source register number + // rs2 - second source register number + // funct + // xd - is the destination register being used? + // xs1 - is the first source register being used? + // xs2 - is the second source register being used? + // rs1 - the value of source register 1 + // rs2 - the value of source register 2 + ... + } + + +The ``opcodes`` parameter for ``LazyRoCC`` is the set of custom opcodes that will map to this accelerator. +More on this in the next subsection. + +The ``LazyRoCC`` class contains two TLOutputNode instances, ``atlNode`` and ``tlNode``. +The former connects into a tile-local arbiter along with the backside of the L1 instruction cache. +The latter connects directly to the L1-L2 crossbar. +The corresponding Tilelink ports in the module implementation's IO bundle are ``atl`` and ``tl``, respectively. + +The other interfaces available to the accelerator are ``mem``, which provides access to the L1 cache; +``ptw`` which provides access to the page-table walker; +the ``busy`` signal, which indicates when the accelerator is still handling an instruction; +and the ``interrupt`` signal, which can be used to interrupt the CPU. + +Look at the examples in ``generators/rocket-chip/src/main/scala/tile/LazyRocc.scala`` for detailed information on the different IOs. + +Adding RoCC accelerator to Config +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +RoCC accelerators can be added to a core by overriding the ``BuildRoCC`` parameter in the configuration. +This takes a sequence of functions producing ``LazyRoCC`` objects, one for each accelerator you wish to add. + +For instance, if we wanted to add the previously defined accelerator and route custom0 and custom1 instructions to it, we could do the following. + +.. code-block:: scala + + class WithCustomAccelerator extends Config((site, here, up) => { + case BuildRoCC => Seq((p: Parameters) => LazyModule( + new CustomAccelerator(OpcodeSet.custom0 | OpcodeSet.custom1)(p))) + }) + + class CustomAcceleratorConfig extends Config( + new WithCustomAccelerator ++ new RocketConfig) + +To add RoCC instructions in your program, use the RoCC C macros provided in ``tests/rocc.h``. You can find examples in the files ``tests/accum.c`` and ``charcount.c``. + diff --git a/docs/Customization/RoCC-or-MMIO.rst b/docs/Customization/RoCC-or-MMIO.rst new file mode 100644 index 0000000000..dd1ed81c3d --- /dev/null +++ b/docs/Customization/RoCC-or-MMIO.rst @@ -0,0 +1,27 @@ +.. _rocc-vs-mmio: + +RoCC vs MMIO +------------ + +Accelerators or custom IO devices can be added to your SoC in several ways: + +* MMIO Peripheral (a.k.a TileLink-Attached Accelerator) +* Tightly-Coupled RoCC Accelerator + +These approaches differ in the method of the communication between the processor and the custom block. + +With the TileLink-Attached approach, the processor communicates with MMIO peripherals through memory-mapped registers. + +In contrast, the processor communicates with a RoCC accelerators through a custom protocol and custom non-standard ISA instructions reserved in the RISC-V ISA encoding space. +Each core can have up to four accelerators that are controlled by custom instructions and share resources with the CPU. +RoCC coprocessor instructions have the following form. + +.. code-block:: none + + customX rd, rs1, rs2, funct + +The X will be a number 0-3, and determines the opcode of the instruction, which controls which accelerator an instruction will be routed to. +The ``rd``, ``rs1``, and ``rs2`` fields are the register numbers of the destination register and two source registers. +The ``funct`` field is a 7-bit integer that the accelerator can use to distinguish different instructions from each other. + +Note that communication through a RoCC interface requires a custom software toolchain, whereas MMIO peripherals can use that standard toolchain with appropriate driver support. diff --git a/docs/Customization/index.rst b/docs/Customization/index.rst index cd52a4993f..c76c1f3f76 100644 --- a/docs/Customization/index.rst +++ b/docs/Customization/index.rst @@ -3,18 +3,41 @@ Customization These guides will walk you through customization of your system-on-chip: -- Contructing heterogenous systems-on-chip using the Chipyard generators and configuration system. +- Contructing heterogenous systems-on-chip using the existing Chipyard generators and configuration system. -- Adding custom accelerators to your system-on-chip. +- How to include your custom Chisel sources in the Chipyard build system -Hit next to get started! +- Adding custom RoCC accelerators to an existing Chipyard core (BOOM or Rocket) + +- Adding custom MMIO widgets to the Chipyard memory system by Tilelink or AXI4, with custom Top-level IOs + +- Standard practices for using Keys, Traits, and Configs to parameterize your design + +- Customizing the memory hierarchy + +- Connect widgets which act as TileLink masters + +- Adding custom blackboxed verilog to a Chipyard design + +We also provide information on: + +- The boot process for Chipyard SoCs + +- Examples of FIRRTL transforms used in Chipyard, and where they are specified + +We recommend reading all these pages in order. Hit next to get started! .. toctree:: :maxdepth: 2 :caption: Customization: Heterogeneous-SoCs - Adding-An-Accelerator + Custom-Chisel + RoCC-or-MMIO + RoCC-Accelerators + MMIO-Peripherals + Keys-Traits-Configs + DMA-Devices Incorporating-Verilog-Blocks Memory-Hierarchy Boot-Process diff --git a/docs/Generators/Gemmini.rst b/docs/Generators/Gemmini.rst index d90e6224eb..66f8e017c4 100644 --- a/docs/Generators/Gemmini.rst +++ b/docs/Generators/Gemmini.rst @@ -56,7 +56,7 @@ The ``software`` directory of the generator includes the aforementioned library The Gemmini generator generates a C header file based on the generator parameters. This header files gets compiled together with the matrix multiplication library to tune library performance. The generated header file can be found under ``software/gemmini-rocc-tests/include/gemmini_params.h`` Build and Run Gemmini Tests -^^^^^^^^^^^^^^^^^^^^^^^^^ +^^^^^^^^^^^^^^^^^^^^^^^^^^^ To build Gemmini tests: diff --git a/docs/Generators/SHA3.rst b/docs/Generators/SHA3.rst index a61e7e820e..61b5f87a6d 100644 --- a/docs/Generators/SHA3.rst +++ b/docs/Generators/SHA3.rst @@ -78,6 +78,6 @@ this mixin is shown here: :end-before: DOC include end: Sha3Rocket The SHA3 example baremetal and Linux tests are located in the SHA3 repository. -Please refer to its `README.md`__ for more information on how to run/build the tests. +Please refer to its `README.md`_ for more information on how to run/build the tests. diff --git a/docs/Generators/SiFive-Generators.rst b/docs/Generators/SiFive-Generators.rst index 8f2202b052..1936016256 100644 --- a/docs/Generators/SiFive-Generators.rst +++ b/docs/Generators/SiFive-Generators.rst @@ -20,17 +20,11 @@ To integrate one of these devices in your SoC, you will need to define a custom .. literalinclude:: ../../generators/example/src/main/scala/ConfigMixins.scala :language: scala - :start-after: DOC include start: WithGPIO - :end-before: DOC include end: WithGPIO + :start-after: DOC include start: gpio mixin + :end-before: DOC include end: gpio mixin Additionally, if the device requires top-level IOs, you will need to define a mixin to change the top-level configuration of your SoC. When adding a top-level IO, you should also be aware of whether it interacts with the test-harness. -For example, a GPIO device would require a GPIO pin, and therefore we would write a mixin to augment the top level as follows: - -.. literalinclude:: ../../generators/example/src/main/scala/ConfigMixins.scala - :language: scala - :start-after: DOC include start: WithGPIOTop - :end-before: DOC include end: WithGPIOTop This example instantiates a top-level module with include GPIO ports (``TopWithGPIO``), and then ties-off the GPIO port inputs to 0 (``false.B``). diff --git a/docs/Makefile b/docs/Makefile index adea9f26be..43a6abe7cb 100644 --- a/docs/Makefile +++ b/docs/Makefile @@ -2,8 +2,8 @@ # # You can set these variables from the command line. -SPHINXOPTS = -SPHINXBUILD = python -msphinx +SPHINXOPTS = -w warnings.txt +SPHINXBUILD = python3 -msphinx SPHINXPROJ = Chipyard SOURCEDIR = . BUILDDIR = _build diff --git a/docs/Quick-Start.rst b/docs/Quick-Start.rst index d1d7ed93dd..cc650bd666 100644 --- a/docs/Quick-Start.rst +++ b/docs/Quick-Start.rst @@ -54,7 +54,7 @@ This depends on what you are planning to do with Chipyard. * If you intend to run a full-system FireSim simulation, go to :ref:`firesim-sim-intro` and follow the instructions. -* If you intend to add a new accelerator, go to :ref:`adding-an-accelerator` and follow the instructions. +* If you intend to add a new accelerator, go to :ref:`customization` and follow the instructions. * If you want to learn about the structure of Chipyard, go to :ref:`chipyard-components`. diff --git a/generators/example/src/main/resources/vsrc/GCDMMIOBlackBox.v b/generators/example/src/main/resources/vsrc/GCDMMIOBlackBox.v index 9104ae878c..46acd5c842 100644 --- a/generators/example/src/main/resources/vsrc/GCDMMIOBlackBox.v +++ b/generators/example/src/main/resources/vsrc/GCDMMIOBlackBox.v @@ -10,7 +10,8 @@ module GCDMMIOBlackBox input [WIDTH-1:0] y, input output_ready, output output_valid, - output reg [WIDTH-1:0] gcd + output reg [WIDTH-1:0] gcd, + output busy ); // DOC include end: GCD portlist @@ -21,6 +22,7 @@ module GCDMMIOBlackBox assign input_ready = state == S_IDLE; assign output_valid = state == S_DONE; + assign busy = state != S_IDLE; always @(posedge clock) begin if (reset) diff --git a/generators/example/src/main/scala/BoomConfigs.scala b/generators/example/src/main/scala/BoomConfigs.scala index 0f1535ead9..4ecab09673 100644 --- a/generators/example/src/main/scala/BoomConfigs.scala +++ b/generators/example/src/main/scala/BoomConfigs.scala @@ -9,54 +9,72 @@ import freechips.rocketchip.config.{Config} // --------------------- class SmallBoomConfig extends Config( - new WithTop ++ // use normal top + new WithTSI ++ // use normal top + new WithNoGPIO ++ // no GPIO pins new WithBootROM ++ // use testchipip bootrom new WithUART ++ // add a UART + new freechips.rocketchip.subsystem.WithNoMMIOPort ++ // no mmio master port + new freechips.rocketchip.subsystem.WithNoSlavePort ++ // no mmio slave port new freechips.rocketchip.subsystem.WithInclusiveCache ++ // use SiFive L2 cache new boom.common.WithSmallBooms ++ // 1-wide BOOM new boom.common.WithNBoomCores(1) ++ // single-core new freechips.rocketchip.system.BaseConfig) // "base" rocketchip system class MediumBoomConfig extends Config( - new WithTop ++ + new WithTSI ++ + new WithNoGPIO ++ new WithBootROM ++ new WithUART ++ + new freechips.rocketchip.subsystem.WithNoMMIOPort ++ + new freechips.rocketchip.subsystem.WithNoSlavePort ++ new freechips.rocketchip.subsystem.WithInclusiveCache ++ new boom.common.WithMediumBooms ++ // 2-wide BOOM new boom.common.WithNBoomCores(1) ++ new freechips.rocketchip.system.BaseConfig) class LargeBoomConfig extends Config( - new WithTop ++ + new WithTSI ++ + new WithNoGPIO ++ new WithBootROM ++ new WithUART ++ + new freechips.rocketchip.subsystem.WithNoMMIOPort ++ + new freechips.rocketchip.subsystem.WithNoSlavePort ++ new freechips.rocketchip.subsystem.WithInclusiveCache ++ new boom.common.WithLargeBooms ++ // 3-wide BOOM new boom.common.WithNBoomCores(1) ++ new freechips.rocketchip.system.BaseConfig) class MegaBoomConfig extends Config( - new WithTop ++ + new WithTSI ++ + new WithNoGPIO ++ new WithBootROM ++ new WithUART ++ + new freechips.rocketchip.subsystem.WithNoMMIOPort ++ + new freechips.rocketchip.subsystem.WithNoSlavePort ++ new freechips.rocketchip.subsystem.WithInclusiveCache ++ new boom.common.WithMegaBooms ++ // 4-wide BOOM new boom.common.WithNBoomCores(1) ++ new freechips.rocketchip.system.BaseConfig) class DualSmallBoomConfig extends Config( - new WithTop ++ + new WithTSI ++ + new WithNoGPIO ++ new WithBootROM ++ new WithUART ++ + new freechips.rocketchip.subsystem.WithNoMMIOPort ++ + new freechips.rocketchip.subsystem.WithNoSlavePort ++ new freechips.rocketchip.subsystem.WithInclusiveCache ++ new boom.common.WithSmallBooms ++ new boom.common.WithNBoomCores(2) ++ // dual-core new freechips.rocketchip.system.BaseConfig) class SmallRV32BoomConfig extends Config( - new WithTop ++ + new WithTSI ++ + new WithNoGPIO ++ new WithBootROM ++ new WithUART ++ + new freechips.rocketchip.subsystem.WithNoMMIOPort ++ + new freechips.rocketchip.subsystem.WithNoSlavePort ++ new freechips.rocketchip.subsystem.WithInclusiveCache ++ new boom.common.WithoutBoomFPU ++ // no fp new boom.common.WithBoomRV32 ++ // rv32 (32bit) @@ -65,9 +83,12 @@ class SmallRV32BoomConfig extends Config( new freechips.rocketchip.system.BaseConfig) class HwachaLargeBoomConfig extends Config( - new WithTop ++ + new WithTSI ++ + new WithNoGPIO ++ new WithBootROM ++ new WithUART ++ + new freechips.rocketchip.subsystem.WithNoMMIOPort ++ + new freechips.rocketchip.subsystem.WithNoSlavePort ++ new freechips.rocketchip.subsystem.WithInclusiveCache ++ new hwacha.DefaultHwachaConfig ++ // use Hwacha vector accelerator new boom.common.WithLargeBooms ++ // 3-wide BOOM @@ -75,11 +96,15 @@ class HwachaLargeBoomConfig extends Config( new freechips.rocketchip.system.BaseConfig) class LoopbackNICBoomConfig extends Config( - new WithIceNIC ++ - new WithLoopbackNICTop ++ + new WithTSI ++ + new WithLoopbackNIC ++ // loopback the NIC + new WithIceNIC ++ // add IceNIC new WithBootROM ++ new WithUART ++ + new freechips.rocketchip.subsystem.WithNoMMIOPort ++ + new freechips.rocketchip.subsystem.WithNoSlavePort ++ new freechips.rocketchip.subsystem.WithInclusiveCache ++ - new boom.common.WithLargeBooms ++ // 3-wide BOOM + new boom.common.WithLargeBooms ++ new boom.common.WithNBoomCores(1) ++ new freechips.rocketchip.system.BaseConfig) + diff --git a/generators/example/src/main/scala/ConfigMixins.scala b/generators/example/src/main/scala/ConfigMixins.scala index 441a928945..bd4bfeb0b6 100644 --- a/generators/example/src/main/scala/ConfigMixins.scala +++ b/generators/example/src/main/scala/ConfigMixins.scala @@ -7,7 +7,8 @@ import freechips.rocketchip.config.{Field, Parameters, Config} import freechips.rocketchip.subsystem.{SystemBusKey, RocketTilesKey, WithRoccExample, WithNMemoryChannels, WithNBigCores, WithRV32, CacheBlockBytes} import freechips.rocketchip.diplomacy.{LazyModule, ValName} import freechips.rocketchip.devices.tilelink.BootROMParams -import freechips.rocketchip.tile.{RocketTileParams, MaxHartIdBits, XLen, BuildRoCC, TileKey, LazyRoCC} +import freechips.rocketchip.devices.debug.{Debug} +import freechips.rocketchip.tile.{XLen, BuildRoCC, TileKey, LazyRoCC, RocketTileParams, MaxHartIdBits} import freechips.rocketchip.rocket.{RocketCoreParams, MulDivParams, DCacheParams, ICacheParams} import boom.common.{BoomTilesKey} @@ -33,23 +34,26 @@ import ConfigValName._ // Common Parameter Mixins // ----------------------- -/** - * Class to specify where the BootRom file is (from `rebar` top) - */ class WithBootROM extends Config((site, here, up) => { case BootROMParams => BootROMParams( contentFileName = s"./bootrom/bootrom.rv${site(XLen)}.img") }) -// DOC include start: WithGPIO -/** - * Class to add in GPIO - */ +// DOC include start: gpio mixin class WithGPIO extends Config((site, here, up) => { case PeripheryGPIOKey => Seq( GPIOParams(address = 0x10012000, width = 4, includeIOF = false)) + case BuildTop => (clock: Clock, reset: Bool, p: Parameters, success: Bool) => { + val top = up(BuildTop, site)(clock, reset, p, success) + for (gpio <- top.gpio) { + for (pin <- gpio.pins) { + pin.i.ival := false.B + } + } + top + } }) -// DOC include end: WithGPIO +// DOC include end: gpio mixin /** * Class to add in UART @@ -59,92 +63,58 @@ class WithUART extends Config((site, here, up) => { UARTParams(address = 0x54000000L, nTxEntries = 256, nRxEntries = 256)) }) -// ----------------------------------------------- -// BOOM and/or Rocket Top Level System Parameter Mixins -// ----------------------------------------------- -/** - * Class to specify a "plain" top level BOOM and/or Rocket system - */ -class WithTop extends Config((site, here, up) => { - case BuildTop => (clock: Clock, reset: Bool, p: Parameters) => { - Module(LazyModule(new Top()(p)).module) - } +class WithNoGPIO extends Config((site, here, up) => { + case PeripheryGPIOKey => Seq() }) -/** - * Class to specify a top level BOOM and/or Rocket system with DTM - */ -class WithDTMTop extends Config((site, here, up) => { - case BuildTopWithDTM => (clock: Clock, reset: Bool, p: Parameters) => { - Module(LazyModule(new TopWithDTM()(p)).module) +// DOC include start: tsi mixin +class WithTSI extends Config((site, here, up) => { + case SerialKey => true + case BuildTop => (clock: Clock, reset: Bool, p: Parameters, success: Bool) => { + val top = up(BuildTop, site)(clock, reset, p, success) + success := top.connectSimSerial() + top } }) +// DOC include end: tsi mixin -/** - * 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) +class WithDTM extends Config((site, here, up) => { + case BuildTop => (clock: Clock, reset: Bool, p: Parameters, success: Bool) => { + val top = up(BuildTop, site)(clock, reset, p, success) + top.reset := reset.asBool | top.debug.get.ndreset + Debug.connectDebug(top.debug, top.psd, clock, reset.asBool, success)(p) + top + } }) -// DOC include end: WithPWMTop -/** - * Class to specify a top level BOOM and/or Rocket system with a PWM AXI4 - */ -class WithPWMAXI4Top extends Config((site, here, up) => { - case BuildTop => (clock: Clock, reset: Bool, p: Parameters) => - Module(LazyModule(new TopWithPWMAXI4()(p)).module) +// DOC include start: GCD mixin +class WithGCD(useAXI4: Boolean, useBlackBox: Boolean) extends Config((site, here, up) => { + case GCDKey => Some(GCDParams(useAXI4 = useAXI4, useBlackBox = useBlackBox)) }) +// DOC include end: GCD mixin -/** - * Class to specify a top level BOOM and/or Rocket system with a TL-attached GCD device - */ -class WithGCDTop extends Config((site, here, up) => { - case BuildTop => (clock: Clock, reset: Bool, p: Parameters) => - Module(LazyModule(new TopWithGCD()(p)).module) -}) - -/** - * Class to specify a top level BOOM and/or Rocket system with a block device - */ -class WithBlockDeviceModelTop extends Config((site, here, up) => { - case BuildTop => (clock: Clock, reset: Bool, p: Parameters) => { - val top = Module(LazyModule(new TopWithBlockDevice()(p)).module) +class WithBlockDeviceModel extends Config((site, here, up) => { + case BuildTop => (clock: Clock, reset: Bool, p: Parameters, success: Bool) => { + val top = up(BuildTop, site)(clock, reset, p, success) top.connectBlockDeviceModel() top } }) -/** - * Class to specify a top level BOOM and/or Rocket system with a simulator block device - */ -class WithSimBlockDeviceTop extends Config((site, here, up) => { - case BuildTop => (clock: Clock, reset: Bool, p: Parameters) => { - val top = Module(LazyModule(new TopWithBlockDevice()(p)).module) +class WithSimBlockDevice extends Config((site, here, up) => { + case BuildTop => (clock: Clock, reset: Bool, p: Parameters, success: Bool) => { + val top = up(BuildTop, site)(clock, reset, p, success) top.connectSimBlockDevice(clock, reset) top } }) -// DOC include start: WithGPIOTop -/** - * Class to specify a top level BOOM and/or Rocket system with GPIO - */ -class WithGPIOTop extends Config((site, here, up) => { - case BuildTop => (clock: Clock, reset: Bool, p: Parameters) => { - val top = Module(LazyModule(new TopWithGPIO()(p)).module) - for (gpio <- top.gpio) { - for (pin <- gpio.pins) { - pin.i.ival := false.B - } - } - top - } +// DOC include start: WithInitZero +class WithInitZero(base: BigInt, size: BigInt) extends Config((site, here, up) => { + case InitZeroKey => InitZeroConfig(base, size) }) -// DOC include end: WithGPIOTop +// DOC include end: WithInitZero // ------------------ // Multi-RoCC Support @@ -184,16 +154,6 @@ class WithMultiRoCCHwacha(harts: Int*) extends Config((site, here, up) => { } }) -// DOC include start: WithInitZero -class WithInitZero(base: BigInt, size: BigInt) extends Config((site, here, up) => { - case InitZeroKey => InitZeroConfig(base, size) -}) - -class WithInitZeroTop extends Config((site, here, up) => { - case BuildTop => (clock: Clock, reset: Bool, p: Parameters) => - Module(LazyModule(new TopWithInitZero()(p)).module) -}) -// DOC include end: WithInitZero /** * Mixin to add a small Rocket core to the system as a "control" core. @@ -233,9 +193,9 @@ class WithIceNIC(inBufFlits: Int = 1800, usePauser: Boolean = false) checksumOffload = true) }) -class WithLoopbackNICTop extends Config((site, here, up) => { - case BuildTop => (clock: Clock, reset: Bool, p: Parameters) => { - val top = Module(LazyModule(new TopWithIceNIC()(p)).module) +class WithLoopbackNIC extends Config((site, here, up) => { + case BuildTop => (clock: Clock, reset: Bool, p: Parameters, success: Bool) => { + val top = up(BuildTop, site)(clock, reset, p, success) top.connectNicLoopback() top } diff --git a/generators/example/src/main/scala/GCD.scala b/generators/example/src/main/scala/GCD.scala new file mode 100644 index 0000000000..f3a363636d --- /dev/null +++ b/generators/example/src/main/scala/GCD.scala @@ -0,0 +1,207 @@ +package example + +import chisel3._ +import chisel3.util._ +import chisel3.core.{IntParam, Reset} +import freechips.rocketchip.amba.axi4._ +import freechips.rocketchip.subsystem.BaseSubsystem +import freechips.rocketchip.config.{Parameters, Field} +import freechips.rocketchip.diplomacy._ +import freechips.rocketchip.regmapper.{HasRegMap, RegField} +import freechips.rocketchip.tilelink._ +import freechips.rocketchip.util.UIntIsOneOf + +// DOC include start: GCD params +case class GCDParams( + address: BigInt = 0x2000, + width: Int = 32, + useAXI4: Boolean = false, + useBlackBox: Boolean = true) +// DOC include end: GCD params + +// DOC include start: GCD key +case object GCDKey extends Field[Option[GCDParams]](None) +// DOC include end: GCD key + +class GCDIO(w: Int) extends Bundle { + val clock = Input(Clock()) + val reset = Input(Bool()) + val input_ready = Output(Bool()) + val input_valid = Input(Bool()) + val x = Input(UInt(w.W)) + val y = Input(UInt(w.W)) + val output_ready = Input(Bool()) + val output_valid = Output(Bool()) + val gcd = Output(UInt(w.W)) + val busy = Output(Bool()) +} + +trait GCDTopIO extends Bundle { + val gcd_busy = Output(Bool()) +} + +// DOC include start: GCD blackbox +class GCDMMIOBlackBox(w: Int) extends BlackBox(Map("WIDTH" -> IntParam(w))) with HasBlackBoxResource +{ + val io = IO(new GCDIO(w)) + + addResource("/vsrc/GCDMMIOBlackBox.v") +} +// DOC include end: GCD blackbox + +// DOC include start: GCD chisel +class GCDMMIOChiselModule(w: Int) extends Module +{ + val io = IO(new GCDIO(w)) + + val s_idle :: s_run :: s_done :: Nil = Enum(3) + + val state = RegInit(s_idle) + val tmp = Reg(UInt(w.W)) + val gcd = Reg(UInt(w.W)) + + io.input_ready := state === s_idle + io.output_valid := state === s_done + io.gcd := gcd + + when (state === s_idle && io.input_valid) { + state := s_run + } .elsewhen (state === s_run && tmp === 0.U) { + state := s_done + } .elsewhen (state === s_done && io.output_ready) { + state := s_idle + } + + when (state === s_idle && io.input_valid) { + gcd := io.x + tmp := io.y + } .elsewhen (state === s_run) { + when (gcd > tmp) { + gcd := gcd - tmp + } .otherwise { + tmp := tmp - gcd + } + } + + io.busy := state =/= s_idle +} +// DOC include end: GCD chisel + +// DOC include start: GCD instance regmap + +trait GCDModule extends HasRegMap { + val io: GCDTopIO + + implicit val p: Parameters + def params: GCDParams + val clock: Clock + val reset: Reset + + + // How many clock cycles in a PWM cycle? + val x = Reg(UInt(params.width.W)) + val y = Wire(new DecoupledIO(UInt(params.width.W))) + val gcd = Wire(new DecoupledIO(UInt(params.width.W))) + val status = Wire(UInt(2.W)) + + if (params.useBlackBox) { + val impl = Module(new GCDMMIOBlackBox(params.width)) + + impl.io.clock := clock + impl.io.reset := reset.asBool + impl.io.x := x + impl.io.y := y.bits + impl.io.input_valid := y.valid + y.ready := impl.io.input_ready + + gcd.bits := impl.io.gcd + gcd.valid := impl.io.output_valid + impl.io.output_ready := gcd.ready + + status := Cat(impl.io.input_ready, impl.io.output_ready) + io.gcd_busy := impl.io.busy + } else { + val impl = Module(new GCDMMIOChiselModule(params.width)) + + impl.io.clock := clock + impl.io.reset := reset.asBool + + impl.io.x := x + impl.io.y := y.bits + impl.io.input_valid := y.valid + y.ready := impl.io.input_ready + + gcd.bits := impl.io.gcd + gcd.valid := impl.io.output_valid + impl.io.output_ready := gcd.ready + + status := Cat(impl.io.input_ready, impl.io.output_ready) + io.gcd_busy := impl.io.busy + } + + regmap( + 0x00 -> Seq( + RegField.r(2, status)), // a read-only register capturing current status + 0x04 -> Seq( + RegField.w(params.width, x)), // a plain, write-only register + 0x08 -> Seq( + RegField.w(params.width, y)), // write-only, y.valid is set on write + 0x0C -> Seq( + RegField.r(params.width, gcd))) // read-only, gcd.ready is set on read +} +// DOC include end: GCD instance regmap + +// DOC include start: GCD router +class GCDTL(params: GCDParams, beatBytes: Int)(implicit p: Parameters) + extends TLRegisterRouter( + params.address, "gcd", Seq("ucbbar,gcd"), + beatBytes = beatBytes)( + new TLRegBundle(params, _) with GCDTopIO)( + new TLRegModule(params, _, _) with GCDModule) + +class GCDAXI4(params: GCDParams, beatBytes: Int)(implicit p: Parameters) + extends AXI4RegisterRouter( + params.address, + beatBytes=beatBytes)( + new AXI4RegBundle(params, _) with GCDTopIO)( + new AXI4RegModule(params, _, _) with GCDModule) +// DOC include end: GCD router + +// DOC include start: GCD lazy trait +trait CanHavePeripheryGCD { this: BaseSubsystem => + private val portName = "gcd" + + // Only build if we are using the TL (nonAXI4) version + val gcd = p(GCDKey) match { + case Some(params) => { + if (params.useAXI4) { + val gcd = LazyModule(new GCDAXI4(params, pbus.beatBytes)(p)) + pbus.toSlave(Some(portName)) { + gcd.node := + AXI4Buffer () := + TLToAXI4 () := + // toVariableWidthSlave doesn't use holdFirstDeny, which TLToAXI4() needsx + TLFragmenter(pbus.beatBytes, pbus.blockBytes, holdFirstDeny = true) + } + Some(gcd) + } else { + val gcd = LazyModule(new GCDTL(params, pbus.beatBytes)(p)) + pbus.toVariableWidthSlave(Some(portName)) { gcd.node } + Some(gcd) + } + } + case None => None + } +} +// DOC include end: GCD lazy trait + +// DOC include start: GCD imp trait +trait CanHavePeripheryGCDModuleImp extends LazyModuleImp { + val outer: CanHavePeripheryGCD + outer.gcd.map { g => + val gcd_busy = IO(Output(Bool())) + gcd_busy := g.module.io.gcd_busy + } +} + +// DOC include end: GCD imp trait diff --git a/generators/example/src/main/scala/GCDMMIOBlackBox.scala b/generators/example/src/main/scala/GCDMMIOBlackBox.scala deleted file mode 100644 index 891fe1c9fe..0000000000 --- a/generators/example/src/main/scala/GCDMMIOBlackBox.scala +++ /dev/null @@ -1,98 +0,0 @@ -package example - -import chisel3._ -import chisel3.util._ -import chisel3.core.{IntParam, Reset} -import freechips.rocketchip.amba.axi4._ -import freechips.rocketchip.subsystem.BaseSubsystem -import freechips.rocketchip.config.{Parameters, Field} -import freechips.rocketchip.diplomacy._ -import freechips.rocketchip.regmapper.{HasRegMap, RegField} -import freechips.rocketchip.tilelink._ -import freechips.rocketchip.util.UIntIsOneOf - -// DOC include start: GCD blackbox -class GCDMMIOBlackBox(w: Int) extends BlackBox(Map("WIDTH" -> IntParam(w))) with HasBlackBoxResource { - val io = IO(new Bundle { - val clock = Input(Clock()) - val reset = Input(Bool()) - val input_ready = Output(Bool()) - val input_valid = Input(Bool()) - val x = Input(UInt(w.W)) - val y = Input(UInt(w.W)) - val output_ready = Input(Bool()) - val output_valid = Output(Bool()) - val gcd = Output(UInt(w.W)) - }) - - addResource("/vsrc/GCDMMIOBlackBox.v") -} -// DOC include end: GCD blackbox - -// DOC include start: GCD instance regmap -case class GCDParams(address: BigInt, beatBytes: Int, width: Int) - -trait GCDModule extends HasRegMap { - implicit val p: Parameters - def params: GCDParams - val clock: Clock - val reset: Reset - - val impl = Module(new GCDMMIOBlackBox(params.width)) - - // How many clock cycles in a PWM cycle? - val x = Reg(UInt(params.width.W)) - val y = Wire(new DecoupledIO(impl.io.y)) - val gcd = Wire(new DecoupledIO(impl.io.gcd)) - val status = Cat(impl.io.input_ready, impl.io.output_valid) - - impl.io.clock := clock - impl.io.reset := reset.asBool - impl.io.x := x - impl.io.y := y.bits - impl.io.input_valid := y.valid - y.ready := impl.io.input_ready - - gcd.bits := impl.io.gcd - gcd.valid := impl.io.output_valid - impl.io.output_ready := gcd.ready - - regmap( - 0x00 -> Seq( - RegField.r(2, status)), // a read-only register capturing current status - 0x04 -> Seq( - RegField.w(params.width, x)), // a plain, write-only register - 0x08 -> Seq( - RegField.w(params.width, y)), // write-only, y.valid is set on write - 0x0C -> Seq( - RegField.r(params.width, gcd))) // read-only, gcd.ready is set on read -} -// DOC include end: GCD instance regmap - -// DOC include start: GCD cake -class GCD(c: GCDParams)(implicit p: Parameters) - extends TLRegisterRouter( - c.address, "gcd", Seq("ucbbar,gcd"), - beatBytes = c.beatBytes)( - new TLRegBundle(c, _))( - new TLRegModule(c, _, _) with GCDModule) - -trait HasPeripheryGCD { this: BaseSubsystem => - implicit val p: Parameters - - private val address = 0x2000 - private val portName = "gcd" - private val gcdWidth = 32 - - val gcd = LazyModule(new GCD( - GCDParams(address, pbus.beatBytes, gcdWidth))(p)) - - pbus.toVariableWidthSlave(Some(portName)) { gcd.node } -} - -trait HasPeripheryGCDModuleImp extends LazyModuleImp { - implicit val p: Parameters - val outer: HasPeripheryGCD -} - -// DOC include end: GCD cake diff --git a/generators/example/src/main/scala/HeteroConfigs.scala b/generators/example/src/main/scala/HeteroConfigs.scala index e5cebef93d..6dda511796 100644 --- a/generators/example/src/main/scala/HeteroConfigs.scala +++ b/generators/example/src/main/scala/HeteroConfigs.scala @@ -9,10 +9,13 @@ import freechips.rocketchip.config.{Config} // --------------------- class LargeBoomAndRocketConfig extends Config( - new WithTop ++ // default top + new WithTSI ++ // default top + new WithNoGPIO ++ // no GPIO pins new WithBootROM ++ // default bootrom new WithUART ++ // add a UART new freechips.rocketchip.subsystem.WithInclusiveCache ++ // use SiFive l2 + new freechips.rocketchip.subsystem.WithNoMMIOPort ++ // no mmio master port + new freechips.rocketchip.subsystem.WithNoSlavePort ++ // no mmio slave port new boom.common.WithRenumberHarts ++ // avoid hartid overlap new boom.common.WithLargeBooms ++ // 3-wide boom new boom.common.WithNBoomCores(1) ++ // single-core boom @@ -20,10 +23,13 @@ class LargeBoomAndRocketConfig extends Config( new freechips.rocketchip.system.BaseConfig) // "base" rocketchip system class SmallBoomAndRocketConfig extends Config( - new WithTop ++ + new WithTSI ++ + new WithNoGPIO ++ new WithBootROM ++ new WithUART ++ new freechips.rocketchip.subsystem.WithInclusiveCache ++ + new freechips.rocketchip.subsystem.WithNoMMIOPort ++ + new freechips.rocketchip.subsystem.WithNoSlavePort ++ new boom.common.WithRenumberHarts ++ new boom.common.WithSmallBooms ++ // 1-wide boom new boom.common.WithNBoomCores(1) ++ @@ -32,11 +38,14 @@ class SmallBoomAndRocketConfig extends Config( // DOC include start: BoomAndRocketWithHwacha class HwachaLargeBoomAndHwachaRocketConfig extends Config( - new WithTop ++ + new WithTSI ++ + new WithNoGPIO ++ new WithBootROM ++ new WithUART ++ new hwacha.DefaultHwachaConfig ++ // add hwacha to all harts new freechips.rocketchip.subsystem.WithInclusiveCache ++ + new freechips.rocketchip.subsystem.WithNoMMIOPort ++ + new freechips.rocketchip.subsystem.WithNoSlavePort ++ new boom.common.WithRenumberHarts ++ new boom.common.WithLargeBooms ++ new boom.common.WithNBoomCores(1) ++ @@ -45,10 +54,13 @@ class HwachaLargeBoomAndHwachaRocketConfig extends Config( // DOC include end: BoomAndRocketWithHwacha class RoccLargeBoomAndRoccRocketConfig extends Config( - new WithTop ++ + new WithTSI ++ + new WithNoGPIO ++ new WithBootROM ++ new WithUART ++ new freechips.rocketchip.subsystem.WithRoccExample ++ // add example rocc accelerator to all harts + new freechips.rocketchip.subsystem.WithNoMMIOPort ++ + new freechips.rocketchip.subsystem.WithNoSlavePort ++ new freechips.rocketchip.subsystem.WithInclusiveCache ++ new boom.common.WithRenumberHarts ++ new boom.common.WithLargeBooms ++ @@ -57,9 +69,12 @@ class RoccLargeBoomAndRoccRocketConfig extends Config( new freechips.rocketchip.system.BaseConfig) class DualLargeBoomAndRocketConfig extends Config( - new WithTop ++ + new WithTSI ++ + new WithNoGPIO ++ new WithBootROM ++ new WithUART ++ + new freechips.rocketchip.subsystem.WithNoMMIOPort ++ + new freechips.rocketchip.subsystem.WithNoSlavePort ++ new freechips.rocketchip.subsystem.WithInclusiveCache ++ new boom.common.WithRenumberHarts ++ new boom.common.WithLargeBooms ++ @@ -69,10 +84,13 @@ class DualLargeBoomAndRocketConfig extends Config( // DOC include start: DualBoomAndRocketOneHwacha class DualLargeBoomAndHwachaRocketConfig extends Config( - new WithTop ++ + new WithTSI ++ + new WithNoGPIO ++ new WithBootROM ++ new WithUART ++ new freechips.rocketchip.subsystem.WithInclusiveCache ++ + new freechips.rocketchip.subsystem.WithNoMMIOPort ++ + new freechips.rocketchip.subsystem.WithNoSlavePort ++ new WithMultiRoCC ++ // support heterogeneous rocc new WithMultiRoCCHwacha(2) ++ // put hwacha on hart-2 (rocket) new boom.common.WithRenumberHarts ++ @@ -83,10 +101,13 @@ class DualLargeBoomAndHwachaRocketConfig extends Config( // DOC include end: DualBoomAndRocketOneHwacha class LargeBoomAndRV32RocketConfig extends Config( - new WithTop ++ + new WithTSI ++ + new WithNoGPIO ++ new WithBootROM ++ new WithUART ++ new freechips.rocketchip.subsystem.WithInclusiveCache ++ + new freechips.rocketchip.subsystem.WithNoMMIOPort ++ + new freechips.rocketchip.subsystem.WithNoSlavePort ++ new boom.common.WithRenumberHarts ++ new boom.common.WithLargeBooms ++ new boom.common.WithNBoomCores(1) ++ @@ -96,10 +117,13 @@ class LargeBoomAndRV32RocketConfig extends Config( // DOC include start: DualBoomAndRocket class DualLargeBoomAndDualRocketConfig extends Config( - new WithTop ++ + new WithTSI ++ + new WithNoGPIO ++ new WithBootROM ++ new WithUART ++ new freechips.rocketchip.subsystem.WithInclusiveCache ++ + new freechips.rocketchip.subsystem.WithNoMMIOPort ++ + new freechips.rocketchip.subsystem.WithNoSlavePort ++ new boom.common.WithRenumberHarts ++ new boom.common.WithLargeBooms ++ new boom.common.WithNBoomCores(2) ++ // 2 boom cores @@ -108,10 +132,12 @@ class DualLargeBoomAndDualRocketConfig extends Config( // DOC include end: DualBoomAndRocket class MultiCoreWithControlCoreConfig extends Config( - new WithTop ++ + new WithTSI ++ new WithBootROM ++ new WithUART ++ new freechips.rocketchip.subsystem.WithInclusiveCache ++ + new freechips.rocketchip.subsystem.WithNoMMIOPort ++ + new freechips.rocketchip.subsystem.WithNoSlavePort ++ new WithControlCore ++ // add small control core (last hartid) new boom.common.WithRenumberHarts ++ new boom.common.WithLargeBooms ++ diff --git a/generators/example/src/main/scala/InitZero.scala b/generators/example/src/main/scala/InitZero.scala index 3a90bfccf4..cfde23b128 100644 --- a/generators/example/src/main/scala/InitZero.scala +++ b/generators/example/src/main/scala/InitZero.scala @@ -8,7 +8,7 @@ import freechips.rocketchip.diplomacy.{LazyModule, LazyModuleImp, IdRange} import testchipip.TLHelper case class InitZeroConfig(base: BigInt, size: BigInt) -case object InitZeroKey extends Field[InitZeroConfig] +case object InitZeroKey extends Field[Option[InitZeroConfig]](None) class InitZero(implicit p: Parameters) extends LazyModule { val node = TLHelper.makeClientNode( @@ -41,7 +41,7 @@ class InitZeroModuleImp(outer: InitZero) extends LazyModuleImp(outer) { mem.d.ready := state === s_resp when (state === s_init) { - addr := config.base.U + addr := config.get.base.U bytesLeft := config.size.U state := s_write } @@ -57,13 +57,11 @@ class InitZeroModuleImp(outer: InitZero) extends LazyModuleImp(outer) { } } -trait HasPeripheryInitZero { this: BaseSubsystem => +trait CanHavePeripheryInitZero { this: BaseSubsystem => implicit val p: Parameters - val initZero = LazyModule(new InitZero()(p)) - fbus.fromPort(Some("init-zero"))() := initZero.node -} - -trait HasPeripheryInitZeroModuleImp extends LazyModuleImp { - // Don't need anything here + p(InitZeroKey) .map { k => + val initZero = LazyModule(new InitZero()(p)) + fbus.fromPort(Some("init-zero"))() := initZero.node + } } diff --git a/generators/example/src/main/scala/PWM.scala b/generators/example/src/main/scala/PWM.scala deleted file mode 100644 index bd6056f45a..0000000000 --- a/generators/example/src/main/scala/PWM.scala +++ /dev/null @@ -1,134 +0,0 @@ -package example - -import chisel3._ -import chisel3.util._ -import freechips.rocketchip.amba.axi4._ -import freechips.rocketchip.subsystem.BaseSubsystem -import freechips.rocketchip.config.{Parameters, Field} -import freechips.rocketchip.diplomacy._ -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 { - val io = IO(new Bundle { - val pwmout = Output(Bool()) - val period = Input(UInt(w.W)) - val duty = Input(UInt(w.W)) - val enable = Input(Bool()) - }) - - // The counter should count up until period is reached - val counter = Reg(UInt(w.W)) - - when (counter >= (io.period - 1.U)) { - counter := 0.U - } .otherwise { - counter := counter + 1.U - } - - // If PWM is enabled, pwmout is high when counter < duty - // If PWM is not enabled, it will always be low - io.pwmout := io.enable && (counter < io.duty) -} - -trait PWMBundle extends Bundle { - val pwmout = Output(Bool()) -} - -trait PWMModule extends HasRegMap { - val io: PWMBundle - implicit val p: Parameters - def params: PWMParams - - // How many clock cycles in a PWM cycle? - val period = Reg(UInt(32.W)) - // For how many cycles should the clock be high? - val duty = Reg(UInt(32.W)) - // Is the PWM even running at all? - val enable = RegInit(false.B) - - val base = Module(new PWMBase(32)) - io.pwmout := base.io.pwmout - base.io.period := period - base.io.duty := duty - base.io.enable := enable - - regmap( - 0x00 -> Seq( - RegField(32, period)), - 0x04 -> Seq( - RegField(32, duty)), - 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 - - private val address = 0x2000 - private val portName = "pwm" - - val pwm = LazyModule(new PWMTL( - PWMParams(address, pbus.beatBytes))(p)) - - 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 - - val pwmout = IO(Output(Bool())) - - pwmout := outer.pwm.module.io.pwmout -} -// DOC include end: HasPeripheryPWMTLModuleImp - -trait HasPeripheryPWMAXI4 { this: BaseSubsystem => - implicit val p: Parameters - - private val address = 0x2000 - private val portName = "pwm" - - val pwm = LazyModule(new PWMAXI4( - PWMParams(address, pbus.beatBytes))(p)) - - pbus.toSlave(Some(portName)) { - pwm.node := - AXI4Buffer () := - TLToAXI4() := - // toVariableWidthSlave doesn't use holdFirstDeny, which TLToAXI4() needs - TLFragmenter(pbus.beatBytes, pbus.blockBytes, holdFirstDeny = true) - } -} - -trait HasPeripheryPWMAXI4ModuleImp extends LazyModuleImp { - implicit val p: Parameters - val outer: HasPeripheryPWMAXI4 - - val pwmout = IO(Output(Bool())) - - pwmout := outer.pwm.module.io.pwmout -} diff --git a/generators/example/src/main/scala/RocketConfigs.scala b/generators/example/src/main/scala/RocketConfigs.scala index edd18a36c6..c70e2b809a 100644 --- a/generators/example/src/main/scala/RocketConfigs.scala +++ b/generators/example/src/main/scala/RocketConfigs.scala @@ -9,17 +9,23 @@ import freechips.rocketchip.config.{Config} // -------------- class RocketConfig extends Config( - new WithTop ++ // use default top + new WithTSI ++ // use TSI bringup + new WithNoGPIO ++ // no GPIO pins new WithBootROM ++ // use default bootrom new WithUART ++ // add a UART + new freechips.rocketchip.subsystem.WithNoMMIOPort ++ // no MMIO master port + new freechips.rocketchip.subsystem.WithNoSlavePort ++ // no MMIO slave port new freechips.rocketchip.subsystem.WithInclusiveCache ++ // use Sifive L2 cache new freechips.rocketchip.subsystem.WithNBigCores(1) ++ // single rocket-core new freechips.rocketchip.system.BaseConfig) // "base" rocketchip system class HwachaRocketConfig extends Config( - new WithTop ++ + new WithTSI ++ + new WithNoGPIO ++ new WithBootROM ++ new WithUART ++ + new freechips.rocketchip.subsystem.WithNoMMIOPort ++ + new freechips.rocketchip.subsystem.WithNoSlavePort ++ new freechips.rocketchip.subsystem.WithInclusiveCache ++ new hwacha.DefaultHwachaConfig ++ // use Hwacha vector accelerator new freechips.rocketchip.subsystem.WithNBigCores(1) ++ @@ -27,9 +33,11 @@ class HwachaRocketConfig extends Config( // DOC include start: GemminiRocketConfig class GemminiRocketConfig extends Config( - new WithTop ++ + new WithTSI ++ new WithBootROM ++ new WithUART ++ + new freechips.rocketchip.subsystem.WithNoMMIOPort ++ + new freechips.rocketchip.subsystem.WithNoSlavePort ++ new freechips.rocketchip.subsystem.WithInclusiveCache ++ new gemmini.DefaultGemminiConfig ++ // use Gemmini systolic array GEMM accelerator new freechips.rocketchip.subsystem.WithNBigCores(1) ++ @@ -37,9 +45,12 @@ class GemminiRocketConfig extends Config( // DOC include end: GemminiRocketConfig class RoccRocketConfig extends Config( - new WithTop ++ + new WithTSI ++ + new WithNoGPIO ++ new WithBootROM ++ new WithUART ++ + new freechips.rocketchip.subsystem.WithNoMMIOPort ++ + new freechips.rocketchip.subsystem.WithNoSlavePort ++ new freechips.rocketchip.subsystem.WithInclusiveCache ++ new freechips.rocketchip.subsystem.WithRoccExample ++ // use example RoCC-based accelerator new freechips.rocketchip.subsystem.WithNBigCores(1) ++ @@ -47,10 +58,13 @@ class RoccRocketConfig extends Config( // DOC include start: JtagRocket class jtagRocketConfig extends Config( - new WithDTMTop ++ // use top with dtm - new freechips.rocketchip.subsystem.WithJtagDTM ++ // add jtag+DTM module to coreplex + new WithDTM ++ // use top with dtm + new WithNoGPIO ++ new WithBootROM ++ new WithUART ++ + new freechips.rocketchip.subsystem.WithJtagDTM ++ // add jtag+DTM module to coreplex + new freechips.rocketchip.subsystem.WithNoMMIOPort ++ + new freechips.rocketchip.subsystem.WithNoSlavePort ++ new freechips.rocketchip.subsystem.WithInclusiveCache ++ new freechips.rocketchip.subsystem.WithNBigCores(1) ++ new freechips.rocketchip.system.BaseConfig) @@ -58,100 +72,127 @@ class jtagRocketConfig extends Config( // DOC include start: DmiRocket class dmiRocketConfig extends Config( - new WithDTMTop ++ // use top with dtm + new WithDTM ++ // use top with dtm + new WithNoGPIO ++ new WithBootROM ++ new WithUART ++ + new freechips.rocketchip.subsystem.WithNoMMIOPort ++ + new freechips.rocketchip.subsystem.WithNoSlavePort ++ new freechips.rocketchip.subsystem.WithInclusiveCache ++ new freechips.rocketchip.subsystem.WithNBigCores(1) ++ new freechips.rocketchip.system.BaseConfig) // DOC include end: DmiRocket -// DOC include start: PWMRocketConfig -class PWMRocketConfig extends Config( - new WithPWMTop ++ // use top with tilelink-controlled PWM - new WithBootROM ++ +// DOC include start: GCDTLRocketConfig +class GCDTLRocketConfig extends Config( + new WithTSI ++ + new WithNoGPIO ++ new WithUART ++ - new freechips.rocketchip.subsystem.WithInclusiveCache ++ - new freechips.rocketchip.subsystem.WithNBigCores(1) ++ - new freechips.rocketchip.system.BaseConfig) -// DOC include end: PWMRocketConfig - -class PWMAXI4RocketConfig extends Config( - new WithPWMAXI4Top ++ // use top with axi4-controlled PWM + new WithGCD(useAXI4=false, useBlackBox=false) ++ // Use GCD Chisel, connect Tilelink new WithBootROM ++ - new WithUART ++ + new freechips.rocketchip.subsystem.WithNoMMIOPort ++ + new freechips.rocketchip.subsystem.WithNoSlavePort ++ new freechips.rocketchip.subsystem.WithInclusiveCache ++ new freechips.rocketchip.subsystem.WithNBigCores(1) ++ new freechips.rocketchip.system.BaseConfig) +// DOC include end: GCDTLRocketConfig -class GCDRocketConfig extends Config( // add MMIO GCD module - new WithGCDTop ++ - new WithBootROM ++ +// DOC include start: GCDAXI4BlackBoxRocketConfig +class GCDAXI4BlackBoxRocketConfig extends Config( + new WithTSI ++ new WithUART ++ + new WithNoGPIO ++ + new WithGCD(useAXI4=true, useBlackBox=true) ++ // Use GCD blackboxed verilog, connect by AXI4->Tilelink + new WithBootROM ++ + new freechips.rocketchip.subsystem.WithNoMMIOPort ++ + new freechips.rocketchip.subsystem.WithNoSlavePort ++ new freechips.rocketchip.subsystem.WithInclusiveCache ++ new freechips.rocketchip.subsystem.WithNBigCores(1) ++ new freechips.rocketchip.system.BaseConfig) +// DOC include end: GCDAXI4BlackBoxRocketConfig class SimBlockDeviceRocketConfig extends Config( + new WithTSI ++ + new WithNoGPIO ++ new testchipip.WithBlockDevice ++ // add block-device module to peripherybus - new WithSimBlockDeviceTop ++ // use top with block-device IOs and connect to simblockdevice + new WithSimBlockDevice ++ // use top with block-device IOs and connect to simblockdevice new WithBootROM ++ new WithUART ++ + new freechips.rocketchip.subsystem.WithNoMMIOPort ++ + new freechips.rocketchip.subsystem.WithNoSlavePort ++ new freechips.rocketchip.subsystem.WithInclusiveCache ++ new freechips.rocketchip.subsystem.WithNBigCores(1) ++ new freechips.rocketchip.system.BaseConfig) class BlockDeviceModelRocketConfig extends Config( + new WithTSI ++ + new WithNoGPIO ++ new testchipip.WithBlockDevice ++ // add block-device module to periphery bus - new WithBlockDeviceModelTop ++ // use top with block-device IOs and connect to a blockdevicemodel + new WithBlockDeviceModel ++ // use top with block-device IOs and connect to a blockdevicemodel new WithBootROM ++ new WithUART ++ + new freechips.rocketchip.subsystem.WithNoMMIOPort ++ + new freechips.rocketchip.subsystem.WithNoSlavePort ++ new freechips.rocketchip.subsystem.WithInclusiveCache ++ new freechips.rocketchip.subsystem.WithNBigCores(1) ++ new freechips.rocketchip.system.BaseConfig) // DOC include start: GPIORocketConfig class GPIORocketConfig extends Config( + new WithTSI ++ new WithGPIO ++ // add GPIOs to the peripherybus - new WithGPIOTop ++ // use top with GPIOs new WithBootROM ++ new WithUART ++ + new freechips.rocketchip.subsystem.WithNoMMIOPort ++ + new freechips.rocketchip.subsystem.WithNoSlavePort ++ new freechips.rocketchip.subsystem.WithInclusiveCache ++ new freechips.rocketchip.subsystem.WithNBigCores(1) ++ new freechips.rocketchip.system.BaseConfig) // DOC include end: GPIORocketConfig class DualCoreRocketConfig extends Config( - new WithTop ++ + new WithTSI ++ new WithBootROM ++ new WithUART ++ + new WithNoGPIO ++ + new freechips.rocketchip.subsystem.WithNoMMIOPort ++ + new freechips.rocketchip.subsystem.WithNoSlavePort ++ new freechips.rocketchip.subsystem.WithInclusiveCache ++ new freechips.rocketchip.subsystem.WithNBigCores(2) ++ // dual-core (2 RocketTiles) new freechips.rocketchip.system.BaseConfig) class RV32RocketConfig extends Config( - new WithTop ++ + new WithTSI ++ + new WithNoGPIO ++ new WithBootROM ++ new WithUART ++ + new freechips.rocketchip.subsystem.WithNoMMIOPort ++ + new freechips.rocketchip.subsystem.WithNoSlavePort ++ new freechips.rocketchip.subsystem.WithInclusiveCache ++ new freechips.rocketchip.subsystem.WithRV32 ++ // set RocketTiles to be 32-bit new freechips.rocketchip.subsystem.WithNBigCores(1) ++ new freechips.rocketchip.system.BaseConfig) class GB1MemoryRocketConfig extends Config( - new WithTop ++ + new WithTSI ++ + new WithNoGPIO ++ new WithBootROM ++ new WithUART ++ + new freechips.rocketchip.subsystem.WithNoMMIOPort ++ + new freechips.rocketchip.subsystem.WithNoSlavePort ++ new freechips.rocketchip.subsystem.WithInclusiveCache ++ - new freechips.rocketchip.subsystem.WithExtMemSize((1<<30) * 1L) ++ // use 2GB simulated external memory + new freechips.rocketchip.subsystem.WithExtMemSize((1<<30) * 1L) ++ // use 1GB simulated external memory new freechips.rocketchip.subsystem.WithNBigCores(1) ++ new freechips.rocketchip.system.BaseConfig) // DOC include start: Sha3Rocket class Sha3RocketConfig extends Config( - new WithTop ++ + new WithTSI ++ + new WithNoGPIO ++ new WithBootROM ++ new WithUART ++ + new freechips.rocketchip.subsystem.WithNoMMIOPort ++ + new freechips.rocketchip.subsystem.WithNoSlavePort ++ new freechips.rocketchip.subsystem.WithInclusiveCache ++ new sha3.WithSha3Accel ++ // add SHA3 rocc accelerator new freechips.rocketchip.subsystem.WithNBigCores(1) ++ @@ -160,10 +201,13 @@ class Sha3RocketConfig extends Config( // DOC include start: InitZeroRocketConfig class InitZeroRocketConfig extends Config( - new WithInitZero(0x88000000L, 0x1000L) ++ - new WithInitZeroTop ++ + new WithInitZero(0x88000000L, 0x1000L) ++ // add InitZero + new WithNoGPIO ++ + new WithTSI ++ new WithBootROM ++ new WithUART ++ + new freechips.rocketchip.subsystem.WithNoMMIOPort ++ + new freechips.rocketchip.subsystem.WithNoSlavePort ++ new freechips.rocketchip.subsystem.WithInclusiveCache ++ new freechips.rocketchip.subsystem.WithNBigCores(1) ++ new freechips.rocketchip.system.BaseConfig) @@ -171,9 +215,11 @@ class InitZeroRocketConfig extends Config( class LoopbackNICRocketConfig extends Config( new WithIceNIC ++ - new WithLoopbackNICTop ++ + new WithLoopbackNIC ++ new WithBootROM ++ new WithUART ++ + new freechips.rocketchip.subsystem.WithNoMMIOPort ++ + new freechips.rocketchip.subsystem.WithNoSlavePort ++ new freechips.rocketchip.subsystem.WithInclusiveCache ++ new freechips.rocketchip.subsystem.WithNBigCores(1) ++ new freechips.rocketchip.system.BaseConfig) diff --git a/generators/example/src/main/scala/TestHarness.scala b/generators/example/src/main/scala/TestHarness.scala index 3eaa05e29d..b811af378c 100644 --- a/generators/example/src/main/scala/TestHarness.scala +++ b/generators/example/src/main/scala/TestHarness.scala @@ -10,12 +10,22 @@ import freechips.rocketchip.config.{Field, Parameters} import freechips.rocketchip.util.GeneratorApp import freechips.rocketchip.devices.debug.{Debug} +/** + * TODO: Why do we need this? + */ +import ConfigValName._ + // ------------------------------- // BOOM and/or Rocket Test Harness // ------------------------------- -case object BuildTop extends Field[(Clock, Bool, Parameters) => TopModule[Top]] -case object BuildTopWithDTM extends Field[(Clock, Bool, Parameters) => TopWithDTMModule[TopWithDTM]] +case object BuildTop extends Field[(Clock, Bool, Parameters, Bool) => TopModule[Top]]( + (clock: Clock, reset: Bool, p: Parameters, success: Bool) => { + val top = Module(LazyModule(new Top()(p)).module) + top.debug.map { debug => debug := DontCare } + top + } +) /** * Test harness using TSI to bringup the system @@ -28,45 +38,8 @@ class TestHarness(implicit val p: Parameters) extends Module { // force Chisel to rename module override def desiredName = "TestHarness" - val dut = p(BuildTop)(clock, reset.toBool, p) - - dut.debug.foreach(_ := DontCare) - dut.connectSimAXIMem() - dut.connectSimAXIMMIO() - dut.dontTouchPorts() - dut.tieOffInterrupts() - dut.l2_frontend_bus_axi4.foreach(axi => { - axi.tieoff() - experimental.DataMirror.directionOf(axi.ar.ready) match { - case core.ActualDirection.Input => - axi.r.bits := DontCare - axi.b.bits := DontCare - case core.ActualDirection.Output => - axi.aw.bits := DontCare - axi.ar.bits := DontCare - axi.w.bits := DontCare - } - }) + val dut = p(BuildTop)(clock, reset.toBool, p, io.success) dut.connectSimUARTs() - - io.success := dut.connectSimSerial() -} - -/** - * Test harness using the Debug Test Module (DTM) to bringup the system - */ -class TestHarnessWithDTM(implicit p: Parameters) extends Module -{ - val io = IO(new Bundle { - val success = Output(Bool()) - }) - - // force Chisel to rename module - override def desiredName = "TestHarness" - - val dut = p(BuildTopWithDTM)(clock, reset.toBool, p) - - dut.reset := reset.asBool | dut.debug.get.ndreset dut.connectSimAXIMem() dut.connectSimAXIMMIO() dut.dontTouchPorts() @@ -84,5 +57,4 @@ class TestHarnessWithDTM(implicit p: Parameters) extends Module } }) - Debug.connectDebug(dut.debug, dut.psd, clock, reset.asBool, io.success) } diff --git a/generators/example/src/main/scala/Top.scala b/generators/example/src/main/scala/Top.scala index defb4ef42d..cd22237926 100644 --- a/generators/example/src/main/scala/Top.scala +++ b/generators/example/src/main/scala/Top.scala @@ -15,103 +15,33 @@ import utilities.{System, SystemModule} import sifive.blocks.devices.gpio._ import sifive.blocks.devices.uart._ -import icenet.{HasPeripheryIceNIC, HasPeripheryIceNICModuleImp} +import icenet.{CanHavePeripheryIceNIC, CanHavePeripheryIceNICModuleImp} // ------------------------------------ // BOOM and/or Rocket Top Level Systems // ------------------------------------ +// DOC include start: Top class Top(implicit p: Parameters) extends System - with HasNoDebug - with HasPeripherySerial - with CanHavePeripheryUARTWithAdapter { + with CanHavePeripheryUARTAdapter // Enables optionally adding the UART print adapter + with HasPeripheryUART // Enables optionally adding the sifive UART + with HasPeripheryGPIO // Enables optionally adding the sifive GPIOs + with CanHavePeripheryBlockDevice // Enables optionally adding the block device + with CanHavePeripheryInitZero // Enables optionally adding the initzero example widget + with CanHavePeripheryGCD // Enables optionally adding the GCD example widget + with CanHavePeripherySerial // Enables optionally adding the TSI serial-adapter and port + with CanHavePeripheryIceNIC // Enables optionally adding the IceNIC for firesim +{ override lazy val module = new TopModule(this) } class TopModule[+L <: Top](l: L) extends SystemModule(l) - with HasNoDebugModuleImp - with HasPeripherySerialModuleImp - with CanHavePeripheryUARTWithAdapterImp - with DontTouch - -//--------------------------------------------------------------------------------------------------------- -// DOC include start: TopWithPWMTL - -class TopWithPWMTL(implicit p: Parameters) extends Top - with HasPeripheryPWMTL { - override lazy val module = new TopWithPWMTLModule(this) -} - -class TopWithPWMTLModule(l: TopWithPWMTL) extends TopModule(l) - with HasPeripheryPWMTLModuleImp - -// DOC include end: TopWithPWMTL -//--------------------------------------------------------------------------------------------------------- - -class TopWithPWMAXI4(implicit p: Parameters) extends Top - with HasPeripheryPWMAXI4 { - override lazy val module = new TopWithPWMAXI4Module(this) -} - -class TopWithPWMAXI4Module(l: TopWithPWMAXI4) extends TopModule(l) - with HasPeripheryPWMAXI4ModuleImp - -//--------------------------------------------------------------------------------------------------------- - -class TopWithGCD(implicit p: Parameters) extends Top - with HasPeripheryGCD { - override lazy val module = new TopWithGCDModule(this) -} - -class TopWithGCDModule(l: TopWithGCD) extends TopModule(l) - with HasPeripheryGCDModuleImp - -//--------------------------------------------------------------------------------------------------------- - -class TopWithBlockDevice(implicit p: Parameters) extends Top - with HasPeripheryBlockDevice { - override lazy val module = new TopWithBlockDeviceModule(this) -} - -class TopWithBlockDeviceModule(l: TopWithBlockDevice) extends TopModule(l) - with HasPeripheryBlockDeviceModuleImp - -//--------------------------------------------------------------------------------------------------------- - -class TopWithGPIO(implicit p: Parameters) extends Top - with HasPeripheryGPIO { - override lazy val module = new TopWithGPIOModule(this) -} - -class TopWithGPIOModule(l: TopWithGPIO) - extends TopModule(l) with HasPeripheryGPIOModuleImp - -//--------------------------------------------------------------------------------------------------------- - -class TopWithDTM(implicit p: Parameters) extends System -{ - override lazy val module = new TopWithDTMModule(this) -} - -class TopWithDTMModule[+L <: TopWithDTM](l: L) extends SystemModule(l) - -//--------------------------------------------------------------------------------------------------------- -// DOC include start: TopWithInitZero -class TopWithInitZero(implicit p: Parameters) extends Top - with HasPeripheryInitZero { - override lazy val module = new TopWithInitZeroModuleImp(this) -} - -class TopWithInitZeroModuleImp(l: TopWithInitZero) extends TopModule(l) - with HasPeripheryInitZeroModuleImp -// DOC include end: TopWithInitZero - -class TopWithIceNIC(implicit p: Parameters) extends Top - with HasPeripheryIceNIC { - override lazy val module = new TopWithIceNICModule(this) -} - -class TopWithIceNICModule(outer: TopWithIceNIC) - extends TopModule(outer) - with HasPeripheryIceNICModuleImp + with HasPeripheryUARTModuleImp + with CanHavePeripheryBlockDeviceModuleImp + with CanHavePeripheryGCDModuleImp + with CanHavePeripherySerialModuleImp + with CanHavePeripheryIceNICModuleImp + with CanHavePeripheryUARTAdapterModuleImp + with DontTouch +// DOC include end: Top diff --git a/generators/firechip/src/main/scala/BridgeBinders.scala b/generators/firechip/src/main/scala/BridgeBinders.scala index c3a6ca80cd..f0c9c664ed 100644 --- a/generators/firechip/src/main/scala/BridgeBinders.scala +++ b/generators/firechip/src/main/scala/BridgeBinders.scala @@ -10,7 +10,7 @@ import freechips.rocketchip.devices.debug.HasPeripheryDebugModuleImp import freechips.rocketchip.subsystem.{CanHaveMasterAXI4MemPortModuleImp} import sifive.blocks.devices.uart.HasPeripheryUARTModuleImp -import testchipip.{HasPeripherySerialModuleImp, HasPeripheryBlockDeviceModuleImp} +import testchipip.{CanHavePeripherySerialModuleImp, CanHavePeripheryBlockDeviceModuleImp} import icenet.HasPeripheryIceNICModuleImpValidOnly import junctions.{NastiKey, NastiParameters} @@ -32,19 +32,19 @@ class WithTiedOffDebug extends RegisterBridgeBinder({ case target: HasPeripheryD }) class WithSerialBridge extends RegisterBridgeBinder({ - case target: HasPeripherySerialModuleImp => Seq(SerialBridge(target.serial)(target.p)) + case target: CanHavePeripherySerialModuleImp => Seq(SerialBridge(target.serial.get)(target.p)) }) class WithNICBridge extends RegisterBridgeBinder({ - case target: HasPeripheryIceNICModuleImpValidOnly => Seq(NICBridge(target.net)(target.p)) + case target: HasPeripheryIceNICModuleImpValidOnly => Seq(NICBridge(target.net)(target.p)) }) class WithUARTBridge extends RegisterBridgeBinder({ - case target: HasPeripheryUARTModuleImp => target.uart.map(u => UARTBridge(u)(target.p)) + case target: HasPeripheryUARTModuleImp => target.uart.map(u => UARTBridge(u)(target.p)) }) class WithBlockDeviceBridge extends RegisterBridgeBinder({ - case target: HasPeripheryBlockDeviceModuleImp => Seq(BlockDevBridge(target.bdev, target.reset.toBool)(target.p)) + case target: CanHavePeripheryBlockDeviceModuleImp => Seq(BlockDevBridge(target.bdev.get, target.reset.toBool)(target.p)) }) class WithFASEDBridge extends RegisterBridgeBinder({ diff --git a/generators/firechip/src/main/scala/TargetConfigs.scala b/generators/firechip/src/main/scala/TargetConfigs.scala index 4cb0b99036..23c21e7c1a 100644 --- a/generators/firechip/src/main/scala/TargetConfigs.scala +++ b/generators/firechip/src/main/scala/TargetConfigs.scala @@ -12,7 +12,7 @@ import freechips.rocketchip.subsystem._ import freechips.rocketchip.devices.tilelink.BootROMParams import freechips.rocketchip.devices.debug.{DebugModuleParams, DebugModuleKey} import boom.common.BoomTilesKey -import testchipip.{BlockDeviceKey, BlockDeviceConfig} +import testchipip.{BlockDeviceKey, BlockDeviceConfig, SerialKey} import sifive.blocks.devices.uart.{PeripheryUARTKey, UARTParams} import scala.math.{min, max} import tracegen.TraceGenKey @@ -47,6 +47,10 @@ class WithUARTKey extends Config((site, here, up) => { nRxEntries = 256)) }) +class WithSerial extends Config((site, here, up) => { + case SerialKey => true +}) + class WithBlockDevice extends Config(new testchipip.WithBlockDevice) class WithNICKey extends Config((site, here, up) => { @@ -112,6 +116,7 @@ class FireSimRocketChipConfig extends Config( new WithoutTLMonitors ++ new WithUARTKey ++ new WithNICKey ++ + new WithSerial ++ new WithBlockDevice ++ new WithRocketL2TLBs(1024) ++ new WithPerfCounters ++ @@ -169,6 +174,7 @@ class FireSimBoomConfig extends Config( new WithoutTLMonitors ++ new WithUARTKey ++ new WithNICKey ++ + new WithSerial ++ new WithBlockDevice ++ new WithBoomL2TLBs(1024) ++ new WithoutClockGating ++ diff --git a/generators/firechip/src/main/scala/Targets.scala b/generators/firechip/src/main/scala/Targets.scala index 4c79019535..b608e67bd2 100644 --- a/generators/firechip/src/main/scala/Targets.scala +++ b/generators/firechip/src/main/scala/Targets.scala @@ -42,10 +42,10 @@ class FireSimDUT(implicit p: Parameters) extends Subsystem with HasHierarchicalBusTopology with CanHaveMasterAXI4MemPort with HasPeripheryBootROM - with HasPeripherySerial + with CanHavePeripherySerial with HasPeripheryUART - with HasPeripheryIceNIC - with HasPeripheryBlockDevice + with CanHavePeripheryIceNIC + with CanHavePeripheryBlockDevice with HasTraceIO { override lazy val module = new FireSimModuleImp(this) @@ -55,10 +55,10 @@ class FireSimModuleImp[+L <: FireSimDUT](l: L) extends SubsystemModuleImp(l) with HasRTCModuleImp with CanHaveMasterAXI4MemPortModuleImp with HasPeripheryBootROMModuleImp - with HasPeripherySerialModuleImp + with CanHavePeripherySerialModuleImp with HasPeripheryUARTModuleImp with HasPeripheryIceNICModuleImpValidOnly - with HasPeripheryBlockDeviceModuleImp + with CanHavePeripheryBlockDeviceModuleImp with HasTraceIOImp with CanHaveMultiCycleRegfileImp @@ -68,9 +68,9 @@ class FireSimNoNICDUT(implicit p: Parameters) extends Subsystem with HasHierarchicalBusTopology with CanHaveMasterAXI4MemPort with HasPeripheryBootROM - with HasPeripherySerial + with CanHavePeripherySerial with HasPeripheryUART - with HasPeripheryBlockDevice + with CanHavePeripheryBlockDevice with HasTraceIO { override lazy val module = new FireSimNoNICModuleImp(this) @@ -80,9 +80,9 @@ class FireSimNoNICModuleImp[+L <: FireSimNoNICDUT](l: L) extends SubsystemModule with HasRTCModuleImp with CanHaveMasterAXI4MemPortModuleImp with HasPeripheryBootROMModuleImp - with HasPeripherySerialModuleImp + with CanHavePeripherySerialModuleImp with HasPeripheryUARTModuleImp - with HasPeripheryBlockDeviceModuleImp + with CanHavePeripheryBlockDeviceModuleImp with HasTraceIOImp with CanHaveMultiCycleRegfileImp @@ -107,12 +107,11 @@ class FireSimSupernode(implicit p: Parameters) extends DefaultFireSimHarness(() // Verilog blackbox integration demo class FireSimVerilogGCDDUT(implicit p: Parameters) extends FireSimDUT - with example.HasPeripheryGCD + with example.CanHavePeripheryGCD { override lazy val module = new FireSimVerilogGCDModuleImp(this) } class FireSimVerilogGCDModuleImp[+L <: FireSimVerilogGCDDUT](l: L) extends FireSimModuleImp(l) - with example.HasPeripheryGCDModuleImp class FireSimVerilogGCD(implicit p: Parameters) extends DefaultFireSimHarness(() => new FireSimVerilogGCDDUT) diff --git a/generators/icenet b/generators/icenet index 87b3bf5e46..b560a46f04 160000 --- a/generators/icenet +++ b/generators/icenet @@ -1 +1 @@ -Subproject commit 87b3bf5e46da3db6f9a653fdd6786699c075bff3 +Subproject commit b560a46f048ceb0b613195f4627cc3fdffc5cfe4 diff --git a/generators/testchipip b/generators/testchipip index db01ac1514..62cf2629a7 160000 --- a/generators/testchipip +++ b/generators/testchipip @@ -1 +1 @@ -Subproject commit db01ac1514d68fe55af2eb8f5bffb52da596ed75 +Subproject commit 62cf2629a7f2df054224c7dfbb9ff84b9e2b1203 diff --git a/sims/firesim b/sims/firesim index d799550b42..5f6bd4fa16 160000 --- a/sims/firesim +++ b/sims/firesim @@ -1 +1 @@ -Subproject commit d799550b42c4bf0a1030cf93dde3a27263bfcc95 +Subproject commit 5f6bd4fa16af5d2fc15c49b54358f57dbd2c1469 diff --git a/variables.mk b/variables.mk index a303eafe37..a74b3b806c 100644 --- a/variables.mk +++ b/variables.mk @@ -135,7 +135,8 @@ sim_common_files ?= $(build_dir)/sim_files.common.f # java arguments used in sbt ######################################################################################### JAVA_HEAP_SIZE ?= 8G -JAVA_ARGS ?= -Xmx$(JAVA_HEAP_SIZE) -Xss8M -XX:MaxPermSize=256M +JAVA_ARGS ?= -Xmx$(JAVA_HEAP_SIZE) -Xss8M -XX:MaxPermSize=256M -Dsbt.ivy.home=/scratch/jerryz/.ivy2 -Dsbt.global.base=/scratch/jerryz/.sbt + ######################################################################################### # default sbt launch command