GSys LibreCore — a source-available RISC-V core and agentic build platform, derived from OpenHW CVA6. Explore the layered architecture.
CPU CoreOut-of-Order

Out-of-Order Execution

Full multi-issue out-of-order is a config-gated backend on GSys LibreCore. Minimal packages keep OoOEn=0 for netlist identity with the in-order path — a product option, not a quality disclaimer.

Authoritative detail: architecture/out-of-order/README.md, the contract core/ooo/AGENTS-ooo-contract.md, the working plan core/ooo/AGENTS-ooo-plan.md, and the running log architecture/out-of-order/log-2026-09.md.

Two knobs

KnobMeaning
SliceOoOEnU4 slice OoO path (core/cva6_slice_*.sv); often default off
OoOEnU5 full rename/IQ/ROB/LSQ backend (core/ooo/*); identity when 0

Invariant: SliceOoOEn and OoOEn are mutually exclusive product choices (XOR) — do not enable both.

Pipeline when OoOEn=1

decode → scoreboard (in-order alloc + commit)
              │
              ▼
     g6lc_ooo_dispatch
        multi-port rename + freelist
        age-ordered IQ + chain wakeup
        ROB multi-WB complete
        LSQ + memdep / STL
        PRF + WB bypass → issue operands
        mispredict: cancel mask → squash younger IQ/ROB/LSQ
              │
              ▼
     issue_read_operands → EX → WB → commit

When OoOEn=0, the dispatch module is not in the path (identity).

Module map (core/ooo/)

ModuleRole
g6lc_rename.svMulti-port RAT, free pool, busy, branch checkpoint
g6lc_iq.svCompacting IQ, multi-grant, cancel squash
g6lc_rob.svROB, multi-WB complete by trans_id
g6lc_lsq.svMulti-alloc LSQ, CAM, store-to-load forward
g6lc_memdep.svStore-set style memory dependence
g6lc_prf.svMulti-port physical register file
g6lc_ooo_dispatch.svGlue, AGU, PRF outs, PMU probes

Scoreboard entries carry physical tags (p_rs1/p_rs2/p_rd, ooo_renamed) when on; zeros when off. RVFI/commit observe tags via the scoreboard entry.

Production packages

PackageRole
g6lc64_ooo_int_config_pkg.svInteger-only single-hart OoO — the bring-up/verification baseline: elaborates, lints and synthesizes clean
g6lc64_smt2_ooo_int_config_pkg.svProduction SMT2 over OoO: NrHarts=2, integer-only, mixed residency (T9d), Sstc; ring-16 window adopted in T10d (NrScoreboardEntries=16 — deterministic, mixed boot faster; the T9f/M3 ring-32/TAGE/FTQ uplift bundle stays off)
g6lc64_ooo_int2_config_pkg.svTwo-core WT + L2 COH_OOO integration target — OoO coherence envelope, not a production profile
g6lc64_ooo_int2_l3_config_pkg.svTwo-core WT + L2/L3 COH_OOO, drained handoff; ring-16 window adopted in T10d (T9f/M3 uplift bundle not adopted); RV64GC+B — RVF/RVD on (T9g/M4)
g6lc64_ooo_config_pkg.svDual-issue OoO lite (area-lean bring-up) — legal single-hart FP since T9g/M4
g6lc64_ooo_server_config_pkg.svServer: wide issue, multi-core×hart, L2/L3 auto, deep spec, memdep — opt-in/unqualified (drained-FP legal; COH_FILTERED coherence leg unqualified)
Default cv64a6_imafdc_sv39 (etc.)OoOEn=0 identity

check_cfg legality for OoO (core/include/config_pkg.sv):

assert (!(Cfg.OoOEn && !Cfg.SpeculativeSb));
assert (!(Cfg.OoOEn && Cfg.NrHarts > 1 && Cfg.FpPresent && !Cfg.SmtDrainedHandoff));
                                                     // FP + mixed residency: refused
assert (Cfg.SmtDrainedHandoff || (Cfg.OoOEn && Cfg.NrHarts > 1));
`ifndef G6LC_OOO_SMT_MIXED_QUALIFY
assert (Cfg.SmtDrainedHandoff);                      // multi-core mixed residency: qualification-gated
`endif
`ifndef G6LC_OOO_FP_QUALIFY
assert (!(Cfg.OoOEn && Cfg.FpPresent && Cfg.NrHarts > 1 && !Cfg.SmtDrainedHandoff));
                                                     // single-hart and drained FP lifted (T9g/M4)
`endif

OoOEn && NrHarts > 1 is no longer refused: integer multi-hart OoO is legal under the drained handoff — the thread selector switches only when the scoreboard and store queues are empty (asserted at the switch in cva6.sv as ooo_switch_drained), so the hart-blind IQ/ROB/LSQ never hold two harts’ work at once. Since T9g/M4 the FP register class exists on the OoO path (per-hart g6lc_rename FP maps/pools/checkpoints, per-committing-hart dirty_fp_state, op-agnostic LSQ) and the fpu_wrap owner table is proven — so FP is legal single-hart (g6lc64_ooo) and under the drained handoff (g6lc64_ooo_int2_l3, RV64GC+B). FP under mixed residency stays refused pending the hart-tagged lazy-FS audit. g6lc64_ooo_int clears every FP format and keeps NrHarts=1, which is what makes it legal — treat it as a bring-up and verification baseline, not a qualified product.

Physical-address load validation (COH_OOO)

On the COH_OOO coherence fabric (g6lc64_ooo_int2) the load tag/check stage exports the accepted physical address of each granted load together with its saved TID, hart and access size (the legacy virtual load_paddr_o STQ key is not reused). The LSQ keeps that record until the load retires or is cancelled and checks it against physical store/load and load/load aliases, remote modifications, sibling-hart committed stores and TID reuse. A modification event holds load retirement for one cycle; matching loads are cancelled and replayed through the existing precise path, and PMA non-idempotent loads are never replay candidates. The uncertified early STQ forward shortcut is disabled in this mode. Contract and evidence: core/ooo/AGENTS-ooo-contract.md (physical validation candidate), core/ooo/AGENTS-ooo-plan.md T7/T7b, and the coherence envelope on Multi-Core Cluster.

ROB / IQ / LSQ / PRF depths scale from issue width when left at 0 in package builders (see build_config_pkg / package sources).

Bottlenecks the design targets

RiskMitigation (product view)
Multi-issue WAW/WARSingle-cycle multi-port rename
Mispredict blast radiusCheckpoint restore of the rename map + scoreboard cancel mask; the cancelled entries themselves are marked and drained through the commit head (measured T9f: ~8 recovery cycles at ring 8, ~17–19 at ring ≥ 16) — a one-cycle fast squash (M3b) is the sketched next step and the precondition for wider windows / 4-issue
Dependent ALU bubblesSame-cycle producer→consumer IQ wakeup
PRF read latencyWrite-through PRF + WB bypass
Memory orderStore-set + LSQ CAM; STL with live AGU

Measured state of the window (T9f–T10d): the 16-entry ring is adopted on g6lc64_ooo_int2_l3 and g6lc64_smt2_ooo_int; ring 32, the 3×64-entry TAGE_LITE, DeepSpec/memdep and the FTQ/FDIP/loop-buffer frontend each regressed the strict boot on their own and stay off. The prefetcher (g6lc_l2_pf) and the window bundle ship config-gated with their evidence rather than enabled.

Observability

PMU group 1 (see architecture README) exposes rename/IQ/ROB/LSQ/STL-class events. Prefer counters + RVFI when debugging mispredict or memory-order bugs.

Verification

SuitePath / id
Directed listverif/tests/testlist_ooo_l3.yaml
Regressverif/regress/ooo-l3-tests.* → suite ooo-l3-tests (optional)
ILP / renameverif/tests/custom/ooo/ooo_ilp_chain.S
Memdep / STLverif/tests/custom/ooo/ooo_mem_dep.S
Branch-bound IPCverif/tests/custom/multicore/mc_branchy.S (LFSR branches; the window ablation’s yardstick)
FP on OoOooo_fp_{ooo,rename}.S (Spike-ordered), mc_fp_smt.S (four-hart FP residency), core/ooo/formal/g6lc_ooo_fp_owner.sby
Frontend switch safetycore/fetch_B/formal/g6lc_fetch_restore.sby, verif/tb/core/tb_g6lc_fetch_restore.sv
Probes+misp_stats (recovery cycles per mispredict), +smt_stats (drain requests / durations) — sim-only
# The OoO targets that elaborate end to end:
g6lc-build verify --lint --synth --target g6lc64_ooo_int
g6lc-build verify --lint --synth --target g6lc64_smt2_ooo_int
g6lc-build verify --lint --synth --target g6lc64_ooo_int2
g6lc-build verify --lint --synth --target g6lc64_ooo_int2_l3   # RV64GC+B, ring 16
g6lc-build verify --lint --synth --target g6lc64_ooo            # single-hart FP, legal since M4
g6lc-build verify --target g6lc64_ooo_server                    # opt-in / unqualified
g6lc-build test --suite ooo-l3-tests

Optional suites are long-running by design; gate them in CI deliberately.

SoC-readiness notes

  • DFT: preserve test_en_i / testmode_i through new stateful structures.
  • Timing: IQ select, rename, and LSQ CAM are first-class critical paths — structural FO4 with sv-timing is useful early; STA still owns sign-off.
  • Do not break in-order packages: OoOEn=0 must remain identity.