Beispiel #1
0
    def test_reset(self):
        """
        Tests for CPU reset
        """
        e = ElfCPU()
        e.load_string('1,0,0,0,99')
        e.execute()
        e.reset()

        # Halted gets cleared
        self.assertFalse(e.is_halted)
        # Program counter goes to 0
        self.assertEqual(e.pc, 0)
        # Memory gets wiped so address 1 becomes invalid
        with self.assertRaises(ValueError):
            e.peek(1)
Beispiel #2
0
 def test_halt(self):
     """
     Tests for the halt op code
     """
     e = ElfCPU()
     e.load_string('1,0,0,0,99')
     e.step()
     self.assertFalse(e.is_halted)
     e.step()
     self.assertTrue(e.is_halted)
Beispiel #3
0
 def test_invalid_instr(self):
     """
     Tests for invalid op code
     """
     e = ElfCPU()
     e.load_string('123456789')
     with self.assertRaises(InvalidInstructionError):
         e.execute()
Beispiel #4
0
 def test_load_string_types(self):
     """
     Checks for TypeError
     """
     e = ElfCPU()
     with self.assertRaises(TypeError):
         # noinspection PyTypeChecker
         e.load_string(0)
     e.load_string('1,2,3,4')
Beispiel #5
0
 def test_gpf(self):
     """
     Tests for a general protection fault by allowing the program counter to
     go past the end of the memory.
     """
     e = ElfCPU()
     # Jump to 2**20, the last memory address
     e.load_string('1106,0,1048576')
     with self.assertRaises(ProtectionFaultError):
         e.execute()
Beispiel #6
0
    def test_op_add(self):
        """
        Tests ADD op code
        [dst]:=[a]+[b]
        """
        e = ElfCPU()
        # Invalid address 123456789 for a
        e.load_string('1,123456789,0,0')
        with self.assertRaises(ProtectionFaultError):
            e.step()

        # Invalid address 123456789 for b
        e.load_string('1,0,123456789,0')
        with self.assertRaises(ProtectionFaultError):
            e.step()

        # Invalid address 123456789 for dst
        e.load_string('1,0,0,123456789')
        with self.assertRaises(ProtectionFaultError):
            e.step()

        # 1 + 1 = 2 @ address 0
        e.load_string('1,0,0,0,99')
        e.step()
        self.assertEqual(e.peek(0), 2)

        # 2**64 + 1 = 1 @ address 0 (overflow and wrap)
        #e.load_string('1,5,6,0,99,'+str(2**64)+',1')
        #e.step()
        #self.assertEqual(e.peek(0), 1)

        # [dst]:=a+[b]
        e.load_string('101,44,5,6,99,2,6')
        e.execute()
        self.assertEqual(e.peek(6), 46)

        # [dst]:=[a]+b
        e.load_string('1001,5,50,6,99,2,6')
        e.execute()
        self.assertEqual(e.peek(6), 52)

        # [dst]:=a+b
        e.load_string('1101,5,5,6,99,2,6')
        e.execute()
        self.assertEqual(e.peek(6), 10)

        # [dst]:=r[a]+b
        e.load_string('109,10,1201,0,5,7,99,7,3,3,5')
        e.execute()
        self.assertEqual(e.peek(7), 10)

        # [dst]:=a+r[b]
        e.load_string('109,10,2101,20,0,7,99,7,3,3,10')
        e.execute()
        self.assertEqual(e.peek(7), 30)

        # [dst]:=a+r[b]
        e.load_string('109,10,2101,20,0,7,99,7,3,3,10')
        e.execute()
        self.assertEqual(e.peek(7), 30)

        # r[dst]:=a+b
        e.load_string('109,10,21101,16,16,0,99,7,3,3,7')
        e.execute()
        self.assertEqual(e.peek(10), 32)
Beispiel #7
0
    def test_op_relative_base(self):
        """
        Tests the relative base mode op code
        """
        e = ElfCPU()

        # Position
        e.load_string('9,5,204,1,99,6,7,777')
        e.interrupts = True
        # Step over relative mode op
        e.step()
        with self.assertRaises(OutputInterrupt):
            e.execute()
        self.assertEqual(e.output_buffer, 777)

        # Immediate
        e.reset()
        e.load_string('109,5,204,1,99,444,777')
        e.interrupts = True
        # Step over relative mode op
        e.step()
        with self.assertRaises(OutputInterrupt):
            e.execute()
        self.assertEqual(e.output_buffer, 777)

        # Relative
        e.reset()
        e.load_string('209,9,209,6,204,-2,99,5,333,4,6')
        e.interrupts = True
        e.debug = True
        with self.assertRaises(OutputInterrupt):
            e.execute()
        self.assertEqual(e.output_buffer, 333)
