def write_at(self, control: 'bit', addr: 32, value: 32): dest, addr = addr[:3], addr[3:-2] + bit('00000') for dest_id, dest_obj, is_memory in self.sources: isdest = bit(True) for a, b in zip(dest_id, dest): isdest = isdest & (b if a == '1' else ~b) dest_obj.write_at(control & isdest, addr, value)
def do_division(dividend, divisor, step): if step >= len(dividend): return (bit(size=0), dividend) quotient_up, dividend_up = do_division(dividend, divisor << 1, step + 1) # Don't overflow dividend = mux(divisor[1], dividend_up, dividend) quotient = mux(divisor[1], quotient_up, bit(0, size=len(quotient_up))) sub = hdl.simple_adder(dividend, hdl.negative_of_int(divisor))[0] return (mux(sub[0], quotient + '1', quotient + '0'), mux(sub[0], sub, dividend))
def read_at(self, control: 'bit', addr: 32, memory_only=False): dest, addr = addr[:3], addr[3:][:-2] + bit('00000') self.used = self.used | (control & (~(dest[0] | dest[1]))) # RAM and ROM -> 00x output = bit(0, size=32) for dest_id, dest_obj, is_memory in self.sources: if not memory_only or is_memory: isdest = ~(bit(dest) ^ dest_id) isdest = isdest[0] & isdest[1] & isdest[2] dest_out = dest_obj.read_at(control & isdest, addr) if dest_out is not None: output = mux(isdest, output, dest_out) return output
def __init__(self, rom, ram, out_format): self.input_signal = bit(-1, size=out_format[0][1]) # We don't add the first output to the controller because it is reserved self.output = OutputController([size for _, size in out_format[1:]]) self.sources = [ ('000', ram, True), ('001', rom, True), ('101', self.output, False), ] self.used = bit(0) # If the ROM or RAM has already been used # Set default actions rom.read_at('0', '0' * rom.rom_size) ram.read_at('1', '0' * ram.ram_size)
def add(self, control, left, right, inv=None): self.input1.add(control, left) self.input2.add(control, right) if inv is not None: inv = bit(inv) self.inv.set((control & inv) | self.inv.get()) return self.result
def __init__(self, nb_registers, word_size): self.nb_registers = nb_registers self.reg_addr_size = math.ceil(math.log2(nb_registers)) self.word_size = word_size self.registers = [ Register(size=word_size, name=f'register_{i}') for i in range(nb_registers) ] self.registers[0] = bit(0, size=word_size)
def __init__(self, inputs): self.input_control = MultiControl() self.input_addr = virtual(IO_SIGNIFICANT_BITS, self.input_control) self.plexer = Multiplexer(control=self.input_addr) self.plexer_out = virtual(32, self.plexer) self.plexer.plzshutup = True self.plexer.add(*inputs) # Read at -1 if no address self.read_at(1, bit(-1, size=32))
def __init__(self, ram_size, word_size): self.ram_size = ram_size # Size of the address self.word_size = word_size self.inputs = MultiControl() self.write_addrs = hdl.VirtualBit(ram_size) self.write_data = hdl.VirtualBit(word_size) self.write_enabled = virtual(1, bit('0')) self.output = RamOp(ram_size, word_size, virtual(ram_size, self.inputs), self.write_enabled, self.write_addrs, self.write_data)
def right_shift(bits, shift, invert=False, lead_bit=bit('0')): if invert: return left_shift(bits, shift) lead = lead_bit shift = list(shift) k = 1 while shift: bits = mux(shift.pop(), bits, lead + bits[:-k]) k *= 2 lead = lead + lead return bits
def __init__(self, size, adder_function): self.input1 = MultiControl() self.input2 = MultiControl() self.inv = virtual(1, bit(0)) self.signed = virtual(1, bit(0)) self.word_size = size operand1 = virtual(size, self.input1) operand1 = mux( self.signed, hdl.extend(size + 1, operand1), hdl.sign_extend(size + 1, operand1), ) operand2 = virtual(size, self.input2) operand2 = mux( self.signed, hdl.extend(size + 1, operand2), hdl.sign_extend(size + 1, operand2), ) operand2 = mux(self.inv, operand2, hdl.negative_of_int(operand2)) self.num_result, self.carry = adder_function(operand1, operand2) self.result = self.num_result[1:], self.num_result[0]
def op_auipc(self, control, rd, imm): result = self.alu.add(control, self.proc.reg_pc, imm + bit(0, size=12))[0] self.write_rd(control, result)
def op_lui(self, control, rd, imm): result = imm + bit(0, size=12) self.write_rd(control, result)
def __init__(self, out_sizes): self.outputs = [bit(0, size=s) for s in out_sizes] self.out_addresses = [ bit(k, size=IO_SIGNIFICANT_BITS) for k in range(len(out_sizes)) ]
def first_less_than(self, control, first, second, unsigned=False): r = self.comp(control, first, second, bit(not unsigned)) return '0' * (self.word_size - 1) + r