Architecture · 1945 · John von Neumann

First Draft of a Report on the EDVAC

Decompose a programmable computer into arithmetic, control, memory, input, and output, with instructions represented in memory alongside data.

How to read the original

  1. Identify the report’s arithmetic, control, memory, and input/output functions before following circuit details.
  2. Track how stored orders determine the next operation and distinguish the report from the invented teaching ISA below.
  3. Treat the authorship line as report metadata, not as proof that one person alone originated stored-program computing.

Separate a machine’s functions from its parts

The report describes a programmable electronic machine through arithmetic, control, memory, and input/output functions. Its importance is architectural: stored orders can direct reusable hardware rather than requiring every new computation to be wired as a new physical arrangement. The linked edition is a later reprint of the 1945 draft. Neither the report’s byline nor this teaching model should erase the collaborative development of stored-program computing.

To make the idea concrete, use an original toy machine rather than pretending to reconstruct EDVAC’s exact instruction format. Memory contains numbered words. A word fetched as an instruction has an opcode and an address; a word loaded by an arithmetic instruction is interpreted as an integer. The machine state is memory M, accumulator A, program counter PC, and a halted flag. Assume unbounded mathematical integers for this exercise, so overflow does not distract from control sequencing.

Trace a stored program

Define LOAD a as A:=M[a], ADD a as A:=A+M[a], STORE a as M[a]:=A, and HALT as setting the halted flag. Nonhalting instructions advance PC by one. Put LOAD 20, ADD 21, STORE 22, and HALT at addresses zero through three. Initialize M[20]=7 and M[21]=5.

Beginning with PC=0 and A=0, the first fetch interprets M[0] as LOAD 20 and changes A to 7. The second fetch adds M[21], producing 12. The third writes 12 at address 22. The fourth halts. The hardware transition rules did not change; replacing ADD with another supported operation would change the computation through a memory edit.

An instruction word is not inherently a command in every context. Its role depends on which mechanism reads it. A loader may copy it as uninterpreted data; the control unit may later decode it as an order. This shared representational substrate makes assemblers, loaders, interpreters, and code inspection possible. It also means accidental writes to code locations can alter future execution unless protection mechanisms prevent them.

Branches turn sequences into algorithms

Add a conditional branch, BRANCHZERO a, which sets PC to a when A=0 and otherwise advances it. Now control flow depends on computed state. A loop can repeatedly update data and return to an earlier instruction until a predicate holds. To prove such a program correct, specify both the arithmetic invariant and the allowed PC locations. A correct addition circuit cannot rescue a branch aimed at the wrong instruction.

The minimal model also reveals a resource question. Instruction fetches and data accesses both use memory. A LOAD instruction requires fetching the instruction and reading its operand. If one abstract memory interface handles only one word per cycle and there is no overlap, these requests compete. This is a teaching cost model, not a numerical claim about the historical machine or all modern processors.

Keep abstraction boundaries visible

Architecture specifies observable instructions and state transitions. Implementation chooses circuits, timing, memory technology, and internal organization that realize them. Two implementations can execute the same stored program while having very different performance. Conversely, changing the integer width or overflow rule can change observable results even when instruction names stay unchanged.

Read the report as a design argument with historical constraints, not as a timeless claim that every computer must have one undifferentiated physical memory. Separate instruction and data caches, protected address spaces, and other later implementations can preserve stored-program behavior while changing the physical paths. The enduring idea is programmable control represented and manipulated within a computing system.

Reconstruction exercise

Extend the toy machine with SUB a and BRANCHZERO a. Design a finite program that copies a nonnegative input n into an output cell by repeatedly decrementing a counter and incrementing the output. You may add an unconditional JUMP instruction, but define its PC effect. State an invariant linking input, counter, and output. Trace n=2, explain why n=0 must avoid one subtraction, and identify what changes if arithmetic wraps modulo 256 instead of using mathematical integers.

Worked solution

Initialize counter to n and output to zero. At the loop header, load counter and branch to HALT when it is zero. Otherwise subtract a constant one and store counter, then load output, add one, store output, and jump to the loop header. The invariant is counter+output=n with both quantities nonnegative. For n=2, successive header states are (2,0), (1,1), and (0,2), after which the program halts. Checking zero before subtraction handles n=0 immediately and prevents a negative counter. The counter strictly decreases on each nonhalting iteration, establishing termination. With byte arithmetic, input must be restricted to representable values, and a misplaced subtraction on zero wraps to 255 rather than producing negative one. The instruction semantics and proof assumptions must agree. The unconditional JUMP sets PC to its target instead of also performing the ordinary increment.

Test the limits and transfer the idea

1. Interpreter trace · allow 45 minutes

Trace data becoming an instruction

Use this original integer-word machine, not an EDVAC instruction reconstruction. An instruction is 100 × opcode + address. Opcodes are 1 LOAD, 2 ADD, 3 STORE, 4 JUMP, and 9 HALT. LOAD and ADD read memory into accumulator A; STORE writes A. PC advances by one except for JUMP and HALT. Memory is writable and instructions are fetched afresh.