Beispiel #8
0
    def test_poke(self):
        """
        Tests address range and data for poke
        """
        e = ElfCPU()
        e.load_string('0,1,2,3,4,5,6,7,8,9')

        # TypeError
        with self.assertRaises(TypeError):
            # noinspection PyTypeChecker
            e.poke('x', 2)
        # Above memory range
        with self.assertRaises(ValueError):
            e.poke(2**65, 2)
        # Below memory range
        with self.assertRaises(ValueError):
            e.poke(-1, 2)

        # Value
        with self.assertRaises(ValueError):
            e.poke(0, 2**64+1)

        self.assertEqual(e.poke(0, 99), 99)
        self.assertEqual(e.poke(9, 88), 88)
        self.assertEqual(e.peek(0), 99)
        self.assertEqual(e.peek(9), 88)
Beispiel #9
0
    def test_op_eq(self):
        """
        Tests equals op code
        """

        e = ElfCPU()

        """
        Tests if value of address 5 (10) is equal to value
        of address 6 (10).  Since this is true, write 1 to
        address 10.
        """
        e.load_string('8,8,9,10,99,10,10,-1,10,10,7')
        e.execute()
        self.assertEqual(e.peek(10), 1)

        """
        Tests if value of address 5 (10) is equal to value
        of address 6 (0).  Since this is false, write 0 to
        address 10.
        """
        e.load_string('8,8,9,10,99,10,0,-1,5,6,7')
        e.execute()
        self.assertEqual(e.peek(10), 0)

        """
        Tests if immediate value 10 is equal to immediate value
        10.  Since this is true, write 1 to address 7.
        """
        e.load_string('1108,10,10,7,99,2,3,-1')
        e.execute()
        self.assertEqual(e.peek(7), 1)

        """
        Tests if immediate value of 0 is equal to immediate value
        10.  Since this is false, write 0 to address 7.
        """
        e.load_string('1108,0,10,7,99,2,3,-1')
        e.execute()
        self.assertEqual(e.peek(7), 0)

        """
            if r[a] = r[b]
                r[dst]:=1
            else
                r[dst]:=0
        """
        e.load_string('109,10,22208,0,1,2,99,222,222,222,555,555,1')
        e.execute()
        self.assertEqual(e.peek(12), 1)

        """
            if r[a] < r[b]
                r[dst]:=1
            else
                r[dst]:=0
        """
        e.load_string('109,10,22208,0,1,2,99,222,222,222,-500,100,1')
        e.execute()
        self.assertEqual(e.peek(12), 0)
Beispiel #10
0
    def test_op_cmp_lessthan(self):
        """
        Tests compare less than op code
        """
        e = ElfCPU()

        """
        Tests if value of address 8 (5) is less than value of
        address 9 (10).  Since this is true write 1 to address 10.
        """
        e.load_string('7,8,9,10,99,5,10,-1,5,10,7')
        e.execute()
        self.assertEqual(e.peek(10), 1)

        """
        Tests if value of address 5 (10) is less than value of
        address 6 (5).  Since this is false write 0 to address 10.
        """
        e.load_string('7,8,9,10,99,5,10,-1,10,5,7')
        e.execute()
        self.assertEqual(e.peek(10), 0)

        """
        Tests if immediate value of 5 is less than immediate value of
        10.  Since this is true write 1 to address 7.
        """
        e.load_string('1107,5,10,7,99,0,0,-1')
        e.execute()
        self.assertEqual(e.peek(7), 1)

        """
        Tests if immediate value of 10 is less than immediate value of
        5.  Since this is false write 0 to address 7.
        """
        e.load_string('11107,10,5,7,99,0,0,-1')
        e.execute()
        self.assertEqual(e.peek(7), 0)

        """
            if r[a] < r[b]
                r[dst]:=1
            else
                r[dst]:=0
        """
        e.load_string('109,10,22207,0,1,2,99,222,222,222,100,50,1')
        e.execute()
        self.assertEqual(e.peek(12), 0)

        """
            if r[a] < r[b]
                r[dst]:=1
            else
                r[dst]:=0
        """
        e.load_string('109,10,22207,0,1,2,99,222,222,222,50,100,1')
        e.execute()
        self.assertEqual(e.peek(12), 1)
