Quack is a small computer simulator written in C, together with its own
assembler. It simulates a simple CPU with memory, registers, and
memory-mapped I/O, and runs compiled programs stored in .duck binary
files, which qasm assembles from .qasm source. By the end of the
project the simulator can run a fully interactive maze game.
./quack run programs/maze.duckThe starting frame:
####################
#@.................#
#.##..#..######.##.#
#....##......#.....#
###.######.#.#.###.#
#.....#....#.#...#.#
#.###.#.####.###.#.#
#...#.#......#...#E#
#.#.#.########.###.#
####################
The maze is driven entirely by memory-mapped keyboard input and byte load/store instructions.
- 4096 bytes of memory, shared between code, data, the stack, and I/O
- Four general-purpose registers (
R0toR3), plus a program counter, a stack pointer, and a zero flag - Every instruction is exactly 4 bytes: one opcode byte, one register byte, and two further bytes for a second register or a 16-bit immediate value
- Keyboard and screen access are memory-mapped I/O, not special instructions
The full instruction set, memory map, and encoding are in docs/ISA.md.
See docs/SETUP.md if you don't already have a C
compiler and make. Once you do:
make
./quack run programs/sum10.duckExpected final value: R0(final)=0037. That's hexadecimal;
0x0037 = 55 decimal, and 1+2+...+10 = 55.
Then try the maze:
./quack run programs/maze.duckType one key and press Enter:
W= upA= leftS= downD= rightQ= quit
Goal: reach the exit E. Player is @, walls are #.
Debug mode prints the CPU state every step:
./quack run --debug programs/sum10.duckUse it to check whether pc advances correctly and whether a program is
looping.
Instead of typing, you can provide a script of keys:
./quack run --script "DDSSAAQ" programs/maze.duckThis makes debugging and test runs reproducible.
The scaffolding came with the course: the memory map, opcode definitions, program loader and command-line interface. We wrote the implementations inside it.
- The four memory functions (
mem_read8,mem_write8,mem_read16,mem_write16), with bounds checking and 16-bit little-endian access. - The fetch/decode/execute loop in
cpu_step, covering data movement, the ALU, byte and word load/store, control flow, and the stack withCALLandRET. - Memory-mapped keyboard and screen handling in
io_read8andio_write8. - Four instructions of our own:
INC(0x12),DEC(0x13),CLR(0x14) andOUTDEC(0x42), plus an instruction counter that prints atHALT.
Report.pdf explains the design and records who did what.
.qasm source assembles into a .duck binary:
./qasm programs/yourprogram.qasm -o programs/yourprogram.duckIf you omit -o, the output path is the input path with a trailing
.qasm replaced by .duck (or .duck appended if it has no such
suffix).
A program is one instruction, directive, or label per line. Registers are
r0 through r3; immediates are $5 or $0x0b; addresses are decimal,
0xHEX, or a label name. For example:
# Sum 1..10 into r0
irmovb $0, r0
irmovb $1, r1
irmovb $11, r2
irmovb $1, r3
loop:
addw r1, r0
addw r3, r1
cmpw r1, r2
je done
jmp loop
done:
halt
The full instruction list, byte encodings, and directives (.byte,
.word, .string, .org) are in docs/ISA.md.
make memtest # unit tests for the four memory functions
make test # everything belowmake test runs:
tests/roundtrip.sh: assembling every committed.qasmfile must reproduce its committed.duckbinary byte-for-byte.tests/e2e.sh: running every committed program must produce exactly its expected stdout.tests/errors.sh: feedingqasmmalformed source must fail with the right error.tests/coverage.sh: every opcode defined inquack.cmust be exercised by at least one program with readable.qasmsource.tests/runtime_errors.sh: programs that hit a documented runtime failure mode must exit non-zero with the specific stderr message for that failure, not a generic one.
Project for the Computer Architecture course at Maastricht University (Ashish Sai, Guangzhi Tang).
All rights reserved. See LICENSE.
This repository is published for viewing only. Parts of the code were provided as course material and remain the property of their authors; the LICENSE says which.