Chromium Code Reviews| Index: src/trusted/validator_arm/dgen_core.py |
| =================================================================== |
| --- src/trusted/validator_arm/dgen_core.py (revision 8275) |
| +++ src/trusted/validator_arm/dgen_core.py (working copy) |
| @@ -1,9 +1,8 @@ |
| #!/usr/bin/python |
| # |
| -# Copyright 2009 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 2009, Google Inc. |
| +# 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. |
| # |
| """ |
| @@ -11,8 +10,6 @@ |
| modules both operate in terms of these classes. |
| """ |
| -import re |
| - |
| def _popcount(int): |
| """Returns the number of 1 bits in the input.""" |
| count = 0 |
| @@ -85,6 +82,17 @@ |
| 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. |
| @@ -206,29 +214,101 @@ |
| """ |
| self._columns.append( (name, hi_bit, lo_bit) ) |
| - def add_row(self, col_patterns, action_string): |
| + def add_row(self, patterns, action, arch): |
| """Adds a row to the table. |
| Args: |
| - col_patterns: a list containing a BitPattern for every column in the |
| + 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. |
| + table-change. |
| + arg: a string defining the architectures it applies to. None |
| + implies all. |
| """ |
| - arch = None |
| - m = re.match(r'^(=[A-Za-z0-9_]+)\(([^)]+)\)$', action_string) |
| - if m: |
| - action_string = m.group(1) |
| - arch = m.group(2) |
| + self.rows.append(Row(patterns, action, arch)) |
| - 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)) |
| + 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.""" |
| + def __init__(self, name, rule, pattern, constraints): |
| + self.name = name |
|
robertm
2012/04/17 17:12:19
for private member fields we usually use the leadi
Karl
2012/04/17 19:28:31
These fields are intentionally public.
|
| + 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): |
| + value = cmp(other.__class__.__name__, 'DecoderAction') |
|
robertm
2012/04/17 17:12:19
add a function comment
Karl
2012/04/17 19:28:31
Done.
|
| + 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.""" |
|
robertm
2012/04/17 17:12:19
maybe give example of a parse method
Karl
2012/04/17 19:28:31
Done.
|
| + 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): |
| + 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): |
| @@ -277,3 +357,60 @@ |
| 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, with a primary |
|
robertm
2012/04/17 17:12:19
give example of a class
(it would be nice if one
Karl
2012/04/17 19:28:31
Done.
|
| + (i.e. start) table to parse intructions and select the proper ClassDecoder |
| + to use. 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())) |