Example #1
0
    def test_example(self):
        example_data = '\n'.join(['b inc 5 if a > 1',
                                  'a inc 1 if b < 5',
                                  'c dec -10 if a >= 1',
                                  'c inc -20 if c == 10',
                                  ''])
        try:
            with tempfile.NamedTemporaryFile(mode='w', delete=False) as f:
                f.write(example_data)

            registers = Registers()
            registers.parse_file(f.name)
        finally:
            os.remove(f.name)

        self.assertEqual(registers.registers, {'a': 1, 'c': -10})
        self.assertEqual(registers.get_largest_value(), 1)
        self.assertEqual(registers.get_largest_value_ever_held(), 10)
Example #2
0
class Parser:
    '''
    This class stepwise calls all the functions necessary to parse modules
    and retrieve the information necessary to extend gnu binutils and gem5.
    '''
    def __init__(self, tcpath, modelpath):
        self._compiler = Compiler(None, None, tcpath)
        self._gem5 = Gem5([], None)
        self._exts = None
        self._models = []
        self._regs = Registers()
        self._modelpath = modelpath
        self._tcpath = tcpath

    def restore(self):
        '''
        Restore the toolchain to its defaults.
        '''

        logger.info('Remove custom instructions from GNU binutils files')
        self._compiler.restore()
        self._gem5.restore()

    def parse_models(self):
        '''
        Parse the c++ reference implementation
        of the custom instruction.
        '''

        logger.info('Determine if modelpath is a folder or a single file')
        if os.path.isdir(self._modelpath):
            # restore the toolchain to its defaults
            self.restore()
            logger.info('Traverse over directory')
            self.treewalk(self._modelpath)
        else:
            logger.info('Single file, start parsing')
            model = Model(self._modelpath)
            self._models.append(model)

        # add model for read function
        self._models.append(Model(read=True))
        # add model for write function
        self._models.append(Model(write=True))

        self._exts = Extensions(self._models)
        self._compiler = Compiler(self._exts, self._regs, self._tcpath)
        self._gem5 = Gem5(self._exts, self._regs)

    def treewalk(self, top):
        logger.info('Search for models in {}'.format(top))
        logger.debug('Directory content: {}'.format(os.listdir(top)))
        for file in os.listdir(top):
            pathname = os.path.join(top, file)
            mode = os.stat(pathname)[ST_MODE]

            if S_ISDIR(mode):
                # directory
                self.treewalk(pathname)
            elif S_ISREG(mode):
                # file
                if pathname.endswith('.cc'):
                    logger.info('Model definition in file {}'.format(pathname))
                    model = Model(pathname)

                    self._models.append(model)
                # registers
                if pathname.endswith('registers.hh'):
                    logger.info('Custom registers in file {}'.format(pathname))
                    self._regs.parse_file(pathname)
            else:
                # unknown file type
                logger.info('Unknown file type, skip')

    def extend_compiler(self):
        '''
        Extend the riscv compiler.
        '''
        self._compiler.extend_compiler()

    def extend_gem5(self):
        '''
        Extend the gem5 simulator.
        '''
        self._gem5.extend_gem5()

    @property
    def args(self):
        return self._args

    @property
    def compiler(self):
        return self._compiler

    @property
    def decoder(self):
        return self._gem5

    @property
    def extensions(self):
        return self._exts

    @property
    def models(self):
        return self._models

    @property
    def regs(self):
        return self._regs
Example #3
0
class RegisterTest(unittest.TestCase):
    def setUp(self):
        self.registers = Registers()

    def test_init_creates_registers(self):
        self.assertNotIn('registers', Registers.__dict__)
        registers = Registers()
        self.assertIsInstance(registers.registers, dict)

    def test_parse_instruction(self):
        code, comparison = self.registers.parse_instruction('b inc 5 if a > 1')
        self.assertEqual(code, ('b', 'inc', 5))
        self.assertEqual(comparison, ('a', '>', 1))

    def test_is_true(self):
        self.registers.registers = {'a': 10}

        self.assertTrue(self.registers.is_true(('a', '>', 1)))
        self.assertFalse(self.registers.is_true(('a', '>', 10)))

        self.assertTrue(self.registers.is_true(('foo', '>', -1)))
        self.assertFalse(self.registers.is_true(('bar', '>', 0)))

        self.assertTrue(self.registers.is_true(('a', '<', 11)))
        self.assertFalse(self.registers.is_true(('a', '<', 9)))

        self.assertTrue(self.registers.is_true(('a', '==', 10)))
        self.assertFalse(self.registers.is_true(('a', '==', 1)))

        self.assertTrue(self.registers.is_true(('a', '!=', 1)))
        self.assertFalse(self.registers.is_true(('a', '!=', 10)))

        self.assertTrue(self.registers.is_true(('a', '>=', 9)))
        self.assertTrue(self.registers.is_true(('a', '>=', 10)))
        self.assertFalse(self.registers.is_true(('a', '>=', 11)))

        self.assertTrue(self.registers.is_true(('a', '<=', 11)))
        self.assertTrue(self.registers.is_true(('a', '<=', 10)))
        self.assertFalse(self.registers.is_true(('a', '<=', 9)))

        with self.assertRaises(RuntimeError):
            self.registers.is_true(('a', '===', 1))

    def test_exececute_instruction(self):
        self.registers.registers = {}

        self.registers.execute_instruction(('a', 'inc', 1))
        self.assertEqual(self.registers.registers['a'], 1)
        self.registers.execute_instruction(('a', 'inc', 2))
        self.assertEqual(self.registers.registers['a'], 3)

        self.registers.execute_instruction(('b', 'dec', 1))
        self.assertEqual(self.registers.registers['b'], -1)
        self.registers.execute_instruction(('b', 'dec', 2))
        self.assertEqual(self.registers.registers['b'], -3)

        self.registers.execute_instruction(('b', 'inc', 10))
        self.assertEqual(self.registers.registers['b'], 7)

        with self.assertRaises(RuntimeError):
            self.registers.execute_instruction(('a', 'mul', 2))

    def test_exececute_instruction_stores_highest_value_ever(self):
        self.registers.registers = {}
        self.registers.execute_instruction(('a', 'inc', 10))
        self.assertEqual(self.registers.highest_value_ever, 10)
        self.registers.execute_instruction(('a', 'dec', 10))
        self.assertEqual(self.registers.highest_value_ever, 10)

    @patch.object(Registers, 'process_and_execute_instruction')
    def test_parse_file(self, mock_process):
        m = mock_open(read_data='foo\nbar\n')
        with patch('registers.open', m):
            self.registers.parse_file(sentinel.filename)
        m.assert_called_once_with(sentinel.filename)
        mock_process.assert_has_calls([call('foo\n'), call('bar\n')])

    def test_get_largest_value(self):
        self.registers.registers = {'a': 1, 'b': -10, 'c': 5}
        self.assertEqual(self.registers.get_largest_value(), 5)