1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
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 <outfile.bin>")
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)
|