Instruction sets: the contract beneath a program
Separate architectural behavior from processor implementation and trace a small RV32I program without assuming its timing.
On this page
The question for today
What you’ll understand
- Trace register state through an RV32I instruction sequence.
- Distinguish ISA guarantees, ABI conventions, and microarchitecture.
- Identify when a performance claim needs a particular processor model.
An executable is more than a sequence of mathematical operations. Its bytes must be interpreted according to an instruction-set architecture, or ISA, that defines visible state and permitted behavior. Two processors can run the same executable while arranging the internal work differently. Learning that separation lets you ask a precise question: is this property promised to software, imposed by a calling convention, or merely observed on one implementation?
A state transition with a documented boundary
For a small integer program, architectural state includes the program counter, integer registers, and relevant memory. An instruction reads part of that state and defines an allowed change. RV32I supplies 32 integer registers of 32 bits, with x0 fixed to zero. An ADD writes the low 32 bits of a sum to its destination; writing x0 discards the result. These rules are useful even before you know how many execution units a processor contains. They let you trace a program by hand.
Think of execution as repeated transitions rather than informal verbs such as add and jump. Specify operand width, destination, memory effects, and next instruction address. For an ordinary RV32I instruction without a control transfer, the next address advances by four bytes. This example deliberately excludes compressed instructions and traps. Extensions change the available instruction encodings and operations, so a binary built for an unsupported extension is not made compatible by using the same operating system name.
The implementation may rearrange invisible work
An ISA generally does not promise that one instruction occupies one cycle. Fetch, decoding, translation, operand readiness, execution resources, and memory access can all affect progress. A processor may split an architectural instruction into internal operations or overlap independent instructions. Another processor may implement the same visible contract more simply. Correct code relies on the documented results, exceptions, and memory rules rather than a drawing of one pipeline. Performance code also measures the particular implementation it intends to improve.
The contract has several layers. An ISA says what a call-related instruction does to registers or control flow. An application binary interface, or ABI, says which arguments use which registers and which registers a function must preserve. A language adds its own rules: an operation forbidden by the language can be optimized in ways that surprise someone reasoning only from hardware arithmetic. Inspect all relevant layers when an optimized program behaves unexpectedly, and resist treating the disassembly as the entire language specification.
Use a trace before a benchmark
A trace records the visible state after each instruction. Begin with known register contents, mark each source read, and update only the specified destinations. If an instruction overwrites a register, later instructions see the new value. If the destination is x0, later reads still return zero. A trace can expose a wrong register assumption without requiring performance tools. For memory operations, also record byte addresses and widths rather than drawing memory as an untyped list of numbers.
The probability lab models a different, deliberately narrower contract: exact binomial probabilities from a success probability and an integer trial count. Predict the mean from those inputs, then change one control and explain which outputs must change. This is a useful exercise in identifying a model boundary. It does not decode instructions, simulate a CPU, or measure branch behavior. Carry the same discipline back to machine code: read the model definition before deciding what an observation proves.
Work it through
Trace three RV32I operations
Initially x5=9 and x6=4. Execute ADD x7,x5,x6; ADDI x5,x7,-3; ADD x0,x5,x6, with no traps.
The first operation reads the original x5 and x6, so x7 becomes 9+4=13. Neither source register changes because neither is the destination.
ADDI uses the current x7 and a sign-extended immediate of minus three. Its result is ten, so x5 becomes 10 while x7 remains 13.
The final sum would be 10+4=14, but its destination is x0. The result is discarded, and a subsequent read of x0 still yields zero. Nothing in this trace states how many cycles execution needed.
The final visible values are x5=10, x6=4, x7=13, and x0=0; correctness and timing are separate questions.
The living notebook
Explore the model
Interactive lab · probability
Read a model as a contract
Set success probability p and integer trials n. Predict the exact binomial mean np before inspecting the bars. These controls define a probability distribution, not instruction decoding or CPU execution.
- Mean · np
- 5
- Variance · np(1−p)
- 2.5
- Total probability
- 1
These are exact binomial probabilities for independent trials with one fixed success probability. Playback tours the distribution; it does not resample outcomes. Parameter changes pause playback and recompute the model at the current elapsed time. Reset restores both parameters and returns time to zero. Playback starts paused. Adjust either parameter, then choose Play or Step.
Look forAn explicit model tells you which outputs follow from its inputs and which claims require other evidence.
Pause & reason
Check your understanding
Your turn
Try it yourself
A toy benchmark retires 1,200 instructions in 1,800 core cycles at a constant 3 GHz. Compute CPI and elapsed time, then state what this proves about other processors.
Take a moment to make a prediction or work it out on paper. Open a hint when you need one.
Give me a hint
Use the counter units explicitly; do not interpret clock frequency as instructions per second.
Compare with the solution
CPI is 1,800/1,200=1.5 cycles per instruction. Time is 1,800/(3 billion)=0.6 microseconds under constant frequency and the stated counter scope. It describes this run only; the ISA does not promise that CPI on another implementation.
Keep the idea
Take it with you
- An ISA specifies visible behavior, not a universal cycle count.
- ABIs and language rules add contracts above instruction semantics.
- Trace state for correctness and measure a specified machine for performance.
Read further
Original sources and deeper explanations to follow at your own pace.
Optional progress, saved in this browser when available. Revisit any lesson at any time.
Lesson not marked complete.