Ejemplo n.º 1
0
    def _register_device(self, ioport_number, data):
        try:
            data = json.loads(data)
        except json.decoder.JSONDecodeError:
            return (HTTPStatus.BAD_REQUEST, {
                'error': 'Could not parse data.',
            })
        for field_name in {'type', 'id', 'host', 'port'}:
            if field_name not in data:
                return (HTTPStatus.BAD_REQUEST, {
                    'error': 'Field "{}" missing.'.format(field_name),
                })
        try:
            device_type = int(data['type'], 16)
            if device_type < 0x00 or device_type > 0xFF:
                raise ValueError()
        except ValueError:
            return (HTTPStatus.BAD_REQUEST, {
                'error': 'Device type must be a 1-byte hex number.',
            })
        try:
            device_id = int(data['id'], 16)
            if device_id < 0x00 or device_id > 0xFFFFFF:
                raise ValueError()
            device_id = list(device_id.to_bytes(3, 'big'))
        except ValueError:
            return (HTTPStatus.BAD_REQUEST, {
                'error': 'Device ID must be a 1-byte hex number.',
            })
        device_host, device_port = data['host'], data['port']
        if self.ioports[ioport_number].registered:
            logger.info('A device is already registered to IOPort %s.',
                        ioport_number)
            return (HTTPStatus.FORBIDDEN, {
                'error': 'A device is already registered to this IOPort.',
            })
        if self.ioports[ioport_number].input_queue.qsize() > 0:
            logger.info('IOPort %s input queue not empty.', ioport_number)
            return (HTTPStatus.FORBIDDEN, {
                'error': 'IOPort input queue not empty.',
            })

        logger.info('Registering device to IOPort %s...', ioport_number)
        logger.info(
            'Device type and ID: %s %s',
            utils.byte_to_str(device_type),
            ' '.join(utils.byte_to_str(device_id[i]) for i in range(3)),
        )
        logger.info('Device host and port: %s:%s', device_host, device_port)
        self._device_registry[4 * ioport_number] = device_type
        for idx in range(3):
            self._device_registry[4 * ioport_number + 1 + idx] = device_id[idx]
        self._set_device_status(ioport_number, 0)
        self.ioports[ioport_number].register_device(device_host, device_port)
        self.interrupt_controller.send(
            self.system_interrupts['device_registered'])
        logger.info('Device registered to IOPort %s.', ioport_number)
        return (HTTPStatus.OK, {
            'message': 'Device registered.',
        })
Ejemplo n.º 2
0
 def _check_subtimer(self, subtimer_number, subtimer):
     if subtimer.mode == SubtimerMode.OFF:
         return
     if subtimer.speed > 1:
         if self._step_count % subtimer.speed != subtimer.phase:
             return
     logger.info(
         'Subtimer %s called IRQ %s.',
         utils.byte_to_str(subtimer_number),
         utils.byte_to_str(subtimer.interrupt_number),
     )
     self._interrupt_controller.send(subtimer.interrupt_number)
     if subtimer.mode == SubtimerMode.ONESHOT:
         subtimer.mode = SubtimerMode.OFF
Ejemplo n.º 3
0
 def _check_subtimer(self, subtimer_number, subtimer):
     if subtimer.mode == SubtimerMode.OFF:
         return
     if subtimer.speed > 1:
         if self._step_count % subtimer.speed != subtimer.phase:
             return
     logger.info(
         'Subtimer %s called IRQ %s.',
         utils.byte_to_str(subtimer_number),
         utils.byte_to_str(subtimer.interrupt_number),
     )
     self._interrupt_controller.send(subtimer.interrupt_number)
     if subtimer.mode == SubtimerMode.ONESHOT:
         subtimer.mode = SubtimerMode.OFF
Ejemplo n.º 4
0
def operand_to_str(operand):
    '''
    Get the string representation of an operand
    '''
    if operand.optype == OpType.EXTENDED:
        raise InvalidOperandError('Extended optype not supported yet.')
    if operand.optype == OpType.VALUE:
        if operand.oplen == OpLen.BYTE:
            return utils.byte_to_str(operand.opvalue)
        else:
            return utils.word_to_str(operand.opvalue)
    if operand.optype == OpType.ADDRESS:
        if operand.opvalue < 0:
            return '^-{}'.format(utils.word_to_str(-operand.opvalue))
        return '^{}'.format(utils.word_to_str(operand.opvalue))
    if operand.optype == OpType.REGISTER:
        return operand.opreg

    if operand.oplen == OpLen.BYTE:
        oplen_str = 'B'
    else:
        oplen_str = ''
    if operand.optype == OpType.ABS_REF_REG:
        if operand.opoffset == 0:
            opoffset_str = ''
        elif operand.opoffset > 0:
            opoffset_str = '+{}'.format(utils.byte_to_str(operand.opoffset))
        else:
            opoffset_str = '-{}'.format(utils.byte_to_str(-operand.opoffset))
        return '[{}{}]{}'.format(
            operand.opreg,
            opoffset_str,
            oplen_str,
        )

    if operand.opbase < 0:
        opbase_str = '-{}'.format(utils.word_to_str(-operand.opbase))
    else:
        opbase_str = '{}'.format(utils.word_to_str(operand.opbase))
    if operand.optype == OpType.REL_REF_WORD_BYTE:
        opoffset_str = '+{}'.format(utils.byte_to_str(operand.opoffset))
    elif operand.optype == OpType.REL_REF_WORD_REG:
        opoffset_str = '+{}'.format(operand.opreg)
    else:
        opoffset_str = ''
    return '[{}{}]{}'.format(
        opbase_str,
        opoffset_str,
        oplen_str,
    )
