Ejemplo n.º 1
0
 def __call__(self, in_: Bool16, load: bool, address: Tuple[bool,
                                                            ...]) -> Bool16:
     if load:
         print('loading new value: ', bool16_to_int(in_))
         self.data_dec[bool16_to_int(address)] = bool16_to_int(in_)
         self.data[address] = in_
     print('reading from address ', bool16_to_int(address), ': ',
           bool16_to_int(self.data[address]))
     return self.data[address]
Ejemplo n.º 2
0
    def test_unary_alu(self):
        for num in self.test_numbers:
            num_bool16 = int_to_bool16(num)

            num_z = bool16_to_int(
                unary_alu(zero=True, negation=False, in_=num_bool16))
            num_n = bool16_to_int(
                unary_alu(zero=False, negation=True, in_=num_bool16))
            num_zn = bool16_to_int(
                unary_alu(zero=True, negation=True, in_=num_bool16))
            num_plain = bool16_to_int(
                unary_alu(zero=False, negation=False, in_=num_bool16))

            self.assertEqual(0, num_z)
            self.assertEqual(~num, num_n)
            self.assertEqual(~0, num_zn)
            self.assertEqual(num, num_plain)
Ejemplo n.º 3
0
 def test_adder_16(self):
     # for a, b in self.values:
     for a, b in ((5, 25), ):
         a_bools = int_to_bool16(a)
         b_bools = int_to_bool16(b)
         c_bools = adder_16(a_bools, b_bools)
         c = bool16_to_int(c_bools)
         self.assertEqual(a + b, c)
Ejemplo n.º 4
0
 def read_address(self, address):
     """Read from the bool16 address location."""
     address_index = bool16_to_int(address)
     try:
         out = tuple(True if c == '1' else False for c in self.data[address_index])
         return out
     except IndexError:
         return (False, ) * 16
Ejemplo n.º 5
0
    def py_alu(self, zx: bool, nx: bool, zy: bool, ny: bool, f: bool, no: bool,
               x: Bool16, y: Bool16) -> Tuple[Bool16, bool, bool]:
        """Python implementation of an ALU to use as a comparison."""
        if zx:
            x = (False, ) * 16
        if zy:
            y = (False, ) * 16
        if nx:
            x = tuple(not i for i in x)
        if ny:
            y = tuple(not i for i in y)
        if f:
            f_out = adder_16(x, y)
        else:
            f_out = tuple(x_i and y_i for x_i, y_i in zip(x, y))

        if no:
            f_out = tuple(not i for i in f_out)

        is_zero = bool16_to_int(f_out) == 0
        is_negative = bool16_to_int(f_out) < 0

        return f_out, is_zero, is_negative
Ejemplo n.º 6
0
 def _read_memory(self, register: Callable) -> int:
     output = register(clock=True)
     register(clock=False)
     return bool16_to_int(output)