Beispiel #11
0
    def test_op_jmp_true(self):
        """
        Tests jump if true op code
        """

        e = ElfCPU()

        """
        Tests address 8 (which is 1) if it is non-zero.  Since this is
        true, it jumps to the value of address 9 (which is 7).  This
        terminates the program.
        """
        e.load_string('5,8,9,1101,1,1,8,99,1,7')
        e.execute()
        self.assertEqual(e.peek(8), 1)

        """
        Tests immediate value 8 if it is non-zero.  Since it is
        true, jump to immediate address 7 which terminates.
        """
        e.load_string('1105,8,7,1101,1,1,8,99,1,7')
        e.execute()
        self.assertEqual(e.peek(8), 1)

        """
        Tests address 8 (which is 0) if it is non-zero.  Since this is
        false it does not jump and instead adds 1+1 to address 8.
        """
        e.load_string('5,8,9999,11101,1,1,8,99,0,7')
        e.execute()
        self.assertEqual(e.peek(8), 2)

        """
        Tests immediate value 0 if it is non-zero.  Since it is
        false it does not jump and instead adds 1+1 to address 8. 
        """
        e.load_string('1105,0,9999,11101,1,1,8,99,0,7')
        e.execute()
        self.assertEqual(e.peek(8), 2)
Beispiel #12
0
    def test_op_output(self):
        """
        Tests output op code

        Use io.StringIO() to capture the output
        """
        e = ElfCPU()

        # Interrupts off
        e.load_string('4,5,104,66,99,55,5')
        e.interrupts = False

        result = None
        with patch('sys.stdout', new=io.StringIO()) as output:
            e.execute()
            result = output.getvalue()
        result = result.splitlines()

        # First is a reference to memory address 5
        self.assertEqual(result[0].strip(), '55')
        # Second is an immediate value
        self.assertEqual(result[1].strip(), '66')

        # Interrupts on

        e.load_string('4,5,104,66,99,55,5')
        e.interrupts = True

        with self.assertRaises(OutputInterrupt):
            e.execute()
        self.assertEqual(e.output_buffer, 55)
        # Don't clear buffer
        with self.assertRaises(OutputOverflow):
            e.execute()

        # Restart test
        e.reset()
        e.load_string('4,5,104,66,99,55,5')
        e.interrupts = True

        with self.assertRaises(OutputInterrupt):
            e.execute()
        self.assertEqual(e.output_buffer, 55)

        # Clear buffer
        del e.output_buffer

        with self.assertRaises(OutputInterrupt):
            e.execute()
        self.assertEqual(e.output_buffer, 66)

        ###############################################
        # Interrupts on RELATIVE MODE
        # Restart test
        e.reset()
        e.load_string('109,5,204,1,99,6,1234')
        e.interrupts = True

        with self.assertRaises(OutputInterrupt):
            e.execute()
        self.assertEqual(e.output_buffer, 1234)
Beispiel #13
0
    def test_peek(self):
        """
        Tests address range for peek
        """
        e = ElfCPU()
        e.load_string('0,1,2,3,4,5,6,7,8,9')

        # TypeError
        with self.assertRaises(TypeError):
            # noinspection PyTypeChecker
            e.peek('x')
        # Above memory range
        with self.assertRaises(ValueError):
            e.peek(2**65)
        # Below memory range
        with self.assertRaises(ValueError):
            e.peek(-1)

        self.assertEqual(e.peek(0), 0)
        self.assertEqual(e.peek(9), 9)
