SoCeteer - A framework for designing and running RISC-V-based SoCs on FPGA and in Simulation, built on top of Chisel.
Important
This project is in early development and is NOT ready for any serious use. We recomment using SoCeteer for experimentation and learning purposes only at this time. For a more stable experience, please use the tagged releases.
Note
Please take a look at Known Issues for a list of current limitations and issues. Feel free to open issues and contribute to the project if you find any problems or have ideas for improvements!
-
Included generators contain: RocketChip, BOOM, Gemmini and more!
-
Emit designs for Simulation using Verilator, FPGA synthesis using Vivado and Yosys-based flows for open-source FPGA toolchains (in development)
-
Built-in Vivado Block Design DSL: Describe Vivado IP block designs directly in Scala - components, ports, connections, clock domains, timing constraints and TCL generation, all without hand-writing TCL
-
Support for edu.berkeley.cs.chisel (3.6.1) and org.chipsalliance.chisel (7.11.0)
-
CMake projects for building bootroms and binaries to run on the generated designs (both in simulation and on FPGA)
-
Very fast design generation (several times faster than other SoC builders)
-
Docker images available for easy setup and use, with support for both x86_64 and ARM64 hosts (including Apple Silicon)
-
Runs natively on Linux, macOS(ARM / x86_64), and Windows
The recommended way to use SoCeteer is via IntelliJ IDEA with the Scala plugin, which provides excellent support for sbt projects. However, you can also use it via the command line (CLI) with sbt (either in a docker container or natively).
- Clone the repository with recursive submodules to get the included generators and other dependencies.
# Clone the main branch with submodules:
git clone --recurse-submodules https://github.com/soct-org/SoCeteer.git
# Clone the latest release with submodules:
git clone --recurse-submodules --branch v<latest-version> https://github.com/soct-org/SoCeteer.git
# If already cloned without --recurse-submodules:
git submodule update --init --recursiveNext, ensure you have the necessary tools installed. For a full setup refer to the Dockerfile.
- IntelliJ IDEA: Install the Scala plugin and set a JDK 11+ (
File -> Project Structure -> SDK). - CLI: Install Java 11+ and SBT. Ensure
javaandsbtare in your systemPATH.
The following tools are required for building bootroms/binaries, compiling device trees, and compiling Verilator for simulation:
- CMake & Ninja: For building C/C++ projects.
- Device Tree Compiler (dtc): For compiling
.dtsto.dtb. - Flex & Bison: Required by Verilator.
# Ubuntu/Debian
sudo apt-get install cmake ninja-build device-tree-compiler flex bison
# Arch Linux
sudo pacman -S cmake ninja dtc flex bison
# macOS
brew install cmake ninja dtc flex bison
# Windows (via Chocolatey)
choco install cmake ninja dtc-msys2 winflexbison3The following tools are automatically downloaded or built when running SoCeteer:
- RISC-V Toolchain (xpack-dev-tools): For compiling RISC-V programs and bootroms.
- Verilator (for Simulation): A maintained submodule is built automatically during the first simulation run. (Windows requires Visual Studio 2022 and MinGW).
Running SoCeteer with --target verilator elaborates the Chisel design and emits Verilog into the output directory.
The CMake project in sim then verilates that Verilog and compiles a C++ harness
(using main.cpp, dpi-c.cpp, FESVR, and the RISC-V ISA disassembler) into a native simulator binary.
The simulator loads a RISC-V ELF, communicates with the program's syscalls via FESVR (Front-End Server)
over the Debug Transport Module (DTM) using DPI-C, and exits when the program calls tohost.
A remote JTAG bitbang interface (port 1337) is also exposed for live debugging with OpenOCD/GDB.
SoCeteer emits a SOCTSystem.cmake file at workspace/RocketB1-64/sim/SOCTSystem.cmake alongside the Verilog.
This file contains CMake variables (architecture, core count, ABI, source paths, etc.) consumed by both the
simulator CMake project and the binaries CMake project - so neither needs to be reconfigured between designs.
# Emit the simulation design:
sbt "runMain soct.SOCTLauncher --target verilator [options]"Key simulation options (pass --help for a full list):
| Option | Description |
|---|---|
--config <class> |
Generator config class (default: soct.RocketB1). |
--xlen 32/64 |
RISC-V word width (default: 64). |
--core-freq-mhz <f> |
Sets all bus clock frequencies in MHz (default: 100). |
--periphery-freq-mhz <f> |
Periphery bus frequency in MHz (default: 100). |
--out-dir <path> |
Output directory (default: workspace subdirectory). |
The simulator CMake project (sim) accepts the following CMake variables:
| Variable | Description |
|---|---|
SOCT_SYSTEM |
(Required) Path to the emitted SOCTSystem.cmake file. |
VL_THREADS |
Number of Verilator threads (default: SOCT_NCPUS + 1). |
VL_TRACE |
Enable VCD waveform tracing (off by default). |
VL_TRACE_DEPTH |
Hierarchy depth limit for tracing (default: 2). |
PASS_UNKNOWN_SYSCALLS |
Forward unknown syscalls to the host OS. |
ENABLE_TRACE |
Enable TRACE-level simulator log output. |
FORCE_ASSERTS |
Enable assertions in release builds. |
# Run the simulator (pass ELF as first positional argument):
workspace/RocketB1-64/sim/build/sim-build/simulator <elf> [options]| Option | Description |
|---|---|
<elf> |
RISC-V ELF binary to run. |
--reset-cycles=<n> |
Number of reset cycles before releasing reset (default: 100). |
--log-level=<level> |
Log level: trace, debug, info, warn, error. |
--log-file=<path> |
Write simulator logs to a file. |
--all2console |
Mirror all log output to the console regardless of level. |
--vcd-file=<path> |
VCD output path when VL_TRACE is enabled (default: dump.vcd). |
IntelliJ IDEA / CLion: Run the main method in ./src/main/scala/soct/SOCTLauncher.scala to emit the design, then open
binaries and sim as separate CLion projects and add -DSOCT_SYSTEM=workspace/RocketB1-64/sim/SOCTSystem.cmake to CMake options.
CLI:
# 1. Emit the design
sbt "runMain soct.SOCTLauncher"
# Or via Docker:
# docker run --rm -it -u $(id -u):$(id -g) -v "$PWD":/soceteer -w /soceteer ghcr.io/soct-org/soceteer:latest bash
# 2. Build the example binary
mkdir -p workspace/RocketB1-64/sim/build/prog-build
cmake -S binaries -B workspace/RocketB1-64/sim/build/prog-build -DSOCT_SYSTEM=workspace/RocketB1-64/sim/SOCTSystem.cmake
cmake --build workspace/RocketB1-64/sim/build/prog-build --target hello-hart
# 3. Build and run the Verilator simulator
mkdir -p workspace/RocketB1-64/sim/build/sim-build
cmake -S sim -B workspace/RocketB1-64/sim/build/sim-build -DCMAKE_BUILD_TYPE=Release -DSOCT_SYSTEM=workspace/RocketB1-64/sim/SOCTSystem.cmake
cmake --build workspace/RocketB1-64/sim/build/sim-build
workspace/RocketB1-64/sim/build/sim-build/simulator workspace/RocketB1-64/sim/elfs/hello-hart.elfAfter running the launcher with --target verilator, the output directory contains:
- Verilog source files (
*.v/*.sv) for the full SoC SOCTSystem.cmake- CMake variables for arch, core count, paths, ABI, etc.- FIRRTL intermediate files (low FIRRTL + optimised Verilog)
- Device tree source (
.dts) and blob (.dtb) - Register map files
The Simulation Tests show all supported configurations. The GitHub Workflow shows the full native setup for Windows, Linux and macOS.
SoCeteer targets Xilinx FPGAs via Vivado. It emits Verilog, a Vivado block design (TCL), timing constraints (XDC), and optionally runs Vivado to generate the project automatically.
- Vivado: Required for synthesis. Download from here.
- Supported boards: ZCU104 - add new boards by extending
FPGAand registering inFPGARegistry.
# Emit a design for the ZCU104 board and (optionally) run Vivado to create the project:
sbt "runMain soct.SOCTLauncher --target vivado --board ZCU104 --vivado /path/to/vivado [options]"Key options for Vivado synthesis:
| Option | Description |
|---|---|
--board <name> |
Target FPGA board (required). Available: ZCU104 |
--vivado <path> |
Path to the vivado executable. If omitted, only the TCL/Verilog files are emitted. |
--core-freq-mhz <f> |
Core/bus frequency in MHz (default: 100). |
--periphery-freq-mhz <f> |
Periphery bus frequency in MHz (default: 100). |
--no-override-vivado-project |
Do not overwrite an existing Vivado project in the output directory. |
--remote-dir <path> |
Sync design files and run Vivado on a remote machine (requires --ssh-config). |
--ssh-config <name> |
OpenSSH config entry to use for remote Vivado. |
--use-remote-vivado |
Treat the --vivado path as a path on the remote machine. |
After running, the output directory contains:
- Verilog source files (top-level
.v+ supporting modules) SOCTSystem.cmake- CMake variables for arch, core count, paths, ABI, etc. (same as simulation)init.tcl- Vivado project initialisation scriptbd.tcl- Block design TCL (AXI interconnect, clocks, DDR4, UART, JTAG, etc.)synth.tcl- Synthesis run scripttiming.tcl- Timing constraintsxdc/- Per-component XDC constraint files- Device tree source (
.dts) and blob (.dtb) - Register map files
SoCeteer includes a Scala-embedded DSL for describing Vivado IP block designs (soct.system.vivado). Rather than
hand-writing TCL scripts, you compose a design programmatically:
- Components (
soct.system.vivado.components) - pre-built wrappers for common Xilinx IPs: AXI SmartConnect, ClkWiz, DDR4, UART Lite, JTAG, Proc System Reset, SD Card PMOD, and more. - Connections & Ports - typed pin/port abstractions handle signal connections, clock domains, and resets.
- FPGA targets (
soct.system.vivado.fpga) - board-specific definitions (e.g. ZCU104). Add new boards by extendingFPGA. - TCL generation - the
SOCTBdBuildertraverses the design graph and emits the TCL commands needed to recreate the block design in Vivado.
Custom components can be added by extending BdComp and implementing the TCL emission logic.
- Every time SoCeteer emits a design it creates (or updates) a symbolic link at the project root
SOCTSystem-latest.cmakepointing to the latest emittedSOCTSystem.cmake. All CMake projects in the repository use this if no explicit SOCT_SYSTEM variable is provided. - The firtool binary needed for Chisel is only available for x86_64 architecture, requiring Rosetta to run on ARM64 hosts. Make sure it is installed and configured correctly.
To force installation run
softwareupdate --install-rosetta --agree-to-licensein the terminal. - If you are using Docker via CLI, we recommend not opening the project in an IDE as it may cause issues with file permissions and generated files. Rather use two separate cloned repositories - one for CLI usage via Docker and one for IDE usage.
- If UART to the board fails, close the Vivado hardware manager. Sometimes the /dev/ttyUSB* disappears where
udevadm triggercan help. We also advice against using USB hubs for the board connection as they can cause issues with the serial connection.