| Index: src/trusted/validator_mips/dgen/dgen_core.py
 | 
| diff --git a/src/trusted/validator_mips/dgen/dgen_core.py b/src/trusted/validator_mips/dgen/dgen_core.py
 | 
| new file mode 100755
 | 
| index 0000000000000000000000000000000000000000..395d2b17c31942447f8db00bd92736f94cf8b810
 | 
| --- /dev/null
 | 
| +++ b/src/trusted/validator_mips/dgen/dgen_core.py
 | 
| @@ -0,0 +1,279 @@
 | 
| +#!/usr/bin/python
 | 
| +#
 | 
| +# Copyright 2012 The Native Client Authors.  All rights reserved.
 | 
| +# Use of this source code is governed by a BSD-style license that can
 | 
| +# be found in the LICENSE file.
 | 
| +# Copyright 2012, Google Inc.
 | 
| +#
 | 
| +
 | 
| +"""
 | 
| +The core object model for the Decoder Generator.  The dg_input and dg_output
 | 
| +modules both operate in terms of these classes.
 | 
| +"""
 | 
| +
 | 
| +import re
 | 
| +
 | 
| +def _popcount(int):
 | 
| +    """Returns the number of 1 bits in the input."""
 | 
| +    count = 0
 | 
| +    for bit in range(0, 32):
 | 
| +        count = count + ((int >> bit) & 1)
 | 
| +    return count
 | 
| +
 | 
| +
 | 
| +class BitPattern(object):
 | 
| +    """A pattern for matching strings of bits.  See parse() for syntax."""
 | 
| +
 | 
| +    @staticmethod
 | 
| +    def parse(pattern, hi_bit, lo_bit):
 | 
| +        """ Parses a string pattern describing some bits.  The string can
 | 
| +        consist of '1' and '0' to match bits explicitly, 'x' or 'X' to ignore
 | 
| +        bits, '_' as an ignored separator, and an optional leading '~' to
 | 
| +        negate the entire pattern.  Examples:
 | 
| +          10xx0
 | 
| +          1111_xxxx
 | 
| +          ~111x
 | 
| +
 | 
| +        The pattern may also optionally be '-', which is equivalent to a
 | 
| +        sequence of 'xxx...xxx' of the requested width.
 | 
| +
 | 
| +        Args:
 | 
| +            pattern: a string in the format described above.
 | 
| +            hi_bit: the top of the range matched by this pattern, inclusive.
 | 
| +            lo_bit: the bottom of the range matched by this pattern, inclusive.
 | 
| +        Returns:
 | 
| +            A BitPattern instance that describes the match, and is capable of
 | 
| +            transforming itself to a C expression.
 | 
| +        Raises:
 | 
| +            Exception: the input didn't meet the rules described above.
 | 
| +        """
 | 
| +        num_bits = hi_bit - lo_bit + 1
 | 
| +        # Convert - into a full-width don't-care pattern.
 | 
| +        if pattern == '-':
 | 
| +            return BitPattern.parse('x' * num_bits, hi_bit, lo_bit)
 | 
| +
 | 
| +        # Derive the operation type from the presence of a leading tilde.
 | 
| +        if pattern.startswith('~'):
 | 
| +            op = '!='
 | 
| +            pattern = pattern[1:]
 | 
| +        else:
 | 
| +            op = '=='
 | 
| +
 | 
| +        # Allow use of underscores anywhere in the pattern, as a separator.
 | 
| +        pattern = pattern.replace('_', '')
 | 
| +
 | 
| +        if len(pattern) != num_bits:
 | 
| +            raise Exception('Pattern %s is wrong length for %d:%u'
 | 
| +                % (pattern, hi_bit, lo_bit))
 | 
| +
 | 
| +        mask = 0
 | 
| +        value = 0
 | 
| +        for c in pattern:
 | 
| +            if c == '1':
 | 
| +                mask = (mask << 1) | 1
 | 
| +                value = (value << 1) | 1
 | 
| +            elif c == '0':
 | 
| +                mask = (mask << 1) | 1
 | 
| +                value = value << 1
 | 
| +            elif c == 'x' or c == 'X':
 | 
| +                mask = mask << 1
 | 
| +                value = value << 1
 | 
| +            else:
 | 
| +                raise Exception('Invalid characters in pattern %s' % pattern)
 | 
| +
 | 
| +        mask = mask << lo_bit
 | 
| +        value = value << lo_bit
 | 
