Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1183)

Unified Diff: src/trusted/validator_arm/dgen_core.py

Issue 10191011: Moving dgen_ scripts out of validator_arm into a common directory. (Closed)
Patch Set: Updates per code review. Created 8 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/trusted/validator_arm/build.scons ('k') | src/trusted/validator_arm/dgen_decoder_output.py » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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()))
« no previous file with comments | « src/trusted/validator_arm/build.scons ('k') | src/trusted/validator_arm/dgen_decoder_output.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698