Rocket Chip Documentation
repository·master·Indexed 26 days ago
https://github.com/chipsalliance/rocket-chipA Scala-based generator using the Chisel hardware construction language to instantiate the RISC-V Rocket Core and complete SoC designs. Includes documentation on the Diplomacy parameter negotiation framework, LazyModule patterns, AXI4 interface definitions (AXI4Bundle, AXI4AsyncBundle, AXI4CreditedBundle), and the Debug Module Interface (DMI) protocol.
What's inside Rocket Chip
- Diplomacy is a parameter negotiation framework used in Rocket Chip to generate parameterized protocol implementations. It allows different components of a hardware design to negotiate parameters (such as bus widths, address maps, or protocol features) before the final hardware structure is instantiated. This walkthrough demonstrates these concepts by building a simple parameterized adder.
Generate Verilog from Rocket Chip
masterUsemaketo invoke the Chisel compiler and generate Verilog RTL. You can generate a default Verilog output or specify a particular configuration using theCONFIGvariable.Connect Diplomacy nodes using binding operators
masterTo complete a Diplomacy graph, you must bind nodes together in a top-level module (often a
LazyModuleacting as a testbench). The most common binding operator is:=.- Directionality: Sinks are typically placed on the left-hand side, and sources on the right-hand side (e.g.,
sinkNode := sourceNode). - Binding multiple nodes: You can iterate through sequences of nodes to establish multiple connections between modules.
- Directionality: Sinks are typically placed on the left-hand side, and sources on the right-hand side (e.g.,
Configure IDE support (IntelliJ and VSCode) using Mill and Nix
masterRocket Chip uses
millas its build tool andnixto configure the development environment. Follow these steps to enable language server support in your IDE.- Install
nixfor your OS. - Generate the BSP configuration:
mill mill.bsp.BSP/install - Patch the
.bsp/mill-bsp.jsonfile. Change theargvarray to usenix developso the IDE runs Mill within the Nix environment.
For IntelliJ:
- Install the Scala plugin.
- If BSP doesn't run automatically, click
bspin the right sidebar and right-click your project to reload.
For VSCode:
- Install the Metals extension.
- Run the command
Metals: Import build.
- Install
Update Rocket Chip and Submodules
masterTo keep your local repository up-to-date with the upstream master branch, pull the latest changes and recursively update the submodules.
If the
rocket-toolsversion has changed, you must recompile and install it by running the build scripts within therocket-toolsdirectory.Generate documentation using mdoc
masterThe documentation in this repository is partially generated from source files using
mdoc. To generate the documentation, ensure you are in the repository's root directory and run thedocs/mdoccommand from SBT.The resulting documentation will be output to the
generatedfolder.Use the Rocket Chip Select library for LazyModules
masterWhile Chisel provides aSelectlibrary for finding hardware nodes, it can be fragile when used with Diplomacy because Diplomacy abstracts away much of the underlying Chisel hardware. Rocket Chip provides its ownSelectlibrary designed specifically to operate onLazyModules andNodes instead ofModules andWires. This library allows you to traverse and query the hierarchy of your Diplomacy design.Define hardware using LazyModule and LazyModuleImp
masterBecause Diplomacy performs parameter negotiation lazily after the graph is constructed, hardware must be defined using the
LazyModulepattern:- Extend
LazyModuleto define the module structure and its Diplomacy nodes. - Define the actual Chisel hardware inside a
lazy val module = new LazyModuleImp(this) { ... }block. - Inside
LazyModuleImp, you can access negotiated parameters via the nodes (e.g.,node.inornode.out) to parameterize Chisel wires, bundles, and logic.
class Adder(implicit p: Parameters) extends LazyModule { val node = new AdderNode(...) // Define node here lazy val module = new LazyModuleImp(this) { require(node.in.size >= 2) node.out.head._1 := node.in.unzip._1.reduce(_ + _) } override lazy val desiredName = "Adder" }- Extend
Install and Checkout Rocket Chip
masterTo use the Rocket Chip generator, clone the repository and initialize the required Git submodules.
Note: You must also install dependencies for
rocket-tools(see its specific README) andchisel3(see Chisel3 installation guides) to ensure a functional environment.$ git clone https://github.com/ucb-bar/rocket-chip.git $ cd rocket-chip $ git submodule update --initAdd external interrupts using HasAsyncExtInterrupts or HasSyncExtInterrupts
masterTo add externally driven interrupts to a
BaseSubsystem, use one of the following synchronization traits. Do not useHasExtInterruptsdirectly.HasAsyncExtInterrupts: Use this if the external interrupts have NOT yet been synchronized to the Periphery (PLIC) clock. It automatically wiresextInterruptstoibus.fromAsync.HasSyncExtInterrupts: Use this if the external interrupts have ALREADY been synchronized to the Periphery (PLIC) clock. It automatically wiresextInterruptstoibus.fromSync.
Force invalidating the riscv-tools or Verilator caches
masterRocket Chip uses GitHub Actions caching for
riscv-toolsandVerilator. While caches are automatically invalidated whenriscv-tools.hashorverilator.hashchanges, you can manually force an invalidation by incrementing the version number in the cache key within the workflow configuration.To invalidate a cache:
- Open
.github/workflows/continuous-integration.yml. - Find the job (e.g.,
prepare-riscv-tools-cache) containing theactions/cache@*step. - Locate the
keyproperty. The key ends with a version suffix like-v1. - Increment this number (e.g., change
-v1to-v2). - Crucially, find all other occurrences of that specific cache key within the same file and increment them to match the new version number.
- Commit and push the changes to trigger a new cache build.
- Open
Select nodes based on connectivity using Select.collectInwardEdges and Select.collectOutwardEdges
masterYou can select
LazyModules based on how they are connected in the design.Select.collectInwardEdges(node)(partialFunction): Applies the partial function to allInwardEdges of the specifiedBaseNode.Select.collectOutwardEdges(node)(partialFunction): Applies the partial function to allOutwardEdges of the specifiedBaseNode.
Note:
LazyModules also provide agetNodesmethod which returns all nodes instantiated within that module. This is often used in conjunction with theSelectedge collectors to find connected modules.// Find all Leaf modules in 'top' that are connected to an 'A' module // and do not belong to the 'foo:Foo' subhierarchy. Select.filterCollectDeep (top) { case _: Foo => false case _ => true } { case a: A => // Function.unlift used to convert `InwardEdge => Option[String]` to `PartialFunction[InwardEdge, String]` a.getNodes.flatMap(Select.collectInwardEdges(_)(Function.unlift { edge => edge.node.lazyModule match { case l: Leaf => Some(l.pathName) case _ => None } })) }