Repository navigation
Releases: bubblebabyboi/sigil
Release list
Sigil 2026-10-22: whole SoC on AWS F2 (public AFI) + whole-SoC nangate45 GDS
The whole Sigil SoC — the in-house RV64GCV core (vector unit, L1 caches) plus the crypto/hash engine and peripherals — running on a real AWS F2 FPGA from a public AFI, and placed and routed to a GDS on nangate45.
Run it on your own F2
Public AFI agfi-035116450e0a0d093 (AFI afi-019aabf5d4a815ae5, us-east-1, Small Shell 0x10212415, PCI 0x1D0F:0xF054), core clock 62.5 MHz (interim; 100 MHz is #53).
# on an f2.6xlarge (FPGA Developer AMI, us-east-1)
git clone -b v2.3.5 https://github.com/aws/aws-fpga ~/aws-fpga && (cd ~/aws-fpga && source sdk_setup.sh)
sudo fpga-load-local-image -S 0 -I agfi-035116450e0a0d093 -H
git clone https://github.com/bubblebabyboi/sigil ~/sigil && cd ~/sigil
make -C fpga/host SDK_DIR=$HOME/aws-fpga/sdk
sudo fpga/host/sigil_host --ignore-mem-err --bin hello.bin # any program linked at 0x8000_0000Write your own programs with the SDK: docs/PROGRAMMING.md. Full F2 guide: docs/FPGA_F2.md.
Proven on F2 hardware (measured 62.5 MHz)
| Program | Result |
|---|---|
| Hello world + all 7 SDK examples (timer IRQs, SHA-256 engine, SHA-512/SHA3 streaming, Ed25519, RVV vector, FP) | SIGIL TEST PASS |
| secp256k1 ECDSA verify + tamper reject | SOC CRYPTO PASS in 0.44 s |
| Ed25519 (RFC 8032 TEST 1/2) + tampered / non-canonical rejects | SOC CRYPTO PASS in 0.46 s |
| 512 KiB DDR4 memory test + UART input from the host | FPGA SMOKE PASS |
| OpenSBI v1.9 | HELLO FROM S-MODE |
| Linux 6.6 | boots to userspace (init: userspace alive, uname riscv64) |
FPGA build: Vivado 2025.2, aws-fpga v2.3.5, commit 4058108, no negative slack at 62.5 MHz; 122k LUTs (9.4% of the VU47P) for the full CL, 79k for the SoC.
Whole-SoC GDS — nangate45
sigil_soc_top through the full OpenROAD-flow-scripts flow (15 SRAM macros):
| Setup at 10 ns (100 MHz) | met, worst slack +0.74 ns, TNS 0 — fmax 107.9 MHz |
| Hold | met |
| Route DRC (OpenROAD) | 0 |
| Antenna (OpenROAD ANT) | 0 net / 0 pin |
| Power-grid connectivity | clean |
| Die / std-cell area | 2,020 × 2,020 µm (4.08 mm²) / 0.934 mm², 23 % utilization |
| Power (estimate) | 0.129 W |
KLayout make drc with the FreePDK45 deck additionally reports 179 markers (176 antenna per that deck's model, 2 WELL.4, 1 METAL1.5 inside library cell OAI221_X4) that OpenROAD's own checks do not flag; earlier releases reported only the OpenROAD checks. Details: soc-pnr-nangate45-11-2026-10-21/summary.log.
GDS generated / place-and-route complete — not taped out. nangate45 is an open research PDK. The sky130 (Caravel-sized) implementation is in progress with a hierarchical flow (#11) and will ship in its own release.
Assets
| File | What |
|---|---|
sigil_soc_top_nangate45_6_final.gds.gz |
nangate45 whole-SoC GDS (gunzip → 442 MB; sha256 of the .gds dd7b3b6d…dfab) |
sigil_f2_cl_dcp_4058108.Developer_CL.tar |
unencrypted F2 design checkpoint the public AFI was created from — rebuild or modify it yourself |
sigil_programs_2026-10-22.tar.gz |
prebuilt firmware (crypto, Ed25519, hash, smoke) and the 7 SDK example binaries |
sigil_evidence_2026-10-22.tar.gz |
nangate45 reports, Vivado F0/CL reports, every F2 host log and UART capture (incl. the Linux boot) |
SHA256SUMS |
checksums of the above |
Known issues
- #62 — the first AFI sets a sticky AXI error flag early in every run without affecting results; use
sigil_host --ignore-mem-err. - #63 — the virtual UART can drop characters during bursty Linux console output.
- #64 — the Linux payloads used for the F2 boot predate the rename (marker, DTB, 10 MHz timebase); Sigil-built payloads will follow.
- The crypto engine has not had a side-channel or fault-injection review — do not use real keys.
Sigil: Debian 13 on AWS F2 — 64 GiB DDR4 + 16 GiB HBM (2026-10-22)
The whole Sigil SoC — the in-house RV64GCV core (vector unit, L1 caches) plus the crypto/hash engine and peripherals — now boots Debian 13 "trixie" with gcc and glibc on a real AWS F2 FPGA, with all of the board's memory: 48 GiB DDR4 as NUMA node 0, 16 GiB HBM as NUMA node 1, and a 16 GiB DDR4 window as the root disk /dev/pmem0. On an f2.6xlarge it reaches the login prompt 5 min 48 s after the SoC starts and passes 22/22 acceptance checks. New public AFI, Sigil-built OpenSBI v1.9 + Linux 6.12 LTS payloads, and a ready-to-boot Debian image.
The first Debian boots on the F2 found a bug in the core: a data-TLB miss that preempted an instruction-fetch page walk could take that walk's page-table response as its own: a page fault on a valid address, or wrong data without a trap. It made the kernel oops (#74). The race is in every earlier Sigil core, including the first public AFI agfi-035116450e0a0d093 and the sigil-soc-2026-10-22 release. It needs address translation, so bare-metal M-mode programs are not affected. The new AFI has the fix, plus an atomic Svadu A/D-bit update found in the same review.
Boot Debian on your own F2
Public AFI agfi-0c8aa56fde1a48495 (AFI afi-059766f9a85c6d39a, us-east-1, Small Shell 0x10212415, PCI 0x1D0F:0xF054), core clock 62.5 MHz (interim; 100 MHz is #53), HBM AXI 250 MHz. It supersedes agfi-0a1fd54ef68bdc754 (afi-035809e576d7ea8d5), whose core has the walker race: do not use that one for Linux.
# on a new f2.6xlarge (FPGA Developer AMI, us-east-1), logged in as ubuntu
curl -fsSL https://raw.githubusercontent.com/bubblebabyboi/sigil/main/fpga/scripts/f2_playground_setup.sh | bash
tmux # recommended: keeps the session alive if SSH drops
~/bin/sigil-linux # downloads this release, loads the AFI, boots to the login promptThe console is your terminal. The login prompt appears 5 min 48 s after the SoC starts (measured on the F2; before that the host zeroes DDR4 and loads the 8 GiB disk, about 21 s, and the first run downloads the release). The F2 runs below used the sigil_host command that sigil-linux wraps (by hand, next block); sigil-linux itself passed its tests against a simulated sigil_host. Log in as sigil / sigil (sudo) or root / sigil, then for example:
gcc hello.c && ./a.out # native gcc 14 / glibc 2.41
numactl --hardware # node 0 = DDR4 48 GiB, node 1 = HBM 16 GiB
numactl --membind=1 ~/examples/memwhere 1024 # 1 GiB placed in HBM
sudo poweroff # saves your disk (~/sigil-disk.ext4) for the next sigil-linuxsigil-linux copies the disk back after poweroff; Ctrl-] leaves without saving (the window is kept as ~/sigil-disk.ext4.unclean); sudo reboot keeps the session going on the same disk. The first run after an AFI load zeroes all DDR4 once, which takes about 17 s. Rerunning the setup one-liner updates ~/sigil, sigil_host and the helpers.
By hand (sigil_host), as in docs/LINUX.md §4.2:
R=https://github.com/bubblebabyboi/sigil/releases/download/sigil-linux-f2-2026-10-22
for f in SHA256SUMS fw_jump.bin Image sigil-f2.dtb sigil-debian-13-riscv64.ext4.zst; do curl -fsSLO "$R/$f"; done
sha256sum -c --ignore-missing SHA256SUMS
zstd -d --sparse sigil-debian-13-riscv64.ext4.zst # 8 GiB ext4 image
sudo ~/sigil/fpga/host/sigil_host --linux --fw fw_jump.bin --image Image --dtb sigil-f2.dtb \
--load 0xC80000000=sigil-debian-13-riscv64.ext4 \
--save 0xC80000000=sigil-disk-saved.ext4:8G \
--consoleGuides: docs/LINUX.md (build it, QEMU, F2, NUMA, vector code, the disk), docs/LINUX_PLATFORM.md (memory map and devices), docs/FPGA_F2.md (the AFI and sigil_host). Bare-metal programs still work as before: docs/PROGRAMMING.md, sudo fpga/host/sigil_host --bin prog.bin (no --ignore-mem-err needed any more).
What is in the image
| Layer | What |
|---|---|
| Firmware | OpenSBI v1.9 generic fw_jump (cbf9f673) + a Sigil patch that writes back the L1 D$ before power-off/reboot |
| Kernel | Linux 6.12.114 LTS, sw/linux/kernel/sigil_defconfig; user-space vector on Zve64d (VLEN 512) |
| Device tree | sigil-f2.dtb (timebase 62.5 MHz), one source sw/linux/dts/sigil.dtsi for F2, QEMU and RTL simulation |
| Root file system | Debian 13.7 "trixie" riscv64 from snapshot.debian.org 20261020T000000Z, 257 packages, systemd 257, ext4 (8 GiB file system in the 16 GiB pmem window) |
| Tools | build-essential (gcc/g++ 14.2, binutils 2.44, make 4.4, glibc 2.41), gdb 16.3, git 2.47, python3 3.13, numactl/libnuma 2.0.19, vim, nano, tmux, htop, strace, man pages |
~/examples |
hello, malloc_test, numa_hbm (libnuma, DDR4 vs. HBM timing), memwhere (NUMA node of every page), rvv_vadd (RVV intrinsics), autovec (GCC auto-vectorization for Zve64d) |
Memory as Linux sees it on the F2:
| NUMA node | Memory | Physical range | Size |
|---|---|---|---|
| 0 (CPU node) | DDR4 | 0x0_8000_0000 – 0xC_7FFF_FFFF |
48 GiB |
| — | DDR4 pmem window = root disk /dev/pmem0 |
0xC_8000_0000 – 0x10_7FFF_FFFF |
16 GiB |
| 1 (no CPUs) | HBM | 0x10_8000_0000 – 0x14_7FFF_FFFF |
16 GiB |
Proven on F2 hardware (measured 62.5 MHz)
Debian 13 on the new AFI (f2.6xlarge, us-east-1):
| Check | Result |
|---|---|
SoC release → SIGIL_LINUX_BOOT_OK → login prompt |
337.7 s → 347.9 s (5 min 48 s); second boot 333.2 s → 343.2 s; no kernel oops in either |
| Where the time goes | ≈ 129 s OpenSBI + early memory setup for 64 + 16 GiB, then systemd-analyze: 10.6 s kernel + 3 min 25.5 s userspace (dev-pmem0.device 2 min 13 s); about 5 core cycles per instruction (estimate: F2 kernel time divided by QEMU icount instruction count) |
Login, uname, systemd state, root on /dev/pmem0 |
PASS: Linux 6.12.114 + Debian 13, isa with zve64d, systemd running with no failed units, / = /dev/pmem0 ext4 rw |
numactl --hardware (node 0 DDR4, node 1 HBM) |
PASS: 2 nodes, node 0 48305 MB with cpu 0, node 1 16110 MB without CPUs; free -h 62 GiB |
numactl --membind=1 memory lands in HBM |
PASS: memwhere 1024 → node 1: 1024 MiB; numa_hbm: dependent load 1791 ns DDR4 / 1878 ns HBM |
gcc hello.c && ./a.out, time |
PASS: 22.9 s; make of the 6 examples 6 min 23 s; python3 -c 9.9 s; malloc_test OK |
RVV Zve64d user program (rvv_vadd) |
PASS: VLEN 512; GCC auto-vectorized autovec PASS |
sudo, git/gdb/strace/vim/file/man |
PASS |
poweroff → sigil_host --save → second boot from the saved disk |
PASS: the file written in run 1 is there, journalctl --list-boots shows both boots |
sigil-linux: boot, sudo poweroff, save to ~/sigil-disk.ext4, second boot from it |
not yet run on an F2 (the runs above used the sigil_host command it wraps); 35/35 tests against a simulated sigil_host |
22/22 acceptance checks plus the persistence check, linux-debian-73-2026-10-22/f2-boot-fixed/ (full consoles, check summaries, instance and AFI info). F2 time for all of #73: about 3.8 instance-hours (2.97 h + 0.78 h).
The memory platform (on the platform AFI agfi-0a1fd54ef68bdc754, the same CL without the core's walker-race fix and atomic A/D update (#74); not repeated on the new AFI, f2-platform-73-2026-10-22):
| Test | Result |
|---|---|
| Full-range memory test, CL memory engine, two seeds | DDR4 64 GiB + HBM 16 GiB: 0 mismatches, 0 error responses, 4.0 GB/s |
| Sparse test from the core through the L1s | DDR4 1,048,576 lines + HBM 262,144 lines over the whole ranges: 0 errors |
| Cold 64-byte refill latency from the core | DDR4 729 ns (45.6 cycles avg) / HBM 813 ns (50.8 cycles avg) |
| Bulk load / save through PCIe | 3.6 GB/s load, 1.0 GB/s save (8 threads); 4 GiB and 8 GiB images round-trip sha256-identical |
| #62 sticky memory error | root cause: ECC on never-written DDR4; fixed by zeroing DDR4 once per AFI load (64 GiB in 17.2 s) |
| #63 UART drops | fixed: Linux console lines intact, 16-byte UART bursts byte-exact |
| Test finisher, RTC | power off / fail code / reboot keeping the disk window; RTC at the host's wall clock, alarm on PLIC source 11 |
| Firmware + all 7 SDK examples, OpenSBI to S-mode | PASS without --ignore-mem-err |
Before the F2 Debian boot, the same OS was brought up in QEMU shaped like the platform (23/23 acceptance checks, linux-debian-73-2026-10-22), and the all-RTL SoC model booted Linux 6.12 to SIGIL_LINUX_BOOT_OK in 261 M cycles.
FPGA build of the new AFI: Vivado 2025.2, aws-fpga v2.3.5, commit 31a1568, all timing constraints met (WNS +0.095 ns on the core clock at 16 ns; HBM AXI +0.198 ns at 4 ns); 131,259 LUTs (10.08 % of the VU47P) for the full CL, 82,201 for the SoC + OCL block (f2-platform-73-oopsfix-2026-10-22). The walker race and its fix: linux-oops-fix-73-2026-10-22 (13 race tests under the checkers 0/3...
OpenROAD rerun: muse_crypto nangate45 GDS (2026-10-14, #31)
OpenROAD place-and-route rerun of the muse_crypto_top crypto accelerator macro on nangate45, now on the current SystemVerilog sources. GDS generated / place-and-route complete for the macro — this is not a tapeout and not full-SoC closure.
Results at the 10 ns (100 MHz) constraint:
- Setup worst slack 4.34 ns, hold worst slack 0.039 ns, setup/hold TNS 0
- ORFS fmax estimate 176.7 MHz
- Route DRC 0, antenna 0, liberty max-cap/max-slew/max-fanout violators 0
- 63,474 stdcells, die 308,436 um2, utilization 0.321, total power 0.0211 W
First rerun found 3 liberty max-capacitance violators (AOI221_X1/OAI221_X1); both cell types are now in DONT_USE_CELLS and the released rerun is liberty-clean. Full metrics and the b3 (2026-10-13) comparison: docs/evidence/openroad-nangate45-31-2026-10-14.log.
This milestone also closes the run that started with the human-readability refactor (#27), expanded CI (#28), FP vector Zve32f/Zve64f/Zve64d (#29), and the QEMU reference-boot oracle (#30).
Asset: muse_crypto_top_nangate45_6_final.gds (60 MB, 6_final.gds from the ORFS run; GDS is a release asset, not in git).
B3: muse_crypto nangate45 GDS (2026-10-13)
OpenROAD closure for the muse_crypto macro on nangate45 at 100 MHz (#3).
- Detail-route DRC 0, antenna 0, liberty max-cap/slew/fanout violations 0
- Setup worst slack +4.52 ns, hold +0.039 ns @ 10 ns, TNS 0/0
- 61,590 stdcells, 95,431 um2 stdcell area (296,867 um2 core), 20.16 mW
- Evidence: docs/evidence/b3-openroad-nangate45-2026-10-13.log at this tag; reproduce with make openroad then ./scripts/orfs_liberty_check.sh
- 6_final.gds md5 6e2b5ad1ca4a7693091de3e27f5969d8
Local Docker ORFS run (emulated amd64) - an engineering closure result, not a foundry signoff.