Ejemplo n.º 5
0
def operand_to_str(operand):
    '''
    Get the string representation of an operand
    '''
    if operand.optype == OpType.EXTENDED:
        raise InvalidOperandError('Extended optype not supported yet.')
    if operand.optype == OpType.VALUE:
        if operand.oplen == OpLen.BYTE:
            return utils.byte_to_str(operand.opvalue)
        else:
            return utils.word_to_str(operand.opvalue)
    if operand.optype == OpType.ADDRESS:
        if operand.opvalue < 0:
            return '^-{}'.format(utils.word_to_str(-operand.opvalue))
        return '^{}'.format(utils.word_to_str(operand.opvalue))
    if operand.optype == OpType.REGISTER:
        return operand.opreg

    if operand.oplen == OpLen.BYTE:
        oplen_str = 'B'
    else:
        oplen_str = ''
    if operand.optype == OpType.ABS_REF_REG:
        if operand.opoffset == 0:
            opoffset_str = ''
        elif operand.opoffset > 0:
            opoffset_str = '+{}'.format(utils.byte_to_str(operand.opoffset))
        else:
            opoffset_str = '-{}'.format(utils.byte_to_str(-operand.opoffset))
        return '[{}{}]{}'.format(
            operand.opreg,
            opoffset_str,
            oplen_str,
        )

    if operand.opbase < 0:
        opbase_str = '-{}'.format(utils.word_to_str(-operand.opbase))
    else:
        opbase_str = '{}'.format(utils.word_to_str(operand.opbase))
    if operand.optype == OpType.REL_REF_WORD_BYTE:
        opoffset_str = '+{}'.format(utils.byte_to_str(operand.opoffset))
    elif operand.optype == OpType.REL_REF_WORD_REG:
        opoffset_str = '+{}'.format(operand.opreg)
    else:
        opoffset_str = ''
    return '[{}{}]{}'.format(
        opbase_str,
        opoffset_str,
        oplen_str,
    )
Ejemplo n.º 6
0
Archivo: cpu.py Proyecto: cu2/aldebaran
 def _call_hardware_interrupt(self, interrupt_number):
     logger.debug('Calling hardware interrupt: %s', utils.byte_to_str(interrupt_number))
     self.halt = False
     self.stack.push_flags()
     self.disable_interrupts()
     self.stack.push_word(self.ip)
     self.ip = self.memory.read_word(self.system_addresses['IVT'] + 2 * interrupt_number)
