memory2.py (3745B)
1import sys 2 3memory_block_start = """ 4 mov UP, LEFT 5 6 mov UP, ACC 7 mov UP, LEFT 8 9 jne 0, is_write 10 mov LEFT, DOWN 11 mov 0, DOWN 12 mov UP, DOWN 13 mov LEFT, NIL 14 jmp wrap 15 16is_write: 17 mov LEFT, DOWN 18 mov 1, DOWN 19 mov UP, ACC 20 xor LEFT 21 mov ACC, DOWN 22 swp 23 24wrap: 25 mov DOWN, ACC 26 xor LEFT 27 mov LEFT, RIGHT 28 mov ${{addr}}, RIGHT 29 mov ${OP_ACK}, RIGHT 30 mov ACC, RIGHT 31 mov ${OP_NIL}, RIGHT 32""" 33 34memory_block_start_left = """ 35 mov RIGHT, ACC 36 swp 37 mov RIGHT, ACC 38 mov ACC, RIGHT 39 mov ACC, RIGHT 40 mov ACC, RIGHT 41 swp 42 mov ACC, RIGHT 43""" 44 45memory_block_start_right = """ 46 mov LEFT, UP 47""" 48 49code_memory_cell = """ 50 mov 0x{val:02x}, ACC 51 sav 52start: 53 mov {inp}, ACC 54 jne {idx}, fwd 55 mov {inp}, ACC 56 jne 0, WRITE 57 mov {inp}, NIL 58 swp 59 mov ACC, {inp} 60 sav 61 jmp start 62write: 63 mov {inp}, ACC 64 swp 65 mov ACC, {inp} 66 jmp start 67fwd: 68 mov ACC, {outp} 69 mov {inp}, {outp} 70 mov {inp}, {outp} 71 mov {outp}, {inp} 72 jmp start 73""" 74 75pattern = """ 76# 77# 78# ################## 79# # # 80# ################ # 81# # 82#################### 83 84""" 85assert(pattern.count("#") == 64) 86pattern = pattern.strip("\n").split("\n") 87 88dirs = ((1, 0), (0, 1), (-1, 0), (0, -1)) 89 90x,y = (0, 0) 91seen = set() 92seen.add((x,y)) 93path = [(x,y),] 94while True: 95 npos = None 96 for dx,dy in dirs: 97 nx,ny = x+dx,y+dy 98 if nx < 0 or nx >= len(pattern[0]): continue 99 if ny < 0 or ny >= len(pattern): continue 100 if pattern[ny][nx] == "#" and (nx,ny) not in seen: 101 npos = (nx,ny) 102 break 103 if npos is None: 104 break 105 x,y = npos 106 seen.add((x,y)) 107 path.append((x,y)) 108 109class BlockMap(dict): 110 def __setattr__(self, key, value): 111 if key in self.__dict__: 112 raise ValueError("Already exists") 113 super().__setattr__(key, value) 114 115def gen_memory(blocks, start, idx_offset, depth, contents, dtype): 116 opposite = { "UP": "DOWN", "LEFT": "RIGHT", "RIGHT": "LEFT", "DOWN": "UP" } 117 ports = { (-1, 0): "LEFT", (0, 1): "DOWN", (1, 0): "RIGHT", (0, -1): "UP" } 118 sx,sy = start 119 maxi = 2**depth-1 120 for i in range(2**depth): 121 fix = lambda x,y: (-x,y) if dtype == "left" else (x,y) 122 x,y = fix(*path[i]) 123 px,py = (0,0) if i == 0 else fix(*path[i-1]) 124 nx,ny = (0,0) if i == maxi else fix(*path[i+1]) 125 pd = x-px,y-py 126 nd = nx-x,ny-y 127 inp = "UP" if i == 0 else opposite[ports[pd]] 128 outp = opposite[inp] if i == maxi else ports[nd] 129 addr = idx_offset + i 130 cell = code_memory_cell.format(idx=addr,val=addr^contents[i],inp=inp,outp=outp) 131 if dtype == "left": 132 blocks[(sx+x,sy+y)] = cell 133 elif dtype == "right": 134 blocks[(sx+x,sy+y)] = cell 135 else: 136 assert(dtype == "straight") 137 blocks[(sx,sy+i)] = cell 138 139def write_blocks(blocks, filepath, addr_tmpl): 140 with open(filepath, "w+") as f: 141 for i,(x,y) in enumerate(blocks): 142 f.write(f"tpu X{x} Y{y}\n") 143 if i == 0: 144 f.write("\t## ${" + addr_tmpl + "}\n") 145 for l in blocks[(x,y)].strip("\n").split("\n"): 146 f.write(f"{l}\n") 147 f.write(f"end\n") 148 f.write("\n") 149 150if __name__ == "__main__": 151 blocks = {} 152 blocks[(0, 0)] = memory_block_start.replace("{addr}", sys.argv[5]) 153 blocks[(-1, 0)] = memory_block_start_left 154 blocks[(1, 0)] = memory_block_start_right 155 gen_memory(blocks, (0, 1), int(sys.argv[2]), int(sys.argv[3]), 156 open(sys.argv[4], "rb").read().ljust(256, b"\x00"), sys.argv[6]) 157 write_blocks(blocks, sys.argv[1], sys.argv[5])