Index: src/trusted/validator_arm/dgen_core.py |
diff --git a/src/trusted/validator_arm/dgen_core.py b/src/trusted/validator_arm/dgen_core.py |
deleted file mode 100644 |
index b9b8fdd62c3c589c6f1663e035255b16ad9445e0..0000000000000000000000000000000000000000 |
--- a/src/trusted/validator_arm/dgen_core.py |
+++ /dev/null |
@@ -1,449 +0,0 @@ |
-#!/usr/bin/python |
-# |
-# Copyright (c) 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. |
-# |
- |
-""" |
-The core object model for the Decoder Generator. The dg_input and dg_output |
-modules both operate in terms of these classes. |
-""" |
- |
-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) |
- |
- @staticmethod |
- def parse_catch(pattern, hi_bit, lo_bit): |
- """"Calls parse with given arguments, and catches exceptions |
- raised. Prints raised exceptions and returns None. |
- """ |
- try: |
- return BitPattern.parse(pattern, hi_bit, lo_bit); |
- except Exception as ex: |
- print "Error: %s" % ex |
- return None |
- |
- 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, patterns, action, arch): |
- """Adds a row to the table. |
- Args: |
- patterns: a list containing a BitPattern for every column in the |
- table. |
- action: The action associated with the row. Must either be |
- a DecoderAction or a DecoderMethod. |
- arch: a string defining the architectures it applies to. None |
- implies all. |
- """ |
- self.rows.append(Row(patterns, action, arch)) |
- |
- def define_pattern(self, pattern, column): |
- """Converts the given input pattern (for the given column) to the |
- internal form. Returns None if pattern is bad. |
- """ |
- if column >= len(self._columns): return None |
- col = self._columns[column] |
- return BitPattern.parse_catch(pattern, col[1], col[2]) |
- |
- def action_filter(self, names): |
- """Returns a table with DecoderActions reduced to the given field names. |
- Used to optimize out duplicates, depending on context. |
- """ |
- table = Table(self.name, self.citation) |
- table._columns = self._columns |
- for r in self.rows: |
- table.add_row(r.patterns, r.action.action_filter(names), r.arch) |
- return table |
- |
-class DecoderAction: |
- """An action defining a class decoder to apply. |
- |
- Corresponds to the parsed decoder action: |
- decoder_action ::= id (id (word (id)?)?)? |
- |
- Fields are: |
- name - Name of class decoder selected. |
- rule - Name of the rule in ARM manual that defines |
- the decoder action. |
- pattern - The placement of 0/1's within any instruction |
- that is matched by the corresponding rule. |
- constraints - Additional constraints that apply to the rule. |
- """ |
- def __init__(self, name, rule, pattern, constraints): |
- self.name = name |
- self.rule = rule |
- self.pattern = pattern |
- self.constraints = constraints |
- |
- def action_filter(self, names): |
- return DecoderAction( |
- self.name if 'name' in names else None, |
- self.rule if 'rule' in names else None, |
- self.pattern if 'pattern' in names else None, |
- self.constraints if 'constraints' in names else None) |
- |
- def __eq__(self, other): |
- return (other.__class__.__name__ == 'DecoderAction' |
- and self.name == other.name |
- and self.rule == other.rule |
- and self.pattern == other.pattern |
- and self.constraints == other.constraints) |
- |
- def __cmp__(self, other): |
- # Order lexicographically on type/fields. |
- value = cmp(other.__class__.__name__, 'DecoderAction') |
- if value != 0: return value |
- value = cmp(self.name, other.name) |
- if value != 0: return value |
- value = cmp(self.rule, other.rule) |
- if value != 0: return value |
- value = cmp(self.pattern, other.pattern) |
- if value != 0: return value |
- return cmp(self.constraints, other.constraints) |
- |
- def __hash__(self): |
- return (hash('DecoderAction') + hash(self.name) + hash(self.rule) + |
- hash(self.pattern) + hash(self.constraints)) |
- |
- def __repr__(self): |
- return '=%s %s %s %s' % (self.name, self.rule, |
- self.pattern, self.constraints) |
- |
-class DecoderMethod(object): |
- """An action defining a parse method to call. |
- |
- Corresponds to the parsed decoder method: |
- decoder_method ::= '->' id |
- |
- Fields are: |
- name - The name of the corresponding table (i.e. method) that |
- should be used to continue searching for a matching class |
- decoder. |
- """ |
- def __init__(self, name): |
- self.name = name |
- |
- def action_filter(self, unused_names): |
- return self |
- |
- def __eq__(self, other): |
- return (self.__class__.__name__ == 'DecoderMethod' |
- and self.name == other.name) |
- |
- def __cmp__(self, other): |
- # Lexicographically compare types/fields. |
- value = cmp(other.__class__.__name__, 'DecoderMethod') |
- if value != 0: return value |
- return cmp(self.name, other.name) |
- |
- def __hash__(self): |
- return hash('DecoderMethod') + hash(self.name) |
- |
- def __repr__(self): |
- return '->%s' % self.name |
- |
-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)) |
- |
-class Decoder(object): |
- """Defines a class decoder which consists of set of tables. |
- |
- A decoder has a primary (i.e. start) table to parse intructions (and |
- select the proper ClassDecoder), as well as a set of additional |
- tables to complete the selection of a class decoder. Instances of |
- this class correspond to the internal representation of parsed |
- decoder tables recognized by dgen_input.py (see that file for |
- details). |
- |
- Fields are: |
- primary - The entry parse table to find a class decoder. |
- tables - The (sorted) set of tables defined by a decoder. |
- |
- Note: maintains restriction that tables have unique names. |
- """ |
- |
- def __init__(self): |
- self.primary = None |
- self._is_sorted = False |
- self._tables = [] |
- |
- def add(self, table): |
- """Adds the table to the set of tables. Returns true if successful. |
- """ |
- if filter(lambda(t): t.name == table.name, self._tables): |
- # Table with name already defined, report error. |
- return False |
- else: |
- if not self._tables: |
- self.primary = table |
- self._tables.append(table) |
- self.is_sorted = False |
- return True |
- |
- def tables(self): |
- """Returns the sorted (by table name) list of tables""" |
- if self._is_sorted: return self._tables |
- self._tables = sorted(self._tables, key=lambda(tbl): tbl.name) |
- self._is_sorted = True |
- return self._tables |
- |
- def action_filter(self, names): |
- """Returns a new set of tables with actions reduced to the set of |
- field names. |
- """ |
- decoder = Decoder() |
- decoder._tables = sorted([ t.action_filter(names) for t in self._tables ], |
- key=lambda(tbl): tbl.name) |
- decoder.primary = filter( |
- lambda(t): t.name == self.primary.name, self._tables)[0] |
- return decoder |
- |
- def decoders(self): |
- """Returns the sorted sequence of DecoderAction's defined in the tables.""" |
- decoders = set() |
- for t in self._tables: |
- for r in t.rows: |
- if r.action.__class__.__name__ == 'DecoderAction': |
- decoders.add(r.action) |
- return sorted(decoders) |
- |
- def rules(self): |
- """Returns the sorted sequence of DecoderActions that define |
- the rule field. |
- """ |
- return sorted(filter(lambda (r): r.rule, self.decoders())) |