CPU simulator: guide

How a computer runs a program, one step at a time · Week 1: Python

The simulator is a small computer in the style of John von Neumann's 1945 design. The program and its data sit side by side in the same memory. The processor repeats one cycle for every instruction: fetch it from memory, decode it, execute it. Every line of Python you write in this course ends up as long runs of instructions like these.

Open the simulator Open it with Simple Add loaded

On this page
  1. The screen, part by part
  2. Controls and shortcuts
  3. Instructions: how a number becomes a command
  4. Walkthrough 1: Simple Add (15 + 27)
  5. Walkthrough 2: Countdown loop (5, 4, 3, 2, 1)
  6. Walkthrough 3: Input and output
  7. Questions for class
  8. What the simulator leaves out

1. The screen, part by part

The simulator after six steps of Simple Add: the accumulator holds 42 and all three buses are highlighted.

Simple Add after six steps: the ADD instruction has just run, so the accumulator holds 42. Each memory cell shows its bits and, below them, what they mean.

PartWhat it isWhat to watch
Memory (RAM), left100 numbered cells. Each shows its address (8 bits, and #0 to #99), its content (16 bits, split into the 4-bit opcode and the 12-bit operand), and what the bits mean: → LOAD 90 for a cell of the program, = 15 for a data cell. Hover over a cell to see both readings of the same bits. Cells 0 onwards hold the program; cells 90–92 hold the data.The crimson border marks the next instruction (the cell the PC points to). A blue glow marks the cell just read; a blue fill marks the cell just written.
Program Counter (PC)The address of the next instruction.It goes up by one at every fetch. Jumps (JMP, JZ) overwrite it: that is how loops happen.
MAR (memory address register)The address the processor is about to read or write.During fetch it copies the PC; during LOAD/ADD/SUB/STO it holds the data address (90, 91, 92).
MDR (memory data register)The value that has just come from memory.During fetch it holds the instruction; the IR then copies it.
Instruction Register (IR)The instruction being worked on, in 16 bits.The line below the bits spells it out, for example LOAD 90.
Accumulator (ACC)The one working register. Every calculation starts and ends here.The result of ADD and SUB appears here; STO copies it to memory.
ALUThe arithmetic logic unit, which does the sums.Shows the instruction name while an instruction executes, otherwise Idle.
Control UnitRuns the cycle.Shows the phase coming next: FETCH, DECODE or EXECUTE (or HALTED, WAIT_INPUT).
BusesThe wires between processor and memory. The address bus carries where, the data bus carries what, the control bus carries commands.The buses used in the last step light up in crimson. A fetch uses address and data; a decode only control; LOAD/ADD/SUB/STO use all three.
Input, rightA box that becomes active when the program asks for a value (IN).Type a number and press Enter or Send.
OutputValues the program has sent out with OUT, in binary and decimal.Countdown writes 5, 4, 3, 2, 1 here.
Execution LogOne sentence per step, saying what just happened.Read it aloud while stepping: it is the script for the walkthroughs below.

2. Controls and shortcuts

ControlKeyWhat it does
Program menu + LoadPuts one of three example programs and its data into memory and resets the processor.
StepSpaceRuns one phase: fetch, decode or execute. One instruction takes three steps.
Run / PauseEnterSteps automatically. The Speed slider sets the pace (right is faster).
ResetRReloads the current program and sets every register to 0.
OpcodesShows the instruction set (the table in section 3).
Presentation modeP, then + / −Enlarges the page for the lecture hall and shows its address in the top bar.
Help?Lists the shortcuts.

Links that open in a given state. Add these to the address to prepare a slide or a class exercise:

3. Instructions: how a number becomes a command

Every memory cell holds 16 bits. When the processor fetches a cell as an instruction, it reads the first 4 bits as the opcode (which command) and the other 12 bits as the operand (usually a memory address):

0001 000001011010
└──┘ └──────────┘
LOAD      90

The same 16 bits could just as well be read as the number 4186. Nothing in the cell says whether it is an instruction or data: it depends only on whether the PC points at it. That is the heart of the von Neumann design. The simulator labels the cells of the loaded program as instructions (→ LOAD 90) and the others as numbers (= 15); hover over any cell to see both readings.

OpcodeNameWhat it doesMemory?
0000NOPNothing.
0001LOAD aACC = memory[a]read
0010ADD aACC = ACC + memory[a]read
0011SUB aACC = ACC − memory[a]read
0100STO amemory[a] = ACCwrite
0101JMP aPC = a: continue at address a
0110JZ aIf ACC is 0, PC = a; otherwise carry on
0111INWait for a number in the Input box, put it in ACC
1000OUTSend ACC to the Output box
1111HALTStop

4. Walkthrough 1: Simple Add (15 + 27)

Open with Simple Add loaded  12 steps · about 5 minutes

addr  bits                 instruction
 0    0001 000001011010    LOAD 90     ACC = 15
 1    0010 000001011011    ADD 91      ACC = 15 + 27
 2    0100 000001011100    STO 92      memory[92] = 42
 3    1111 000000000000    HALT
 ...
90    0000000000001111     data: 15
91    0000000000011011     data: 27
92    0000000000000000     result goes here
StepPhaseWhat happensPoint out
1FETCHPC 0 → MAR; memory[0] → MDR → IR; PC becomes 1Address and data buses light up. The PC already points at the next instruction.
2DECODEopcode 0001 = LOAD, operand 90Only the control bus: decoding happens inside the processor.
3EXECUTEACC = memory[90] = 15Cell 90 glows: the processor goes back to memory, this time for data.
4–6F · D · EADD 91: ACC = 15 + 27 = 42The ALU shows ADD. The result exists only inside the processor so far.
7–9F · D · ESTO 92: memory[92] = 42Cell 92 turns blue: the first write. It now holds 0000000000101010, which is 42.
10–12F · D · EHALTThe Control Unit shows HALTED. Four instructions took twelve steps.
Ask the room.

5. Walkthrough 2: Countdown loop (5, 4, 3, 2, 1)

Open with Countdown loaded  105 steps in total · step through the first round, then press Run

addr  instruction    meaning
 0    LOAD 90        ACC = 5 (start value)
 1    STO 91         counter = ACC
 2    LOAD 91        ACC = counter          ◄─ loop starts here
 3    JZ 8           if ACC is 0: go to 8 (HALT)
 4    OUT            show the counter
 5    SUB 92         ACC = ACC − 1
 6    STO 91         counter = ACC
 7    JMP 2          back to address 2      ─┘
 8    HALT
90: 5   91: counter   92: 1

In Python this is

counter = 5
while counter != 0:
    print(counter)
    counter = counter - 1
StepsWhat happensPoint out
1–6LOAD 90, STO 91: counter = 5Set-up, done once.
7–12LOAD 91, then JZ 8 with ACC = 5The log says ACC is 5, not 0, so carry on: this is the test of the while.
13–15OUT5 appears in Output. Link to this state
16–21SUB 92, STO 91counter becomes 4; cell 91 turns blue.
22–24JMP 2Watch the PC: it jumps back from 8 to 2. The crimson border moves back up the memory. Link to this state
25–102Four more rounds, 21 steps eachPress Run and turn up the speed.
103–105ACC is 0: JZ jumps to 8, HALTOutput shows 5, 4, 3, 2, 1. Link to the end
Ask the room.

6. Walkthrough 3: Input and output

Open with Input/Output loaded

0  IN        wait for a number
1  OUT       show it
2  JMP 0     and again
  1. Step three times. At the third step the Control Unit shows WAIT_INPUT and the Input box becomes active.
  2. Type a number, press Enter. The number arrives in the accumulator.
  3. Step six more times: OUT shows it, JMP goes back to 0 and the processor waits again.

This program never halts; press Reset to stop. It is the pattern of every interactive program: wait for input, react, wait again.

7. Questions for class

  1. A program with 4 instructions took 12 steps. Why do computers need billions of steps per second?
  2. Memory cell 0 holds 0001000001011010. Is that an instruction or the number 4186? Who decides?
  3. The processor can only do one of a handful of things. Where does all the complexity of Python come from?
  4. Find the line in the Countdown that corresponds to Python's while counter != 0.

8. What the simulator leaves out

Real processors have many registers rather than one accumulator, work on several instructions at once (pipelining), keep copies of memory close by (caches), and use far larger instruction sets. The phases here are also simplified: a fetch is shown as one step, while real hardware spends several clock ticks on it. None of this changes the basic idea the simulator shows: a program is data in memory, and a processor runs it by fetching, decoding and executing one instruction after the other.

Used in the Week 1 lecture. Source: tools/cpu.