Set memory[0..5] = [120,303,403,900,322,900], memory[20] = 121, memory[21] = 7, and all other words to zero. Start with PC = A = 0. Trace every executed instruction and final memory[22]. Compare with a machine that forbids stores to addresses 0 through 5. Explain what this demonstrates and why it is not an argument that self-modification is necessary for general computation.

Get a starting hint

The store at address 1 changes the word that the jump at address 2 will later fetch. Decode a word when it is fetched, not just when the initial program is listed.

Compare your reasoning with the worked solution

At PC 0, word 120 means LOAD 20, so A becomes 121 and PC becomes 1. At PC 1, word 303 means STORE 3, replacing the original HALT word 900 with 121. At PC 2, word 403 means JUMP 3. The fresh fetch at PC 3 now reads 121, which means LOAD 21; A becomes 7. PC 4 contains STORE 22, so memory[22] becomes 7. PC 5 contains HALT. Six instructions execute, and the final accumulator is 7.

With code-write protection, the store to address 3 traps or is rejected according to the protection rule. It does not silently continue as the same machine: execution stops before memory[22] is written. If instead an implementation explicitly ignored the forbidden store, the later jump would reach the original HALT and memory[22] would remain zero. These are distinct specified policies.

The shared integer representation lets one instruction treat 121 as data and a later fetch treat it as an operation plus address. The effect depends on unified addressing, write permission, and fresh instruction fetches. It does not follow merely from the phrase stored program, nor does it make writable code indispensable: programs can keep instructions fixed while changing data and control state. The EDVAC report is the historical source for studying stored instructions and control organization; this small ISA and protection experiment are pedagogical constructions.

Check your reasoning

  • Decodes the modified word at fetch time and obtains memory[22] = 7.
  • Distinguishes a protection fault from an explicitly ignored write.
  • Separates a capability of the toy representation from a necessity or historical reconstruction.

2. Cost model · allow 40 minutes

Count the traffic behind a stored program

A toy accumulator program repeats LOAD 20; ADD 21; STORE 20 exactly N times, then HALT. Its code is unrolled, memory[20] begins at 0, and memory[21] is constant 3. Each instruction fetch costs one word transfer; LOAD and ADD each read one data word; STORE writes one. Registers and arithmetic have no transfer cost. There are no caches or speculative accesses.

Derive the final value, instruction-fetch count, data-transfer count, and total shared-port traffic. Evaluate N = 4. If instruction and data memories have separate one-word-per-cycle ports, derive a bandwidth lower bound and explain why that bound alone is not a complete execution-time prediction. State how a cached instruction stream would change the model.

Get a starting hint

Count instruction fetches separately from operand reads and result writes. A resource lower bound constrains a schedule but does not prove that all dependency constraints permit that schedule.

Compare your reasoning with the worked solution

After k completed repetitions, memory[20] = 3k. Initially this holds with k = 0. LOAD obtains 3k, ADD produces 3k+3, and STORE establishes the invariant for k+1. Thus the final value is 3N.

There are 3N + 1 instruction fetches, including HALT, and 3N data transfers: two reads and one write per repetition. A shared single-word port must therefore perform 6N + 1 transfers. For N = 4, the result is 12, with 13 instruction fetches, 12 data transfers, and 25 total transfers. If that port completes at most one transfer per cycle, execution requires at least 25 cycles under the stated model.

With independent instruction and data ports, the corresponding bandwidth bound is max(3N + 1, 3N) = 3N + 1 cycles, or 13 for N = 4. This is only a necessary bound. Fetch/decode timing, the load-to-add dependency, instruction buffering, memory latency, and when HALT completes determine whether it is attainable. Two ports do not by themselves prove a speedup of 25/13.

An instruction cache changes which fetches reach the measured memory port. One must specify whether the metric counts architectural fetches, cache accesses, or lower-memory transfers, and whether code is looped or unrolled. This is an original model for reasoning about control, arithmetic, and memory organization. It is not a performance measurement of the proposed EDVAC or a claim that its particular timing matches these assumptions.

Check your reasoning

  • Proves the final value 3N and counts 3N+1 instruction plus 3N data transfers.
  • Obtains the shared-port bound 25 and separate-port bound 13 for N=4.
  • Treats bandwidth as a lower bound and states how caching changes the measured boundary.

Check your understanding

Why does changing an instruction word change behavior without rewiring the toy machine?

  • The control mechanism decodes stored orders at runtime.
  • The memory cell changes the physical laws of the adder.
  • Every memory word is always executed.
Explanation

The fixed transition mechanism interprets the stored opcode and operands.

A proof assumes mathematical integers, but hardware wraps at 256. What must be checked?

  • Only the printed instruction names.
  • Whether overflow changes any invariant or control decision.
  • Nothing, because stored programs ignore representation.
Explanation

Arithmetic semantics are part of the model on which the proof depends.

Original paper and sources

John von Neumann. First Draft of a Report on the EDVAC. Moore School of Electrical Engineering, University of Pennsylvania, 30 June 1945. Linked MIT copy is a later reset reprint with editorial corrections, not an untouched scan of the typescript.

Read the original paper →

Read the primary paper: MIT