From ab22426a6819acd73291fb3b752c8dce27f57f9d Mon Sep 17 00:00:00 2001 From: n loewen Date: Sun, 24 Sep 2023 19:59:50 -0700 Subject: [PATCH] =?UTF-8?q?(docs)=20readme=20-=20WIP=20-=20Change/Move:=20?= =?UTF-8?q?Change=20readme=20to=20reflect=20ideas=20for=20a=20"family"=20o?= =?UTF-8?q?f=20Cardiograph=20computers=C2=A0+=20move=20information=20about?= =?UTF-8?q?=20the=20simulator=20to=20a=20separate=20file?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- micro/readme-micro.md | 41 ++++++ readme.md | 324 +++++++++++++++++++++++------------------- 2 files changed, 219 insertions(+), 146 deletions(-) create mode 100644 micro/readme-micro.md diff --git a/micro/readme-micro.md b/micro/readme-micro.md new file mode 100644 index 0000000..22a7a21 --- /dev/null +++ b/micro/readme-micro.md @@ -0,0 +1,41 @@ +### Dependencies + +- Node.js + + +### Quick examples + +Assemble and run: +```./assembler.js -i | ./cardiograph.js``` + +Assemble to a file: +```./assembler.js -i -o ``` + +Run from a file: +```./cardiograph.js -i ``` + + +### Assembler: assembler.js + +``` +Usage: ./assembler.js [-a] -i [-o ] + +-a, --annotate Output code with debugging annotations +-i, --in Assembly-language input +-o, --out Machine-code output +``` + +- If an output file is not provided, the output is printed to stdout + +- If the `annotate` flag is not set, the machine code is returned as a string of space-separated decimal numbers + + +### Simulator: cardiograph.js + +``` +Usage: ./cardiograph.js [-i ] + +-i, --in Machine-code input +``` + +- If an input file is not provided, the input is read from stdin \ No newline at end of file diff --git a/readme.md b/readme.md index 6acb72f..fd05f88 100644 --- a/readme.md +++ b/readme.md @@ -1,144 +1,98 @@ -# Cardiograph Mark I — simulator for an imaginary computer +# Cardiograph computers -Cardiograph is an imaginary computer. It has three main components: +The Cardiographs are a pair of imaginary computers. +The "Cardiograph Mark I" is an educational model of a mainframe machine. +The "MicroCardiograph" is a its miniaturized descendent, a microprocessor trainer. +They use the same instruction set and have very similar CPUs. +The main difference is in their peripheral hardware: +the Mark I is designed for batch processing programs on punched cards, +while the MicroCardiograph is designed to be used interactively. -1. the CPU, *Card* (short for 'Completely Analogue Risc Machine') -2. an input-output processor, *IO* -3. a display, *Graph* +The Cardiographs were built by an imaginary enterprise, the Electronic Computer Group (ECG). ## Simulator -### Dependencies -Cardiograph is an imaginary computer. It has three main components: - -1. the CPU, *Card* (short for 'Completely Analogue Risc Machine') -2. an input-output processor, *IO* -3. a display, *Graph* - -## Simulator - -### Dependencies - -- Node.js - - -### Quick examples - -Assemble and run: -```./assembler.js -i | ./cardiograph.js``` - -Assemble to a file: -```./assembler.js -i -o ``` - -Run from a file: -```./cardiograph.js -i ``` - - -### Assembler: assembler.js - -``` -Usage: ./assembler.js [-a] -i [-o ] - --a, --annotate Output code with debugging annotations --i, --in Assembly-language input --o, --out Machine-code output -``` - -- If an output file is not provided, the output is printed to stdout - -- If the `annotate` flag is not set, the machine code is returned as a string of space-separated decimal numbers - - -### Simulator: cardiograph.js - -``` -Usage: ./cardiograph.js [-i ] - --i, --in Machine-code input -``` - -- If an input file is not provided, the input is read from stdin - +There is a [simulator](micro/readme-micro.md) for the MicroCardiograph. ## CPU -### Registers and Flags +### Registers -There are three registers: +There are three 8-bit registers: -1. **A**, an 8-bit accumulator -2. **IP**, an 8-bit instruction pointer (aka program counter) -3. **flags**, a 4-bit flag register +1. **A**, the accumulator (and the only general-purpose register) +2. **IP**, the instruction pointer (aka program counter) +3. **Status** -The four flags are **O**verflow, **N**egative, **Z**ero, and **C**arry. +#### Status register -(Overflow is the high bit and carry is the low bit.) +The *high byte* holds the ID number of the current **IO** device. (See the section on [IO programming](#io-programming).) -In decimal: +The *low byte* holds four flags: +**O**verflow, **N**egative, **Z**ero, and **C**arry. + +The flags are accessed by number: | O | N | Z | C | |---|---|---|---| -| 3 | 2 | 1 | 0 | - +| 8 | 4 | 2 | 1 | ### Instruction set -#### Operations - -``` -Hex Mnem. Operand Effect - -00 END (ignored) Halt CPU -01 STO literal # mem[lit#] = A -02 STO address mem[mem[addr]] = A -03 LDA literal # A = lit# -04 LDA address A = addr -05 ADD literal # A = A + lit# -06 ADD address A = A + mem[addr] -07 SUB literal # A = A - lit# -08 SUB address A = A - mem[addr] -09 HOP literal # If A == lit#, skip next op (IP += 4) -0A HOP address If A == mem[addr], skip next instruction (IP += 4) -0B JMP literal # IP = lit# -0C JMP address IP = mem[addr] -0D FTG literal # Toggle flag, where flag number == lit# -0E FHP literal # Skip next op if flag is set, where flag number == lit# -0F NOP (ignored) None -``` - - Instructions are two bytes long: one byte for the opcode, one for the operand +```GGMM IIII``` - **G**roup, **M**ode, **I**nstruction -#### Effects on memory, flags, registers +| lo ↓ / hi → | 0 (G0, M0) | 5 (G1, M1) | 6 (G1, M2) | 9 (G2, M1) | A (G2, M2) | +|-------------|------------|------------|------------|------------|------------| +| **0** | END | LDA # | LDA ind | DEV # | DEV ind | +| **1** | NOP | STO # | STO ind | INP # | INP ind | +| **2** | | ADD # | ADD ind | OUT # | OUT ind | +| **3** | | SUB # | SUB ind | FED | FED | +| **4** | | JMP # | JMP ind | | | +| **5** | | JEQ # | JEQ ind | | | +| **6** | | JFL # | JFL ind | | | +| **7** | | FTG # | FTG ind | | | +| | | | | | | +| **8** | | MUL # | MUL ind | | | +| **9** | | DIV # | DIV ind | | | +| **A** | | RRL # | RRL ind | | | +| **B** | | RRR # | RRR ind | | | +| **C** | | ARL # | ARL ind | | | +| **D** | | ARR # | ARR ind | | | +| **E** | | JLT # | JLT ind | | | +| **F** | | JGT # | JGT ind | | | -``` -op mem flags IP +- RRL/RRR: Ring Rotate +- JLT: Jump Less Than -END +2 -NOP +2 +- DEV: IO device select +- FED: "feed" - line feed / end of card -STO w +2 -LDA r NZ +2 -ADD ONZC +2 -SUB ONZC +2 -HOP +2/+4 -JMP arg -FTG ONZC +2 -FHP ONZC +2/+4 +TODO: assess JMPs vs. HOPs -STO r,w +2 -LDA r,r NZ +2 -ADD r ONZC +2 -SUB r ONZC +2 -HOP r +2/+4 -JMP r arg -FTG r ONZC +2 -FHP r ONZC +2/+4 -``` + +### Connections (pinout) + +TBC + +| number | name | in/out? | description | +|---------|-----------|---------|---------------| +| 1 | RST | in | *reset* | +| 2 | VCC | in | *power* | +| 3 | GND | in | *ground* | +| 4 | CLK | in | *clock* | +| 5 - 13 | A0 - A7 | out | *address bus* | +| 15 - 23 | D0 - D7 | out | *data bus* | +| 24 | ABE | out | *address bus enable*:
low when the CPU is using the address bus | +| 25 | DBE | out | *data bus enable*:
low when the CPU is using the data bus | +| 26 | WAIT | in | *wait* — when pulled low,
the current operation is completed
and then execution pauses | ### Start-up +TODO: see if this makes sense for the mainframe + When starting up, the CPU executes a `JMP $FF`. Put differently: it starts executing instructions at the address contained in `$FF`. @@ -146,7 +100,118 @@ Put differently: it starts executing instructions at the address contained in `$ TODO: currently the simulator doesn't actually do this -### Assembly language +## Cardiograph Mark I (mainframe) + +The components of a Mark I are: + +- an ECG 101 Central Processing Unit +- an ECG 102 Core Memory Unit +- an ECG 103 Card Reader +- an ECG 104 Card Punch +- an ECG 105 Line Printer +- an ECG 106 Matrix Display + +Additionally, an *ECG 100 Keypunch* is used for the initial preparation of cards or tape. + +### Console + +The console is equipped with: + +- Power switch +- Load button +- Run button +- Run Single Step button +- Halt button +- Memory Read button +- Memory Read Next button +- Memory Write button +- Memory Write Next button +- 16 Sense switches (TBC) +- 8 Accumulator lights +- 8 Address lights +- 8 Data lights +- 8 Instruction Pointer lights (TBC) +- 4 Status Register lights + +## IO programming + +Only one input or output device can be accessed at a time. + +### Reading data + +1. Use `DEV xx` to select input device _xx_ +2. Use `INP yy` to read one card into memory, beginning at address _yy_ + +### Writing data + +1. Use `DEV xx` to select output device _xx_ +2. Use `OUT yy` to write one byte +3. Use `FED xx` to signal the end of a card, or the end of a line on the printer or display + +### Punched card format + +- Cards are punched in EBCDIC +- EBCDIC data is translated into binary by the card reader/punch +- Only columns 1-64 are used (for a maximum of 64 bytes of data per card) + +### Printer format + +The printer can print up to 64 characters per line. + +### Matrix display format + +- The display is a 5x5 grid of lights +- Each light has 16 possible brightness levels (0 = off, 15 = maximum) +- The display is written one line at a time +- After the display is selected with `DEV`, writing begins on the top line +- Writing wraps around and begins at the top again, if more than 5 lines are written + +### Device numbers + +1. Input - Card Reader +2. Output - Card Punch +3. Output - Line Printer +4. Output - Matrix Display + + +## MicroCardiograph (microprocessor trainer) + +The MicroCardiograph uses memory-mapped IO. + +### Memory map + +| Address | Used for... | +|----------|-----------------------------------------------| +| 00 to 19 | display (5x5) | +| 1A | pointer to display memory | +| 1B | keypad: value of latest key pressed | +| 1C | reserved for future use (bank switching flag) | +| 1D | initial IP | +| 1D to FE | free | +| FF | * ROM (unwriteable) pointer to initial IP | + +\* Not implemented yet + + +### Peripherals + +#### Keypad + +The value of the latest keypress on a hex keypad is stored at `$1B`. + +The keypad uses the same layout as the COSMAC VIP (and CHIP-8). The CPU simulator maps those keys onto a Qwerty set: + +`1` `2` `3` `C`   =   `1` `2` `3` `4` +`4` `5` `6` `D`   =   `Q` `W` `E` `R` +`7` `8` `9` `E`   =   `A` `S` `D` `F` +`A` `0` `B` `F`   =   `Z` `X` `C` `V` + +The arrow keys are also mapped onto the hex keypad: + +` ` `5` ` `   =   ` ` `↑` ` ` +`7` `8` `9`   =   `←` `↓` `→` + +## Assembly language ADD $01 ; comments follow a `;` @@ -174,37 +239,4 @@ Put differently: it starts executing instructions at the address contained in `$ - Prefix hexadecimal numbers with `$` (or `0x`) - Prefix binary numbers with `0b` -- Whitespace is ignored - -## Cardiograph memory map - -| Address | Used for... | -|----------|-----------------------------------------------| -| 00 to 19 | display (5x5) | -| 1A | pointer to display memory | -| 1B | keypad: value of latest key pressed | -| 1C | reserved for future use (bank switching flag) | -| 1D | initial IP | -| 1D to FE | free | -| FF | * ROM (unwriteable) pointer to initial IP | - -\* Not implemented yet - - -## Cardiograph peripherals - -### Keypad - -The value of the latest keypress on a hex keypad is stored at `$1B`. - -The keypad uses the same layout as the COSMAC VIP (and CHIP-8). The CPU simulator maps those keys onto a Qwerty set: - -`1` `2` `3` `C`   =   `1` `2` `3` `4` -`4` `5` `6` `D`   =   `Q` `W` `E` `R` -`7` `8` `9` `E`   =   `A` `S` `D` `F` -`A` `0` `B` `F`   =   `Z` `X` `C` `V` - -The arrow keys are also mapped onto the hex keypad: - -` ` `5` ` `   =   ` ` `↑` ` ` -`7` `8` `9`   =   `←` `↓` `→` \ No newline at end of file +- Whitespace is ignored \ No newline at end of file