Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
e07b9c6
update csr_file misa to advertise C and D extension support
adambagley Jun 19, 2026
6b80304
Add RISC-V User mode (U-mode) to the core
adambagley Jun 19, 2026
1838c02
docs: reflect M+U privilege model (U-mode addition)
adambagley Jun 19, 2026
3b61c2c
Fix interrupt mcause delivery and double trap-entry
adambagley Jun 19, 2026
747f773
Trap CSR/MRET-from-U-mode as illegal instruction
adambagley Jun 19, 2026
81a2aed
Add U-mode directed test (umode_test)
adambagley Jun 19, 2026
f4e742b
Add ns16550a UART face for the Linux console
adambagley Jun 19, 2026
36eae45
Add SiFive CLINT alias for the Linux timer
adambagley Jun 19, 2026
56474c2
docs: document the ns16550a UART face and CLINT alias
adambagley Jun 19, 2026
828457c
Fix LR/SC store-conditional deadlock under speculation; boot nommu Li…
adambagley Jun 19, 2026
a0cfdf7
Docs + CI for the LR/SC store-conditional fix
adambagley Jun 19, 2026
718f8cc
nommu Linux: fix MRET->U-mode timer interrupt-resume-PC (0x80388bba p…
adambagley Jun 21, 2026
3d7766c
productionize 718f8cc bring-up changeset: drop debug harness, sync docs
adambagley Jun 21, 2026
21d5af7
linux_boot: make ret_from_exception patch rebuild-robust
adambagley Jun 21, 2026
4b148f4
handoff: nommu Linux boots to userspace; flaky M-mode timer race isol…
adambagley Jun 21, 2026
a8f3098
test: add mtimer_stress (M-mode timer+MRET deadlock stress, flaky-han…
adambagley Jun 21, 2026
3bc3ecd
handoff: M-mode race hunt status (repro approach scoped, not yet repr…
adambagley Jun 21, 2026
3c30849
checkpoint: no-MMU Linux bring-up — fetch fix + memory/IRQ WIP
adambagley Jun 28, 2026
98ef43d
sim: SIM_FAST_MAINT — fast fence.i cache maintenance in simulation
adambagley Jun 28, 2026
f535fc8
ci: Buildroot BR2_EXTERNAL for reproducible no-MMU Linux kernel builds
adambagley Jun 28, 2026
eed131f
pde_return_hazard: fix unreachable rb-tree node + add cycle budget
adambagley Jun 29, 2026
e0d1bf9
if_stage: fix compressed-branch link_address under flush-in-stall
adambagley Jun 29, 2026
43d6ecf
wfi_mepc_test: fix t1-clobber that hung the post-WFI poll loop
adambagley Jun 29, 2026
73f091f
mtimer_stress: fix interrupt-saturation livelock (timer period < roun…
adambagley Jun 29, 2026
66b1112
test: add opt-in trap/MRET/IRQ wedge monitor for deadlock diagnosis
adambagley Jun 29, 2026
be90384
wfi_lost_tick: raise per-app cycle cap to 800000 for the ddr axis
adambagley Jun 29, 2026
5207cfd
store_queue: scope benign "alloc during flush" sim assertion to parti…
adambagley Jun 29, 2026
709689b
test(if_stage): drive the i_served_addr port so the unit suite passes
adambagley Jun 29, 2026
df568c4
fence.i: bound real-FSM cache writeback to the dirty index span
adambagley Jun 29, 2026
87d7902
if_stage: cure no-MMU Linux timer-IRQ boot hang (the gremlin)
adambagley Jun 29, 2026
3b54862
reorder_buffer: don't retire a serial head during a recovery-flush bu…
adambagley Jun 30, 2026
21e0066
buildroot: uclibc: default page size to PAGE_SIZE on no-MMU (fixes ma…
adambagley Jul 1, 2026
045afdf
buildroot(frost): fold the manual rootfs/build customizations into th…
adambagley Jul 1, 2026
077a678
fix formal and reorder_buffer unit test for no_mmu rtl changes
adambagley Jul 1, 2026
fd4c074
linux: vendor buildroot submodule + self-build the no-MMU Linux image
adambagley Jul 1, 2026
596a807
ci: build + boot FROST no-MMU Linux in the CI workflow
adambagley Jul 1, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
199 changes: 199 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -342,3 +342,202 @@ jobs:
run: |
docker run --rm -v ${{ github.workspace }}:/workspace frost-dev:latest \
pre-commit run --all-files

# ---------------------------------------------------------------------------
# FROST no-MMU M-mode Linux: build the image from source, then boot it two
# ways off the SAME artifact -- on the FROST RTL in cocotb (the gremlin
# regression) and under QEMU (a fast full boot-to-shell reference).
# ---------------------------------------------------------------------------

# Build the kernel + busybox initramfs + FROST memory images from the vendored
# Buildroot submodule (linux/buildroot @ pinned SHA) driven by the FROST
# BR2_EXTERNAL tree. Runs inside the frost-dev image, which ships Buildroot's
# host deps + QEMU, so the host deps are single-sourced in the Dockerfile. The
# first build compiles a full rv32 uClibc cross toolchain from source; the dl/
# and ccache caches make later runs much faster.
build-frost-linux:
name: Build FROST Linux Image (Buildroot)
runs-on: ubuntu-24.04
needs: build-docker
timeout-minutes: 120
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
# Recursive so the pinned linux/buildroot submodule is fetched.
submodules: recursive

- name: Download Docker image
uses: actions/download-artifact@v4
with:
name: frost-docker-image
path: /tmp

- name: Load Docker image
run: docker load --input /tmp/frost-dev.tar

- name: Cache Buildroot downloads (source tarballs)
uses: actions/cache@v4
with:
path: linux/dl
# dl/ only changes when a package version (kernel/toolchain) changes.
key: br2-dl-${{ hashFiles('linux/buildroot-external/configs/frost_nommu_rv32_defconfig', 'linux/buildroot-external/board/frost/**') }}
restore-keys: |
br2-dl-

- name: Cache Buildroot ccache (toolchain + kernel object cache)
uses: actions/cache@v4
with:
path: linux/ccache
key: br2-ccache-${{ github.sha }}
restore-keys: |
br2-ccache-

- name: Build kernel + initramfs + FROST memory images
run: |
docker run --rm \
-e BR2_DL_DIR=/workspace/linux/dl \
-e BR2_CCACHE_DIR=/workspace/linux/ccache \
-v ${{ github.workspace }}:/workspace frost-dev:latest \
bash -c '
set -euo pipefail
make -C linux/buildroot O=/workspace/linux/build \
BR2_EXTERNAL=/workspace/linux/buildroot-external \
frost_nommu_rv32_defconfig
# Enable ccache for CI only (kept out of the committed defconfig).
echo "BR2_CCACHE=y" >> /workspace/linux/build/.config
make -C linux/buildroot O=/workspace/linux/build olddefconfig
make -C linux/buildroot O=/workspace/linux/build
# Stage the memory images where the cocotb linux_boot test resolves
# them (sw/apps/linux_boot/{sw,sw_ddr}.mem).
mkdir -p sw/apps/linux_boot
cp linux/build/images/sw.mem sw/apps/linux_boot/sw.mem
cp linux/build/images/sw_ddr.mem sw/apps/linux_boot/sw_ddr.mem
ls -l linux/build/images/
'

- name: Upload FROST Linux boot images
uses: actions/upload-artifact@v4
with:
name: frost-linux-boot-images
path: |
linux/build/images/Image
linux/build/images/rootfs.cpio.gz
linux/build/images/frost-nommu-fpga.dtb
linux/build/images/sw.mem
linux/build/images/sw_ddr.mem
retention-days: 7
if-no-files-found: error

# Boot the freshly built image on the FROST RTL in cocotb, bounded to ~22M
# cycles in the genesys2-faithful cache shape (128 KiB L1I, no L2). This is the
# "gremlin" regression: that window is silent mem_init after devtmpfs (no deep
# console marker), so the run captures the full boot (FROST_LINUX_RUN_FULL) and
# check_linux_boot_regression.py then asserts boot health -- banner + devtmpfs,
# no panic, the periodic CLINT timer tick serviced (mtimecmp re-armed, the
# thing the gremlin hung), and forward progress (retire) all the way to the
# cap. CACHED_HAS_L2=0 must be an env/make var (the test's own -GCACHED_HAS_L2=0
# is otherwise overridden by the tests/Makefile default).
linux-boot-cocotb:
name: Cocotb Linux Boot (22M, genesys2 shape)
runs-on: ubuntu-24.04
needs: [build-docker, build-frost-linux]
timeout-minutes: 180
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
submodules: recursive

- name: Download Docker image
uses: actions/download-artifact@v4
with:
name: frost-docker-image
path: /tmp

- name: Load Docker image
run: docker load --input /tmp/frost-dev.tar

- name: Download FROST Linux boot images
uses: actions/download-artifact@v4
with:
name: frost-linux-boot-images
path: /tmp/frost-linux-images

- name: Stage boot images for the cocotb linux_boot test
run: |
mkdir -p sw/apps/linux_boot
cp /tmp/frost-linux-images/sw.mem sw/apps/linux_boot/sw.mem
cp /tmp/frost-linux-images/sw_ddr.mem sw/apps/linux_boot/sw_ddr.mem

- name: Run cocotb linux_boot (22M-cycle gremlin regression)
run: |
docker run --rm \
-e CACHED_HAS_L2=0 \
-e FROST_LINUX_RUN_FULL=1 \
-e COCOTB_NUM_RUNS=1 \
-e COCOTB_LINUX_MAX_CYCLES=22000000 \
-e COCOTB_PROGRESS_INTERVAL=500000 \
-v ${{ github.workspace }}:/workspace frost-dev:latest \
bash -c '
set -o pipefail
cd tests && make clean
# RUN_FULL capture always trips the cocotb never-match assertion by
# design; the boot-health verdict comes from the checker below.
./test_run_cocotb.py linux_boot_128k 2>&1 \
| tee /workspace/linux_boot_cocotb.log || true
python3 check_linux_boot_regression.py /workspace/linux_boot_cocotb.log
'

- name: Upload cocotb boot log
if: always()
uses: actions/upload-artifact@v4
with:
name: linux-boot-cocotb-log
path: linux_boot_cocotb.log
if-no-files-found: ignore

# Boot the SAME kernel + rootfs to a login prompt under QEMU: a fast (seconds)
# full-userspace reference that the RTL boot is bounded well short of. Confirms
# the built image itself reaches a shell, independent of the FROST core.
linux-boot-qemu:
name: QEMU Linux Boot to Shell
runs-on: ubuntu-24.04
needs: [build-docker, build-frost-linux]
timeout-minutes: 20
steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Download Docker image
uses: actions/download-artifact@v4
with:
name: frost-docker-image
path: /tmp

- name: Load Docker image
run: docker load --input /tmp/frost-dev.tar

- name: Download FROST Linux boot images
uses: actions/download-artifact@v4
with:
name: frost-linux-boot-images
path: /tmp/frost-linux-images

- name: Boot to a shell under QEMU (assert login prompt)
run: |
docker run --rm -v /tmp/frost-linux-images:/img frost-dev:latest \
bash -c '
set -euo pipefail
# QEMU sits at the login prompt forever, so time-box it and assert
# the marker from the captured log (file redirect, never a pipe --
# piping QEMUs stdout to grep deadlocks).
timeout -k5 120 qemu-system-riscv32 -M virt -bios none \
-kernel /img/Image \
-append "earlycon=sbi console=ttyS0 rdinit=/sbin/init" \
-initrd /img/rootfs.cpio.gz -nographic -cpu rv32,mmu=off \
</dev/null >/tmp/qemu-boot.log 2>&1 || true
echo "===== QEMU boot log (tail) ====="
tail -n 20 /tmp/qemu-boot.log
grep -q "buildroot login:" /tmp/qemu-boot.log
'
7 changes: 7 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,13 @@ sw_ddr.bin
sw_imem_*.mem
sw/apps/*/sw.S

# FROST no-MMU Linux: out-of-tree Buildroot build output + download/ccache
# caches. Regenerated from the linux/buildroot submodule + linux/buildroot-external
# tree by `make -C sw/apps/linux_boot` (and the CI build-frost-linux job).
/linux/build/
/linux/dl/
/linux/ccache/

# mypy
.mypy_cache/

Expand Down
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,6 @@
[submodule "sw/apps/coremark_pro/coremark-pro"]
path = sw/apps/coremark_pro/coremark-pro
url = https://github.com/eembc/coremark-pro.git
[submodule "linux/buildroot"]
path = linux/buildroot
url = https://github.com/buildroot/buildroot.git
4 changes: 2 additions & 2 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ This document provides guidelines for contributors. The detailed style sections

## Project Overview

FROST is an out-of-order RISC-V processor implementing **RV32GCB** (G = IMAFD) with a Tomasulo back-end and full machine-mode privilege support. Understanding the architecture helps you contribute effectively:
FROST is an out-of-order RISC-V processor implementing **RV32GCB** (G = IMAFD) with a Tomasulo back-end and Machine + User (M/U) privilege modes. Understanding the architecture helps you contribute effectively:

### Architecture Outline

Expand Down Expand Up @@ -577,7 +577,7 @@ We welcome contributions in these areas:
|------|----------|
| Bug fixes | OOO ordering, instruction encoding, timing issues |
| ISA extensions | Additional standard or custom extensions |
| Privilege modes | S-mode (supervisor), U-mode (user) support |
| Privilege modes | S-mode (supervisor), PMP, virtual memory (M and U modes already supported) |
| Board support | New FPGA boards, SoC integrations |
| Performance | Branch predictor, scheduler, memory-system, or cache improvements |
| Peripherals | SPI, I2C, GPIO, timers |
Expand Down
27 changes: 27 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,33 @@ ENV RISCV_PREFIX=riscv-none-elf-
# Fix git "dubious ownership" error when mounting repo as volume
RUN git config --global --add safe.directory /workspace

# Buildroot host dependencies + QEMU. Used by the FROST no-MMU Linux CI jobs:
# * build-frost-linux - builds the kernel + initramfs + FROST memory images
# from the linux/buildroot-external tree (Buildroot compiles its own rv32
# uClibc cross toolchain from source, so it needs a full host build env).
# * qemu-linux-boot - boots the same Image + rootfs to a shell under
# qemu-system-riscv32 (qemu-system-misc provides the riscv32 target).
# `load_software.py <board> linux_boot` self-builds via the same path, so these
# are the single source of truth for the Linux build's host deps. Kept as a late
# layer so the expensive Verilator/Yosys/SMT source builds above stay cached.
RUN apt-get update && apt-get install -y --no-install-recommends \
build-essential \
patch \
cpio \
rsync \
bc \
file \
unzip \
wget \
bzip2 \
ccache \
libssl-dev \
libelf-dev \
libncurses-dev \
device-tree-compiler \
qemu-system-misc \
&& rm -rf /var/lib/apt/lists/*

# Install Python dependencies (cocotb, pytest, pre-commit, etc.)
RUN pip install --no-cache-dir --break-system-packages \
"cocotb==2.0.1" \
Expand Down
17 changes: 9 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

**F**PGA **R**ISC-V **O**pen-sourced in **S**ystemVerilog by **T**woSigma

An out-of-order RISC-V processor implementing **RV32GCB** (G = IMAFD) with a Tomasulo back-end and full machine-mode privilege support for RTOS operation. Achieves 300 MHz on UltraScale+. Designed for FPGA deployment with clean, portable SystemVerilog.
An out-of-order RISC-V processor implementing **RV32GCB** (G = IMAFD) with a Tomasulo back-end and Machine + User (M/U) privilege modes for RTOS operation. Achieves 300 MHz on UltraScale+. Designed for FPGA deployment with clean, portable SystemVerilog.

## Why FROST?

Expand Down Expand Up @@ -55,7 +55,7 @@ There are many RISC-V cores. Here's what makes FROST different:
│ │
│ ┌──────────────────────────┐ ┌─────────────────────────────────────┐ │
│ │ Trap Unit │ │ Peripherals │ │
│ │ (M-mode, mret, wfi, │ │ UART, mtime/mtimecmp, FIFO0/1 │ │
│ │ (M/U traps, mret, wfi, │ │ UART, mtime/mtimecmp, FIFO0/1 │ │
│ │ interrupts, exceptions) │ │ │ │
│ └──────────────────────────┘ └─────────────────────────────────────┘ │
│ │
Expand All @@ -82,6 +82,7 @@ There are many RISC-V cores. Here's what makes FROST different:
| **Zbkb** | Bit manipulation for crypto |
| **Zihintpause** | Pause hint for spin-wait loops |
| **Machine Mode** | M-mode privilege (mret, wfi, ecall, ebreak) |
| **User Mode** | U-mode privilege (ecall traps to M-mode) |

### Architecture Highlights

Expand All @@ -96,7 +97,7 @@ There are many RISC-V cores. Here's what makes FROST different:
- **Two-tier branch recovery** — conditional-branch mispredictions use a fast ~2-cycle path (front-end redirect + RAT restore in the same cycle); JALR and exceptions take the slower commit-time path
- **Branch prediction** with a 256-entry 2-bit BTB (trained for conditional branches and JAL, with slot-2 lookup support), 1024-entry bimodal direction predictor, 8-entry return address stack, and PD-stage computed-target redirects for conditional BTB misses predicted taken
- **L0 cache** in front of the load queue reduces load-use latency (direct-mapped, write-through)
- **M-mode trap handling** for RTOS support (interrupts and exceptions)
- **Machine + User (M/U) privilege modes** for RTOS support — traps from both modes are taken in M-mode (interrupts and exceptions)
- **CLINT-compatible timer** (mtime/mtimecmp) for preemptive scheduling
- **Harvard architecture** with separate instruction and data memory ports
- **Write-back cache hierarchy over DDR** — a 1 GiB cached region at `0x8000_0000` served by recursive line-port caches (`frost_cache`: direct-mapped, 32 B lines, write-back/write-allocate). Both instruction fetch (a 16 KiB read-only L1I) and data (a 128 KiB L1D) run through it on every board — so code can execute from DDR, not just from low BRAM — sharing a 2:1 line-port arbiter (data-side priority), plus a 2 MiB UltraRAM L2 spliced in on UltraScale+, over the board's DDR (DDR3 on Genesys2, DDR4 on X3) through a single-beat AXI bridge
Expand Down Expand Up @@ -352,12 +353,12 @@ controller calibrates, so software never observes an uninitialized main memory.

| Resource | Used | Available | Util% |
|----------|-----:|----------:|------:|
| Slice LUTs | 129,281 | 203,800 | 63.4% |
| LUT as Logic | 120,714 | 203,800 | 59.2% |
| LUT as Distributed RAM | 7,722 | — | — |
| Slice LUTs | 130,622 | 203,800 | 64.1% |
| LUT as Logic | 122,015 | 203,800 | 59.9% |
| LUT as Distributed RAM | 7,762 | — | — |
| LUT as Shift Register | 845 | — | — |
| Slice Registers | 86,734 | 407,600 | 21.3% |
| Block RAM Tile | 189.5 | 445 | 42.6% |
| Slice Registers | 87,375 | 407,600 | 21.4% |
| Block RAM Tile | 219 | 445 | 49.2% |
| DSPs | 36 | 840 | 4.3% |
| F7 Muxes | 98 | 101,900 | 0.1% |
| F8 Muxes | 33 | 50,950 | 0.1% |
Expand Down
2 changes: 1 addition & 1 deletion __init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
"""FROST - RISC-V processor package.

This package contains a complete RV32GCB (G = IMAFD) RISC-V processor
implementation with full machine-mode support and additional extensions
implementation with Machine (M) and User (U) privilege modes and additional extensions
(Zicsr, Zicntr, Zifencei, Zicond, Zbkb, and Zihintpause), along with
verification infrastructure, build tools, and software libraries.

Expand Down
5 changes: 4 additions & 1 deletion boards/genesys2/genesys2_frost.sv
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,10 @@ module genesys2_frost (
// backed by the DDR3 controller through the AXI port below.
.ENABLE_CACHED_TIER(1),
.CACHED_HAS_L2(0),
.USE_BEHAVIORAL_DDR(0)
.USE_BEHAVIORAL_DDR(0),
// Bump L1I 16 KiB -> 128 KiB: hold the kernel tick/softirq/scheduler
// working set to defeat the periodic-tick catch-up livelock (no L2 here).
.L1I_CACHE_BYTES(128 * 1024)
) subsystem (
.i_clk(main_clock),
.i_clk_div4(divided_clock_by_4),
Expand Down
12 changes: 10 additions & 2 deletions boards/xilinx_frost_subsystem.sv
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,13 @@ module xilinx_frost_subsystem #(
// 1 = the cached tier ends in the simulation-only behavioral DDR model;
// 0 = it ends at the o_ddr_axi_*/i_ddr_axi_* ports below, wired to the
// board's DDR controller subsystem (both boards drive 0).
parameter int unsigned USE_BEHAVIORAL_DDR = 1
parameter int unsigned USE_BEHAVIORAL_DDR = 1,
// L1 instruction-cache size in bytes. genesys2 (L1-only, no L2) bumps this
// above the 16 KiB default so the kernel periodic-tick/softirq/scheduler
// working set stays resident, addressing the tick-livelock I$ thrash.
parameter int unsigned L1I_CACHE_BYTES = 16 * 1024,
// Optional boot-hang UART classifier. Leave off for interactive testing.
parameter int unsigned ENABLE_HANG_TRIAGE = 0
) (
input logic i_clk, // Main CPU clock
input logic i_clk_div4, // Divided clock for JTAG/UART (1/4 of main clock)
Expand Down Expand Up @@ -217,7 +223,9 @@ module xilinx_frost_subsystem #(
.CLK_FREQ_HZ(CLK_FREQ_HZ),
.ENABLE_CACHED_TIER(ENABLE_CACHED_TIER),
.CACHED_HAS_L2(CACHED_HAS_L2),
.USE_BEHAVIORAL_DDR(USE_BEHAVIORAL_DDR)
.USE_BEHAVIORAL_DDR(USE_BEHAVIORAL_DDR),
.L1I_CACHE_BYTES(L1I_CACHE_BYTES),
.ENABLE_HANG_TRIAGE(ENABLE_HANG_TRIAGE)
) frost_processor (
.i_clk(i_clk),
.i_clk_div4(i_clk_div4),
Expand Down
2 changes: 1 addition & 1 deletion formal/store_queue.sby
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ smtbmc boolector
[script]
read -formal -sv riscv_pkg.sv
read -sv sdp_dist_ram.sv
read -sv sq_forwarding_unit.sv
read -formal -sv sq_forwarding_unit.sv
read -formal -sv store_queue.sv
prep -top store_queue

Expand Down
Loading
Loading