Ejemplo n.º 1
0
 def pc(in_: Bool16 = (False, ) * 16,
        load: bool = False,
        inc: bool = False,
        reset: bool = False) -> Bool16:
     nonlocal register
     not_load = not_(load)
     use_inc = and_(not_load, inc)
     inc_out = inc_16(register())
     mux_inc = mux_16(use_inc, inc_out, in_)
     mux_reset = mux_16(reset, (False, ) * 16, mux_inc)
     load_or_inc = or_(load, inc)
     load_or_inc_or_reset = or_(load_or_inc, reset)
     return register(mux_reset, load_or_inc_or_reset)
Ejemplo n.º 2
0
Archivo: memory.py Proyecto: M-110/PyPC
    def memory(in_: Bool16, load: bool, address: Bool15) -> Bool16:
        load_ram_1, load_ram_2, load_screen, load_keyboard = demux_4way(
            in_=load, selectors=address[13:15])
        load_ram = or_(load_ram_1, load_ram_2)

        ram_out = ram(in_=in_, load=load_ram, address=address[0:14])
        screen_out = screen(in_=in_, load=load_screen, address=address[0:12])
        keyboard_out = (False, ) * 16

        return mux_16_4way(address[13:15], ram_out, ram_out, screen_out,
                           keyboard_out)
Ejemplo n.º 3
0
def equal_to_zero(in_: Bool16) -> bool:
    """Returns True if in_ is equal to 0."""
    # Reduce to 8
    or_01 = or_(in_[0], in_[1])
    or_23 = or_(in_[2], in_[3])
    or_45 = or_(in_[4], in_[5])
    or_67 = or_(in_[6], in_[7])
    or_89 = or_(in_[8], in_[9])
    or_1011 = or_(in_[10], in_[11])
    or_1213 = or_(in_[12], in_[13])
    or_1415 = or_(in_[14], in_[15])
    # Reduce to 4
    or_0123 = or_(or_01, or_23)
    or_4567 = or_(or_45, or_67)
    or_891011 = or_(or_89, or_1011)
    or_12131415 = or_(or_1213, or_1415)
    # Reduce to 2
    or_01234567 = or_(or_0123, or_4567)
    or_89101112131415 = or_(or_891011, or_12131415)
    # Reduce to 1
    or_result = or_(or_01234567, or_89101112131415)
    # Return inverse
    return nand(or_result, or_result)
Ejemplo n.º 4
0
 def test_logic(self):
     for a, b in self.logic_pairs:
         self.assertEqual(and_(a, b), a and b)
         self.assertEqual(or_(a, b), a or b)
         self.assertEqual(xor_(a, b), (a or b) and not (a and b))
Ejemplo n.º 5
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
Ejemplo n.º 6
0
def or_16(a: Bool16, b: Bool16) -> Bool16:
    """Returns 16-bit bitwise or in the form of a tuple of 16 bool values."""
    return (or_(a[0], b[0]), or_(a[1], b[1]), or_(a[2], b[2]), or_(a[3], b[3]),
            or_(a[4], b[4]), or_(a[5], b[5]), or_(a[6], b[6]), or_(a[7], b[7]),
            or_(a[8], b[8]), or_(a[9], b[9]), or_(a[10], b[10]),
            or_(a[11], b[11]), or_(a[12], b[12]), or_(a[13], b[13]),
            or_(a[14], b[14]), or_(a[15], b[15]))