Ejemplo n.º 7
0
 def _mini_debugger(self):
     if logger.level != logging.DEBUG:
         return
     ram_page_size = 16
     stack_page_size = 32
     sp = self.registers.get_register('SP', silent=True)
     bp = self.registers.get_register('BP', silent=True)
     ram_page = (self.ip // ram_page_size) * ram_page_size
     rel_sp = self.system_addresses['bottom_of_stack'] - sp
     stack_page = self.system_addresses['bottom_of_stack'] - (
         stack_page_size -
         1) - (rel_sp // stack_page_size) * stack_page_size
     if stack_page < 0:
         stack_page = 0
     logger.debug(
         'IP=%s         RAM   %s-%s: %s',
         utils.word_to_str(self.ip),
         utils.word_to_str(ram_page),
         utils.word_to_str(ram_page + ram_page_size - 1),
         ''.join([('>' if idx == self.ip else ' ') +
                  utils.byte_to_str(self.memory.read_byte(idx, silent=True))
                  for idx in range(ram_page, ram_page + ram_page_size)]),
     )
     logger.debug(
         'SP=%s BP=%s Stack %s-%s:  %s',
         utils.word_to_str(sp),
         utils.word_to_str(bp),
         utils.word_to_str(stack_page),
         utils.word_to_str(stack_page + stack_page_size - 1),
         ''.join([
             utils.byte_to_str(self.memory.read_byte(idx, silent=True)) +
             (('{' if idx == bp else '<') if idx == sp else
              ('[' if idx == bp else ' '))
             for idx in range(stack_page, stack_page + stack_page_size)
         ]),
     )
     logger.debug(
         'AX/BX/CX/DX=%s/%s/%s/%s SI/DI=%s/%s',
         utils.word_to_str(self.registers.get_register('AX', silent=True)),
         utils.word_to_str(self.registers.get_register('BX', silent=True)),
         utils.word_to_str(self.registers.get_register('CX', silent=True)),
         utils.word_to_str(self.registers.get_register('DX', silent=True)),
         utils.word_to_str(self.registers.get_register('SI', silent=True)),
         utils.word_to_str(self.registers.get_register('DI', silent=True)),
     )
Ejemplo n.º 8
0
Archivo: cpu.py Proyecto: cu2/aldebaran
 def _mini_debugger(self):
     if logger.level != logging.DEBUG:
         return
     ram_page_size = 16
     stack_page_size = 32
     sp = self.registers.get_register('SP', silent=True)
     bp = self.registers.get_register('BP', silent=True)
     ram_page = (self.ip // ram_page_size) * ram_page_size
     rel_sp = self.system_addresses['bottom_of_stack'] - sp
     stack_page = self.system_addresses['bottom_of_stack'] - (stack_page_size - 1) - (rel_sp // stack_page_size) * stack_page_size
     if stack_page < 0:
         stack_page = 0
     logger.debug(
         'IP=%s         RAM   %s-%s: %s',
         utils.word_to_str(self.ip),
         utils.word_to_str(ram_page),
         utils.word_to_str(ram_page + ram_page_size - 1),
         ''.join([
             ('>' if idx == self.ip else ' ') + utils.byte_to_str(self.memory.read_byte(idx, silent=True))
             for idx in range(ram_page, ram_page + ram_page_size)
         ]),
     )
     logger.debug(
         'SP=%s BP=%s Stack %s-%s:  %s',
         utils.word_to_str(sp),
         utils.word_to_str(bp),
         utils.word_to_str(stack_page),
         utils.word_to_str(stack_page + stack_page_size - 1),
         ''.join([utils.byte_to_str(self.memory.read_byte(idx, silent=True)) + (
             (
                 '{' if idx == bp else '<'
             ) if idx == sp else (
                 '[' if idx == bp else ' '
             )
         ) for idx in range(stack_page, stack_page + stack_page_size)]),
     )
     logger.debug(
         'AX/BX/CX/DX=%s/%s/%s/%s SI/DI=%s/%s',
         utils.word_to_str(self.registers.get_register('AX', silent=True)),
         utils.word_to_str(self.registers.get_register('BX', silent=True)),
         utils.word_to_str(self.registers.get_register('CX', silent=True)),
         utils.word_to_str(self.registers.get_register('DX', silent=True)),
         utils.word_to_str(self.registers.get_register('SI', silent=True)),
         utils.word_to_str(self.registers.get_register('DI', silent=True)),
     )
Ejemplo n.º 9
0
Archivo: ram.py Proyecto: cu2/aldebaran
 def write_byte(self, pos, value, silent=False):
     '''
     Write byte to RAM at position `pos`
     '''
     if pos < 0 or pos > self.size - 1:
         raise SegfaultError('Segmentation fault when trying to write byte at {}'.format(utils.word_to_str(pos)))
     self._content[pos] = value
     if not silent:
         logger.debug('Written byte %s to %s.', utils.byte_to_str(value), utils.word_to_str(pos))
Ejemplo n.º 10
0
 def _set_byte_register(self, register_name, value, silent=False):
     if value < 0x00 or value > 0xFF:
         raise InvalidRegisterValueError('Invalid register value: {}'.format(value))
     if register_name in {'AL', 'BL', 'CL', 'DL'}:
         self._registers[register_name[0] + 'X'] = utils.set_low(self._registers[register_name[0] + 'X'], value)
     else:
         self._registers[register_name[0] + 'X'] = utils.set_high(self._registers[register_name[0] + 'X'], value)
     if not silent:
         logger.debug('Set register %s = %s', register_name, utils.byte_to_str(value))
Ejemplo n.º 11
0
 def set_subtimer(self, subtimer_number, raw_mode, speed, phase, interrupt_number):
     '''
     Set subtimer's config
     '''
     try:
         self._subtimers[subtimer_number].set_config(raw_mode, speed, phase, interrupt_number)
     except IndexError:
         raise NoSubtimerError('No subtimer with number: {}'.format(subtimer_number))
     logger.info('Subtimer %s set.', utils.byte_to_str(subtimer_number))
Ejemplo n.º 12
0
 def write_byte(self, pos, value, silent=False):
     '''
     Write byte to Virtual RAM at position `pos`
     '''
     if pos < self.addresses['device_controller']['first'] or pos > self.addresses['device_controller']['last']:
         raise SegfaultError('Segmentation fault when trying to write byte at {}'.format(utils.word_to_str(pos)))
     self.device_controller.write_byte(pos, value, silent=silent)
     if not silent:
         logger.debug('Written byte %s to %s.', utils.byte_to_str(value), utils.word_to_str(pos))
Ejemplo n.º 13
0
 def _call_hardware_interrupt(self, interrupt_number):
     logger.debug('Calling hardware interrupt: %s',
                  utils.byte_to_str(interrupt_number))
     self.halt = False
     self.stack.push_flags()
     self.disable_interrupts()
     self.stack.push_word(self.ip)
     self.ip = self.memory.read_word(self.system_addresses['IVT'] +
                                     2 * interrupt_number)
Ejemplo n.º 14
0
 def read_byte(self, pos, silent=False):
     '''
     Read byte from Virtual RAM at position `pos`
     '''
     if pos < self.addresses['device_controller']['first'] or pos > self.addresses['device_controller']['last']:
         raise SegfaultError('Segmentation fault when trying to read byte at {}'.format(utils.word_to_str(pos)))
     value = self.device_controller.read_byte(pos, silent=silent)
     if not silent:
         logger.debug('Read byte %s from %s.', utils.byte_to_str(value), utils.word_to_str(pos))
     return value
Ejemplo n.º 15
0
 def do(self):
     subtimer_number = self.get_operand(0)
     self.cpu.timer.set_subtimer(
         subtimer_number,
         raw_mode=self.get_operand(1),
         speed=self.get_operand(2),
         phase=self.get_operand(3),
         interrupt_number=self.get_operand(4),
     )
     self.cpu.cpu_log('Subtimer %s set.', utils.byte_to_str(subtimer_number))
Ejemplo n.º 16
0
Archivo: ram.py Proyecto: cu2/aldebaran
 def read_byte(self, pos, silent=False):
     '''
     Read byte from RAM at position `pos`
     '''
     if pos < 0 or pos > self.size - 1:
         raise SegfaultError('Segmentation fault when trying to read byte at {}'.format(utils.word_to_str(pos)))
     value = self._content[pos]
     if not silent:
         logger.debug('Read byte %s from %s.', utils.byte_to_str(value), utils.word_to_str(pos))
     return value
Ejemplo n.º 17
0
 def check(self):
     '''
     Get interrupt, if there's any
     '''
     try:
         interrupt_number = self._interrupt_queue.get_nowait()
     except queue.Empty:
         return None
     logger.info('Forwarded IRQ to CPU: %s', utils.byte_to_str(interrupt_number))
     logger.debug('Interrupt queue length: %d', self._interrupt_queue.qsize())
     return interrupt_number
Ejemplo n.º 18
0
 def push_byte(self, value):
     '''
     Push byte on stack
     '''
     sp = self._registers.get_register('SP', silent=True)
     if sp < 1:
         raise StackOverflowError('Stack overflow: {}'.format(
             utils.word_to_str(sp)))
     self._ram.write_byte(sp, value, silent=True)
     logger.debug('Pushed byte %s', utils.byte_to_str(value))
     self._registers.set_register('SP', sp - 1, silent=True)
Ejemplo n.º 19
0
Archivo: cpu.py Proyecto: cu2/aldebaran
 def _parse_instruction(self, inst_opcode, operand_buffer):
     try:
         inst_class = self.instruction_opcode_mapping[inst_opcode]
     except KeyError:
         raise UnknownOpcodeError('Unknown opcode: {}'.format(utils.byte_to_str(inst_opcode)))
     instruction = inst_class(self, operand_buffer)
     logger.info('Instruction: %s %s', inst_class.__name__, ' '.join([
         operands.operand_to_str(op)
         for op in instruction.operands
     ]))
     return instruction
Ejemplo n.º 20
0
 def get_register(self, register_name, silent=False):
     '''
     Get register value
     '''
     value = None
     hex_value = None
     if register_name in self._registers:
         value = self._registers[register_name]
         hex_value = utils.word_to_str(value)
     elif register_name in {'AL', 'BL', 'CL', 'DL'}:
         value = utils.get_low(self._registers[register_name[0] + 'X'])
         hex_value = utils.byte_to_str(value)
     elif register_name in {'AH', 'BH', 'CH', 'DH'}:
         value = utils.get_high(self._registers[register_name[0] + 'X'])
         hex_value = utils.byte_to_str(value)
     else:
         raise InvalidRegisterNameError('Invalid register name: {}'.format(register_name))
     if not silent:
         logger.debug('Get register %s = %s', register_name, hex_value)
     return value
Ejemplo n.º 21
0
 def get_register(self, register_name, silent=False):
     '''
     Get register value
     '''
     value = None
     hex_value = None
     if register_name in self._registers:
         value = self._registers[register_name]
         hex_value = utils.word_to_str(value)
     elif register_name in {'AL', 'BL', 'CL', 'DL'}:
         value = utils.get_low(self._registers[register_name[0] + 'X'])
         hex_value = utils.byte_to_str(value)
     elif register_name in {'AH', 'BH', 'CH', 'DH'}:
         value = utils.get_high(self._registers[register_name[0] + 'X'])
         hex_value = utils.byte_to_str(value)
     else:
         raise InvalidRegisterNameError(
             'Invalid register name: {}'.format(register_name))
     if not silent:
         logger.debug('Get register %s = %s', register_name, hex_value)
     return value
Ejemplo n.º 22
0
 def pop_byte(self):
     '''
     Pop byte from stack
     '''
     sp = self._registers.get_register('SP', silent=True)
     if sp >= self._bottom_of_stack:
         raise StackUnderflowError('Stack underflow: {}'.format(
             utils.word_to_str(sp)))
     self._registers.set_register('SP', sp + 1, silent=True)
     value = self._ram.read_byte(sp + 1, silent=True)
     logger.debug('Popped byte %s', utils.byte_to_str(value))
     return value
Ejemplo n.º 23
0
 def set_subtimer(self, subtimer_number, raw_mode, speed, phase,
                  interrupt_number):
     '''
     Set subtimer's config
     '''
     try:
         self._subtimers[subtimer_number].set_config(
             raw_mode, speed, phase, interrupt_number)
     except IndexError:
         raise NoSubtimerError(
             'No subtimer with number: {}'.format(subtimer_number))
     logger.info('Subtimer %s set.', utils.byte_to_str(subtimer_number))
Ejemplo n.º 24
0
 def write_byte(self, pos, value, silent=False):
     '''
     Write byte to RAM at position `pos`
     '''
     if pos < 0 or pos > self.size - 1:
         raise SegfaultError(
             'Segmentation fault when trying to write byte at {}'.format(
                 utils.word_to_str(pos)))
     self._content[pos] = value
     if not silent:
         logger.debug('Written byte %s to %s.', utils.byte_to_str(value),
                      utils.word_to_str(pos))
Ejemplo n.º 25
0
 def send(self, interrupt_number):
     '''
     Send interrupt
     '''
     try:
         interrupt_number = int(interrupt_number)
     except ValueError:
         raise InvalidInterruptError('Invalid interrupt: {}'.format(interrupt_number))
     if interrupt_number < 0 or interrupt_number > 255:
         raise InvalidInterruptError('Invalid interrupt: {}'.format(interrupt_number))
     self._interrupt_queue.put(interrupt_number)
     logger.info('Received IRQ: %s', utils.byte_to_str(interrupt_number))
     logger.debug('Interrupt queue length: %d', self._interrupt_queue.qsize())
Ejemplo n.º 26
0
 def check(self):
     '''
     Get interrupt, if there's any
     '''
     try:
         interrupt_number = self._interrupt_queue.get_nowait()
     except queue.Empty:
         return None
     logger.info('Forwarded IRQ to CPU: %s',
                 utils.byte_to_str(interrupt_number))
     logger.debug('Interrupt queue length: %d',
                  self._interrupt_queue.qsize())
     return interrupt_number
Ejemplo n.º 27
0
 def _set_byte_register(self, register_name, value, silent=False):
     if value < 0x00 or value > 0xFF:
         raise InvalidRegisterValueError(
             'Invalid register value: {}'.format(value))
     if register_name in {'AL', 'BL', 'CL', 'DL'}:
         self._registers[register_name[0] + 'X'] = utils.set_low(
             self._registers[register_name[0] + 'X'], value)
     else:
         self._registers[register_name[0] + 'X'] = utils.set_high(
             self._registers[register_name[0] + 'X'], value)
     if not silent:
         logger.debug('Set register %s = %s', register_name,
                      utils.byte_to_str(value))
Ejemplo n.º 28
0
 def read_byte(self, pos, silent=False):
     '''
     Read byte from RAM at position `pos`
     '''
     if pos < 0 or pos > self.size - 1:
         raise SegfaultError(
             'Segmentation fault when trying to read byte at {}'.format(
                 utils.word_to_str(pos)))
     value = self._content[pos]
     if not silent:
         logger.debug('Read byte %s from %s.', utils.byte_to_str(value),
                      utils.word_to_str(pos))
     return value
Ejemplo n.º 29
0
 def write_byte(self, pos, value, silent=False):
     '''
     Write byte to Virtual RAM at position `pos`
     '''
     if pos < self.addresses['device_controller'][
             'first'] or pos > self.addresses['device_controller']['last']:
         raise SegfaultError(
             'Segmentation fault when trying to write byte at {}'.format(
                 utils.word_to_str(pos)))
     self.device_controller.write_byte(pos, value, silent=silent)
     if not silent:
         logger.debug('Written byte %s to %s.', utils.byte_to_str(value),
                      utils.word_to_str(pos))
Ejemplo n.º 30
0
 def read_byte(self, pos, silent=False):
     '''
     Read byte from device registry or device status table
     '''
     if self.system_addresses['device_registry_address'] <= pos < self.system_addresses['device_registry_address'] + self.system_addresses['device_registry_size']:
         value = self._device_registry[pos - self.system_addresses['device_registry_address']]
     elif self.system_addresses['device_status_table_address'] <= pos < self.system_addresses['device_status_table_address'] + self.system_addresses['device_status_table_size']:
         value = self._device_status_table[pos - self.system_addresses['device_status_table_address']]
     else:
         raise SegfaultError('Segmentation fault when trying to read byte at {}'.format(utils.word_to_str(pos)))
     if not silent:
         logger.debug('Read byte %s from %s.', utils.byte_to_str(value), utils.word_to_str(pos))
     return value
Ejemplo n.º 31
0
 def parse_instruction(self, inst_opcode, operand_buffer):
     '''
     Parse opcode and operand buffer into instruction and operands
     '''
     try:
         inst_class = self.instruction_opcode_mapping[inst_opcode]
     except KeyError:
         raise UnknownOpcodeError('Unknown opcode: {}'.format(
             utils.byte_to_str(inst_opcode)))
     instruction = inst_class(self, operand_buffer)
     logger.info(
         'Instruction: %s %s', inst_class.__name__, ' '.join(
             [operands.operand_to_str(op) for op in instruction.operands]))
     return instruction
Ejemplo n.º 32
0
 def read_byte(self, pos, silent=False):
     '''
     Read byte from Virtual RAM at position `pos`
     '''
     if pos < self.addresses['device_controller'][
             'first'] or pos > self.addresses['device_controller']['last']:
         raise SegfaultError(
             'Segmentation fault when trying to read byte at {}'.format(
                 utils.word_to_str(pos)))
     value = self.device_controller.read_byte(pos, silent=silent)
     if not silent:
         logger.debug('Read byte %s from %s.', utils.byte_to_str(value),
                      utils.word_to_str(pos))
     return value
Ejemplo n.º 33
0
 def _get_stack(self):
     bottom_of_stack = self.cpu.system_addresses['bottom_of_stack']
     first_address = max(
         self.cpu.registers.get_register('SP', silent=True) - 7, 0)
     length = bottom_of_stack - first_address + 1
     return {
         'first_address':
         utils.word_to_str(first_address),
         'last_address':
         utils.word_to_str(bottom_of_stack),
         'content': [
             utils.byte_to_str(self.memory.read_byte(first_address + idx))
             for idx in range(length)
         ],
     }
Ejemplo n.º 34
0
 def send(self, interrupt_number):
     '''
     Send interrupt
     '''
     try:
         interrupt_number = int(interrupt_number)
     except ValueError:
         raise InvalidInterruptError(
             'Invalid interrupt: {}'.format(interrupt_number))
     if interrupt_number < 0 or interrupt_number > 255:
         raise InvalidInterruptError(
             'Invalid interrupt: {}'.format(interrupt_number))
     self._interrupt_queue.put(interrupt_number)
     logger.info('Received IRQ: %s', utils.byte_to_str(interrupt_number))
     logger.debug('Interrupt queue length: %d',
                  self._interrupt_queue.qsize())
Ejemplo n.º 35
0
 def _log_code(self):
     logger.debug('===CODE===')
     max_line_opcode_length = max(
         len(line_opcode) for line_number, opcode_pos, line_opcode,
         source_line, tokens in self.augmented_opcode)
     if max_line_opcode_length > MAX_LINE_OPCODE_LENGTH:
         max_line_opcode_length = MAX_LINE_OPCODE_LENGTH
     for line_number, opcode_pos, line_opcode, source_line, tokens in self.augmented_opcode:
         line_label_names = [
             token.value for token in tokens
             if token.type == TokenType.LABEL
         ]
         if not line_label_names and not line_opcode:
             continue
         logger.debug(' '.join([
             '{:4}'.format(line_number),
             utils.word_to_str(opcode_pos),
             ' '.join([utils.byte_to_str(op) for op in line_opcode]),
             ' ' if line_opcode else '',
             '   ' * (max_line_opcode_length - len(line_opcode)),
             source_line,
         ]))
Ejemplo n.º 36
0
 def _log_code(self):
     logger.debug('===CODE===')
     max_line_opcode_length = max(
         len(line_opcode)
         for line_number, opcode_pos, line_opcode, source_line, tokens in self.augmented_opcode
     )
     if max_line_opcode_length > MAX_LINE_OPCODE_LENGTH:
         max_line_opcode_length = MAX_LINE_OPCODE_LENGTH
     for line_number, opcode_pos, line_opcode, source_line, tokens in self.augmented_opcode:
         line_label_names = [token.value for token in tokens if token.type == TokenType.LABEL]
         if not line_label_names and not line_opcode:
             continue
         logger.debug(
             ' '.join([
                 '{:4}'.format(line_number),
                 utils.word_to_str(opcode_pos),
                 ' '.join([utils.byte_to_str(op) for op in line_opcode]),
                 ' ' if line_opcode else '',
                 '   ' * (max_line_opcode_length - len(line_opcode)),
                 source_line,
             ])
         )
Ejemplo n.º 37
0
 def _get_instruction(self, ip):
     inst_opcode, operand_buffer = self.cpu.read_instruction(ip)
     try:
         instruction = self.cpu.parse_instruction(inst_opcode,
                                                  operand_buffer)
     except AldebaranError:
         return None
     last_idx = 0
     operands = []
     for op, idx in zip(instruction.operands,
                        instruction.operand_buffer_indices):
         operands.append({
             'name':
             operand_to_str(op),
             'opcode':
             utils.binary_to_str(operand_buffer[last_idx:idx]),
         })
         last_idx = idx
     return {
         'name': instruction.__class__.__name__,
         'opcode': utils.byte_to_str(inst_opcode),
         'operands': operands,
     }
Ejemplo n.º 38
0
    def _get_memory(self, offset, length):
        if offset >= config.memory_size or offset < 0:
            return (HTTPStatus.BAD_REQUEST, {
                'error':
                'Cannot access memory beyond 0000-{}'.format(
                    utils.word_to_str(config.memory_size - 1)),
            })
        if offset + length > config.memory_size:
            length = config.memory_size - offset

        first_address = offset
        content = []
        for idx in range(length):
            try:
                content.append(
                    utils.byte_to_str(
                        self.memory.read_byte(first_address + idx)))
            except SegfaultError:
                content.append(None)
        return (HTTPStatus.OK, {
            'first_address': utils.word_to_str(first_address),
            'last_address': utils.word_to_str(first_address + length - 1),
            'content': content,
        })
Ejemplo n.º 39
0
 def read_byte(self, pos, silent=False):
     '''
     Read byte from device registry or device status table
     '''
     if self.system_addresses[
             'device_registry_address'] <= pos < self.system_addresses[
                 'device_registry_address'] + self.system_addresses[
                     'device_registry_size']:
         value = self._device_registry[
             pos - self.system_addresses['device_registry_address']]
     elif self.system_addresses[
             'device_status_table_address'] <= pos < self.system_addresses[
                 'device_status_table_address'] + self.system_addresses[
                     'device_status_table_size']:
         value = self._device_status_table[
             pos - self.system_addresses['device_status_table_address']]
     else:
         raise SegfaultError(
             'Segmentation fault when trying to read byte at {}'.format(
                 utils.word_to_str(pos)))
     if not silent:
         logger.debug('Read byte %s from %s.', utils.byte_to_str(value),
                      utils.word_to_str(pos))
     return value
Ejemplo n.º 40
0
 def crash_dump(self):
     '''
     Print crash dump
     '''
     logger_crash_dump.error('### CRASH DUMP ###')
     # ip
     ip = self.cpu.ip
     logger_crash_dump.error('')
     logger_crash_dump.error('IP=%s', utils.word_to_str(ip))
     logger_crash_dump.error(
         'Entry point=%s',
         utils.word_to_str(self.cpu.system_addresses['entry_point']))
     logger_crash_dump.error('Halt=%s', self.cpu.halt)
     # ram
     ram_page_size = 16
     ram_page = (ip // ram_page_size) * ram_page_size
     logger_crash_dump.error('')
     logger_crash_dump.error('RAM:')
     for page_offset in range(-2, 3):
         offset = page_offset * ram_page_size
         if offset + ram_page < 0:
             continue
         if offset + ram_page + ram_page_size - 1 > self.ram.size:
             continue
         logger_crash_dump.error(
             '%s: %s',
             utils.word_to_str(offset + ram_page),
             ''.join([
                 ('>' if idx == ip else ' ') +
                 utils.byte_to_str(self.ram.read_byte(idx, silent=True))
                 for idx in range(offset + ram_page, offset + ram_page +
                                  ram_page_size)
             ]),
         )
     # stack
     sp = self.cpu.registers.get_register('SP', silent=True)
     bp = self.cpu.registers.get_register('BP', silent=True)
     logger_crash_dump.error('')
     logger_crash_dump.error('SP=%s', utils.word_to_str(sp))
     logger_crash_dump.error('BP=%s', utils.word_to_str(bp))
     logger_crash_dump.error(
         'Bottom of stack=%s',
         utils.word_to_str(self.cpu.system_addresses['bottom_of_stack']))
     logger_crash_dump.error('')
     logger_crash_dump.error('Stack:')
     stack_page_size = 16
     stack_page = (sp // stack_page_size) * stack_page_size
     if stack_page < 0:
         stack_page = 0
     for page_offset in range(-1, 4):
         offset = page_offset * stack_page_size
         if offset + stack_page < 0:
             continue
         if offset + stack_page + stack_page_size - 1 > self.ram.size:
             continue
         logger_crash_dump.error(
             '%s:  %s',
             utils.word_to_str(offset + stack_page),
             ''.join([
                 utils.byte_to_str(self.ram.read_byte(idx, silent=True)) +
                 (('{' if idx == bp else '<') if idx == sp else
                  ('[' if idx == bp else ' '))
                 for idx in range(offset + stack_page, offset + stack_page +
                                  stack_page_size)
             ]),
         )
     # registers
     logger_crash_dump.error('')
     logger_crash_dump.error('Registers:')
     for reg in ['AX', 'BX', 'CX', 'DX', 'SI', 'DI']:
         logger_crash_dump.error(
             '%s=%s', reg,
             utils.word_to_str(
                 self.cpu.registers.get_register(reg, silent=True)))
Ejemplo n.º 41
0
    def _register_device(self, ioport_number, data):
        try:
            data = json.loads(data)
        except json.decoder.JSONDecodeError:
            return (
                HTTPStatus.BAD_REQUEST,
                {
                    'error': 'Could not parse data.',
                }
            )
        for field_name in {'type', 'id', 'host', 'port'}:
            if field_name not in data:
                return (
                    HTTPStatus.BAD_REQUEST,
                    {
                        'error': 'Field "{}" missing.'.format(field_name),
                    }
                )
        try:
            device_type = int(data['type'], 16)
            if device_type < 0x00 or device_type > 0xFF:
                raise ValueError()
        except ValueError:
            return (
                HTTPStatus.BAD_REQUEST,
                {
                    'error': 'Device type must be a 1-byte hex number.',
                }
            )
        try:
            device_id = int(data['id'], 16)
            if device_id < 0x00 or device_id > 0xFFFFFF:
                raise ValueError()
            device_id = list(device_id.to_bytes(3, 'big'))
        except ValueError:
            return (
                HTTPStatus.BAD_REQUEST,
                {
                    'error': 'Device ID must be a 1-byte hex number.',
                }
            )
        device_host, device_port = data['host'], data['port']
        if self.ioports[ioport_number].registered:
            logger.info('A device is already registered to IOPort %s.', ioport_number)
            return (
                HTTPStatus.FORBIDDEN,
                {
                    'error': 'A device is already registered to this IOPort.',
                }
            )
        if self.ioports[ioport_number].input_queue.qsize() > 0:
            logger.info('IOPort %s input queue not empty.', ioport_number)
            return (
                HTTPStatus.FORBIDDEN,
                {
                    'error': 'IOPort input queue not empty.',
                }
            )

        logger.info('Registering device to IOPort %s...', ioport_number)
        logger.info(
            'Device type and ID: %s %s',
            utils.byte_to_str(device_type),
            ' '.join(utils.byte_to_str(device_id[i]) for i in range(3)),
        )
        logger.info('Device host and port: %s:%s', device_host, device_port)
        self._device_registry[4 * ioport_number] = device_type
        for idx in range(3):
            self._device_registry[4 * ioport_number + 1 + idx] = device_id[idx]
        self._device_status_table[ioport_number] = 0
        self.ioports[ioport_number].register_device(device_host, device_port)
        self.interrupt_controller.send(self.system_interrupts['device_registered'])
        logger.info('Device registered to IOPort %s.', ioport_number)
        return (
            HTTPStatus.OK,
            {
                'message': 'Device registered.',
            }
        )
Ejemplo n.º 42
0
 def crash_dump(self):
     '''
     Print crash dump
     '''
     logger_crash_dump.error('### CRASH DUMP ###')
     # ip
     ip = self.cpu.ip
     logger_crash_dump.error('')
     logger_crash_dump.error('IP=%s', utils.word_to_str(ip))
     logger_crash_dump.error('Entry point=%s', utils.word_to_str(self.cpu.system_addresses['entry_point']))
     logger_crash_dump.error('Halt=%s', self.cpu.halt)
     # ram
     ram_page_size = 16
     ram_page = (ip // ram_page_size) * ram_page_size
     logger_crash_dump.error('')
     logger_crash_dump.error('RAM:')
     for page_offset in range(-2, 3):
         offset = page_offset * ram_page_size
         if offset + ram_page < 0:
             continue
         if offset + ram_page + ram_page_size - 1 > self.ram.size:
             continue
         logger_crash_dump.error(
             '%s: %s',
             utils.word_to_str(offset + ram_page),
             ''.join([
                 ('>' if idx == ip else ' ') + utils.byte_to_str(self.ram.read_byte(idx, silent=True))
                 for idx in range(offset + ram_page, offset + ram_page + ram_page_size)
             ]),
         )
     # stack
     sp = self.cpu.registers.get_register('SP', silent=True)
     bp = self.cpu.registers.get_register('BP', silent=True)
     logger_crash_dump.error('')
     logger_crash_dump.error('SP=%s', utils.word_to_str(sp))
     logger_crash_dump.error('BP=%s', utils.word_to_str(bp))
     logger_crash_dump.error('Bottom of stack=%s', utils.word_to_str(self.cpu.system_addresses['bottom_of_stack']))
     logger_crash_dump.error('')
     logger_crash_dump.error('Stack:')
     stack_page_size = 16
     stack_page = (sp // stack_page_size) * stack_page_size
     if stack_page < 0:
         stack_page = 0
     for page_offset in range(-1, 4):
         offset = page_offset * stack_page_size
         if offset + stack_page < 0:
             continue
         if offset + stack_page + stack_page_size - 1 > self.ram.size:
             continue
         logger_crash_dump.error(
             '%s:  %s',
             utils.word_to_str(offset + stack_page),
             ''.join([utils.byte_to_str(self.ram.read_byte(idx, silent=True)) + (
                 (
                     '{' if idx == bp else '<'
                 ) if idx == sp else (
                     '[' if idx == bp else ' '
                 )
             ) for idx in range(offset + stack_page, offset + stack_page + stack_page_size)]),
         )
     # registers
     logger_crash_dump.error('')
     logger_crash_dump.error('Registers:')
     for reg in ['AX', 'BX', 'CX', 'DX', 'SI', 'DI']:
         logger_crash_dump.error('%s=%s', reg, utils.word_to_str(self.cpu.registers.get_register(reg, silent=True)))