Visual walkthrough — RISC-V custom extensions for accelerators
This is the picture-first companion to 6.5.11 RISC-V custom extensions for accelerators (Hinglish) and its English parent. If a word here is new, we build it before we use it.
Step 1 — What is an instruction? A row of 32 light switches
WHAT. A single RISC-V instruction is nothing more mystical than a fixed group of 32 binary digits — 32 tiny switches, each either OFF () or ON (). We number them from the right: bit is the far right, bit is the far left. The notation just means "switches number 0 through 6" — the seven rightmost switches.
WHY. Before we can talk about "opcode space" or "fields", we have to agree that an instruction is a physical row of switches with fixed positions. Every idea after this is just carving that row into labelled zones. If the row weren't a fixed width, none of the accounting would work.
PICTURE. Below: the 32-switch row. The seven orange switches on the right are the zone that decides which family of instruction this is.

Step 2 — The opcode: the 7 switches that name the family
WHAT. The lowest 7 bits, , are the opcode. Seven switches can show different patterns, so there are at most 128 instruction "families".
WHY seven, and why ? Each switch doubles the number of distinct patterns: 1 switch → 2 patterns, 2 switches → 4, and in general switches → . This doubling is the only counting rule we need on the whole page, so pin it down now:
PICTURE. We zoom into just those 7 orange switches and watch the pattern count double as we light switches one at a time.

Step 3 — Four of those 128 families are legally yours
WHAT. Out of the 128 possible opcode patterns, the RISC-V spec permanently reserves four for non-standard (custom) use. Their bit patterns:
Each of those seven-digit strings is one specific setting of the seven orange switches from Step 2.
WHY reserved? A promise from the spec: no future ratified standard extension will ever emit these four patterns. So an instruction you invent with, say, opcode can never collide with a standard one — the decoder will never be confused about who owns it. That guarantee is the entire legal foundation of custom extensions.
PICTURE. The 128-slot opcode map, most slots claimed by standard families, four slots glowing as yours.

Step 4 — Inside one family: borrow the R-type shape
WHAT. Picking a family (opcode) only fixes the 7 rightmost switches. The other 25 switches () are still free. We choose to lay them out like the standard R-type format — the register-to-register template:
Check the accounting: . Every switch is spoken for.
WHY R-type? Two of those fields point at data and three point at operation identity — and the split matters enormously in the next step. But the immediate reason is hardware reuse: the register file already has two read ports and one write port. An R-type op reads two registers () and writes one (), which is exactly what those ports provide. See R-type instruction format.
PICTURE. The 32-switch row re-carved into the six R-type zones, colour-coded by job.

Step 5 — The key split: which fields choose the operation?
WHAT. We want to count distinct operations per opcode slot — how many genuinely different instructions we can define. Only the fields that change behaviour count. So we keep and , and we ignore .
WHY ignore the register fields? Because changing from register 5 to register 6 does not create a new instruction — it runs the same instruction on different data. mac x10,... and mac x11,... are the same operation. Counting register combinations would count data, not operations. So the operation-selecting bits are only:
PICTURE. The row split into a "chooses operation" half (funct3 + funct7, glowing) and a "chooses data" half (the three register fields, dimmed).

Step 6 — Count one slot:
WHAT. Apply the Step-2 counting rule to the 10 operation bits:
Each of the 8 possible patterns can pair with each of the 128 possible patterns, and .
WHY multiply? Because the two fields are independent — any value works with any value. Independent choices multiply (this is the same reason "3 shirts × 4 trousers = 12 outfits"). If they weren't independent we'd have to subtract collisions; here we don't.
PICTURE. An grid: rows = funct3 values, columns = funct7 values, every cell a distinct instruction. All 1024 cells belong to one opcode slot.

Step 7 — Four slots:
WHAT. There are 4 reserved custom slots (Step 3), and the grid of Step 6 sits inside each one. So:
WHY add slots by multiplying? Each slot is a fresh, non-overlapping opcode value, so its 1024 operations are all distinct from the other slots' operations. Four identical, disjoint grids stacked together → .
PICTURE. Four copies of the Step-6 grid, one per custom opcode, totalled to 4096.

Step 8 — Edge & degenerate cases (so you never hit a surprise)
WHAT / WHY / PICTURE, three corners the counting hides:
- All-zero function code (, ). This is a perfectly valid custom instruction, not "no instruction" — it's one specific cell of the grid (the corner). The MAC example in the parent note uses exactly this cell. Nothing degenerate happens; zero is a legal code.
- A core that doesn't implement your op. The 1024 cells are available names, not implemented units. If silicon has no logic behind a cell, executing it raises an illegal-instruction trap — a clean, defined failure, never a silent wrong result. (This is why custom extensions don't break compatibility; see the parent's mistake box.)
- Non-R-type shapes. Our 4096 counts only R-type-shaped ops. You may carve those 25 upper bits differently (e.g. an immediate field), trading function bits for data bits — which lowers the operation count for that slot. So 4096 is the R-type maximum, not a hard ceiling on every possible layout.

The one-picture summary

Read it left to right: 32 switches → 7 are the opcode → 4 opcodes are yours → each carves into R-type → only the 10 function bits pick the operation → per slot → .
Recall Feynman: retell the whole walkthrough in plain words
Picture a form 32 boxes wide that every RISC-V command fills in. The 7 boxes on the right are the title box — they say what kind of command this is, and there are possible titles. The RISC-V rule-makers set aside four of those titles for you to invent whatever you like, promising they'll never use them for official commands. Inside your title, the form still has 25 empty boxes. If you fill them in the standard "R-type" way, three little groups of boxes just say which storage slots to read and write (that's data, not a new command), while two groups — 3 boxes plus 7 boxes, ten boxes total — say what the command actually does. Ten OFF/ON boxes make different "what-it-does" codes. Multiply by your four titles and you get commands you're free to design. And if a chip hasn't actually built the machine behind one of those codes, running it just politely refuses (traps) instead of doing something wrong — which is why your inventions never break anyone else's programs.
Recall Quick self-test
How many patterns do switches make? ::: . Which R-type fields choose the operation (not data)? ::: funct3 (3 bits) and funct7 (7 bits). Why do we ignore rs1/rs2/rd when counting operations? ::: They select data (which registers), not which operation runs. Ops per custom opcode slot? ::: . Total R-type custom ops across all four slots? ::: . What happens if a core executes an unimplemented custom code? ::: It raises an illegal-instruction trap — a clean, defined failure.
Connections
- RISC-V base ISA (RV32I / RV64I)
- R-type instruction format
- Instruction Set Architecture
- Rocket Chip and RoCC coprocessor interface
- Vector / SIMD extensions (RVV)
- Domain-specific architectures