diff options
| -rw-r--r-- | 16bit-cpu.md | 73 | ||||
| -rw-r--r-- | asm/fibo.atk16 (renamed from src/test_fibo.atk16) | 0 | ||||
| -rw-r--r-- | asm/sum.atk16 (renamed from src/test.atk16) | 19 | ||||
| -rw-r--r-- | src/asm_eval.py (renamed from src/assembler_eval.py) | 0 | ||||
| -rw-r--r-- | src/asm_ops.py (renamed from src/assembler_ops.py) | 2 | ||||
| -rw-r--r-- | src/asm_pass1.py | 4 | ||||
| -rw-r--r-- | src/asm_pass2.py | 4 | ||||
| -rw-r--r-- | src/asm_pass3.py | 4 | ||||
| -rw-r--r-- | src/asm_pass4.py | 4 | ||||
| -rwxr-xr-x | src/assembler.py | 4 | ||||
| -rw-r--r-- | src/ext_std.py | 2 | ||||
| -rwxr-xr-x | src/test_alu.py | 48 | ||||
| -rw-r--r-- | src/test_sum.atk16 | 3 | ||||
| -rw-r--r-- | src/test_utils.py | 93 |
14 files changed, 33 insertions, 227 deletions
diff --git a/16bit-cpu.md b/16bit-cpu.md index 73b588e..d862114 100644 --- a/16bit-cpu.md +++ b/16bit-cpu.md @@ -4,79 +4,30 @@ 16-bit data 16-bit address width 16-bit instruction width - -MISC +16-bit control word +Minimal instruction set computer (MISC) 4-bit opcodes +Memory mapped I/O 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. + RA (0) .. RH (7) Expansion port that connects directly to the main bus -Addressing mode: indirect absolute (addresses are stored in registers and point to a complete address) +Default addressing mode: indirect absolute (addresses are stored in registers and point to a complete address). Some instructions use PC-relative addressing. ## 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] +TODO rewrite bit about operations -Flags: -- C = ALU carry bit -- O = ALU overflow bit -- Z = ALU zero bit -- S = ALU sign bit +ALU flags: +- C = carry bit +- O = overflow bit +- Z = zero bit +- S = sign bit -Interrupt lines: 1 (IRQ) +Interrupt lines: ??? diff --git a/src/test_fibo.atk16 b/asm/fibo.atk16 index 8bb7a6e..8bb7a6e 100644 --- a/src/test_fibo.atk16 +++ b/asm/fibo.atk16 diff --git a/src/test.atk16 b/asm/sum.atk16 index 3f2d378..1bc3277 100644 --- a/src/test.atk16 +++ b/asm/sum.atk16 @@ -1,6 +1,5 @@ -; Program: sum two values and store the result in RAM - @use ext_std:* +; Program: sum two values and store the result in RAM ; ROM (and program execution) starts at offset 0x0 @address 0x0 @@ -10,24 +9,24 @@ 0x8000 ; store ram offset for later memory access @label program - ldi RA 10 ; RA := 10 - ldi RB 20 ; RB := 20 + ldi 10 RA ; RA := 10 + ldi 20 RB ; RB := 20 add RA RB RC ; RC := RA + RB - ldi RD @ram_offset ; store address of ram_offset in RD + ldi ram_offset RD ; store address of ram_offset in RD ldr RD RD ; dereference ram_offset address @label debug - str RD RC ; store RC in RAM + str RC RD ; store RC in RAM ; Check that 10 + 20 = 30 mov RC RA ; RA := result of sum - ldi RB 30 ; RB := 30 + ldi 30 RB ; RB := 30 sub RA RB RC ; RC := RA - RB - bri zero @success ; if result is zero, jump to success + bri zero success ; if result is zero, jump to success - ldi RA 2 ; RA := 2 to signal failure + ldi 2 RA ; RA := 2 to signal failure hlt ; Else @label success - ldi RA 1 ; RA := 1 to signal success + ldi 1 RA ; RA := 1 to signal success hlt diff --git a/src/assembler_eval.py b/src/asm_eval.py index 691e4eb..691e4eb 100644 --- a/src/assembler_eval.py +++ b/src/asm_eval.py diff --git a/src/assembler_ops.py b/src/asm_ops.py index b55927b..74e7930 100644 --- a/src/assembler_ops.py +++ b/src/asm_ops.py @@ -1,5 +1,5 @@ from typing import Callable -from assembler_eval import * +from asm_eval import * from dataclasses import dataclass @dataclass diff --git a/src/asm_pass1.py b/src/asm_pass1.py index 6537aea..606a1a1 100644 --- a/src/asm_pass1.py +++ b/src/asm_pass1.py @@ -1,7 +1,7 @@ import importlib from dataclasses import dataclass -from assembler_ops import * -from assembler_eval import * +from asm_ops import * +from asm_eval import * @dataclass class Result1Line: diff --git a/src/asm_pass2.py b/src/asm_pass2.py index 261ba06..e7f48ac 100644 --- a/src/asm_pass2.py +++ b/src/asm_pass2.py @@ -1,6 +1,6 @@ from dataclasses import dataclass -from assembler_ops import * -from assembler_eval import * +from asm_ops import * +from asm_eval import * from asm_pass1 import * @dataclass diff --git a/src/asm_pass3.py b/src/asm_pass3.py index e8e44d3..038e3f7 100644 --- a/src/asm_pass3.py +++ b/src/asm_pass3.py @@ -1,6 +1,6 @@ from dataclasses import dataclass -from assembler_ops import * -from assembler_eval import * +from asm_ops import * +from asm_eval import * from asm_pass2 import * @dataclass diff --git a/src/asm_pass4.py b/src/asm_pass4.py index 926b354..3d4f45c 100644 --- a/src/asm_pass4.py +++ b/src/asm_pass4.py @@ -1,6 +1,6 @@ from dataclasses import dataclass -from assembler_ops import * -from assembler_eval import * +from asm_ops import * +from asm_eval import * from asm_pass3 import * @dataclass diff --git a/src/assembler.py b/src/assembler.py index 4e82deb..3f0c8bc 100755 --- a/src/assembler.py +++ b/src/assembler.py @@ -2,8 +2,8 @@ # Assemble ATK16 assembly to bytecode import sys -from assembler_ops import * -from assembler_eval import * +from asm_ops import * +from asm_eval import * from asm_pass1 import pass_1 from asm_pass2 import pass_2 from asm_pass3 import pass_3 diff --git a/src/ext_std.py b/src/ext_std.py index 5f41f60..11da8aa 100644 --- a/src/ext_std.py +++ b/src/ext_std.py @@ -1,4 +1,4 @@ -from assembler_ops import * +from asm_ops import * def expand_add(left: str, right: str, target: str) -> ExpandResult: return [["alr", "al_plus", left, right, target]] diff --git a/src/test_alu.py b/src/test_alu.py deleted file mode 100755 index af30443..0000000 --- a/src/test_alu.py +++ /dev/null @@ -1,48 +0,0 @@ -#!/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_sum.atk16 b/src/test_sum.atk16 deleted file mode 100644 index 3f69a55..0000000 --- a/src/test_sum.atk16 +++ /dev/null @@ -1,3 +0,0 @@ - ldi RA 10 ; RA := 10 - ldi RB 20 ; RB := 20 - add RA RB RC ; RC := RA + RB diff --git a/src/test_utils.py b/src/test_utils.py deleted file mode 100644 index 1db23b2..0000000 --- a/src/test_utils.py +++ /dev/null @@ -1,93 +0,0 @@ -import random -from dataclasses import dataclass -import tempfile -import sys -import os - -def make_test_file(name: str, table: str) -> str: - return f"""<?xml version="1.0" encoding="utf-8"?> -<circuit> - <version>2</version> - <attributes/> - <visualElements> - <visualElement> - <elementName>Testcase</elementName> - <elementAttributes> - <entry> - <string>Label</string> - <string>{name}</string> - </entry> - <entry> - <string>Testdata</string> - <testData> - <dataString>{table}</dataString> - </testData> - </entry> - </elementAttributes> - <pos x="200" y="200"/> - </visualElement> - </visualElements> - <wires/> - <measurementOrdering/> -</circuit> - """ - -@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]} <circuit.dig>") - 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) |
