This page contains useful commands and tips on how to develop on the Mocha repository. It collects both design, software and verification instructions.
Install Nix:
curl --proto '=https' --tlsv1.2 -L https://nixos.org/nix/install | sh -s -- --daemonMake sure the experimental features "flakes" and "nix-command" are enabled by adding the following to /etc/nix/nix.conf or ~/.config/nix/nix.conf:
experimental-features = nix-command flakes
Enter the development shell that includes Python environment, CHERI compiler and more.
nix developAlternatively if you are using direnv then this can be automated by enabling direnv.
direnv allow .When entering the directory from then on you will automatically enter the dev shell. Changing directory outside the repository root will deactivate the dev shell for you.
Mocha software binaries are built using CMake.
To build all software binaries, run:
# Setup the buildsystem.
cmake -B build/sw -S sw
# Build the software.
cmake --build build/sw -j $(nproc)Outputs with the suffix "_sram" exist only for UVM-based tests, as they presently lack a DRAM backdoor-load mechanism.
The boot-ROM output with the "_scrambled" suffix is the only binary run through the ROM image scrambling script. Attempting to run any unscrambled binary from the scrambled ROM will be blocked by the in-hardware ROM checker.
For software written in C, clang-format and clang-tidy are used to format and lint the code.
Wrapper scripts to run these on all C files in the project are provided for convenience.
To format and lint, run:
# Format all C files.
util/clang_format.py
# Lint all C files.
util/clang_tidy.pyWe use Verilator to simulate our hardware design and use FuseSoC as a build system.
To build and run a Verilator simulation of Mocha, run:
# Build simulator.
fusesoc --cores-root=. run --target=sim --tool=verilator --setup --build lowrisc:mocha:top_chip_verilator --verilator_options="--threads 2 --trace-threads 2" --make_options="-j 4"
# Run simulator.
build/lowrisc_mocha_top_chip_verilator_0/sim-verilator/Vtop_chip_verilator -r build/sw/device/bootrom/bootrom_scrambled.vmem -E build/sw/device/examples/hello_world
# Check the UART output.
cat uart0.logNote that the -j 4 argument speeds up simulator building, while the --threads 2 --trace-threads 2 arguments speed up simulator running.
For maximum tracing performance, omit --threads 2.
For maximum non-tracing performance, or when using Verilator v5.048 onwards, omit --trace-threads 2.
One specific feature of our simulator is that you can exit the simulation by using the following magic string:
Safe to exit simulator.\xd8\xaf\xfb\xa0\xc7\xe1\xa9\xd7
To connect to the debug module:
# Run the simulator with a program that doesn't end.
build/lowrisc_mocha_top_chip_verilator_0/sim-verilator/Vtop_chip_verilator -r build/sw/device/bootrom/bootrom_scrambled.vmem -E build/sw/device/examples/infinite_loop
# In a different terminal, run openocd.
openocd -f util/verilator-openocd-cfg.tcl
# In yet another terminal run GDB.
gdb --eval-command="target extended-remote localhost:3333" build/sw/device/examples/infinite_loopTo run the Verilator tests, first build the software, then run:
ctest --test-dir build/sw -R sim_verilator -LE slowThe contents of the Verilator testbench SD card model can optionally be set by providing an "sd.img" file in the repository root directory.
One way to program your FPGA is to use openFPGALoader.
In Linux you must allow openFPGALoader to access your USB device.
First copy the example rules file in this repository and execute some commands for the rules to take effect (you may need admin rights for the udevadm and usermod commands):
cp util/99-openfpgaloader.rules /etc/udev/rules.d/99-openfpgaloader.rules
udevadm control --reload-rules
udevadm trigger
usermod -a -G plugdev $USERTo build a bitstream with the boot-ROM, make sure that Vivado is on your path, then run:
fusesoc --cores-root=. run --target=synth --setup --build lowrisc:mocha:chip_mocha_genesys2 --RomInitFile=$PWD/build/sw/device/bootrom/bootrom_scrambled.vmem
# Nix alternative: `nix run .#bitstream-build`To exercise a bitstream using a Genesys 2 board, perform the following steps.
Connect to the "UART" and "JTAG" USB ports on the Genesys 2 board.
Load the bitstream into the Genesys 2 FPGA:
openFPGALoader -b genesys2 build/lowrisc_mocha_chip_mocha_genesys2_0/synth-vivado/lowrisc_mocha_chip_mocha_genesys2_0.bit
# Nix alternative: `nix run .#bitstream-load`Then, to load and run a single software binary on FPGA, first build the software, then run:
util/fpga_runner.py run -e build/sw/device/examples/hello_worldReplace run above with test to see UART output in-line, or open a separate UART terminal (instructions below).
Or, to run all the FPGA tests, first build the software, then run:
ctest --test-dir build/sw -R fpga_genesys2To run CHERI Linux on the Genesys 2 board, run:
util/fpga_runner.py run -e build/sw/opensbi/opensbi_fw_jump.elf -e build/sw/uboot/u-boot -f build/sw/linux/linux_image 0x90000000 -f build/sw/rootfs_uboot_image 0xa0000000The UART output will be automatically presented when using fpga_runner.py test or ctest, but otherwise requires a UART terminal.
Open a UART terminal with 1Mbps baud rate:
picocom $(ls /dev/serial/by-id/usb-FTDI_FT232R_USB_UART_*-port0) -b 1000000 -imap lfcrlf
# Alternative: `screen $(ls /dev/serial/by-id/usb-FTDI_FT232R_USB_UART_*-port0) 1000000`Some peripheral tests require additional hardware to be connected to the Genesys 2 board:
- I^2C: AS6212 Temperature Sensor connected to header "JA" according to PMOD Interface Type 6 (I^2C).
- i.e. header "JA" top-row left-to-right: VCC, GND, SDA, SCL, (NC), (NC)
- SPI Host: a FAT32-formatted SDHC/SDXC microSD card containing the "lorem.ips" file inserted in the onboard microSD slot.
- See "lorem_text.h" for details on the file contents.
You can connect to OpenOCD using GDB. Currently we only support connecting to JTAG out of the box in Verilator simulation and FPGA debugging is unsupported. You can build a custom FPGA bitstream by using the patch that is located in the Genesys2 TCL script.
Once you have connected OpenOCD to your hardware target you can connect GDB by using the following command:
gdb --eval-command="target extended-remote localhost:3333" build/sw/device/examples/infinite_loopYou can then read registers using info reg, read memory (e.g. x/x 0x00080000), write memory (e.g. set *0x80001000 = 0xdeadbeef), set break points (e.g. break *0x100000d0) and continue running until that breakpoint with run.
To run block-level verification you can use the following command:
dvsim hw/vendor/lowrisc_ip/ip/uart/dv/uart_sim_cfg.hjson -i uart_smoke -r 1 --tool xceliumTo run block-level formal verification you can use the following command:
dvsim hw/top_chip/formal/top_chip_fpv_ip_cfgs.hjson --select-cfgs rv_plic_fpvTo run top-level verification you can use the following command:
dvsim hw/top_chip/dv/mocha_sim_cfgs.hjson --tool xceliumThis project is licensed under the Apache License, Version 2.0.
This license, as well as the licenses of all vendored sub-projects, can be found in the LICENSES sub-directory.
All code files must start with the following header (in the comment style applicable for the language):
// Copyright lowRISC contributors (COSMIC project).
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0For files that are generated by code or otherwise cannot have comments added to them (e.g images, lock files, markdown),
this information should be specified in the top-level REUSE.toml, but this should be used sparingly.
The hw/vendor directory contains its own REUSE.toml for vendored sub-projects.
To check that all files contain copyright and licensing information, run:
reuse lint