Part 0 · 2 chapters · ~15 min
From Transistors to Instructions
Switches to gates to adders to registers, and the fetch-decode-execute cycle that runs every program: one RISC-V add instruction followed from the program counter through decode, the register file and the ALU to write-back.
1
Transistors, gates and arithmetic
switches all the way down
- Transistors are voltage-controlled switches. CMOS pairs them so almost no power is drawn at rest.
- Gates are built from a handful of transistors. NAND alone can build any other gate.
- A half adder produces a sum (XOR) and a carry (AND).
- A full adder also takes a carry in from the previous bit.
- Chained adders let the carry ripple through, so real CPUs use lookahead adders.
- Latches, flip-flops, registers and multiplexers are the parts of a data path.
code
// a full adder and a 64-bit ripple-carry adder, in software, bit by bit
const fullAdder = (a: number, b: number, cin: number) => ({
sum: a ^ b ^ cin,
cout: (a & b) | (a & cin) | (b & cin), // majority
});
function add64(x: bigint, y: bigint): bigint {
let carry = 0, out = 0n;
for (let bit = 0n; bit < 64n; bit++) {
const { sum, cout } = fullAdder(Number((x >> bit) & 1n), Number((y >> bit) & 1n), carry);
out |= BigInt(sum) << bit; carry = cout; // the ripple: bit n waits for bit n-1
}
return out; // overflow past bit 63 is dropped, as in hardware
}
add64(40n, 2n); // 42nTRANSISTORS TO AN ADDER
switches become gates, gates become a full adder, adders become arithmetic
swipe the figure sideways, or tap expand for full screen
1/6
transistor
The transistor: a MOSFET conducts between source and drain when its gate voltage is high (n-type) or low (p-type). CMOS pairs one of each so that, in a steady state, one is always off: almost no current flows except while switching, which is why chips are efficient and why power grows with switching frequency.
2
The fetch-decode-execute cycle
one loop, billions of times a second
- Fetch the instruction at the PC.
- Decode its fields into control signals.
- Read the source registers.
- Execute in the ALU.
- Write the result back, going through memory first for loads.
- Set the next PC.
| architecture | style | where you meet it |
|---|---|---|
| x86-64 | CISC: variable-length instructions (1 to 15 bytes) decoded into internal micro-ops | most servers and laptops before 2020; Intel, AMD |
| ARM64 (AArch64) | RISC: fixed 4-byte instructions, load/store architecture | every phone, Apple silicon, AWS Graviton, most new servers |
| RISC-V | RISC, open standard, modular extensions | embedded, research, rising in servers |
| WebAssembly | a virtual stack machine, compiled again to one of the above | the browser; the Build Your Own compiler's VM is a cousin |
the frontend link
The phones your users carry run ARM. The 2 GB Android tier from the Architecture course is a phone with in-order or modestly out-of-order ARM cores, small caches and a low clock, which is why the same JavaScript takes six times longer there than on your laptop. Part 1 explains where that factor comes from.
FETCH, DECODE, EXECUTE
one instruction through a simple CPU: the program counter, the instruction, the register file, the ALU and memory
swipe the figure sideways, or tap expand for full screen
1/6
fetch
Fetch: the program counter (PC) holds the address of the next instruction. The CPU reads 4 bytes from that address (from the instruction cache): 0x002081B3, the machine code for add x3, x1, x2.