diff options
Diffstat (limited to 'lab1/lab1ucode.py')
| -rw-r--r-- | lab1/lab1ucode.py | 198 |
1 files changed, 198 insertions, 0 deletions
diff --git a/lab1/lab1ucode.py b/lab1/lab1ucode.py new file mode 100644 index 0000000..cc8c94c --- /dev/null +++ b/lab1/lab1ucode.py @@ -0,0 +1,198 @@ +import sys + +from string import Template + +TWOWAY = { + "ir": "001", + "pm": "010", + "pc": "011", + "hr": "101", + "grx": "110", +} + +# to bus: source +TB = TWOWAY | { + "ar": "100", + # "styrord": "111", +} + +# from bus: destination +FB = TWOWAY | { + "asr": "111" +} + +def compile(lines): + addr = 0 + labels = {} + compiled = [] + todo = [] + for line in lines: + if not line: + # empty line, ignore + continue + if line.startswith(";"): + # comment + continue + if line.endswith(":"): + # label + labels[line.split(":")[0]] = addr + continue + if line.startswith("!"): + # inline + compiled.append(line[1:]) + addr += 1 + continue + + for inst in line.split(", "): + alu = "0000" + tb = "000" + fb = "000" + s = "0" + p = "0" + lc = "00" + seq = "0000" + myadr = "0000000" + + if "->" in inst: + # move a value + fr, to = inst.split("->") + # via bus + if fr in TB: + tb = TB[fr] + if to in FB: + fb = FB[to] + + if "gr" in fr and len(fr) == 3: + tb = TB["grx"] + if "gr" in to and len(to) == 3: + fb = FB["grx"] + + if to == "lc": + lc = "10" + + # load alu + if to == "ar": + alu = "0001" + + # alu addition + if "+" in fr: + if "+'" in fr: + # ignore flags + other = fr.split("+'")[1] + alu = "1000" + else: + other = fr.split("+")[1] + alu = "0100" + tb = TB[other] + + # alu subtraction + if "-" in fr: + other = fr.split("-")[1] + tb = TB[other] + alu = "0101" + + if "&" in fr: + other = fr.split("&")[1] + tb = TB[other] + alu = "0110" + + if inst == "pc++": + p = "1" + + if inst == "k1->upc": + seq = "0001" + if inst == "k2->upc": + seq = "0010" + if inst == "0->upc": + seq = "0011" + if inst == "halt": + seq = "1111" + if inst == "lc--": + lc = "01" + if inst == "lsr": + alu = "1101" + + if "?" in inst: + cond, to = inst.split("? ") + if cond == "l=1": + seq = "1100" + elif cond == "z=1": + seq = "1000" + elif cond == "n=1": + seq = "1001" + elif cond == "o=1": + seq = "1011" + else: + assert False + myadr = f"<{to}>" + + if inst.startswith("b "): + seq = "0110" #TODO 0101? + myadr = "<{}>".format(inst.split("b ")[1]) + + compiled.append((inst, (alu, tb, fb, s, p, lc, seq, myadr))) + + addr += 1 + + linked = [] + for addr, line in enumerate(compiled): + if type(line) is str: + linked.append((addr, line)) + continue + inst, (alu, tb, fb, s, p, lc, seq, myadr) = line + if myadr != "0000000": + for label, label_line in labels.items(): + myadr = myadr.replace(f"<{label}>", str(bin(label_line)[2:]).zfill(7)) + first = alu[0] + rest = alu[1:] + tb + fb + s + p + lc + seq + myadr + hs = "".join([f"{int(first):01x}"] + [f"{int(rest[i:i+4], 2):01x}" for i in range(0, len(rest), 4)]) + linked.append((addr, hs)) + if hs == "0000000": + todo.append(inst) + + if todo: + print("todo", file=sys.stderr) + print("\n".join(todo), file=sys.stderr) + assert False + + return ["{:02x}: {}".format(addr, line) for addr, line in linked], labels + + +def write(prog, labels): + #with open("template.mia", "r") as f: + # template = Template(f.read()) + + ucode_pad = 0x80 - len(prog) + ucode = "\n".join(prog + [f"{len(prog)+n:02x}: 0000000" for n in range(ucode_pad)]) + + insts = [ + "load", + "store", + "add", + "sub", + "and", + "lsr", + "bra", + "bne", + "halt", + "cmp", + "bge", + "beq", + ] + inst_pad = 0x10 - len(insts) + inst_locations = "\n".join([f"{i:02x}: {labels[inst]:02x}" for i, inst in enumerate(insts)] + + [f"{n+len(insts):02x}: 00" for n in range(inst_pad)]) + + print("MyM:") + print(ucode) + print() + + print("K1:") + print(inst_locations) + #print(template.safe_substitute(pm)) + + print("K2:") + + +if __name__ == "__main__": + write(*compile([line.strip() for line in sys.stdin])) |