| +        return BitPattern(mask, value, op)
 | 
| +
 | 
| +    def __init__(self, mask, value, op):
 | 
| +        """Initializes a BitPattern.
 | 
| +
 | 
| +        Args:
 | 
| +            mask: an integer with 1s in the bit positions we care about (e.g.
 | 
| +                those that are not X)
 | 
| +            value: an integer that would match our pattern, subject to the mask.
 | 
| +            op: either '==' or '!=', if the pattern is positive or negative,
 | 
| +                respectively.
 | 
| +        """
 | 
| +        self.mask = mask
 | 
| +        self.value = value
 | 
| +        self.op = op
 | 
| +        self.significant_bits = _popcount(mask)
 | 
| +
 | 
| +    def conflicts(self, other):
 | 
| +        """Returns an integer with a 1 in each bit position that conflicts
 | 
| +        between the two patterns, and 0s elsewhere.  Note that this is only
 | 
| +        useful if the masks and ops match.
 | 
| +        """
 | 
| +        return (self.mask & self.value) ^ (other.mask & other.value)
 | 
| +
 | 
| +    def is_complement(self, other):
 | 
| +        """Checks if two patterns are complements of each other.  This means
 | 
| +        they have the same mask and pattern bits, but one is negative.
 | 
| +        """
 | 
| +        return (self.op != other.op
 | 
| +            and self.mask == other.mask
 | 
| +            and self.value == other.value)
 | 
| +
 | 
| +    def is_strictly_compatible(self, other):
 | 
| +        """Checks if two patterns are safe to merge using +, but are not ==."""
 | 
| +        if self.is_complement(other):
 | 
| +            return True
 | 
| +        elif self.op == other.op:
 | 
| +            return (self.mask == other.mask
 | 
| +                and _popcount(self.conflicts(other)) == 1)
 | 
| +        return False
 | 
| +
 | 
| +    def __add__(self, other):
 | 
| +        """Merges two compatible patterns into a single pattern that matches
 | 
| +        everything either pattern would have matched.
 | 
| +        """
 | 
| +        assert (self == other) or self.is_strictly_compatible(other)
 | 
| +
 | 
| +        if self.op == other.op:
 | 
| +            c = self.conflicts(other)
 | 
| +            return BitPattern((self.mask | other.mask) ^ c,
 | 
| +                (self.value | other.value) ^ c, self.op)
 | 
| +        else:
 | 
| +            return BitPattern(0, 0, '==')  # matches anything
 | 
| +
 | 
| +    def to_c_expr(self, input):
 | 
| +        """Converts this pattern to a C expression.
 | 
| +        Args:
 | 
| +            input: the name (string) of the C variable to be tested by the
 | 
| +                expression.
 | 
| +        Returns:
 | 
| +            A string containing a C expression.
 | 
| +        """
 | 
| +        if self.mask == 0:
 | 
| +            return 'true'
 | 
| +        else:
 | 
| +            return ('(%s & 0x%08X) %s 0x%08X'
 | 
| +                % (input, self.mask, self.op, self.value))
 | 
| +
 | 
| +    def __cmp__(self, other):
 | 
| +        """Compares two patterns for sorting purposes.  We sort by
 | 
| +        - # of significant bits, DESCENDING,
 | 
| +        - then mask value, numerically,
 | 
| +        - then value, numerically,
 | 
| +        - and finally op.
 | 
| +
 | 
| +        This is also used for equality comparison using ==.
 | 
| +        """
 | 
| +        return (cmp(other.significant_bits, self.significant_bits)
 | 
| +            or cmp(self.mask, other.mask)
 | 
| +            or cmp(self.value, other.value)
 | 
| +            or cmp(self.op, other.op))
 | 
| +
 | 
| +    def __repr__(self):
 | 
| +        pat = []
 | 
| +        for i in range(0, 32):
 | 
| +            if (self.mask >> i) & 1:
 | 
| +                pat.append(`(self.value >> i) & 1`)
 | 
| +            else:
 | 
| +                pat.append('x')
 | 
| +        if self.op == '!=':
 | 
| +            pat.append('~')
 | 
| +        return ''.join(reversed(pat))
 | 
| +
 | 
| +
 | 
| +class Table(object):
 | 
| +    """A table in the instruction set definition.  Each table contains 1+
 | 
| +    columns, and 1+ rows.  Each row contains a bit pattern for each column, plus
 | 
| +    the action to be taken if the row matches."""
 | 
