% Copyright (c) 2026 Rana Umar Nadeem, Samrah Mumtaz, Muhammad Imran # Environment Patches `scripts/patch_openpiton.sh` applies nineteen numbered fixes to an OpenPiton checkout and adds one unit-test environment. The fixes edit files in the checkout because some settings have no other hook. The boot ROM `Makefile`, for example, sets its compiler flags with plain `=` assignments, which neither the environment nor a `sims` flag can override. ## Running the script ```bash bash scripts/patch_openpiton.sh /path/to/openpiton PITON_ROOT=/path/to/openpiton bash scripts/patch_openpiton.sh ``` Run it once per checkout, on every worker that hosts one. The GCP worker in `cluster/local.yaml` runs it from `worker_setup_commands`. The script needs `bash`, `git`, `python3`, and GNU `grep` and `sed`. It exits with status 2 when no root is given or the root has no `piton/` directory. It exits with status 1 when the boot ROM `Makefile` is missing, when a text block or anchor it edits does not appear exactly once, or when fix 5 finds a half-applied guard. The script is idempotent. Each fix checks whether its change is already present and, if so, skips it with a message such as `already patched: `. Fixes 5 to 19 skip with a `not found, skipping fix N` message when their target file is absent. Fix 14 also skips when `scripts/openpiton_generic/` is not beside the script. `PATCH_SKIP` names fixes to leave out, as space-separated numbers, and the script prints `skipped fix N (PATCH_SKIP)` for each. A checkout patched with `PATCH_SKIP="11"` has every fix but 11, so the failure fix 11 addresses comes back; the evaluation's reverted-fix runs prepare their checkouts this way. Fix 9 edits the make line that fix 8 writes, so `PATCH_SKIP="8"` on an unpatched checkout makes fix 9 fail and the script exit 1. ```bash PATCH_SKIP="11" bash scripts/patch_openpiton.sh /path/to/openpiton ``` The script's edits change the checkout's source fingerprint, so a model built before the script ran is rebuilt on its next `build()` (see [OpenPitonWorkspaceNode](workspace_node.md)). ## Fixes | # | File(s) touched | What it fixes | |---|---|---| | 1 | `piton/design/chipset/rv64_platform/bootrom/linux/Makefile` | binutils 2.38 and later split `zicsr` and `zifencei` out of base RV64I, so the boot ROM's `csrr s2, mhartid` no longer assembles under `-march=rv64imac`. Changes the flag to `-march=rv64imac_zicsr_zifencei`. | | 2 | Same `Makefile` | GCC 15 and later default to C23, where `void init_uart();` declares a function with no arguments, so the boot ROM's two-argument call fails. Appends `-std=gnu17` to `CFLAGS`. `sims` runs `make clean` for this boot ROM before every build, so the flag applies to the next build. | | 3 | Git-tracked symlinks across the checkout | A Windows-mounted checkout defaults to `core.symlinks=false`, so tracked symlinks become text files that hold their target path, and `dtc` fails on a multi-tile build. When broken links exist, sets `core.symlinks` to true and checks them out again. Does nothing when `core.symlinks` is already true. | | 4 | Every `*.py` and `*.sh` file | A shebang line that ends in CRLF makes `/usr/bin/env` look for a program such as `python3\r`. Converts CRLF line endings to LF in each such file whose shebang line ends in `\r`. | | 5 | `piton/tools/verilator/my_top.cpp` | The Verilator C++ driver never calls the coverage-write API, so a coverage build writes no `coverage.dat`. Adds `#include "verilated_cov.h"` and `VerilatedCov::write("coverage.dat");` under `#if VM_COVERAGE`, since Verilator always defines `VM_COVERAGE` as 0 or 1. Stops with an error on a half-applied guard. | | 6 | `piton/design/chip/tile/pico/rtl/picorv32.v` | PicoRV32's internal `resetn` gate opens only on `pico_int`, an L15 interrupt that a bare configuration never sends, so the core never boots. Adds a `booted` register: the core starts once after reset, and a write to `32'hffffffff` still puts it to sleep until `pico_int`. | | 7 | `piton/verif/env/manycore/pc_cmp.v.pyv` | The `RTL_PICO0` `active_thread` block is a combinational latch gated on `PICO_CORE0.pico_int`, so good-trap and bad-trap detection never fires and the run ends at max cycles. Replaces it with a clocked block that sets `active_thread` after reset, as the `RTL_ARIANE0` block does. | | 8 | `piton/tools/src/sims/sims,2.0`; creates `piton/tools/verilator/unit_top.cpp` | The Verilator build and run paths hardcode `cmp_top` and `Vcmp_top` and ignore `-toplevel=`, so no non-manycore `-sys=` environment builds under Verilator. Makes the Verilator build and run steps honour `-toplevel=`. For a non-manycore system, the build uses `unit_top.cpp`, a generic C++ driver, in place of `my_top.cpp`, and passes the generated top-level class as `-CFLAGS -DMACE_UNIT_TOP=V`. | | 9 | `piton/tools/src/sims/sims,2.0` | The Verilator build runs a bare `make -j`, which overrides `MAKEFLAGS` and can exhaust memory on a large mesh such as a 4x4 Ariane build. Removes the bare `-j` from the make line that fix 8 writes, so `MAKEFLAGS` controls parallelism. | | 10 | `piton/verif/env/manycore/pc_cmp.v.pyv` | Under Verilator, `finish_mask` is a 32-bit `integer`, while `active_thread` and `good` widen per tile. The mask truncates past 8 tiles, so a 4x4 run passes once 8 of its 16 tiles finish. Declares `finish_mask` as `reg [31:0]` for every simulator, so the template widens it too. | | 11 | `piton/verif/diag/assembly/include/riscv/ariane/syscalls.c` | The exit barrier polls `finish_sync0` and `finish_sync1` with plain loads, which do not reliably observe other tiles' atomic updates. On a multi-tile mesh every hart but the last spins forever. Polls through an atomic fetch-add of zero (`ATOMIC_FETCH_OP`). Fix 13 fixes the cause, and with fix 13 `barrier_atomic.c` passes on a 2x2 mesh without this fix. | | 12 | `piton/design/chip/tile/ariane/core/cva6.sv` | CVA6's Verilator instruction tracer always opens `trace_hart_00.dasm`, so all tiles write one file. Names the file `trace_hart_.dasm`. | | 13 | `piton/design/chip/tile/ariane/core/cache_subsystem/wt_l15_adapter.sv` | Under Verilator 5, CVA6's L1.5 adapter sometimes drops cache invalidations, so an L1D keeps stale lines and a plain load misses another tile's update; [Ariane (CVA6)](../05_mace_cores/ariane.md) describes the cause. Moves the adapter's four `inv.vld` and `inv.all` assignments from continuous `assign`s into `p_rtrn_logic`, as upstream CVA6 does in [cva6#2809](https://github.com/openhwgroup/cva6/pull/2809). | | 14 | Creates `piton/design/chip/tile/generic/` and the generic test environment and programs under `piton/verif/diag/assembly/` | Installs the [Generic Tile](../05_mace_cores/generic.md) files from `scripts/openpiton_generic/`. Writes `Flist.core` and the test environment's `link.ld` only when missing, since a core descriptor replaces them. Copies an edited installed file back to the repository's version. | | 15 | `define.h.pyv`, `tile.v.pyv`, `chip.v.pyv`, `pyhplib.py`, `cross_module.h.pyv` | Adds `GENERIC_TILE` as tile type 3, its generate block in the tile, the tile type for every tile under `PITON_GENERIC`, one thread per tile, and the `GENERIC_CORE` and `GENERIC_TRANSDUCER` hierarchy names. | | 16 | `piton/verif/env/manycore/pc_cmp.v.pyv` | Adds an `RTL_GENERIC` branch that reports the transducer's finish register as the program's good or bad trap, once. | | 17 | `piton/tools/src/sims/sims,2.0`, `manycore.config`, `piton/tools/bin/rv32_as` | Adds `sims -generic`: `PITON_GENERIC`, `FLIST_GENERIC` (the generic tile's file lists, `-rv32`, and `CONFIG_DISABLE_BIST_CLEAR`), an `RTL_GENERIC` define per tile, and the RV32 assembly flow. `rv32_as` takes its include directory and link script from `RV32_ENV`. | | 18 | `piton/tools/src/sims/sims,2.0` | `rv32_as` loads every program image at `0x40000000`. Adds `sims -rv32_image_base=<16 hex digits>` (default `0000000040000000`) and exports it as `RV32_IMAGE_BASE` before `rv32_as` runs, so a generic-tile core whose RAM is elsewhere gets its image where its link script puts it. | | 19 | `piton/tools/bin/rv32_as` | Builds a C diag with the generic test environment's runtime (`crt.S`, `syscalls.c`, `util.h`, `link.ld`), for `RV32_MARCH` and `RV32_MABI`, and starts `mem.image` at `RV32_IMAGE_BASE` (16 hex digits, default `0000000040000000`). Adds picolibc's headers when the toolchain has the specs file, since it has no newlib. An assembly diag is built as before. Needs fix 17. | Fixes 3 and 4 address checkouts on a Windows-mounted path, such as `/mnt/c` under WSL. Fixes 14 to 17 change nothing for the other cores: every edit sits behind `PITON_GENERIC`, `FLIST_GENERIC`, `RTL_GENERIC`, or `-generic`. Fix 19 changes only how `rv32_as` builds a C diag and where `mem.image` starts. ## The pico_reset_ut environment The script also adds `pico_reset_ut`, a unit-test environment for fix 6. It creates `piton/verif/env/pico_reset_ut/` with `pico_reset_ut_top.v`, `pico_reset_ut.flist`, and an empty `test_cases/`. It writes `piton/tools/src/sims/pico_reset_ut.config` and appends `#include "pico_reset_ut.config"` to `piton/tools/src/sims/sims.config`. The testbench ties `pico_int` to 0 and checks that `picorv32` raises `mem_valid` with `mem_addr` at `PROGADDR_RESET` after reset. The environment builds under Verilator, using fix 8. Running it, or any other non-manycore testbench such as OpenPiton's `ifu_esl_lfsr`, stops with Verilator's `Settle region did not converge` error. The cause is three macros in the shared `piton/verif/env/test_infrstrct/test_infrstrct.v` harness that place delays inside `always @*` blocks. ## Tests `chia_openpiton/test/test_patch_openpiton.py` runs the script against a small synthetic tree: a git repository with the boot ROM `Makefile`, `picorv32.v`, `pc_cmp.v.pyv`, `syscalls.c`, `cva6.sv`, and `wt_l15_adapter.sv`. It checks that fixes 6, 7, 10, 11, 12, and 13 replace their exact text blocks, that a second run changes nothing and reports `already patched`, and that `PATCH_SKIP` leaves the named fixes out. A second tree with the text fixes 15 to 17 anchor on checks the generic tile's fixes the same way, and that fix 14 installs every file and keeps a descriptor's `Flist.core`. The test holds its own copy of each original and replacement block, so an edit to the script's blocks fails the test. It cannot detect changes in upstream OpenPiton. `chia_openpiton/test/test_patch_openpiton_fix19.py` checks fix 19 the same way on a copy of the whole upstream `rv32_as` (`fixtures/rv32_as_upstream.sh`). It runs the patched script with stub compiler tools, and with the installed `riscv64-unknown-elf-gcc` on every C program the generic ladder uses, for `rv32i`, `rv32im`, `rv32ima`, and `rv32imc`. ```bash pytest chia_openpiton/test/test_patch_openpiton.py -q ```