An interactive reference for RISC-V extensions, profiles, and per-instruction
encodings. Pick a base ISA or start from a supported profile, add extensions, and
get a dependency-resolved configuration with a valid -march string.
- Browse every catalogued extension, grouped and searchable by name, mnemonic, or hex encoding.
- Build a configuration. Select extensions and dependencies resolve automatically, with conflicts blocked and a reason shown for every implied extension.
- Start from a profile. RVA23, RVB23, their frozen 23.1 minor profiles, and the other supported profiles load as a starting point rather than being rebuilt by hand. Profiles are Volume III of the ISA manual, so each ratified profile links to its specification on docs.riscv.org.
- Highlight a profile to see everything in it: mandatory extensions in full, implied ones tagged with the extension that pulls them in, optional ones tagged and outlined. The grid, the download and the comparison all use the same classification.
- Share a view. Selecting an extension puts
?ext=in the address bar, a highlighted profile puts?profile=there (?profile=rva23.1works), and Share copies a link to either the highlighted profile or the whole builder configuration. A configuration link records the profile it started from, the extensions added and removed, and the parameters chosen. If the visitor already has a different configuration saved, the page asks before replacing it. - Export a
-marchstring, a YAML configuration (optionally with every instruction), or a UDB architecture configuration for riscv-arch-test. Parameters chosen in the ISA Configuration Builder go into both files. - Compare entries. Pin extensions, instructions or profiles and read them side by side; a comparison has its own URL and can be shared. With Compare switched on, Compare profiles opens a profile comparison directly, grouping extensions under Mandatory, Implied and Optional (or A–Z), and Show narrows it to required or optional extensions only.
- Download a profile. While a profile is highlighted, download its extensions (mandatory, implied and optional, with status and spec links) as YAML, JSON, CSV or Excel.
- Check an encoding. The Encoder Validator tests a proposed instruction pattern against every existing one and reports overlaps.
- See the encoding space. The Encoding Map draws the 32 base opcode slots, shaded by how many instructions each holds, and shows what is still free.
- Design an extension that does not exist yet. The Custom Extension Sandbox
lets you draft a custom vendor extension or an addition to a ratified one,
lay out the bit encodings, check them against every instruction in the
catalogue, and export
riscv-opcodesJSON plus a proposal document. See docs/sandbox.md. - Read the registers and instructions. CSR chips open each register's fields, and instructions carry descriptions taken from riscv-unified-db, each with a link to its source.
- Write an instruction. Each instruction shows its assembly syntax with a
concrete example, whether it is RV32- or RV64-only or has data-independent
timing, the C intrinsic that emits it (from the RVV intrinsics and RISC-V C
API specifications), and a link that opens the example compiled in Compiler
Explorer with the right
-march. Links to its code in the two reference models, the Sail formal model and the Spike simulator, and to its Architectural Certification Test (ACT) sit beside these; one that does not cover the instruction yet is shown greyed out. - Know which tools take it, and what runs it. Each extension shows the
first release of Clang and GCC that accept it in
-march, of binutils that assembles it, of QEMU that emulates it, and of Linux that detects it, marking the ones Clang and QEMU still treat as experimental and the ones LLVM documents as assembly-only (accepted and assembled, but no code generated, as for RV32E and RV64E). Under the builder's-marchstring, Accepted by gives the oldest Clang, GCC and binutils that accept all of it, or names the extensions no release takes yet. Accepting a-marchis not the same as generating code for every extension in it. The versions are read from each release's own source. - Watch the ISA grow. Evolution plots every dated extension on the month it was ratified, over a cumulative curve banded by family. Below it, one stepped line per tool shows how many extensions each Clang, GCC, binutils, QEMU and Linux release knew, against how many had been ratified by then.
- Link out to the specification. Each extension's Read Online button opens the page that defines it: docs.riscv.org when it is published there, otherwise the specification's source repository, and the button says which.
The catalogue is the product, so a bad description, a missing dependency or a
wrong encoding matters more here than most bugs. Open an issue and cite the
specification section or the riscv-unified-db file that says otherwise. That
turns a report into a fix, and it is usually a small change.
Node.js and npm are the only requirements.
npm ci
npm run build
python3 -m http.server 8080 -d distThen open http://localhost:8080.
These files carry the data, and they do not have the same authority. Worth knowing before changing anything:
| file | holds | source of truth |
|---|---|---|
src/riscv_extensions.json |
the extension catalogue, plus the instruction encodings routed into each extension | riscv-unified-db for metadata and ratification state; src/instr_dict.json for encodings |
src/instr_dict.json |
the instruction encodings themselves | hand-maintained. Checked against riscv-opcodes, but it carries entries upstream lacks and is never regenerated |
src/isa-dependency-graph.json |
dependencies, conflicts and parameter constraints, with a citation on every edge | riscv-unified-db |
src/isa-params.json |
parameter definitions: type, admissible values, when each exists | riscv-unified-db, generated; never edited by hand |
src/instruction-metadata.json |
instruction descriptions, ownership and assembly syntax | riscv-unified-db, generated |
src/isa-manual-status.json |
what each ISA manual preface lists as ratified, to check the catalogue's states against | riscv-isa-manual prefaces, generated, pinned to a commit |
src/toolchain-support.json |
the first Clang, GCC, binutils, QEMU and Linux release that knows each extension | each release's extension table in llvm-project (from 14), gcc (from 12), binutils (from 2.38), qemu (from 7.0) and linux (from 6.6), generated |
src/instruction-references.json |
where each instruction is implemented in Sail and Spike, and its ACT test | sail-riscv, riscv-isa-sim and riscv-arch-test, generated, pinned to a commit of each |
src/instruction-intrinsics.json |
the C intrinsics that emit each instruction | rvv-intrinsic-doc and riscv-c-api-doc, generated |
src/profiles.js |
supported profiles, mandatory extensions, spec links | the profile specifications (Volume III), by hand |
src/profile-optional.json |
each profile's optional extensions | riscv-unified-db, resolved through its profile inheritance |
Two things fall outside that table, because no upstream carries them. The
Zve* embedded vector subsets are derived from V by the EEW/FP rules in
unpriv §30.1.18.2 — riscv-opcodes has no rv_zve* tag and unified-db attributes
every vector instruction to a single owner, so neither can say what belongs in
Zve32x. And the SPMP family (Sspmp, Sspmpen, Smpmpdeleg) is ratified in a
specification of its own that unified-db does not model at all; its dependency
edges cite that document through the graph's spec provenance source. Both are
places where the usual checks cannot help, so both are pinned by tests.
riscv-unified-db is normative for dependencies. clang is the check that what we
emit is actually usable: CI feeds every generated -march string to a real
compiler. riscv-config, RISC-V International's own validator, disagrees with
clang in a few places, and where it does both opinions are recorded rather than
one being quietly preferred.
Regenerate with:
npm run sync # route src/instr_dict.json into the catalogue
npm run sync:udb # extension metadata from riscv-unified-db
npm run sync:params -- <path-to-riscv-unified-db>
npm run sync:instruction-metadata -- <path-to-riscv-unified-db>
npm run sync:intrinsics -- <rvv-intrinsic-doc> <riscv-c-api-doc>
npm run sync:references -- <sail-riscv> <riscv-isa-sim> <riscv-arch-test>
npm run sync:toolchains # fetches LLVM, GCC, binutils, QEMU and Linux sources
node scripts/sync-profile-optional.mjs <path-to-riscv-unified-db>
node scripts/seed-dependency-graph.mjs --udb <path-to-riscv-unified-db>
node scripts/map-doc-links.mjs # documentation linksOr check for drift without writing anything:
npm run sync:check
npm run sync:instruction-metadata:check # expects riscv-unified-db beside this repo
npm run sync:references:check -- <sail-riscv> <riscv-isa-sim> <riscv-arch-test>
npm run graph:check -- <path-to-riscv-unified-db>
npm run links:check
npm run opcodes:check -- <path-to-riscv-opcodes>
npm run udb:check -- <path-to-riscv-unified-db> [--published] # ratified extensions/instructions we lack; --published also checks drafts we listmap-doc-links.mjs reads the ISA manual and profile pages on docs.riscv.org and
links each extension to the page that names it. Entries no page names keep a
hand-written link to their specification's repository.
| how it refreshes | |
|---|---|
| extension metadata, CSRs, ratification state | the sync-udb-extensions workflow, Mondays at 06:00 UTC, opens or updates a PR when a file changes |
| the published site | any push to main rebuilds and publishes to gh-pages |
static extension pages and sitemap.xml |
generated from the catalogue on every build, for search engines and AI crawlers; nothing to run by hand |
| toolchain support | the sync-toolchain-support workflow, the 1st of each month at 10:00 UTC, opens or updates a PR when a new Clang, GCC, binutils, QEMU or Linux release ships or an extension's standing changes |
| Sail, Spike and ACT links | the sync-reference-impls workflow, Mondays at 08:00 UTC, opens or updates a PR when an instruction gains or loses a link; new upstream commits alone do not, since the links are pinned |
| instruction encodings | by hand. The check-opcodes-drift workflow, Mondays at 07:00 UTC, files an issue when upstream is ahead, or carries different bits under a name we list (drafts included) |
| new extensions | by hand. The weekly sync only enriches entries we already have; the check-udb-completeness workflow, Mondays at 09:00 UTC, keeps one issue updated with what riscv-unified-db has and we do not |
src/instr_dict.json is hand-maintained on purpose and is not regenerated from
riscv-opcodes. It carries entries upstream does not: 252 expanded vector segment
load/store forms, which riscv-opcodes does not express individually, and the MOP and C.MOP
encodings expanded from upstream's three _n templates. A regenerate would
delete them, so the drift check reports and leaves the decision to a person.
It compares mnemonics rather than encodings, ignores upstream's
$pseudo_op aliases (mv is addi rd, rs, 0, an encoding we already carry),
and counts extensions/unratified/ separately rather than treating drafts as
gaps to fill.
| file | responsibility |
|---|---|
src/risc_v_visualizer.jsx |
the main view |
src/ExtensionTile.jsx |
a single extension tile, memoised per tile |
src/WorkspacePanel.jsx |
the ISA Configuration Builder panel |
src/isaGraph.js |
dependency resolution: resolveSelection, closure, explain, validateGraph |
src/marchUtils.js |
-march assembly and canonical ordering |
src/exportUtils.js |
YAML and UDB configuration export |
src/profiles.js |
profile definitions |
src/profileExport.js |
profile membership (mandatory, implied, optional) and the profile download |
src/CompareView.jsx, src/compareModel.js |
side-by-side comparison |
src/EncodingMap.jsx, src/encodingMap.js |
the opcode-space map |
src/SandboxPanel.jsx, src/sandboxModel.js |
the Custom Extension Sandbox |
scripts/static-pages.mjs |
the per-extension static pages and sitemap, run by the build |
AGENTS.md has the full map and the gotchas.
npm testCI runs the tests, builds, then validates generated -march strings with both
the distro clang and clang 21. The modern job covers every profile and every
ratified catalogue entry; its small CLANG21_UNSUPPORTED allowlist is checked
for staleness on every run. The suite covers dependency closure, graph integrity, profile
correctness, riscv-config conventions, export formats, documentation links, and
a jsdom smoke test that fails if the page renders blank.
Add an entry to the appropriate group in src/riscv_extensions.json:
{
"id": "Zfoo",
"name": "Zfoo",
"tags": ["rv_zfoo"],
"desc": "Short description",
"use": "What it enables",
"url": "https://docs.riscv.org/reference/..."
}tagsare riscv-opcodes extension names. Instruction membership is derived from them, so a wrong tag produces a wrong instruction count.urlpoints at the extension's page on docs.riscv.org, or at its specification's source when docs.riscv.org does not carry it;npm run links:checkverifies it resolves.discontinued: 1adds the "Discontinued" badge.
Then add a graph node, or the tests fail:
node scripts/seed-dependency-graph.mjs --udb <path-to-riscv-unified-db>
npm testEncodings live in src/instr_dict.json, keyed by the mnemonic lowercased with
. replaced by _, so SC.W becomes sc_w:
"sc_w": {
"encoding": "00011------------010-----0101111",
"variable_fields": ["rd", "rs1", "rs2", "aq", "rl"],
"extension": ["rv_a"],
"match": "0x1800202f",
"mask": "0xf800707f"
}The extension values match the tags on a catalogue entry, and that is what
places the instruction. Merge it in and verify:
npm run sync
npm test && npm run buildThe Encoder Validator in the header checks a proposed encoding against every
instruction in the database. Give it either a 32-bit pattern of 0, 1 and -,
or a match and mask pair in hex; supplying both cross-checks them against
each other.
Overlaps are reported as identical, proposed_subset_of_existing,
existing_subset_of_proposed, or partial_overlap, each with a plain-language
reason and an example 32-bit word that satisfies both patterns.
The Encoding Map, also in the header, answers the question the extension
list cannot: how much of the base encoding space is spoken for. It lays the 32
opcode slots out as the ISA manual does, rows inst[4:2] and columns
inst[6:5], with every cell implying inst[1:0]=11, and shades each by
occupancy on a log scale. Compressed instructions sit outside that grid and are
summarised by quadrant. Selecting a cell lists its instructions and links
through to the extensions that define them.
It is computed from src/riscv_extensions.json at runtime, so there is nothing
to regenerate: sync the catalogue and the map follows.
Every push to main is built by CI and published to the gh-pages branch,
which GitHub Pages serves at
tech.riscv.org/isa-explorer. Nothing is
published by hand. Releases are tagged and described in
CHANGELOG.md.
Contributions are welcome, data corrections especially. See CONTRIBUTING.md for setup, the invariants the tests enforce, and the sign-off requirement.
All commits must be signed off under the Developer Certificate of Origin:
git commit -sParticipation is governed by our Code of Conduct. To report a vulnerability, see SECURITY.md.
