def op1processor(i_op1, i_op1cst, i_regVal, o_reqAddr, o_val): push_context("op1processor") o_reqAddr = WIRE(i_op1, o_reqAddr) zero = hel.wire_expand(64, CONST(0)) o_val = MUX(i_regVal, zero, hel.wire_expand(64, i_op1cst), o_val) pop_context() return o_reqAddr, o_val
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 mux_n(n, l, addr, destr = None): k = nl.get_size(l[0]) if n == 1: return nl.MUX(l[0], l[1], helpers.wire_expand(k, nl.SELECT(1, addr)), destr) z = 1 << (n - 1) return nl.MUX(mux_n(n - 1, l[:z], addr), mux_n(n - 1, l[z:], addr), helpers.wire_expand(k, nl.SELECT(n, addr)), destr)
def register(data, write_enable, destr = None): n = nl.get_size(data) u = nl.fresh(n) destr = nl.REG(u, destr) write_n = helpers.wire_expand(n, write_enable) nl.MUX(destr, data, write_n, u) return destr
def flagsMem(i_flags, i_flagWrite, o_flagsOut): """ Handles the actual flags storage """ writeArray = hel.wire_expand(4, i_flagWrite) regOutWire = fresh(4) flagsInput = MUX(regOutWire, i_flags, writeArray) REG(flagsInput, regOutWire) return regOutWire
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 demux_n(n, l, source, addr): k = nl.get_size(source) u = helpers.wire_expand(k, nl.SELECT(n, addr)) z = 1 << (n - 1) if n == 1: nl.AND(u, source, l[1]) nl.AND(nl.NOT(u), source, l[0]) return demux_n(n - 1, l[:z], nl.AND(nl.NOT(u), source), addr) demux_n(n - 1, l[z:], nl.AND(u, source), addr)
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 barrelShifter(shifter, i_inputVal, i_shiftCode, i_shiftVal, o_val = None): push_context("shifter") interWires = [i_inputVal] + [ fresh(64) for k in range(5) ] + [ o_val ] for shiftWeight in range(6): shifted = shifter(interWires[shiftWeight], i_shiftCode, shiftWeight) interWires[shiftWeight+1] = \ MUX(interWires[shiftWeight], shifted,\ hel.wire_expand(64, SELECT(shiftWeight+1, i_shiftVal)),\ interWires[shiftWeight+1]) pop_context() return interWires[-1]
def op2processor(i_op2, i_reqVal, o_reqAddr = None, o_val = None): push_context("op2processor") o_reqAddr = SLICE(constants.OP2_FRAME.value, constants.OP2_FRAME.value + 3,\ i_op2, o_reqAddr) numCst = CONCAT(\ SLICE(constants.OP2_FRAME.value, constants.OP2_FRAME.value + 15,\ i_op2),\ hel.wire_expand(64-16, CONST(0))) interValue = MUX(\ numCst,\ i_reqVal,\ hel.wire_expand(64, SELECT(constants.OP2_FRAME.isRegister, i_op2))) shiftCode = SLICE(constants.OP2_FRAME.shift_opcode,\ constants.OP2_FRAME.shift_opcode + 1, i_op2) shiftVal = SLICE(constants.OP2_FRAME.shift_val,\ constants.OP2_FRAME.shift_val + 5, i_op2) o_val = MUX( barrelShifter(leftShifter,interValue, shiftCode, shiftVal),\ barrelShifter(rightShifter,interValue, shiftCode, shiftVal),\ hel.wire_expand(64,SELECT(2, shiftCode)),\ o_val) pop_context() return o_reqAddr, o_val
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
def rightShifter(i_inputVal, i_shiftCode, wei): extendWith = AND(SELECT(64, i_inputVal), SELECT(1, i_shiftCode)) return CONCAT(SLICE((1<<wei) + 1, 64, i_inputVal),\ hel.wire_expand(1<<wei, extendWith))
def leftShifter(i_inputVal, i_shiftCode, wei): return CONCAT(hel.wire_expand(1<<wei, CONST(0)),\ SLICE(1, 64 - (1<<wei), i_inputVal))