def wire_expand(n, source, destr = None): """Prend un fil, et retourne une nappe consistant en n copies de ce fil (par exponentiation rapide)""" assert(n > 0) assert(destr == None or nl.get_size(destr) == n * nl.get_size(source)) if n == 1 and destr == None: return source elif n == 1: return nl.WIRE(source, destr) nl.push_context("wire_expand") c = 1 k = 0 l = [source] bits = [] m = n while 2 * c < n: l.append(nl.CONCAT(l[-1], l[-1])) if m % 2 == 1: bits.append(k) m //= 2 c *= 2 k += 1 if 2 * c == n: nl.pop_context() return nl.CONCAT(l[-1], l[-1], destr) u = l[bits[0]] for i in range(1, len(bits)): u = nl.CONCAT(u, l[bits[i]]) nl.pop_context() return nl.CONCAT(u, l[k], destr)
def alu(instr, useCarry, op1, op2, carryFlag, val = None, flags = None): nl.push_context("alu") """calcule les opposés de op1 et op2 si (et seulement si) nécessaire""" op1_1 = nl.XOR(op1, hel.wire_expand(64, nl.SELECT(2, instr))) op2_1 = nl.XOR(op2, hel.wire_expand(64, nl.SELECT(4, instr))) """calcule la sortie pour les opérations arithmétiques seulement""" c_in = nl.MUX(nl.OR(nl.SELECT(4, instr), nl.SELECT(2, instr)), \ carryFlag, useCarry) arith, flag_C, flag_V = full_adder_n(64, op1_1, op2_1, c_in, True) """calcule la sortie pour les opérations booléennes seulement""" eor = nl.XOR(op1, op2_1) orr = nl.OR(op1, op2_1) oand = nl.AND(op1, op2_1) boo_1 = nl.MUX(eor, orr, hel.wire_expand(64, nl.SELECT(1, instr))) boo = nl.MUX(boo_1, oand, hel.wire_expand(64, nl.SELECT(2, instr))) """sélectionne la bonne sortie parmi les deux propositions""" val = nl.MUX(arith, boo, hel.wire_expand(64, nl.SELECT(3, instr)), val) """détermine les flags""" n_flag_Z = hel.or_all(val) flag_Z = nl.NOT(n_flag_Z) flag_N = nl.SELECT(64, val) flags_1 = nl.CONCAT(flag_N, flag_Z) flags_2 = nl.CONCAT(flags_1, flag_C) flags = nl.CONCAT(flags_2, flag_V, flags) nl.pop_context() return (val, flags)
def registers(set_val, r1addr, r2addr, setaddr, value, r1 = None, r2 = None, pc = None): nl.push_context("registers") n = nl.get_size(value) regs = [] for i in range(constants.REGISTERS.number): write_enable = nl.fresh() if i == constants.REGISTERS.pc: pc = register_pc(value, write_enable, pc) reg = pc elif i in constants.REGISTERS.inputs: reg = nl.fresh(n) nl.input(reg) else: reg = register(value, write_enable) if i in constants.REGISTERS.outputs: nl.output(reg) regs.append((write_enable, reg)) addr_size = nl.get_size(r1addr) assert(1 << addr_size == constants.REGISTERS.number) r1 = mux_n(addr_size, [r[1] for r in regs], r1addr, r1) r2 = mux_n(addr_size, [r[1] for r in regs], r2addr, r2) demux_n(addr_size, [r[0] for r in regs], set_val, setaddr) nl.pop_context() return r1, r2, pc
def memory_unit(instr, value, addr, result = None): nl.push_context("memory_unit") is_memory = nl.AND(nl.SELECT(1, instr), nl.SELECT(4, instr)) we = nl.AND(is_memory, nl.SELECT(2, instr)) addr = nl.SLICE(1, 16, addr) if UNUSED_ADDR_ZERO: addr = nl.AND(addr, helpers.wire_expand(16, is_memory)) uu = nl.fresh(16) nl.pop_context() return nl.RAM(16, 64, addr, we, nl.WIRE(addr, uu), value, result)
def register_pc(data, write_enable, destr = None): n = nl.get_size(data) u = nl.fresh(n) destr = nl.REG(u, destr) nl.push_context("incr") incremented, _ = alu.incr(n, destr) nl.pop_context() write_n = helpers.wire_expand(n, write_enable) nl.MUX(incremented, data, write_n, u) return destr
def or_all(source, destr = None): n = nl.get_size(source) if n == 1: return nl.WIRE(source, destr) nl.push_context("or_all") c = 1 while 2 * c < n: c *= 2 w = source if 2 * c > n: w = nl.CONCAT(wire_expand(2 * c - n, nl.CONST(0)), source) while c > 1: w = nl.OR(nl.SLICE(1, c, w), nl.SLICE(c + 1, 2 * c, w)) c //= 2 destr = nl.OR(nl.SLICE(1, c, w), nl.SLICE(c + 1, 2 * c, w), destr) nl.pop_context() return destr
def result_selector(instr, mem_result, alu_result, output = None): nl.push_context("result_selector") is_STR = nl.AND(nl.SELECT(1, instr), nl.SELECT(4, instr)) output = nl.MUX(alu_result, mem_result, hel.wire_expand(64, is_STR), output) nl.pop_context() return output