bus.py (5372B)
1import sys 2 3from tpu import * 4 5# connect up parts to a bus.. layouting not important 6 7# we designate X0 Y0 as the input port from the bus 8# we designate X1 Y0 as the output port to the bus 9 10bus_upper_out_port = """ 11start: 12 mov RIGHT, ACC 13 jne {addr}, fwd 14 mov {addr}, DOWN 15 mov RIGHT, DOWN 16 mov RIGHT, DOWN 17 mov RIGHT, DOWN 18 mov RIGHT, DOWN 19 jmp start 20fwd: 21 mov ACC, LEFT 22 mov RIGHT, LEFT 23 mov RIGHT, LEFT 24 mov RIGHT, LEFT 25 mov RIGHT, LEFT 26""" 27 28bus_lower_out_port = """ 29start: 30 mov ANY, ACC 31 jne {addr}, fwd 32 mov ANY, DOWN 33 mov ANY, DOWN 34 mov ANY, DOWN 35 mov ANY, DOWN 36 jmp start 37fwd: 38 mov ACC, RIGHT 39 mov LEFT, RIGHT 40 mov LEFT, RIGHT 41 mov LEFT, RIGHT 42 mov LEFT, RIGHT 43""" 44 45bus_lower_in_port = """ 46start: 47 mov ANY, ACC 48 sav 49 mov ANY, ACC 50 jne {addr}, fwd 51 swp 52 mov ACC, UP 53 mov ACC, RIGHT 54 mov {addr}, UP 55 mov {addr}, RIGHT 56 mov DOWN, ACC 57 mov ACC, UP 58 mov ACC, RIGHT 59 mov DOWN, ACC 60 mov ACC, UP 61 mov ACC, RIGHT 62 mov DOWN, ACC 63 mov ACC, UP 64 mov ACC, RIGHT 65 jmp start 66fwd: 67 swp 68 mov ACC, RIGHT 69 swp 70 mov ACC, RIGHT 71 mov LEFT, RIGHT 72 mov LEFT, RIGHT 73 mov LEFT, RIGHT 74""" 75 76bus_lower_rail = """ 77mov ANY, RIGHT 78""" 79 80bus_upper_rail = """ 81mov ANY, LEFT 82""" 83 84bus_rail_end = """ 85mov ANY, NIL 86""" 87 88def does_collide(main, offx, part): 89 for (x,y),_ in part["tpus"].items(): 90 if (x+offx,y) in main["tpus"]: 91 return True 92 dirs = {"UP": (0, -1), "RIGHT": (1, 0), "DOWN": (0, 1), "LEFT": (-1, 0)} 93 for port in ("stdin", "stdout"): 94 if port in part: 95 x,y,d = part[port] 96 dx,dy = dirs[d] 97 if (x+offx+dx,y+dy) in main["tpus"]: 98 return True 99 if port in main: 100 x,y,d = main[port] 101 dx,dy = dirs[d] 102 if (x+dx-offx,y+dy) in part["tpus"]: 103 return True 104 return False 105 106def add_part(main, main_maxx, bus_ports, part): 107 portx = main_maxx 108 while portx in bus_ports or portx+1 in bus_ports or does_collide(main, portx, part): 109 portx += 1 110 bus_ports[portx] = ("in", part["addr"]) 111 bus_ports[portx+1] = ("out", part["addr"]) 112 for (x,y),ls in part["tpus"].items(): 113 main["tpus"][(x+portx,y)] = ls 114 if "stdin" in part: 115 assert("stdin" not in main) 116 x,y,d = part["stdin"] 117 main["stdin"] = (portx+x,y,d) 118 if "stdout" in part: 119 assert("stdout" not in main) 120 x,y,d = part["stdout"] 121 main["stdout"] = (portx+x,y,d) 122 return portx + 4 123 124def tolines(asm): 125 return asm.strip("\n").split("\n") 126 127def apply(part, transforms): 128 old_tpus = part["tpus"] 129 part["tpus"] = TPUDict({}) 130 for (x,y),ls in old_tpus.items(): 131 nx = transforms[0](x, y) 132 ny = transforms[1](x, y) 133 part["tpus"][(nx,ny)] = ls 134 135def rotate(part, r90=0): 136 dirs = ("UP", "RIGHT", "DOWN", "LEFT") 137 transforms = ( 138 (lambda x,_: x, lambda _,y: y), 139 (lambda _,y: -y, lambda x,_: x), 140 (lambda x,_: -x, lambda _,y: -y), 141 (lambda _,y: y, lambda x,_: -x), 142 ) 143 apply(part, transforms[r90]) 144 for _,ls in part["tpus"].items(): 145 for li,l in enumerate(ls): 146 for d in dirs: 147 l = l.replace(d, d.upper()) 148 for i,d in enumerate(dirs): 149 nd = dirs[(i+r90)%len(dirs)] 150 l = l.replace(d, nd.lower()) 151 for d in dirs: 152 l = l.replace(d.lower(), d) 153 ls[li] = l 154 155def add_ports(main, bus_ports): 156 for x,(dir,addr) in bus_ports.items(): 157 dir,addr = bus_ports[x] 158 if dir == "in": 159 main["tpus"][(x,-2)] = tolines(bus_upper_out_port.format(addr=addr)) 160 main["tpus"][(x,-1)] = tolines(bus_lower_out_port.format(addr=addr)) 161 else: 162 main["tpus"][(x,-2)] = tolines(bus_upper_rail) 163 main["tpus"][(x,-1)] = tolines(bus_lower_in_port.format(addr=addr)) 164 165def add_rail(main, bus_ports): 166 bus_start = min(bus_ports) 167 bus_end = max(bus_ports) + 1 168 for x in range(bus_start, bus_end + 1): 169 if x not in bus_ports: 170 main["tpus"][(x,-2)] = tolines(bus_upper_rail) 171 main["tpus"][(x,-1)] = tolines(bus_lower_rail) 172 main["tpus"][(bus_start-1,-1)] = tolines(bus_rail_end) 173 main["tpus"][(bus_start-1,-2)] = tolines(bus_rail_end) 174 main["tpus"][(bus_end+1,-1)] = tolines(bus_rail_end) 175 main["tpus"][(bus_end+1,-2)] = tolines(bus_rail_end) 176 177if __name__ == "__main__": 178 main = { "tpus": TPUDict({}) } 179 files = sys.argv[2:] 180 if "--" in files: 181 split = files.index("--") 182 else: 183 split = None 184 185 bus_ports = {} 186 main_maxx = 0 187 for arg in files[:split]: 188 main_maxx = add_part(main, main_maxx, 189 bus_ports, parse(open(arg).read())) 190 add_ports(main, bus_ports) 191 192 if split is not None: 193 rotate(main, 2) 194 apply(main, (lambda x,_: x, lambda _,y: y-3)) 195 196 all_ports = {-k:v for k,v in bus_ports.items()} 197 main_maxx = min(all_ports) 198 for arg in files[split+1:]: 199 main_maxx = add_part(main, main_maxx, 200 all_ports, parse(open(arg).read())) 201 add_ports(main, {k:v for k,v in all_ports.items() if -k not in bus_ports}) 202 add_rail(main, all_ports) 203 else: 204 add_rail(main, bus_ports) 205 206 write(main, sys.argv[1])