diff --git a/docs/architecture-specification.md b/docs/architecture-specification.md new file mode 100644 index 0000000..89b2631 --- /dev/null +++ b/docs/architecture-specification.md @@ -0,0 +1,106 @@ +# [DRAFT] Specification for the _Cardiograph Architecture_ + +## CPU + +### Registers + +There are four 8-bit registers: + +1. **A**, the accumulator (and the only general-purpose register) +2. **IP**, the instruction pointer (aka program counter) +3. **IOD**, the ID of the current I/O device +3. **Status** + +#### Status register + +The *high byte* holds the state of the four Sense Switches. (TODO: is this easy enough to do in hardware?) + +The *low byte* holds four flags: +**O**verflow, **N**egative, **Z**ero, and **C**arry. + +These are all addressed by number:* + +| S1 | S2 | S3 | S4 | | O | N | Z | C | +|----|----|----|----|-|----|----|----|----| +| 80 | 40 | 20 | 10 | | 08 | 04 | 02 | 01 | + +* (Because the core instruction set doesn't include bitwise operations) + +### Instruction set + +- Instructions are two bytes long: + one byte for the opcode, one for the operand + +TODO: revise this based on note dated 2023-09-24 + +```GGMM IIII``` - **G**roup, **M**ode, **I**nstruction + +| lo ↓ / hi → | 0 (G0, M0) | 5 (G1, M1) | 6 (G1, M2) | 9 (G2, M1) | A (G2, M2) | F (G3, M3) | +|-------------|------------|------------|------------|------------|------------|------------| +| **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 | | | RSL A | +| **9** | | DIV # | DIV ind | | | RSR A | +| **A** | | JLT # | JLT # | | | ASL A | +| **B** | | JGT # | JGT # | | | ASR A | +| **C** | | NOT # | NOT # | | | | +| **D** | | AND # | AND # | | | | +| **E** | | OR # | OR # | | | | +| **F** | | XOR # | XOR # | | | | + +TODO: assess JMPs vs. HOPs + +- RSL/RSR: Ring Shift Left/Right +- JLT/JGT: Jump Less/Greater Than +- DEV: select IO device +- FED: "feed" - line feed / end of card + +TODO: format/document better: + +1. core computational operations: low nibbles of 0x, 5x, 6x +2. arithmetic extension (optional): MUL, DIV +3. IO extension (optional): 9x, Ax +4. bitwise arithmetic extension (optional): NOT, AND, OR, XOR and RSL, RSR, ASL, ASR +5. control flow extension (optional): JLT, JGT + +- The mainframe system implements at least 1, 2, and 3 +- The microprocessor trainer implements 1 +- (see note dated 2023-09-24) + + +### Connections (pinout) + +TBC + +| name | in/out? | description | +|-----------|---------|---------------| +| RST | in | *reset* | +| VCC | in | *power* | +| GND | in | *ground* | +| CLK | in | *clock* | +| A0 - A7 | out | *address bus* | +| D0 - D7 | out | *data bus* | +| ABE | out | *address bus enable*:
low when the CPU is using the address bus | +| DBE | out | *data bus enable*:
low when the CPU is using the data bus | +| WAIT | in | *wait* — when pulled low,
the current operation is completed
and then execution pauses | +| /RD | out | TODO | +| /WR | out | | +| M/IO | out | | + + +### 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`. + +TODO: currently the simulator doesn't actually do this \ No newline at end of file diff --git a/docs/assembly-language.md b/docs/assembly-language.md new file mode 100644 index 0000000..e9512e0 --- /dev/null +++ b/docs/assembly-language.md @@ -0,0 +1,31 @@ +# Assembly language + +## Syntax + + ADD $01 ; comments follow a `;` + + ADD $FF ; this is direct addressing + ADD ($CC) ; this is indirect addressing + + END ; END and NOP don't require operands + ; (the assembler will fill in a default value of 0) + + @subroutine ; create a label + ADD $01 ; (it must be on the line before the code it names) + ADD $02 + + JMP @subroutine ; use a label as operand + ; the label will be replaced with + ; the address of the label + + #foo $FF ; define a constant + ; (must be defined before it is referenced) + + ADD #foo ; use a constant as an operand + + LDA * ; `*` is a special label referencing the memory address + ; where the current line will be stored after assembly + +- Prefix hexadecimal numbers with `$` (or `0x`) +- Prefix binary numbers with `0b` +- Whitespace is ignored \ No newline at end of file diff --git a/docs/mainframe-design.md b/docs/mainframe-design.md new file mode 100644 index 0000000..96bfdd9 --- /dev/null +++ b/docs/mainframe-design.md @@ -0,0 +1,100 @@ +## Cardiograph Mark I (mainframe) + +The components of a Mark I are: + +- an CG 101 Central Processing Unit +- an CG 102 Core Memory Unit +- an CG 103 Print-Key-Punch +- an CG 104 Matrix Display + +### Console + +TBC TBC TBC + +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 +- 4 Sense Switches + +- 8 Accumulator lights +- 8 Address lights +- 8 Data lights +- 8 Instruction Pointer lights (review IP size?) +- 8 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 byte into memory at address _yy_ + +TODO: find a way to allow the input device to refuse to provide input + +### Writing data + +1. Use `DEV xx` to select output device _xx_ +2. Use `OUT yy` to write one byte from memory at address _yy_ +3. Use `FED xx` to... + - card punch: load a new card + - printer: begin a new line (CR, LF) + - display: begin a new line + +### Punched card format + +FIXME: +- ~~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 format is the same as the card format +- One line of printing is equivalent to one card +- 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. card reader / typewriter +2. card punch / line printer +3. display + +### Print-Key-Punch configurations + +A dial allows you to select which input device to connect to the CPU: + +1. none +2. card reader +3. keyboard + +A similar dial selects the output device to connect: + +1. none +2. card punch +3. printer + +Thus, this all-in-one device allows the following configurations: + +| | printer | card punch | none | +|-----------------|----------------------|------------------|--------------------------| +| **keyboard** | ***teletypewriter*** | ***auto punch*** | ***keypunch (offline)*** | +| **card reader** | (keys + print) | card duplicator | (card reader) | +| **none** | line printer | (auto punch) | (scrap metal) | \ No newline at end of file diff --git a/docs/micro-design.md b/docs/micro-design.md new file mode 100644 index 0000000..b34d8e2 --- /dev/null +++ b/docs/micro-design.md @@ -0,0 +1,40 @@ +# [DRAFT] Design for the _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`   =   `←` `↓` `→` + +### Keypad as monitor input + +TODO \ No newline at end of file diff --git a/readme.md b/readme.md index 3da513b..c29479e 100644 --- a/readme.md +++ b/readme.md @@ -31,276 +31,9 @@ while the MicroCardiograph is designed to be used interactively. _[Micro ElectroCardiograph (µECG)](micro/readme-micro.md)_ is a simulator for the Micro Cardiograph. -## CPU +## Documentation -### Registers - -There are four 8-bit registers: - -1. **A**, the accumulator (and the only general-purpose register) -2. **IP**, the instruction pointer (aka program counter) -3. **IOD**, the ID of the current I/O device -3. **Status** - -#### Status register - -The *high byte* holds the state of the four Sense Switches. (TODO: is this easy enough to do in hardware?) - -The *low byte* holds four flags: -**O**verflow, **N**egative, **Z**ero, and **C**arry. - -These are all addressed by number:* - -| S1 | S2 | S3 | S4 | | O | N | Z | C | -|----|----|----|----|-|----|----|----|----| -| 80 | 40 | 20 | 10 | | 08 | 04 | 02 | 01 | - -* (Because the core instruction set doesn't include bitwise operations) - -### Instruction set - -- Instructions are two bytes long: - one byte for the opcode, one for the operand - -TODO: revise this based on note dated 2023-09-24 - -```GGMM IIII``` - **G**roup, **M**ode, **I**nstruction - -| lo ↓ / hi → | 0 (G0, M0) | 5 (G1, M1) | 6 (G1, M2) | 9 (G2, M1) | A (G2, M2) | F (G3, M3) | -|-------------|------------|------------|------------|------------|------------|------------| -| **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 | | | RSL A | -| **9** | | DIV # | DIV ind | | | RSR A | -| **A** | | JLT # | JLT # | | | ASL A | -| **B** | | JGT # | JGT # | | | ASR A | -| **C** | | NOT # | NOT # | | | | -| **D** | | AND # | AND # | | | | -| **E** | | OR # | OR # | | | | -| **F** | | XOR # | XOR # | | | | - -TODO: assess JMPs vs. HOPs - -- RSL/RSR: Ring Shift Left/Right -- JLT/JGT: Jump Less/Greater Than -- DEV: select IO device -- FED: "feed" - line feed / end of card - -TODO: format/document better: - -1. core computational operations: low nibbles of 0x, 5x, 6x -2. arithmetic extension (optional): MUL, DIV -3. IO extension (optional): 9x, Ax -4. bitwise arithmetic extension (optional): NOT, AND, OR, XOR and RSL, RSR, ASL, ASR -5. control flow extension (optional): JLT, JGT - -- The mainframe system implements at least 1, 2, and 3 -- The microprocessor trainer implements 1 -- (see note dated 2023-09-24) - - -### Connections (pinout) - -TBC - -| name | in/out? | description | -|-----------|---------|---------------| -| RST | in | *reset* | -| VCC | in | *power* | -| GND | in | *ground* | -| CLK | in | *clock* | -| A0 - A7 | out | *address bus* | -| D0 - D7 | out | *data bus* | -| ABE | out | *address bus enable*:
low when the CPU is using the address bus | -| DBE | out | *data bus enable*:
low when the CPU is using the data bus | -| WAIT | in | *wait* — when pulled low,
the current operation is completed
and then execution pauses | -| /RD | out | TODO | -| /WR | out | | -| M/IO | out | | - - -### 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`. - -TODO: currently the simulator doesn't actually do this - - -## Cardiograph Mark I (mainframe) - -The components of a Mark I are: - -- an CG 101 Central Processing Unit -- an CG 102 Core Memory Unit -- an CG 103 Print-Key-Punch -- an CG 104 Matrix Display - -### Console - -TBC TBC TBC - -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 -- 4 Sense Switches - -- 8 Accumulator lights -- 8 Address lights -- 8 Data lights -- 8 Instruction Pointer lights (review IP size?) -- 8 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 byte into memory at address _yy_ - -TODO: find a way to allow the input device to refuse to provide input - -### Writing data - -1. Use `DEV xx` to select output device _xx_ -2. Use `OUT yy` to write one byte from memory at address _yy_ -3. Use `FED xx` to... - - card punch: load a new card - - printer: begin a new line (CR, LF) - - display: begin a new line - -### Punched card format - -FIXME: -- ~~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 format is the same as the card format -- One line of printing is equivalent to one card -- 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. card reader / typewriter -2. card punch / line printer -3. display - -### Print-Key-Punch configurations - -A dial allows you to select which input device to connect to the CPU: - -1. none -2. card reader -3. keyboard - -A similar dial selects the output device to connect: - -1. none -2. card punch -3. printer - -Thus, this all-in-one device allows the following configurations: - -| | printer | card punch | none | -|-----------------|----------------------|------------------|--------------------------| -| **keyboard** | ***teletypewriter*** | ***auto punch*** | ***keypunch (offline)*** | -| **card reader** | (keys + print) | card duplicator | (card reader) | -| **none** | line printer | (auto punch) | (scrap metal) | - -## 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 `;` - - ADD $FF ; this is direct addressing - ADD ($CC) ; this is indirect addressing - - END ; END and NOP don't require operands - ; (the assembler will fill in a default value of 0) - - @subroutine ; create a label - ADD $01 ; (it must be on the line before the code it names) - ADD $02 - - JMP @subroutine ; use a label as operand - ; the label will be replaced with - ; the address of the label - - #foo $FF ; define a constant - ; (must be defined before it is referenced) - - ADD #foo ; use a constant as an operand - - LDA * ; `*` is a special label referencing the memory address - ; where the current line will be stored after assembly - -- Prefix hexadecimal numbers with `$` (or `0x`) -- Prefix binary numbers with `0b` -- Whitespace is ignored \ No newline at end of file +- [Specification for the Cardiograph Architecture](docs/architecture-specification.md) +- [Design for the mainframe computer](docs/mainframe-design.md) +- [Design for the micro computer](docs/micro-design.md) +- [Assembly Language](docs/assembly-language.md) \ No newline at end of file