Ejemplo n.º 7
0
Archivo: cpu.py Proyecto: M-110/PyPC
    def cpu(m_in: Bool16, instructions: Bool16, reset: bool) \
            -> Tuple[Bool16, bool, Bool15, Bool15]:
        """Simulation of the CPU unit.
        
        Args:
            m_in: Value of the M RAM input.
            instructions: 16 bit instructions for the CPU to follow.
            reset: If True, program will be restarted.
            
        Returns:
            (a, b, c, d) where
            a: M output value.
            b: Write to M instruction.
            c: Address of M
            d: address of the next instruction
        """
        nonlocal alu_out

        # If first instruction digit is 1, then it is a C instruction.
        a_instruction = not_(instructions[15])
        c_instruction = not_(a_instruction)

        print(f'I = {"".join(["1" if x else "0" for x in instructions])}')
        if c_instruction:
            print(f'C instruction')
        else:
            print(f'A instruction')
        print(f'M = {bool16_to_int(m_in)}')
        print(f'A = {bool16_to_int(a_register((False,)*16, False))}')
        print(f'D = {bool16_to_int(d_register((False,)*16, False))}')
        print(f'ALU {bool16_to_int(alu_out)}')
        # # # # # # # # # # # # # # Register A
        # instructions[5] represents whether A is the destination
        alu_to_a = and_(a=c_instruction, b=instructions[5])

        if alu_to_a:
            print('A is destination')

        # If it's a C instruction and the destination is A then send the ALU output
        # to the A register. Otherwise send the instruction to Register A.
        register_a_input = mux_16(alu_to_a, alu_out, instructions)
        # load_a is True if it is an A instruction or the C instruction has A as
        # the destination.
        load_a = or_(a_instruction, alu_to_a)
        a_to_pc = a_register(register_a_input, load_a)
        register_a_out = a_to_pc
        m_address = a_to_pc[0:15]  # Returned as output ->

        # if instructions[12] is True M should be used instead of the A register
        am_mux_out = mux_16(instructions[12], m_in, register_a_out)

        # # # # # # # # # # # # # # Register D
        # If instructions[4] is True the D register is the destination (if it is a
        # c instruction).
        load_d = and_(a=c_instruction, b=instructions[4])
        register_d_out = d_register(alu_out, load_d)
        if load_d:
            print(f'loaded {bool16_to_int(alu_out)} into d')
        # # # # # # # # # # # # # # ALU
        # Send the register_d_out into the ALU
        alu_out, zero_out, neg_out = alu(x=register_d_out,
                                         y=am_mux_out,
                                         zero_x=instructions[11],
                                         negate_x=instructions[10],
                                         zero_y=instructions[9],
                                         negate_y=instructions[8],
                                         add_x_y=instructions[7],
                                         negate_output=instructions[6])

        print(f'ALU(x={bool16_to_int(register_d_out)}, '
              f'y={bool16_to_int(am_mux_out)}, '
              f'zero_x={instructions[11]}, '
              f'negate_x={instructions[10]}, '
              f'zero_y={instructions[9]}, '
              f'negate_y={instructions[8]}, '
              f'add_x_y={instructions[7]}, '
              f'negate_output={instructions[6]})'
              f' = {bool16_to_int(alu_out)}')
        m_out = alu_out  # Returned as output ->
        print(f'm_out/alu_out = {"".join(["1" if x else "0" for x in m_out])}')

        # If it is a C instruction and the destination is M, write to M
        write_m = and_(c_instruction, instructions[3])  # Returned as output ->
        if write_m:
            print('M is the destination')

        # # # # # # # # # # # # # # PC / JUMP conditionals
        # Jump if equal to zero
        jeq = and_(zero_out, instructions[1])
        # Jump if less than zero
        jlt = and_(neg_out, instructions[2])

        # Zero or negative
        zero_or_neg = or_(zero_out, neg_out)
        # Positive
        positive = not_(zero_or_neg)

        # Jump if greater than zero
        jgt = and_(positive, instructions[0])
        # Jump if less than or equal to zero
        jle = or_(jeq, jlt)

        # If any conditions are met, ready the jump to A
        # (less than or equal to and greater than cover all possible conditions
        # so if either is True, there must be a jump).
        jump_to_a = or_(jle, jgt)

        # Only jump if it a C instruction though!
        load_pc = and_(c_instruction, jump_to_a)
        # If not loading an address, increase the PC
        inc_pc = not_(load_pc)

        # If any conditions were met then the PC will load the address,
        # otherwise the PC will just increase the address to the program's next line.
        pc_out = pc(a_to_pc, load_pc, inc_pc, reset)[:15]  # returned as output
        print('## Returns:')
        print('m_out = ', bool16_to_int(m_out))
        print('write_m =', write_m)
        print('m_address = ', bool16_to_int(m_address))
        print('pc_out = ', bool16_to_int(pc_out))
        print(
            '***************************************************************')
        return m_out, write_m, m_address, pc_out