aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--16bit-cpu.md73
-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.py4
-rw-r--r--src/asm_pass2.py4
-rw-r--r--src/asm_pass3.py4
-rw-r--r--src/asm_pass4.py4
-rwxr-xr-xsrc/assembler.py4
-rw-r--r--src/ext_std.py2
-rwxr-xr-xsrc/test_alu.py48
-rw-r--r--src/test_sum.atk163
-rw-r--r--src/test_utils.py93
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)