2IC30 · Topic 05
Processor Architecture
A real CPU: datapath, ALU, instruction set, encoding and the control 'Conductor'.
Von Neumann datapath, buses & ALU
The von Neumann architecture stores program and data together in memory. The CPU's datapath is the network of registers, buses and an ALU through which data flows.
Simple-processor components: REGS register file (R0–R3), 2 reads + 1 write. ALU arithmetic-logic unit with inputs Ain, Bin, an op code, and condition-code output. Three buses: Abus (IP or RA), Bbus (IP, IR, ΣR, RB…), Cbus (ALU result back to registers/memory). RAM 512×16, accessed via address ΣA, write data ΣW, read data ΣR. Programmer-visible registers: IP/PC (instruction pointer), R0–R3, CC (flags C,N,V,Z). Implementation-only registers: IR (instruction register), ΣA/ΣW/ΣR (memory interface).
The ALU is built from 1-bit 'bit slices' chained via carry-in/carry-out, all controlled by the same lines (e.g. F0,F1,ENA,ENB,INVA). Typical ALU ops: loadA, loadB, A+1 (inc), A−1 (dec), A+B (add), A−B (sub), A∧B, A∨B, A⊕B, plus constants. The ALU also produces the C,N,V,Z flags. Word size: all registers 16 bits except CC (4 bits).
This toy CPU mirrors real ones: registers, ALU, buses and a control unit. Modern chips add pipelines, caches and many functional units but keep this skeleton.
Von Neumann datapath, buses & ALU worked examples
1 questions
Common mistakes
- Sending two sources onto one bus in the same cycle.
- Confusing ΣA (address) with ΣR/ΣW (read/write data).
- Forgetting CC is updated by ALU operations.
Exam tips
- Q4 gives a datapath figure (sometimes modified, e.g. an added temp register T) — use exactly its buses and signals.
- Each transfer must name source register(s), destination, bus, and ALU op.
Memory aids
- A/B buses feed the ALU; C bus carries the result back.
- Visible = IP, R0–R3, CC; hidden = IR, ΣA/ΣW/ΣR.
Von Neumann datapath, buses & ALU practice
2 questions
Instruction set & addressing modes
The CPU executes a small set of instruction types: load/store, arithmetic/logic, and flow control.
LOAD reg operand (reg ← operand), STOR reg operand (operand ← reg, operand must be a memory location). Operand forms: (0) value — a literal number (direct) (1) reg — a register (direct) (2) [address] — RAM at a literal address (indirect) (3) [reg] — RAM at the address in a register (indirect) ALU instructions : ADD/SUB/AND/OR/XOR reg operand → reg ← reg op operand (and set CC). Flow control : BRA (always), conditional Bcc (BEQ Z=1, BNE Z=0, BMI N=1, BPL N=0, BVS/BVC, BCS/BCC) — IP ← IP + displacement if the condition holds. BRS/RTS for subroutine call/return.
Richer machines (PP2, ARM) add modes: immediate , register indirect [R1], absolute [42], indexed [R1+42] (base+offset, for structs/arrays), register-indexed [R1+R2], indirect indexed [[R2]+42] (OO objects), and auto inc/dec [R3++], [--R3] (stacks). Displacements in branches are relative, enabling code relocation. Note [address] direct memory operands are NOT available on ARM/PP2.
Addressing modes map directly onto programming-language constructs: indexed = array access, base+offset = struct fields, auto-dec = stack push.
Instruction set & addressing modes worked examples
1 questions
Common mistakes
- Using STOR with a literal/register operand (must be a memory location).
- Confusing direct value vs indirect [value].
- Counting branch displacement from the wrong instruction (IP already points past the branch).
Exam tips
- Map each high-level operand to the right addressing mode in Q5.
- Branch displacement is relative to the instruction AFTER the branch.
Memory aids
- [brackets] = 'contents of memory at'. No brackets = the value itself.
- STOR's destination must be memory.
Instruction set & addressing modes practice
2 questions
Instruction encoding & formats
Each instruction is a fixed 16-bit word: an opcode field plus register and value/displacement fields.
Simple-processor formats (16 bits): Load/store/ALU: op op op op | r r | d | vvvvvvvvv — 4-bit opcode, ra, rb, a direct/indirect bit, and a value field. e.g. STOR=0011, LOADdirect=0100, LOADindirect=0101, ADDd=0110…XORi=1111. Conditional jump: 0001 | ccc | ddddddddd — condition code + 9-bit displacement. Unconditional/call/return: BRA 0000 0 0 0 d… , BRS 0000 r r 1 d… , RTS 0010 r r 0 0… .
Design trade-offs (also Q6 theory): number of operands (0=stack/implied, 1=accumulator, 2=flexible, 3=very flexible) trades flexibility against instruction size. Fixed length = easy fetch/decode but wastes bits; variable length = compact but complex decode. Expanding opcodes reuse one opcode value to mean 'more opcode follows', giving Huffman-like efficiency. This underlies the RISC vs CISC debate: RISC (ARM) = simple fixed instructions; CISC (x86) = complex variable instructions.
ARM uses 32-bit fixed instructions (Thumb adds 16-bit); x86 uses 1–15-byte variable instructions. Encoding density affects code size and instruction-cache pressure.
Instruction encoding & formats worked examples
1 questions
Common mistakes
- Forgetting the displacement/value field is 2's-complement (signed).
- Mixing up direct vs indirect opcode bit.
- Assuming variable-length is always better (decode is harder).
Exam tips
- You usually get the instruction-set summary as an aid — practise reading its encoding tables.
- Relate operand count and instruction length to RISC/CISC for Q6.
Memory aids
- Fixed length: simple decode, wasted bits. Variable: compact, complex decode.
- RISC = Reduced/regular; CISC = Complex/compact.
Instruction encoding & formats practice
2 questions
The Conductor: fetch–execute & RTL
The Conductor is the control FSM that drives the datapath, step by step, to execute each instruction. Its steps are written in Register Transfer Language (RTL) : dest ← expr .
Every instruction starts with Instruction Fetch (3 steps): 0: ΣA, IP ← IP(Bbus), IP(Abus)+1 (incA) ; address = IP, IP++ 1: ΣR ← RAM[ΣA] ; read instruction 2: IR ← ΣR(Bbus) (loadB) ; into instruction register Then instruction-specific steps. Example ADD RA RB adds one step: 3: RA, CC ← RA(Abus)+RB(Bbus), ALU.cc (add) Indirect operands need extra cycles to fetch the operand from RAM (e.g. XOR RA [address] uses 6 cycles).
The execute phase of fetch/decode/operand-fetch/execute/write-back varies per instruction (3–6 cycles). Conditional branches branch the Conductor FSM: BEQ taken does IP ← IP + IR.comp (sign-extended displacement) in 4 cycles; not-taken finishes in 3. The whole control automaton is ~56 states. RTL transfers must specify which bus carries each value and which ALU op is used, because that is exactly what the control signals (IE/OE/ALU.op) encode.
This micro-step control is 'hardwired' here; alternatively a microprogram stores the steps in a control memory — the CISC approach.
The Conductor: fetch–execute & RTL worked examples
1 questions
Common mistakes
- Skipping the 3 fetch cycles — every instruction begins with them.
- Putting two writes onto one bus in a single cycle.
- Forgetting to set CC where the instruction requires it.
- Not naming the bus/ALU op for each transfer.
Exam tips
- Q4 is pure RTL — number each cycle and annotate bus + ALU op.
- Count cycles: fetch(3) + per operand dereference(2) + execute(1).
- Use the exact register/bus names from the given figure.
Memory aids
- Fetch is always 3 cycles: address→read→IR.
- Each [indirect] level costs ~2 extra cycles.
The Conductor: fetch–execute & RTL practice
2 questions
Prefetching, speed-up & I/O
Most fetch cycles are spent reading the next instruction. Prefetching overlaps that with executing the current one, so instructions finish in fewer cycles.
An Instruction Prefetch Buffer (IPB) (plus an IP incrementer and a bypass) lets the CPU start reading the next instruction while still finishing the current one, without clobbering IR too early. Result (cycles, no prefetch → with prefetch): ADD RA RB 4→1; XOR RA [addr] 6→3; STOR RA [RB] 5→2; BEQ 4/3 → 4/1.
With prefetch, IP runs ahead (points two instructions on), so a taken branch wastes the prefetched instruction and must correct IP. The number of memory accesses is a hard lower bound on cycles. Other speed-ups: more buffer registers, more bypasses (e.g. ALU→ΣA), dedicated address adders. Modern CPUs go further with out-of-order execution (respect only true data dependencies) guarded by barrier instructions. I/O : dedicated IN/OUT registers under outside control; polling repeatedly reads status (C flag = no new data, V flag = data overwritten) — simple but CPU-expensive, motivating interrupts.
Prefetch and pipelining are why real CPUs approach 1 instruction/cycle; branch misprediction (the 'wasted prefetch') is still a major performance factor.
Prefetching, speed-up & I/O worked examples
1 questions
Common mistakes
- Assuming prefetch helps taken branches as much as straight-line code.
- Forgetting IP points ahead when prefetching.
- Thinking polling is cheap — it busy-waits.
Exam tips
- Know the cycle-count table with/without prefetch.
- Polling vs interrupts is a Q6 talking point — polling wastes CPU cycles.
Memory aids
- Prefetch = read next while finishing now.
- Taken branch = wasted prefetch + IP fix-up.
Prefetching, speed-up & I/O practice
2 questions