summaryrefslogtreecommitdiffstats
path: root/src/memory2.py
blob: 0da0a896f11748ee693637df37136f2c9e0df742 (plain) (blame)
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])