Skip to content

Rv64 m3 - #41

Merged
adambagley merged 5 commits into
mainfrom
rv64-m3
Jul 31, 2026
Merged

Rv64 m3#41
adambagley merged 5 commits into
mainfrom
rv64-m3

Conversation

@adambagley

Copy link
Copy Markdown
Collaborator

No description provided.

… pc_reg from fetch

The pending-prediction consume (clear_pending_prediction_state) fired on
pending_prediction_target_handoff unconditionally, while the pc_reg flop
it hands off to is stall-gated. A stall landing exactly when pc_reg
reaches the predicted branch PC discarded the pending target with pc_reg
frozen: pc_reg then advanced SEQUENTIALLY past the predicted-taken branch
while fetch followed the target, and the aligner served target-path bytes
under sequential pc_reg addresses. Decode manufactures coherent-looking
phantom instructions from that pairing -- a non-branch can dispatch
wearing a branch's identity, "resolve" as a taken mispredict to
pc+garbage-imm, train the BTB with the phantom entry, and redirect the
machine mid-basic-block into code that never architecturally executed
(observed as wild stores trapping with mcause=6/mtval=0xb, with silent
corruption also possible).

Pre-existing well before the rv64 work (reproduces identically at
9b76e39); every -O2 build dodged it by code-layout luck. Exposed by the
CoreMark-PRO -O3 rebuild: genesys2 -v1 official runs of core and
nnet_test trapped in the report phase after verifying clean, reproduced
cycle-exactly by the coremark_pro_core cocotb sim, and root-caused by
walking the retirement, BTB-update, ROB-allocation, ID-record, and
pending-state traces down to the single ungated consume term.

Gate the consume on !fetch_stall, matching exactly the condition under
which the next_pc_reg mux can apply the target (the !i_fetch_progress
hold arm sits above the handoff arms; pc_update_en blocks i_stall). The
crossing arm needs no gate: it consumes implicitly via
stale_pending_prediction only after pc_reg really advances past the
branch. A sim-only assertion (p_handoff_consume_implies_apply) documents
and polices the remaining assumption that no higher-priority non-redirect
mux arm (window-cannot-serve resteer, slot-2 prediction, post-handoff
holdoff) wins on an un-stalled consume cycle; an independent adversarial
review of the fix argument confirmed the stall-path reasoning and named
those arms as the residual proof obligations, all of which predate this
change and consume identically before and after it.

Verified: coremark_pro_core cocotb fails pre-fix (phantom BEQ dispatched
at the c.or at 0x4134, recovery redirect to 0x4164, trap) and passes
post-fix with the pending state held across the stall and applied at
release; regate of coremark_pro_{core,nnet}, c_ext_test_fetch_fuzz,
branch_pred_test_fetch_fuzz, and control_flow_tracker.
Switch the CoreMark-PRO port's shared optimization level from -O2 to -O3
via the repo-standard OPT_LEVEL variable (env-overridable for A/B runs,
e.g. OPT_LEVEL=-O2 ./fpga/sweep_coremark_pro.py ...). -O3 is legal under
the vendored run rules: "You may change toolchain and build/load/run
options" (coremark-pro README, Run Rules / Allowed #2). The only
flag-related requirements are identical compile+link flags across all
nine workloads -- preserved by construction, since BASE_FLAGS feeds every
translation unit and the link -- and disclosure alongside published
scores. The -O2 in EEMBC's shipped gcc*.mak files is reference-toolchain
convention, not a rule, and the bare-metal porting note (CMP01 sec. 3.6)
explicitly invites tuning compiler options once baselines exist. All nine
official workloads build warning-free at -O3 and fit their memory
regions. This also closes the asymmetry against MicroBlaze V comparisons,
whose published CoreMark-PRO binaries are built at -O3.

Rewrite the two Makefile comments that cited an upstream
"util/make/gccrv32.mak" toolchain file: no such file exists anywhere in
the vendored tree; -O2 had been inherited convention, not a documented
decision.

Pre-scale the per-board -v0 iteration counts (~1.4x integer, ~1.5x FP,
targeting ~10.5s) so the first -O3 score sweep clears the 10-second
score-rule floor in one pass: the -O2-calibrated counts sat at 10.1-10.5s
of measured runtime, so any -O3 speedup pushes them under the floor (the
X3 counts additionally predate the M1 64-bit data tier's FP uplift).
Counts and comments are interim pending measured -O3 times from the next
hardware sweep; BASELINE_SCORES intentionally unchanged until then.

The -O3 rebuild's code layout exposed the pre-existing pending-prediction
handoff bug fixed in the previous commit; hardware -v1/-v0 reruns need a
bitstream carrying that fix.
X3 131.22 (was 111.14 at -O2 before the 64-bit data tier: +18.1%),
genesys2 45.32 (was 44.41 at -O2 after the data tier: +2.05% from -O3
alone). Full -v1 validation passes 9/9 on both boards on bitstreams
carrying the pending-prediction handoff fix -- including core and
nnet_test, the two workloads whose -v1 runs exposed that bug.

Replace the interim pre-scaled iteration counts with values derived from
the measured -O3 rates, targeting the usual ~10s-plus-margin discipline.
The pre-scale survived first contact on 17 of 18 board/workload pairs;
X3 radix2 outran the 1.5x FP allowance (1.69x: its DDR-resident FFT
tables benefit doubly from the 64-bit data tier at 300 MHz) and fell to
9.36s, so its count rises 98 -> 110. X3 nnet's raise to 2 iterations is
now measurement-backed: one iteration runs ~9.8s, under the floor. The
radix2 mark sample was taken at 9.36s; the next -v0 sweep at the new
count re-takes it rules-clean (scores are rate-based, so the mark moves
at most noise from 131.22).

Per-workload -O3-plus-data-tier gains track closely across boards (nnet
+66%, linear_alg +32%, cjpeg +8.2%, sha +3.2% on both; core -2.9% on
both from -O3 code growth); radix2 diverges by design (X3 +69% vs
genesys2 +32%: memory-bound FFT vs core clock) and parser via its
documented heap sensitivity.
@adambagley
adambagley merged commit c855d97 into main Jul 31, 2026
1 check failed
@adambagley
adambagley deleted the rv64-m3 branch July 31, 2026 21:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant