From 10e0c53890701abe53c80f1da4a0b64bbd05914c Mon Sep 17 00:00:00 2001 From: Jan Tuomi Date: Tue, 28 Mar 2023 21:27:05 +0300 Subject: Initial commit --- .gitignore | 4 + .vscode/launch.json | 17 + .vscode/settings.json | 3 + 16bit-cpu.md | 82 + Makefile | 22 + digital/atk16.dig | 1828 +++++++++++++++++ digital/atk16_alu.dig | 2651 ++++++++++++++++++++++++ digital/atk16_alu_carryfix.dig | 270 +++ digital/tests_alu.dig | 26 + logisim/CPU16.circ | 4344 ++++++++++++++++++++++++++++++++++++++++ src/assembler.py | 263 +++ src/test.atk16 | 33 + src/test_alu.py | 48 + src/test_utils.py | 93 + src/ucode.py | 103 + 15 files changed, 9787 insertions(+) create mode 100644 .gitignore create mode 100644 .vscode/launch.json create mode 100644 .vscode/settings.json create mode 100644 16bit-cpu.md create mode 100644 Makefile create mode 100644 digital/atk16.dig create mode 100644 digital/atk16_alu.dig create mode 100644 digital/atk16_alu_carryfix.dig create mode 100644 digital/tests_alu.dig create mode 100644 logisim/CPU16.circ create mode 100755 src/assembler.py create mode 100644 src/test.atk16 create mode 100755 src/test_alu.py create mode 100644 src/test_utils.py create mode 100755 src/ucode.py diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a660363 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +out/ +*.pdf + +*.pyc \ No newline at end of file diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..e60d76b --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,17 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "Python: Current File", + "type": "python", + "request": "launch", + "program": "${file}", + "console": "integratedTerminal", + "justMyCode": true, + "args": ["test.atk16", "test.bin"] + } + ] +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..3516cb9 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "python.formatting.provider": "autopep8" +} \ No newline at end of file diff --git a/16bit-cpu.md b/16bit-cpu.md new file mode 100644 index 0000000..73b588e --- /dev/null +++ b/16bit-cpu.md @@ -0,0 +1,82 @@ +# 16-bit CPU design doc + +## Features +16-bit data +16-bit address width +16-bit instruction width + +MISC +4-bit opcodes + +instruction format +xxxx xxxx xxxx xxxx - xxxx xxxx xxxx xxxx + +General purpose registers: + + 000: Zero register + 001: RA + 010: RB + 011: RC + 100: RD + +Special registers: MAR (memory address), IR (instruction), FR (flag) + +Serial peripheral ports: + + 101: PA + 110: PB + +for communicating with the outside world. + +Expansion port that connects directly to the main bus + +Addressing mode: indirect absolute (addresses are stored in registers and point to a complete address) + +## Operations + +### Memory operations +Format: [ 4 opcode . 3 rt . 3 rx . 6 unused ] + + ldr [rx] [rt] # load value from memory at address (register value) rx to rt + str [rx] [rt] # store value in rt to memory address (register value) rx + +### Immediate operations +Format: [ 4 opcode . 3 reg . 9 imm ] + + ldi [rt] [imm] # load immediate value imm to rt + +### Nullary operations +Format: [ 4 opcode . 12 unused ] + + hlt # halt + +### Arithmetic and logic operations +Format [ 4 opcode . 3 rt . 3 rl . 3 rr . 3 alu S ] + + alu [rl] [rr] [rt] [S] # compute rl ? rr where ? is the operation defined by + # 0SSS in the ALU, and store result in rt + # see datasheet of 74382 and ALU impl + als [rl] [rr] [rt] [S] # compute rl ? rr where ? is the operation defined by + # 1SSS in the ALU, and store result in rt + # see datasheet of 74382 and ALU impl + +Note: mul, div, gt, lt, eq, neq are implemented as pseudoinstructions in the assembler + +### Jump +Format: [ 4 opcode . 3 rx . 9 unused ] + + jmp [rx] # Jump to address in register rx + +### Branch +Format: [ 4 opcode . 1 unused . 2 flag . 9 addr ] +Branch if flag is set (where flag 0b00 = Z, 0b01 = C, ...) + + br [flag] [addr] + +Flags: +- C = ALU carry bit +- O = ALU overflow bit +- Z = ALU zero bit +- S = ALU sign bit + +Interrupt lines: 1 (IRQ) diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..f3366b0 --- /dev/null +++ b/Makefile @@ -0,0 +1,22 @@ +.PHONY: all + +py = /usr/bin/env python3 +digital_path = $(HOME)/.local/share/Digital/digital.jar + +start-digital: + java -jar $(digital_path) & + +# make assemble asm=src/program.atk16 out=out/program.bin +assemble: + $(py) src/assembler.py $(asm) $(out) + +# make gen-ucode out=out/ucode.bin +gen-ucode: + $(py) src/ucode.py $(out) + +# make test +test: + $(py) src/test_alu.py digital/atk16_alu.dig + +run-single-test: + java -cp $(digital_path) CLI test -verbose -circ $(circ) -tests $(tests) diff --git a/digital/atk16.dig b/digital/atk16.dig new file mode 100644 index 0000000..8c350c2 --- /dev/null +++ b/digital/atk16.dig @@ -0,0 +1,1828 @@ + + + 2 + + + + RegisterFile + + + AddrBits + 3 + + + Label + Register file + + + Bits + 16 + + + + + + Register + + + Label + MAR + + + Bits + 16 + + + + + + Register + + + Label + IR + + + Bits + 16 + + + + + + atk16_alu.dig + + + Label + ALU + + + shapeType + SIMPLE + + + + + + Register + + + Label + FR + + + Bits + 4 + + + + + + Tunnel + + + rotation + + + + NetName + FR_IE + + + + + + Driver + + + Bits + 16 + + + + + + Tunnel + + + rotation + + + + NetName + PC_OE + + + + + + Tunnel + + + rotation + + + + NetName + MAR_IE + + + + + + Tunnel + + + rotation + + + + NetName + IR_IE + + + + + + Tunnel + + + rotation + + + + NetName + IR_IE + + + + + + Splitter + + + Input Splitting + 16 + + + Output Splitting + 3,3,3,3,4 + + + rotation + + + + + + + Tunnel + + + rotation + + + + NetName + OPCODE + + + + + + Tunnel + + + rotation + + + + NetName + IR0 + + + + + + Tunnel + + + rotation + + + + NetName + IR1 + + + + + + Tunnel + + + rotation + + + + NetName + IR2 + + + + + + Tunnel + + + rotation + + + + NetName + IR3 + + + + + + Tunnel + + + rotation + + + + NetName + IR0 + + + + + + Tunnel + + + rotation + + + + NetName + IR1 + + + + + + Tunnel + + + rotation + + + + NetName + IR2 + + + + + + Tunnel + + + rotation + + + + NetName + RW_IE + + + + + + Splitter + + + Input Splitting + 3,1 + + + Output Splitting + 4 + + + + + + Tunnel + + + rotation + + + + NetName + IR3 + + + + + + Tunnel + + + rotation + + + + NetName + OP_PARITY + + + + + + RAMAsync + + + Label + MEM_RAM + + + AddrBits + 15 + + + Bits + 16 + + + + + + Tunnel + + + rotation + + + + NetName + MEM_IE + + + + + + EEPROM + + + Label + UCODE + + + AddrBits + 8 + + + Bits + 16 + + + isProgramMemory + true + + + + + + Splitter + + + Input Splitting + 3,1,4 + + + + + + VDD + + + rotation + + + + + + + Tunnel + + + rotation + + + + NetName + OPCODE + + + + + + Ground + + + rotation + + + + + + + BitSelector + + + Selector Bits + 2 + + + + + + Tunnel + + + rotation + + + + NetName + IR0 + + + + + + Splitter + + + rotation + + + + Input Splitting + 3 + + + Output Splitting + 2, + + + + + + VDD + + + rotation + + + + + + + Counter + + + Label + Microsequencer + + + Bits + 3 + + + + + + Tunnel + + + rotation + + + + NetName + US_RS + + + + + + And + + + + + VDD + + + rotation + + + + + + + Not + + + + + Tunnel + + + rotation + + + + NetName + IR_L9 + + + + + + Tunnel + + + rotation + + + + NetName + IR_L12 + + + + + + Splitter + + + Input Splitting + 16 + + + Output Splitting + 12, + + + rotation + + + + + + + Splitter + + + Input Splitting + 16 + + + mirror + true + + + Output Splitting + 1*16 + + + + + + CounterPreset + + + Label + PC + + + Bits + 16 + + + isProgramCounter + true + + + + + + Ground + + + rotation + + + + + + + Ground + + + rotation + + + + + + + Tunnel + + + rotation + + + + NetName + PC_CO + + + + + + Tunnel + + + NetName + PC_CO + + + + + + Tunnel + + + NetName + PC_IE + + + + + + Tunnel + + + NetName + PC_OE + + + + + + Tunnel + + + NetName + MAR_IE + + + + + + Tunnel + + + NetName + MEM_IE + + + + + + Tunnel + + + NetName + MEM_OE + + + + + + Tunnel + + + NetName + RW_IE + + + + + + Driver + + + flipSelPos + true + + + Bits + 16 + + + + + + Driver + + + Bits + 16 + + + flipSelPos + true + + + + + + Tunnel + + + NetName + R2_OE + + + + + + Driver + + + Bits + 16 + + + + + + Tunnel + + + rotation + + + + NetName + ALU_OE + + + + + + Tunnel + + + NetName + R1_OE + + + + + + Tunnel + + + NetName + R2_OE + + + + + + Tunnel + + + NetName + IR_IE + + + + + + Tunnel + + + NetName + R1_OE + + + + + + Tunnel + + + NetName + IR9_OE + + + + + + Tunnel + + + NetName + IR12_OE + + + + + + Tunnel + + + NetName + ALU_OE + + + + + + Tunnel + + + NetName + HALT + + + + + + Tunnel + + + NetName + US_RS + + + + + + Tunnel + + + NetName + FR_IE + + + + + + BitSelector + + + Selector Bits + 4 + + + rotation + + + + flipSelPos + true + + + + + + Tunnel + + + rotation + + + + NetName + OP_PARITY + + + + + + Const + + + rotation + + + + Value + 15 + + + Bits + 4 + + + + + + Splitter + + + rotation + + + + Input Splitting + 16 + + + Output Splitting + 9, + + + + + + Splitter + + + Input Splitting + 9,7 + + + Output Splitting + 16 + + + + + + Ground + + + Bits + 7 + + + + + + Splitter + + + Input Splitting + 12,4 + + + Output Splitting + 16 + + + + + + Ground + + + Bits + 4 + + + + + + Driver + + + rotation + + + + Bits + 16 + + + + + + Tunnel + + + NetName + IR12_OE + + + + + + Driver + + + rotation + + + + Bits + 16 + + + flipSelPos + true + + + + + + Tunnel + + + rotation + + + + NetName + IR9_OE + + + + + + EEPROM + + + Label + MEM_ROM + + + AddrBits + 15 + + + Bits + 16 + + + inverterConfig + + CS + + + + + + + Splitter + + + Input Splitting + 16 + + + Output Splitting + 15,1 + + + + + + Demultiplexer + + + Bits + 15 + + + + + + Ground + + + rotation + + + + + + + Driver + + + rotation + + + + Bits + 16 + + + + + + Tunnel + + + NetName + MEM_OE + + + + + + Driver + + + Bits + 16 + + + + + + Clock + + + small + true + + + + + + Tunnel + + + NetName + CLK + + + + + + Tunnel + + + rotation + + + + NetName + CLK + + + + + + Tunnel + + + rotation + + + + NetName + CLK + + + + + + Tunnel + + + rotation + + + + NetName + CLK + + + + + + Tunnel + + + rotation + + + + NetName + CLK + + + + + + Tunnel + + + rotation + + + + NetName + CLK + + + + + + Tunnel + + + rotation + + + + NetName + CLK + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/digital/atk16_alu.dig b/digital/atk16_alu.dig new file mode 100644 index 0000000..09e0e1b --- /dev/null +++ b/digital/atk16_alu.dig @@ -0,0 +1,2651 @@ + + + 2 + + + + 74382.dig + + + + + 74382.dig + + + + + 74382.dig + + + + + 74382.dig + + + + + VDD + + + rotation + + + + + + + VDD + + + rotation + + + + + + + VDD + + + rotation + + + + + + + VDD + + + rotation + + + + + + + Ground + + + rotation + + + + + + + Ground + + + rotation + + + + + + + Ground + + + rotation + + + + + + + Ground + + + rotation + + + + + + + Splitter + + + mirror + true + + + Input Splitting + 16 + + + Output Splitting + 1*16 + + + + + + In + + + Description + LHS of binary ALU operation + + + Label + A + + + Bits + 16 + + + + + + In + + + Description + RHS of binary ALU operation + + + Label + B + + + Bits + 16 + + + + + + Tunnel + + + NetName + A0 + + + + + + Tunnel + + + NetName + A1 + + + + + + Tunnel + + + NetName + A2 + + + + + + Tunnel + + + NetName + A3 + + + + + + Tunnel + + + NetName + A4 + + + + + + Tunnel + + + NetName + A5 + + + + + + Tunnel + + + NetName + A6 + + + + + + Tunnel + + + NetName + A7 + + + + + + Tunnel + + + NetName + A8 + + + + + + Tunnel + + + NetName + A9 + + + + + + Tunnel + + + NetName + A10 + + + + + + Tunnel + + + NetName + A11 + + + + + + Tunnel + + + NetName + A12 + + + + + + Tunnel + + + NetName + A13 + + + + + + Tunnel + + + NetName + A14 + + + + + + Tunnel + + + NetName + A15 + + + + + + In + + + Description + ALU operation code + + + Label + S + + + Bits + 4 + + + + + + Splitter + + + Input Splitting + 3 + + + Output Splitting + 1*3 + + + + + + Splitter + + + mirror + true + + + Input Splitting + 16 + + + Output Splitting + 1*16 + + + + + + Tunnel + + + NetName + B0 + + + + + + Tunnel + + + NetName + B1 + + + + + + Tunnel + + + NetName + B2 + + + + + + Tunnel + + + NetName + B3 + + + + + + Tunnel + + + NetName + B4 + + + + + + Tunnel + + + NetName + B5 + + + + + + Tunnel + + + NetName + B6 + + + + + + Tunnel + + + NetName + B7 + + + + + + Tunnel + + + NetName + B8 + + + + + + Tunnel + + + NetName + B9 + + + + + + Tunnel + + + NetName + B10 + + + + + + Tunnel + + + NetName + B11 + + + + + + Tunnel + + + NetName + B12 + + + + + + Tunnel + + + NetName + B13 + + + + + + Tunnel + + + NetName + B14 + + + + + + Tunnel + + + NetName + B15 + + + + + + Tunnel + + + rotation + + + + NetName + A0 + + + + + + Tunnel + + + rotation + + + + NetName + A1 + + + + + + Tunnel + + + NetName + A2 + + + + + + Tunnel + + + NetName + A3 + + + + + + Tunnel + + + rotation + + + + NetName + B0 + + + + + + Tunnel + + + rotation + + + + NetName + B1 + + + + + + Tunnel + + + NetName + B2 + + + + + + Tunnel + + + NetName + B3 + + + + + + Tunnel + + + rotation + + + + NetName + Y0 + + + + + + Tunnel + + + rotation + + + + NetName + Y1 + + + + + + Tunnel + + + NetName + Y2 + + + + + + Tunnel + + + NetName + Y3 + + + + + + Tunnel + + + rotation + + + + NetName + Y4 + + + + + + Tunnel + + + rotation + + + + NetName + Y5 + + + + + + Tunnel + + + NetName + Y6 + + + + + + Tunnel + + + NetName + Y7 + + + + + + Tunnel + + + rotation + + + + NetName + Y8 + + + + + + Tunnel + + + rotation + + + + NetName + Y9 + + + + + + Tunnel + + + NetName + Y10 + + + + + + Tunnel + + + NetName + Y11 + + + + + + Tunnel + + + rotation + + + + NetName + Y12 + + + + + + Tunnel + + + rotation + + + + NetName + Y13 + + + + + + Tunnel + + + NetName + Y14 + + + + + + Tunnel + + + NetName + Y15 + + + + + + Tunnel + + + rotation + + + + NetName + A4 + + + + + + Tunnel + + + rotation + + + + NetName + A5 + + + + + + Tunnel + + + NetName + A6 + + + + + + Tunnel + + + NetName + A7 + + + + + + Tunnel + + + rotation + + + + NetName + A8 + + + + + + Tunnel + + + rotation + + + + NetName + A9 + + + + + + Tunnel + + + NetName + A10 + + + + + + Tunnel + + + NetName + A11 + + + + + + Tunnel + + + rotation + + + + NetName + A12 + + + + + + Tunnel + + + rotation + + + + NetName + A13 + + + + + + Tunnel + + + NetName + A14 + + + + + + Tunnel + + + NetName + A15 + + + + + + Tunnel + + + rotation + + + + NetName + B4 + + + + + + Tunnel + + + rotation + + + + NetName + B5 + + + + + + Tunnel + + + NetName + B6 + + + + + + Tunnel + + + NetName + B7 + + + + + + Tunnel + + + rotation + + + + NetName + B8 + + + + + + Tunnel + + + rotation + + + + NetName + B9 + + + + + + Tunnel + + + NetName + B10 + + + + + + Tunnel + + + NetName + B11 + + + + + + Tunnel + + + rotation + + + + NetName + B12 + + + + + + Tunnel + + + rotation + + + + NetName + B13 + + + + + + Tunnel + + + NetName + B14 + + + + + + Tunnel + + + NetName + B15 + + + + + + Out + + + Description + ALU output + + + Label + Y + + + Bits + 16 + + + + + + Splitter + + + Input Splitting + 1*16 + + + Output Splitting + 16 + + + + + + Tunnel + + + rotation + + + + NetName + Y0 + + + + + + Tunnel + + + rotation + + + + NetName + Y1 + + + + + + Tunnel + + + rotation + + + + NetName + Y2 + + + + + + Tunnel + + + rotation + + + + NetName + Y3 + + + + + + Tunnel + + + rotation + + + + NetName + Y4 + + + + + + Tunnel + + + rotation + + + + NetName + Y5 + + + + + + Tunnel + + + rotation + + + + NetName + Y6 + + + + + + Tunnel + + + rotation + + + + NetName + Y7 + + + + + + Tunnel + + + rotation + + + + NetName + Y8 + + + + + + Tunnel + + + rotation + + + + NetName + Y9 + + + + + + Tunnel + + + rotation + + + + NetName + Y10 + + + + + + Tunnel + + + rotation + + + + NetName + Y11 + + + + + + Tunnel + + + rotation + + + + NetName + Y12 + + + + + + Tunnel + + + rotation + + + + NetName + Y13 + + + + + + Tunnel + + + rotation + + + + NetName + Y14 + + + + + + Tunnel + + + rotation + + + + NetName + Y15 + + + + + + BarrelShifter + + + Label + SRL + + + Bits + 16 + + + direction + right + + + + + + Demultiplexer + + + Bits + 3 + + + + + + Splitter + + + Input Splitting + 4 + + + Output Splitting + 3,1 + + + + + + Demultiplexer + + + Selector Bits + 3 + + + Bits + 16 + + + + + + Tunnel + + + rotation + + + + NetName + A + + + + + + Tunnel + + + rotation + + + + NetName + B + + + + + + Tunnel + + + rotation + + + + NetName + A + + + + + + Splitter + + + Input Splitting + 16 + + + Output Splitting + 5, + + + + + + Tunnel + + + rotation + + + + NetName + B + + + + + + Decoder + + + Selector Bits + 3 + + + + + + Driver + + + Bits + 16 + + + flipSelPos + true + + + + + + Tunnel + + + rotation + + + + NetName + ALS_E + + + + + + Driver + + + Bits + 16 + + + flipSelPos + true + + + + + + Tunnel + + + rotation + + + + NetName + ALS_E + + + + + + DriverInvSel + + + Bits + 16 + + + + + + BarrelShifter + + + Label + SRA + + + Bits + 16 + + + barrelShifterMode + arithmetic + + + direction + right + + + + + + Driver + + + Bits + 16 + + + flipSelPos + true + + + + + + BarrelShifter + + + Label + SLL + + + Bits + 16 + + + + + + Driver + + + Bits + 16 + + + flipSelPos + true + + + + + + Splitter + + + Input Splitting + 1*4 + + + Output Splitting + 4 + + + + + + Out + + + Label + FLAGS + + + Bits + 4 + + + + + + Tunnel + + + NetName + ALS_E + + + + + + Splitter + + + splitterSpreading + 2 + + + Input Splitting + 16 + + + Output Splitting + 8*2 + + + + + + BitSelector + + + Selector Bits + 4 + + + + + + Const + + + rotation + + + + Value + 15 + + + Bits + 4 + + + + + + Splitter + + + splitterSpreading + 2 + + + Input Splitting + 8 + + + Output Splitting + 4*2 + + + + + + Testcase + + + Label + Add test 1 + + + Testdata + + A B S FLAGS Y +0x1 0x2 3 0b0000 0x3 +0xff 0x1 3 0b0000 0x100 +0x1 0xffff 3 0b0101 0x0 + + + + + + + Or + + + Bits + 8 + + + + + + Or + + + Bits + 4 + + + + + + Splitter + + + splitterSpreading + 2 + + + Input Splitting + 2 + + + Output Splitting + 1*2 + + + + + + Splitter + + + splitterSpreading + 2 + + + Input Splitting + 4 + + + Output Splitting + 2*2 + + + + + + Or + + + Bits + 2 + + + + + + NOr + + + + + Testcase + + + Label + Sub test 1 + + + Testdata + + A B S FLAGS Y +0x10 0x1 2 0b0001 0xF +0x1 0x0 1 0b1000 0xFFFF + + + + + + + atk16_alu_carryfix.dig + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/digital/atk16_alu_carryfix.dig b/digital/atk16_alu_carryfix.dig new file mode 100644 index 0000000..1c22602 --- /dev/null +++ b/digital/atk16_alu_carryfix.dig @@ -0,0 +1,270 @@ + + + 2 + + + + Out + + + Label + Y + + + Inputs + 1 + + + + + + Or + + + wideShape + true + + + + + + And + + + wideShape + true + + + Inputs + 3 + + + + + + And + + + wideShape + true + + + Inputs + 3 + + + + + + In + + + rotation + + + + Label + S2 + + + + + + Not + + + rotation + + + + + + + In + + + rotation + + + + Label + S1 + + + + + + Not + + + rotation + + + + + + + In + + + rotation + + + + Label + S0 + + + + + + Not + + + rotation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/digital/tests_alu.dig b/digital/tests_alu.dig new file mode 100644 index 0000000..9390503 --- /dev/null +++ b/digital/tests_alu.dig @@ -0,0 +1,26 @@ + + + 2 + + + + Testcase + + + Label + test01 + + + Testdata + + A B Y +0 0 1 + + + + + + + + + \ No newline at end of file diff --git a/logisim/CPU16.circ b/logisim/CPU16.circ new file mode 100644 index 0000000..6f1610b --- /dev/null +++ b/logisim/CPU16.circ @@ -0,0 +1,4344 @@ + + + This file is intended to be loaded by Logisim-evolution v3.8.0(https://github.com/logisim-evolution/). + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + addr/data: 8 16 +c 421 2000 8000 4*0 c 421 2000 +8000 4*0 c 421 2000 8000 4*0 c +421 2000 8000 4*0 c 421 88 120 +8000 0 0 0 c 421 88 120 +8000 0 0 0 c 421 88 210 +8000 0 0 0 c 421 88 210 +8000 0 0 0 c 421 840 8000 +4*0 c 421 840 8000 4*0 c 421 +82 8000 4*0 c 421 82 8000 4*0 +c 421 8000 5*0 c 421 202 8000 +4*0 c 421 8000 5*0 c 421 8000 +5*0 c 421 8000 5*0 c 421 8000 +5*0 c 421 8000 5*0 c 421 8000 +5*0 c 421 8000 5*0 c 421 8000 +5*0 c 421 8000 5*0 c 421 8000 +5*0 c 421 8000 5*0 c 421 8000 +5*0 c 421 8000 5*0 c 421 8000 +5*0 c 421 4000 5*0 c 421 4000 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + addr/data: 15 16 +4203 5200 8000 420a 4414 29b 4802 2900 +38c0 cb 441e 4812 29a 6500 4202 f000 +4201 f000 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/assembler.py b/src/assembler.py new file mode 100755 index 0000000..9e2d92f --- /dev/null +++ b/src/assembler.py @@ -0,0 +1,263 @@ +#!/usr/bin/env python3 +# Assemble ATK16 assembly to bytecode + +import sys + +if len(sys.argv) != 3: + print("usage: assembler.py # read from file") + print(" assembler.py - # read from stdin") + sys.exit(1) + +infile_path = sys.argv[1] +outfile_path = sys.argv[2] + +src = "" +if (infile_path == "-"): + for line in sys.stdin: + src += line +else: + with open(infile_path, "r") as f: + src = f.read() + +src_lines = src.splitlines() + +### Utils + +def parse(line: str) -> list[str]: + depth = 0 + result = [] + acc = "" + for c in line: + if c.isspace() and depth == 0: + result.append(acc) + acc = "" + elif c == "(": + depth += 1 + acc += "(" + elif c == ")": + depth -= 1 + acc += ")" + else: + acc += c + + result.append(acc) + return list(filter(lambda x: len(x) > 0, result)) + +def eval_expr(expr: str) -> int: + expr = eval_symbol(expr) + return eval(expr, labels) # eval as Python expr + +def eval_symbol(c: str): + if c in labels: + return str(labels[c]) + + match c: + # Registers + case "rz": return "0" + case "ra": return "1" + case "rb": return "2" + case "rc": return "3" + case "rd": return "4" + case "pa": return "5" + case "pb": return "6" + # ALU instructions + case "al_clear": return "0" + case "al_b_minus_a": return "1" + case "al_a_minus_b": return "2" + case "al_a_plus_b": return "3" + case "al_a_xor_b": return "4" + case "al_a_or_b": return "5" + case "al_a_and_b": return "6" + case "al_preset": return "7" + case "al_logical_shift_right": return "8" + case "al_arithmetic_shift_right": return "9" + case "al_logical_shift_left": return "10" + # ALU flags + case "f_carry": return "0" + case "f_overflow": return "1" + case "f_zero": return "2" + case "f_sign": return "3" + case _: return c + +# 1st pass, gather labels + +labels: dict[str, int] = {} +address = 0 + +for (lineNo, line) in enumerate(src_lines): + line = line.strip() + if line == "": continue + keyword, *args = line.lower().split() + match keyword: + case "@address": + address = eval(args[0]) + continue + case "@label": + labels[args[0]] = address + continue + + address += 1 + +print("labels:", labels) + +# 2nd pass + +address = 0 +nop = bytearray([0b1000_0000, 0]) +result = bytearray() +# initially one nop +result.extend(nop) + +for (lineNo, line) in enumerate(src_lines): + line = line.split(";")[0].strip() + if line == "": continue + keyword, *args = parse(line.lower()) + match keyword: + # Directives + case "@address": + address = eval_expr(args[0]) + continue + case "@label": + continue + + # Instructions + case "alu": + word = (0b0000 << 12) + \ + (eval_expr(args[0]) << 9) + \ + (eval_expr(args[1]) << 6) + \ + (eval_expr(args[2]) << 3) + \ + (eval_expr(args[3]) << 0) + case "als": + word = (0b0001 << 12) + \ + (eval_expr(args[0]) << 9) + \ + (eval_expr(args[1]) << 6) + \ + (eval_expr(args[2]) << 3) + \ + (eval_expr(args[3]) << 0) + case "ldr": + word = (0b0010 << 12) + \ + (eval_expr(args[0]) << 9) + \ + (eval_expr(args[1]) << 6) + case "str": + word = (0b0011 << 12) + \ + (eval_expr(args[0]) << 9) + \ + (eval_expr(args[1]) << 6) + case "ldi": + word = (0b0100 << 12) + \ + (eval_expr(args[0]) << 9) + \ + (eval_expr(args[1]) << 0) + case "jmp": + word = (0b0101 << 12) + \ + (eval_expr(args[0]) << 9) + case "br": + word = (0b0110 << 12) + \ + (eval_expr(args[0]) << 9) + \ + (eval_expr(args[1]) << 6) + case "hlt": + word = 0b1111 << 12 + + # Pseudoinstructions + case "add": + word = (0b0000 << 12) + \ + (eval_expr(args[0]) << 9) + \ + (eval_expr(args[1]) << 6) + \ + (eval_expr(args[2]) << 3) + \ + (eval_expr("al_a_plus_b") << 0) + case "sub": + word = (0b0000 << 12) + \ + (eval_expr(args[0]) << 9) + \ + (eval_expr(args[1]) << 6) + \ + (eval_expr(args[2]) << 3) + \ + (eval_expr("al_a_minus_b") << 0) + case "mov": + word = (0b0000 << 12) + \ + (eval_expr("rz") << 9) + \ + (eval_expr(args[0]) << 6) + \ + (eval_expr(args[1]) << 3) + \ + (eval_expr("al_a_plus_b") << 0) + + # Default case: evaluate as is (e.g. data word) + case _: + try: + word = eval_expr(keyword) + except: + raise Exception(f"Invalid assembly at {infile_path}:{lineNo + 1}\n\n{line}") + + if len(result) < 2 * address + 1: + result.extend((2 * address + 1 - len(result)) * nop) + + print(f"{address:>08x} 0x{word:>04x} {line}") + result[2 * address + 0] = ((word >> 8) & 0xff) + result[2 * address + 1] = ((word >> 0) & 0xff) + address += 1 + +with open(outfile_path, "wb") as f: + f.write(result) + +print(f"Wrote {len(result)} bytes to {outfile_path}") + +with open(f"{outfile_path}.logisim.txt", "w") as f: + f.write("v2.0 raw\n") + run_length = 0 + run_last = "" + for i in range(len(result) // 2): + b0 = result[2 * i + 0] + b1 = result[2 * i + 1] + word = f"{b0:>02x}{b1:>02x}\n" + + if word != run_last and run_length <= 1: + f.write(f"{run_last}") + run_length = 1 + run_last = word + elif word != run_last and run_length > 1: + f.write(f"{run_length}*{run_last}") + run_length = 1 + run_last = word + else: + run_length += 1 + + if run_length <= 1: + f.write(f"{run_last}") + else: + f.write(f"{run_length}*{run_last}") + +print(f"Wrote Logisim image format to {outfile_path}.logisim.txt") + +with open(f"{outfile_path}.ver.txt", "w") as f: + f.write("addr/data: 15 16") + run_length = 0 + run_last = "" + written = -1 + + def update_layout(): + if run_last == "": return + if written % 8 == 0: + f.write("\n") + else: + f.write(" ") + + for i in range(len(result) // 2): + b0 = result[2 * i + 0] + b1 = result[2 * i + 1] + word = f"{b0:>02x}{b1:>02x}" + + if word != run_last and run_length <= 1: + f.write(f"{run_last}") + run_length = 1 + run_last = word + written += 1 + update_layout() + elif word != run_last and run_length > 1: + f.write(f"{run_length}*{run_last}") + run_length = 1 + run_last = word + written += 1 + update_layout() + else: + run_length += 1 + + if run_length <= 1: + f.write(f"{run_last}") + else: + f.write(f"{run_length}*{run_last}") + +print(f"Wrote verification test format to {outfile_path}.ver.txt") diff --git a/src/test.atk16 b/src/test.atk16 new file mode 100644 index 0000000..399bd7e --- /dev/null +++ b/src/test.atk16 @@ -0,0 +1,33 @@ +; Program: sum two values and store the result in RAM + +; ROM (and program execution) starts at offset 0x0 +@address 0x0 + ldi RA program + jmp RA + +@label ram_offset + 0x8000 ; store ram offset for later memory access + +@label program + ldi RA 10 ; RA := 10 + ldi RB 20 ; RB := 10 + add RA RB RC ; RC := RA + RB + ldi RD ram_offset ; store address of ram_offset in RD + ldr RD RD ; dereference ram_offset address +@label debug + str RD RC ; store RC in RAM + +; Check that 10 + 20 = 30 + mov RC RA ; RA := result of sum + ldi RB 30 ; RB := 30 + ldi RD success + sub RA RB RC ; RC := RA - RB + br f_zero RD ; if result is zero, jump to success + + ldi RA 2 ; RA := 2 to signal failure + hlt + +; Else +@label success + ldi RA 1 ; RA := 1 to signal success + hlt diff --git a/src/test_alu.py b/src/test_alu.py new file mode 100755 index 0000000..af30443 --- /dev/null +++ b/src/test_alu.py @@ -0,0 +1,48 @@ +#!/usr/bin/env python3 + +from test_utils import * + +def make_alu_table() -> str: + alu = ALU() + n = 10000 + alu.generate_cases(n) + alu.process() + print(f"[test] running {n} ALU test cases") + return alu.to_table().strip() + +class ALU(TestGroup): + def __init__(self): + TestGroup.__init__(self, [ + Param("A", 0x0, 0xffff), + Param("B", 0x0, 0xffff), + Param("S", 0, 7), + ], [ + "Y", + "FLAGS", + ]) + + def process(self): + new_cases = [] + for kase in self.cases: + S = kase["S"] + A = kase["A"] + B = kase["B"] + kase["FLAGS"] = "x" + + match S: + case 0: Y = 0 + case 1: Y = (B - A) & 0xFFFF + case 2: Y = (A - B) & 0xFFFF + case 3: Y = (A + B) & 0xFFFF + case 4: Y = (A ^ B) & 0xFFFF + case 5: Y = (A | B) & 0xFFFF + case 6: Y = (A & B) & 0xFFFF + case 7: Y = 0xffff + + kase["Y"] = Y + new_cases.append(kase) + + self.cases = new_cases + +table = make_alu_table() +run_test("ALU", table) diff --git a/src/test_utils.py b/src/test_utils.py new file mode 100644 index 0000000..1db23b2 --- /dev/null +++ b/src/test_utils.py @@ -0,0 +1,93 @@ +import random +from dataclasses import dataclass +import tempfile +import sys +import os + +def make_test_file(name: str, table: str) -> str: + return f""" + + 2 + + + + Testcase + + + Label + {name} + + + Testdata + + {table} + + + + + + + + + + """ + +@dataclass +class Param: + name: str + min: int + max: int + +class TestGroup: + def __init__(self, inputs: list[Param], outputs: list[str]): + self.inputs = inputs + self.outputs = outputs + self.cases = [] + + def generate_cases(self, n = 1000): + for _ in range(n): + result = {} + for param in self.inputs: + val = random.randrange(param.min, param.max + 1) + result[param.name] = val + + self.cases.append(result) + + def process(self): + raise NotImplemented() + + def to_table(self) -> str: + names: list[str] = [] + for param in self.inputs: + names.append(param.name) + for output in self.outputs: + names.append(output) + + ret = " ".join(names) + ret += "\n" + + for case in self.cases: + row_vals = [] + for param_name in names: + row_vals.append(str(case[param_name])) + + ret += " ".join(row_vals) + ret += "\n" + + return ret + +def run_test(name: str, table: str): + if len(sys.argv) != 2: + print(f"usage: {sys.argv[0]} ") + sys.exit(1) + + circuit_path = sys.argv[1] + _, test_path = tempfile.mkstemp(".dig") + + fc = make_test_file(name, table) + with open(test_path, "w") as f: + f.write(fc) + + stream = os.popen(f"make run-single-test circ={circuit_path} tests={test_path}") + output = stream.read() + print(output) diff --git a/src/ucode.py b/src/ucode.py new file mode 100755 index 0000000..ea5c040 --- /dev/null +++ b/src/ucode.py @@ -0,0 +1,103 @@ +#!/usr/bin/env python3 +# Generate .bin file with ATK16 CPU microcode + +# Addressed by OOOO BUUU +# where O = opcode, B = branch flag, U = microsequencer value + +import sys + +if len(sys.argv) != 2: + print("usage: ucode.py ") + sys.exit(1) + +outfile_path = sys.argv[1] + +PC_CO = 0b0000_0000_0000_0001 +PC_IE = 0b0000_0000_0000_0010 +PC_OE = 0b0000_0000_0000_0100 +MAR_IE = 0b0000_0000_0000_1000 +RAM_IE = 0b0000_0000_0001_0000 +RAM_OE = 0b0000_0000_0010_0000 +R1_IE = 0b0000_0000_0100_0000 +R1_OE = 0b0000_0000_1000_0000 +R2_IE = 0b0000_0001_0000_0000 +R2_OE = 0b0000_0010_0000_0000 +IR_IE = 0b0000_0100_0000_0000 +L9_OE = 0b0000_1000_0000_0000 +L12_OE = 0b0001_0000_0000_0000 +ALU_OE = 0b0010_0000_0000_0000 +HALT = 0b0100_0000_0000_0000 +US_RS = 0b1000_0000_0000_0000 + +BRANCH_FLAG_STATES_N = 2 +UCODE_N = 2**3 +CONTROL_WORD_SIZE = 2 + +def not_branch(bs): + return BRANCH_FLAG_STATES_N * [bs] + +def branch(false_branch, true_branch): + return [false_branch, true_branch] + +fetch = [PC_OE|MAR_IE, RAM_OE|IR_IE|PC_CO] + +def nop(): + return not_branch([*fetch, US_RS, 0, 0, 0, 0, 0]) + +ucode = [ + # ALU 0000 LLLR RRTT TSSS + not_branch([*fetch, ALU_OE, US_RS, 0, 0, 0, 0]), + # ALS 0001 LLLR RRTT TSSS + not_branch([*fetch, ALU_OE, US_RS, 0, 0, 0, 0]), + # LDR 0010 RRRT TTXX XXXX + not_branch([*fetch, R1_OE|MAR_IE, RAM_OE|R2_IE, US_RS, 0, 0, 0]), + # STR 0011 RRRT TTXX XXXX + not_branch([*fetch, R1_OE|MAR_IE, R2_OE|RAM_IE, US_RS, 0, 0, 0]), + # LDI 0100 RRRI IIII IIII + not_branch([*fetch, L9_OE|R1_IE, US_RS, 0, 0, 0, 0]), + # JMP 0101 RRRX XXXX XXXX + not_branch([*fetch, R1_OE|PC_IE, US_RS, 0, 0, 0, 0]), + # BR 0110 XFFR RRXX XXXX + branch([*fetch, US_RS, 0, 0, 0, 0, 0], + [*fetch, R2_OE|PC_IE, US_RS, 0, 0, 0, 0]), + # NOP 0111 XXXX XXXX XXXX + nop(), + # NOP 1000 XXXX XXXX XXXX + nop(), + # NOP 1001 XXXX XXXX XXXX + nop(), + # NOP 1010 XXXX XXXX XXXX + nop(), + # NOP 1011 XXXX XXXX XXXX + nop(), + # NOP 1100 XXXX XXXX XXXX + nop(), + # NOP 1101 XXXX XXXX XXXX + nop(), + # NOP 1110 XXXX XXXX XXXX + nop(), + # HLT 1111 XXXX XXXX XXXX + not_branch([*fetch, HALT, 0, 0, 0, 0, 0]), +] + +INST_N = len(ucode) +TOTAL_BYTEARRAY_SIZE = INST_N * BRANCH_FLAG_STATES_N * UCODE_N * CONTROL_WORD_SIZE + +res_b = bytearray(TOTAL_BYTEARRAY_SIZE) + +for i in range(INST_N): + for j in range(BRANCH_FLAG_STATES_N): + for k in range(UCODE_N): + for l in range(CONTROL_WORD_SIZE): + idx = l + \ + k * CONTROL_WORD_SIZE + \ + j * CONTROL_WORD_SIZE * UCODE_N + \ + i * CONTROL_WORD_SIZE * UCODE_N * BRANCH_FLAG_STATES_N + cword = ucode[i][j][k] + assert len(ucode[i][j]) == 8 + cbyte = (cword >> (8 * (CONTROL_WORD_SIZE - l - 1))) & 0xff + print(f"inst: {i:>04b}, idx: {idx:>04x}, cbyte: {cbyte:>08b}") + res_b[idx] = cbyte + +with open(outfile_path, "wb") as f: + f.write(res_b) -- cgit v1.3