Beispiel #1
0
class TestProbe(unittest.TestCase):
    def setUp(self):
        self._probe = Probe()

    def test_stop_method(self):
        self._probe.stop()
        self.assertEqual(self._probe.run(), 'stop method')

    def test_install_method(self):
        self._probe.install()
        self.assertEqual(self._probe.run(), 'install method')

    def test_read_method(self):
        self._probe.read()
        self.assertEqual(self._probe.run(), 'read method')

    def test_uninstall_method(self):
        self._probe.uninstall()
        self.assertEqual(self._probe.run(), 'uninstall method')
Beispiel #2
0
class CPU:

    def __init__ (self, ram_size, reg_count, code, consolog):
        self._ram = Memory(ram_size)
        self._reg = Memory(reg_count)
        self.__ra = reg_count - 1
        self.__sp = reg_count - 2
        self._code = code
        self._probe = Probe(consolog)

    def value (self, val):
        if val[0] == 'imm':
            return val[1]
        if val[0] == 'reg':
            return self._reg[val[1]]
        if val[0] == 'mem':
            return self._ram[val[1]]
        if val[0] == 'ref':
            v = self.value(val[1])
            if len(val) == 3:
                v += self.value(val[2])
            return self._ram[v]

    def write (self, addr, val):
        if addr[0] == 'imm':
            raise WriteError
        if addr[0] == 'reg':
            self._reg[addr[1]] = val
        if addr[0] == 'mem':
            self._ram[addr[1]] = val
        if addr[0] == 'ref':
            a = self.value(addr[1])
            if len(addr) == 3:
                a += self.value(addr[2])
            self._ram[a] = val

    def cycle (self, ip):
        instr = self._code[ip][0]
        opcode = instr[0]

        # opcodes with no arguments
        if opcode == 'nop':
            pass
        elif opcode == 'ret':
            return self.value(('reg', self.__ra))
        else:
            # opcode with 1 argument
            dst = instr[1]
            if opcode == 'cal':
                self.write(('reg', self.__ra), ip + 1)
                return self.value(dst)
            if opcode == 'jmp':
                return self.value(dst)
            if opcode == 'dbg':
                self._probe.dbg(dst)
            elif opcode == 'prn':
                print(self.value(dst), end='')
            elif opcode == 'prx':
                print(format(self.value(dst), '02x'), end='')
            elif opcode == 'prX':
                print(format(self.value(dst), '04x'), end='')
            elif opcode == 'prc':
                print(chr(self.value(dst)), end='')
            else:
                # opcodes with 2 arguments
                val1 = instr[2]
                if opcode == 'prs':
                    ptr = self.value(dst)
                    for i in range(0, self.value(val1)):
                        print(chr(self._ram[ptr+i]), end='')
                    print('')
                elif opcode == 'mov':
                    self.write(dst, self.value(val1))
                elif opcode == 'not':
                    self.write(dst, 0xffff ^ self.value(val1))
                else:
                    # opcodes with 3 arguments
                    val2 = instr[3]
                    if opcode == 'beq':
                        if self.value(val1) == self.value(val2):
                            return self.value(dst)
                    elif opcode == 'bne':
                        if self.value(val1) != self.value(val2):
                            return self.value(dst)
                    elif opcode == 'and':
                        self.write(dst, self.value(val1) & self.value(val2))
                    elif opcode == 'orr':
                        self.write(dst, self.value(val1) | self.value(val2))
                    elif opcode == 'xor':
                        self.write(dst, self.value(val1) ^ self.value(val2))
                    elif opcode == 'lsl':
                        self.write(dst, self.value(val1) << self.value(val2))
                    elif opcode == 'lsr':
                        self.write(dst, self.value(val1) >> self.value(val2))
                    elif opcode == 'min':
                        self.write(dst, min(self.value(val1), self.value(val2)))
                    elif opcode == 'max':
                        self.write(dst, max(self.value(val1), self.value(val2)))
                    elif opcode == 'add':
                        self.write(dst, self.value(val1) + self.value(val2))
                    elif opcode == 'sub':
                        self.write(dst, self.value(val1) - self.value(val2))
                    elif opcode == 'mul':
                        self.write(dst, self.value(val1) * self.value(val2))
                    elif opcode == 'div':
                        self.write(dst, self.value(val1) // self.value(val2))
                    elif opcode == 'mod':
                        self.write(dst, self.value(val1) % self.value(val2))
                    elif opcode == 'cmp':
                        v1 = self.value(val1)
                        v2 = self.value(val2)
                        if v1 < v2:
                            self.write(dst, 1)
                        elif v1 > v2:
                            self.write(dst, -1)
                        else:
                            self.write(dst, 0)

        return None

    def run (self):
        try:
            max_ip = len(self._code)
            self._reg[self.__sp] = self._ram._size # init stack pointer
            self._reg[self.__ra] = max_ip # init return address
            self._ip = 0 # init instruction pointer
            while self._ip >= 0 and self._ip < max_ip:
                ip = self.cycle(self._ip)
                if ip is not None:
                    self._ip = ip
                else:
                    self._ip += 1
                self._probe.read(self._ram.get_activity())
                self._probe.read(self._reg.get_activity())
                self._probe.output_activity()
                sys.stdout.flush()

        except AddrError as e:
            print('Invalid address ' + str(e.addr) + self.dbg(self._ip))
        except ValError as e:
            print('Invalid value ' + str(e.val) + self.dbg(self._ip))
        except WriteError:
            print('Invalid write ' + self.dbg(self._ip))

    def dbg (self, ip):
        return (' on line ' + str(self._code[ip][1][1]) +
                ' of file ' + self._code[ip][1][0])