Beispiel #14
0
    def test_op_input(self):
        """
        Tests input op code

        Use unittest.mock.patch to fake the input value
        """
        e = ElfCPU()

        # Interrupts off
        e.load_string('103,3,99,-1')
        e.interrupts = False
        with patch('builtins.input', return_value='1234'):
            e.execute()
            self.assertEqual(e.peek(3), 1234)

        # Interrupts on IMMEDIATE MODE
        e.load_string('103,5,103,5,99,-1')
        e.interrupts = True
        with self.assertRaises(InputInterrupt):
            e.step()

        # Should be back at pc = 0
        self.assertEqual(e.pc, 0)

        # Load input
        e.input_buffer = 567

        # Loading again overflows
        with self.assertRaises(InputOverflow):
            e.input_buffer = 123

        # Execute the input instruction
        e.step()
        self.assertEqual(e.peek(5), 567)

        # Exec next input instruction
        with self.assertRaises(InputInterrupt):
            e.step()

        e.input_buffer = 987

        # Execute until end
        e.execute()
        self.assertEqual(e.peek(5), 987)

        ######################################################
        # Interrupts on RELATIVE MODE
        e.load_string('109,10,203,0,203,1,203,-1,99,102,100,101')
        e.interrupts = True

        # step past the relative base op code
        e.step()

        with self.assertRaises(InputInterrupt):
            e.step()

        # Should be back at pc = 2 (after relative base op code)
        self.assertEqual(e.pc, 2)

        # Load input
        e.input_buffer = 567

        # Loading again overflows
        with self.assertRaises(InputOverflow):
            e.input_buffer = 123

        # Execute the input instruction
        e.step()
        self.assertEqual(e.peek(10), 567)

        # Exec next input instruction
        with self.assertRaises(InputInterrupt):
            e.step()

        e.input_buffer = 987

        # Step to execute this input
        e.step()
        self.assertEqual(e.peek(11), 987)

        # Exec next input instruction
        with self.assertRaises(InputInterrupt):
            e.step()

        e.input_buffer = 456

        # Execute until end
        e.execute()
        self.assertEqual(e.peek(9), 456)

        ######################################################
        # Interrupts on POSITIONAL MODE
        e.load_string('3,7,3,8,3,9,99,1,3,5')
        e.interrupts = True

        with self.assertRaises(InputInterrupt):
            e.step()

        # Should be back at pc = 0
        self.assertEqual(e.pc, 0)

        # Load input
        e.input_buffer = 345

        # Loading again overflows
        with self.assertRaises(InputOverflow):
            e.input_buffer = 123

        # Execute the input instruction
        e.step()
        self.assertEqual(e.peek(7), 345)

        # Exec next input instruction
        with self.assertRaises(InputInterrupt):
            e.step()

        e.input_buffer = 765

        # Step to execute this input
        e.step()
        self.assertEqual(e.peek(8), 765)

        # Exec next input instruction
        with self.assertRaises(InputInterrupt):
            e.step()

        e.input_buffer = 555

        # Execute until end
        e.execute()
        self.assertEqual(e.peek(9), 555)
Beispiel #15
0
    def test_op_mul(self):
        """
        Tests MUL op code
        [dst]:=[a]*[b]
        """
        e = ElfCPU()
        # Invalid address 123456789 for a
        e.load_string('2,123456789,0,0')
        with self.assertRaises(ProtectionFaultError):
            e.step()

        # Invalid address 123456789 for b
        e.load_string('2,0,123456789,0')
        with self.assertRaises(ProtectionFaultError):
            e.step()

        # Invalid address 123456789 for dst
        e.load_string('2,0,0,123456789')
        with self.assertRaises(ProtectionFaultError):
            e.step()

        # [dst]:=[a]*[b]
        e.load_string('2,0,0,0,99')
        e.step()
        self.assertEqual(e.peek(0), 4)

        # [dst]:=a*[b]
        e.load_string('102,44,5,6,99,2,6')
        e.execute()
        self.assertEqual(e.peek(6), 88)

        # [dst]:=[a]*b
        e.load_string('1002,5,50,6,99,2,6')
        e.execute()
        self.assertEqual(e.peek(6), 100)

        # [dst]:=a*b
        e.load_string('1102,5,5,6,99,2,6')
        e.execute()
        self.assertEqual(e.peek(6), 25)

        # [dst]:=r[a]*b
        e.load_string('109,10,1202,0,4,7,99,7,3,3,4')
        e.execute()
        self.assertEqual(e.peek(7), 16)

        # [dst]:=a*r[b]
        e.load_string('109,10,2102,7,0,7,99,7,3,3,2')
        e.execute()
        self.assertEqual(e.peek(7), 14)

        # [dst]:=r[a]*r[b]
        e.load_string('109,10,2202,0,1,7,99,7,3,3,2,6')
        e.execute()
        self.assertEqual(e.peek(7), 12)

        # dst:=a*b
        e.load_string('11102,6,6,0,99')
        e.execute()
        self.assertEqual(e.peek(0), 36)

        # r[dst]:=a*b
        e.load_string('109,7,21102,8,3,0,99,1')
        e.execute()
        self.assertEqual(e.peek(7), 24)