| +
 | 
| +    def __init__(self, name, citation):
 | 
| +        """Initializes a new Table.
 | 
| +        Args:
 | 
| +            name: a name for the table, used to reference it from other tables.
 | 
| +            citation: the section in the ISA spec this table was derived from.
 | 
| +        """
 | 
| +        self.name = name
 | 
| +        self.citation = citation
 | 
| +        self.rows = []
 | 
| +        self._columns = []
 | 
| +
 | 
| +    def add_column(self, name, hi_bit, lo_bit):
 | 
| +        """Adds a column to the table.
 | 
| +
 | 
| +        Because we don't use the column information for very much, we don't give
 | 
| +        it a type -- we store it as a list of tuples.
 | 
| +
 | 
| +        Args:
 | 
| +            name: the name of the column (for diagnostic purposes only).
 | 
| +            hi_bit: the leftmost bit included.
 | 
| +            lo_bit: the rightmost bit included.
 | 
| +        """
 | 
| +        self._columns.append( (name, hi_bit, lo_bit) )
 | 
| +
 | 
| +    def add_row(self, col_patterns, action_string):
 | 
| +        """Adds a row to the table.
 | 
| +        Args:
 | 
| +            col_patterns: a list containing a BitPattern for every column in the
 | 
| +                table.
 | 
| +            action_string: a string indicating the action to take; must begin
 | 
| +                with '=' for a terminal instruction class, or '->' for a
 | 
| +                table-change.  The action may end with an arch revision in
 | 
| +                parentheses.
 | 
| +        """
 | 
| +        arch = None
 | 
| +        m = re.match(r'^(=[A-Za-z0-9_]+)\(([^)]+)\)$', action_string)
 | 
| +        if m:
 | 
| +            action_string = m.group(1)
 | 
| +            arch = m.group(2)
 | 
| +
 | 
| +        parsed = []
 | 
| +        for i in range(0, len(col_patterns)):
 | 
| +            col = self._columns[i]
 | 
| +            parsed.append(BitPattern.parse(col_patterns[i], col[1], col[2]))
 | 
| +        self.rows.append(Row(parsed, action_string, arch))
 | 
| +
 | 
| +
 | 
| +class Row(object):
 | 
| +    """ A row in a Table."""
 | 
| +    def __init__(self, patterns, action, arch):
 | 
| +        """Initializes a Row.
 | 
| +        Args:
 | 
| +            patterns: a list of BitPatterns that must match for this Row to
 | 
| +                match.
 | 
| +            action: the action to be taken if this Row matches.
 | 
| +            arch: the minimum architecture that this Row can match.
 | 
| +        """
 | 
| +        self.patterns = patterns
 | 
| +        self.action = action
 | 
| +        self.arch = arch
 | 
| +
 | 
| +        self.significant_bits = 0
 | 
| +        for p in patterns:
 | 
| +            self.significant_bits += p.significant_bits
 | 
| +
 | 
| +    def can_merge(self, other):
 | 
| +        """Determines if we can merge two Rows."""
 | 
| +        if self.action != other.action or self.arch != other.arch:
 | 
| +            return False
 | 
| +
 | 
| +        equal_columns = 0
 | 
| +        compat_columns = 0
 | 
| +        for (a, b) in zip(self.patterns, other.patterns):
 | 
| +            if a == b:
 | 
| +                equal_columns += 1
 | 
| +            if a.is_strictly_compatible(b):
 | 
| +                compat_columns += 1
 | 
| +
 | 
| +        cols = len(self.patterns)
 | 
| +        return (equal_columns == cols
 | 
| +            or (equal_columns == cols - 1 and compat_columns == 1))
 | 
| +
 | 
| +    def __add__(self, other):
 | 
| +        assert self.can_merge(other)  # Caller is expected to check!
 | 
| +        return Row([a + b for (a, b) in zip(self.patterns, other.patterns)],
 | 
| +            self.action, self.arch)
 | 
| +
 | 
| +    def __cmp__(self, other):
 | 
| +        """Compares two rows, so we can order pattern matches by specificity.
 | 
| +        """
 | 
| +        return (cmp(self.patterns, other.patterns)
 | 
| +            or cmp(self.action, other.action))
 | 
| +
 | 
| +    def __repr__(self):
 | 
| +        return 'Row(%s, %s)' % (repr(self.patterns), repr(self.action))
 | 
| 
 |