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
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
|
import sys
memory_block_start = """
mov UP, LEFT
mov UP, ACC
mov UP, LEFT
jne 0, is_write
mov LEFT, DOWN
mov 0, DOWN
mov UP, DOWN
mov LEFT, NIL
jmp wrap
is_write:
mov LEFT, DOWN
mov 1, DOWN
mov UP, ACC
xor LEFT
mov ACC, DOWN
swp
wrap:
mov DOWN, ACC
xor LEFT
mov LEFT, RIGHT
mov ${{addr}}, RIGHT
mov ${OP_ACK}, RIGHT
mov ACC, RIGHT
mov ${OP_NIL}, RIGHT
"""
memory_block_start_left = """
mov RIGHT, ACC
swp
mov RIGHT, ACC
mov ACC, RIGHT
mov ACC, RIGHT
mov ACC, RIGHT
swp
mov ACC, RIGHT
"""
memory_block_start_right = """
mov LEFT, UP
"""
code_memory_cell = """
mov 0x{val:02x}, ACC
sav
start:
mov {inp}, ACC
jne {idx}, fwd
mov {inp}, ACC
jne 0, WRITE
mov {inp}, NIL
swp
mov ACC, {inp}
sav
jmp start
write:
mov {inp}, ACC
swp
mov ACC, {inp}
jmp start
fwd:
mov ACC, {outp}
mov {inp}, {outp}
mov {inp}, {outp}
mov {outp}, {inp}
jmp start
"""
pattern = """
#
#
# ##################
# # #
# ################ #
# #
####################
"""
assert(pattern.count("#") == 64)
pattern = pattern.strip("\n").split("\n")
dirs = ((1, 0), (0, 1), (-1, 0), (0, -1))
x,y = (0, 0)
seen = set()
seen.add((x,y))
path = [(x,y),]
while True:
npos = None
for dx,dy in dirs:
nx,ny = x+dx,y+dy
if nx < 0 or nx >= len(pattern[0]): continue
if ny < 0 or ny >= len(pattern): continue
if pattern[ny][nx] == "#" and (nx,ny) not in seen:
npos = (nx,ny)
break
if npos is None:
break
x,y = npos
seen.add((x,y))
path.append((x,y))
class BlockMap(dict):
def __setattr__(self, key, value):
if key in self.__dict__:
raise ValueError("Already exists")
super().__setattr__(key, value)
def gen_memory(blocks, start, idx_offset, depth, contents, dtype):
opposite = { "UP": "DOWN", "LEFT": "RIGHT", "RIGHT": "LEFT", "DOWN": "UP" }
ports = { (-1, 0): "LEFT", (0, 1): "DOWN", (1, 0): "RIGHT", (0, -1): "UP" }
sx,sy = start
maxi = 2**depth-1
for i in range(2**depth):
fix = lambda x,y: (-x,y) if dtype == "left" else (x,y)
x,y = fix(*path[i])
px,py = (0,0) if i == 0 else fix(*path[i-1])
nx,ny = (0,0) if i == maxi else fix(*path[i+1])
pd = x-px,y-py
nd = nx-x,ny-y
inp = "UP" if i == 0 else opposite[ports[pd]]
outp = opposite[inp] if i == maxi else ports[nd]
addr = idx_offset + i
cell = code_memory_cell.format(idx=addr,val=addr^contents[i],inp=inp,outp=outp)
if dtype == "left":
blocks[(sx+x,sy+y)] = cell
elif dtype == "right":
blocks[(sx+x,sy+y)] = cell
else:
assert(dtype == "straight")
blocks[(sx,sy+i)] = cell
def write_blocks(blocks, filepath, addr_tmpl):
with open(filepath, "w+") as f:
for i,(x,y) in enumerate(blocks):
f.write(f"tpu X{x} Y{y}\n")
if i == 0:
f.write("\t## ${" + addr_tmpl + "}\n")
for l in blocks[(x,y)].strip("\n").split("\n"):
f.write(f"{l}\n")
f.write(f"end\n")
f.write("\n")
if __name__ == "__main__":
blocks = {}
blocks[(0, 0)] = memory_block_start.replace("{addr}", sys.argv[5])
blocks[(-1, 0)] = memory_block_start_left
blocks[(1, 0)] = memory_block_start_right
gen_memory(blocks, (0, 1), int(sys.argv[2]), int(sys.argv[3]),
open(sys.argv[4], "rb").read().ljust(256, b"\x00"), sys.argv[6])
write_blocks(blocks, sys.argv[1], sys.argv[5])
|