| OLD | NEW |
| (Empty) |
| 1 #!/usr/bin/python | |
| 2 # | |
| 3 # Copyright (c) 2012 The Native Client Authors. All rights reserved. | |
| 4 # Use of this source code is governed by a BSD-style license that can be | |
| 5 # found in the LICENSE file. | |
| 6 # | |
| 7 | |
| 8 """ | |
| 9 The core object model for the Decoder Generator. The dg_input and dg_output | |
| 10 modules both operate in terms of these classes. | |
| 11 """ | |
| 12 | |
| 13 def _popcount(int): | |
| 14 """Returns the number of 1 bits in the input.""" | |
| 15 count = 0 | |
| 16 for bit in range(0, 32): | |
| 17 count = count + ((int >> bit) & 1) | |
| 18 return count | |
| 19 | |
| 20 | |
| 21 class BitPattern(object): | |
| 22 """A pattern for matching strings of bits. See parse() for syntax.""" | |
| 23 | |
| 24 @staticmethod | |
| 25 def parse(pattern, hi_bit, lo_bit): | |
| 26 """ Parses a string pattern describing some bits. The string can | |
| 27 consist of '1' and '0' to match bits explicitly, 'x' or 'X' to ignore | |
| 28 bits, '_' as an ignored separator, and an optional leading '~' to | |
| 29 negate the entire pattern. Examples: | |
| 30 10xx0 | |
| 31 1111_xxxx | |
| 32 ~111x | |
| 33 | |
| 34 The pattern may also optionally be '-', which is equivalent to a | |
| 35 sequence of 'xxx...xxx' of the requested width. | |
| 36 | |
| 37 Args: | |
| 38 pattern: a string in the format described above. | |
| 39 hi_bit: the top of the range matched by this pattern, inclusive. | |
| 40 lo_bit: the bottom of the range matched by this pattern, inclusive. | |
| 41 Returns: | |
| 42 A BitPattern instance that describes the match, and is capable of | |
| 43 transforming itself to a C expression. | |
| 44 Raises: | |
| 45 Exception: the input didn't meet the rules described above. | |
| 46 """ | |
| 47 num_bits = hi_bit - lo_bit + 1 | |
| 48 # Convert - into a full-width don't-care pattern. | |
| 49 if pattern == '-': | |
| 50 return BitPattern.parse('x' * num_bits, hi_bit, lo_bit) | |
| 51 | |
| 52 # Derive the operation type from the presence of a leading tilde. | |
| 53 if pattern.startswith('~'): | |
| 54 op = '!=' | |
| 55 pattern = pattern[1:] | |
| 56 else: | |
| 57 op = '==' | |
| 58 | |
| 59 # Allow use of underscores anywhere in the pattern, as a separator. | |
| 60 pattern = pattern.replace('_', '') | |
| 61 | |
| 62 if len(pattern) != num_bits: | |
| 63 raise Exception('Pattern %s is wrong length for %d:%u' | |
| 64 % (pattern, hi_bit, lo_bit)) | |
| 65 | |
| 66 mask = 0 | |
| 67 value = 0 | |
| 68 for c in pattern: | |
| 69 if c == '1': | |
| 70 mask = (mask << 1) | 1 | |
| 71 value = (value << 1) | 1 | |
| 72 elif c == '0': | |
| 73 mask = (mask << 1) | 1 | |
| 74 value = value << 1 | |
| 75 elif c == 'x' or c == 'X': | |
| 76 mask = mask << 1 | |
| 77 value = value << 1 | |
| 78 else: | |
| 79 raise Exception('Invalid characters in pattern %s' % pattern) | |
| 80 | |
| 81 mask = mask << lo_bit | |
| 82 value = value << lo_bit | |
| 83 return BitPattern(mask, value, op) | |
| 84 | |
| 85 @staticmethod | |
| 86 def parse_catch(pattern, hi_bit, lo_bit): | |
| 87 """"Calls parse with given arguments, and catches exceptions | |
| 88 raised. Prints raised exceptions and returns None. | |
| 89 """ | |
| 90 try: | |
| 91 return BitPattern.parse(pattern, hi_bit, lo_bit); | |
| 92 except Exception as ex: | |
| 93 print "Error: %s" % ex | |
| 94 return None | |
| 95 | |
| 96 def __init__(self, mask, value, op): | |
| 97 """Initializes a BitPattern. | |
| 98 | |
| 99 Args: | |
| 100 mask: an integer with 1s in the bit positions we care about (e.g. | |
| 101 those that are not X) | |
| 102 value: an integer that would match our pattern, subject to the mask. | |
| 103 op: either '==' or '!=', if the pattern is positive or negative, | |
| 104 respectively. | |
| 105 """ | |
| 106 self.mask = mask | |
| 107 self.value = value | |
| 108 self.op = op | |
| 109 self.significant_bits = _popcount(mask) | |
| 110 | |
| 111 def conflicts(self, other): | |
| 112 """Returns an integer with a 1 in each bit position that conflicts | |
| 113 between the two patterns, and 0s elsewhere. Note that this is only | |
| 114 useful if the masks and ops match. | |
| 115 """ | |
| 116 return (self.mask & self.value) ^ (other.mask & other.value) | |
| 117 | |
| 118 def is_complement(self, other): | |
| 119 """Checks if two patterns are complements of each other. This means | |
| 120 they have the same mask and pattern bits, but one is negative. | |
| 121 """ | |
| 122 return (self.op != other.op | |
| 123 and self.mask == other.mask | |
| 124 and self.value == other.value) | |
| 125 | |
| 126 def is_strictly_compatible(self, other): | |
| 127 """Checks if two patterns are safe to merge using +, but are not ==.""" | |
| 128 if self.is_complement(other): | |
| 129 return True | |
| 130 elif self.op == other.op: | |
| 131 return (self.mask == other.mask | |
| 132 and _popcount(self.conflicts(other)) == 1) | |
| 133 return False | |
| 134 | |
| 135 def __add__(self, other): | |
| 136 """Merges two compatible patterns into a single pattern that matches | |
| 137 everything either pattern would have matched. | |
| 138 """ | |
| 139 assert (self == other) or self.is_strictly_compatible(other) | |
| 140 | |
| 141 if self.op == other.op: | |
| 142 c = self.conflicts(other) | |
| 143 return BitPattern((self.mask | other.mask) ^ c, | |
| 144 (self.value | other.value) ^ c, self.op) | |
| 145 else: | |
| 146 return BitPattern(0, 0, '==') # matches anything | |
| 147 | |
| 148 def to_c_expr(self, input): | |
| 149 """Converts this pattern to a C expression. | |
| 150 Args: | |
| 151 input: the name (string) of the C variable to be tested by the | |
| 152 expression. | |
| 153 Returns: | |
| 154 A string containing a C expression. | |
| 155 """ | |
| 156 if self.mask == 0: | |
| 157 return 'true' | |
| 158 else: | |
| 159 return ('(%s & 0x%08X) %s 0x%08X' | |
| 160 % (input, self.mask, self.op, self.value)) | |
| 161 | |
| 162 def __cmp__(self, other): | |
| 163 """Compares two patterns for sorting purposes. We sort by | |
| 164 - # of significant bits, DESCENDING, | |
| 165 - then mask value, numerically, | |
| 166 - then value, numerically, | |
| 167 - and finally op. | |
| 168 | |
| 169 This is also used for equality comparison using ==. | |
| 170 """ | |
| 171 return (cmp(other.significant_bits, self.significant_bits) | |
| 172 or cmp(self.mask, other.mask) | |
| 173 or cmp(self.value, other.value) | |
| 174 or cmp(self.op, other.op)) | |
| 175 | |
| 176 def __repr__(self): | |
| 177 pat = [] | |
| 178 for i in range(0, 32): | |
| 179 if (self.mask >> i) & 1: | |
| 180 pat.append(`(self.value >> i) & 1`) | |
| 181 else: | |
| 182 pat.append('x') | |
| 183 if self.op == '!=': | |
| 184 pat.append('~') | |
| 185 return ''.join(reversed(pat)) | |
| 186 | |
| 187 | |
| 188 class Table(object): | |
| 189 """A table in the instruction set definition. Each table contains 1+ | |
| 190 columns, and 1+ rows. Each row contains a bit pattern for each column, plus | |
| 191 the action to be taken if the row matches.""" | |
| 192 | |
| 193 def __init__(self, name, citation): | |
| 194 """Initializes a new Table. | |
| 195 Args: | |
| 196 name: a name for the table, used to reference it from other tables. | |
| 197 citation: the section in the ISA spec this table was derived from. | |
| 198 """ | |
| 199 self.name = name | |
| 200 self.citation = citation | |
| 201 self.rows = [] | |
| 202 self._columns = [] | |
| 203 | |
| 204 def add_column(self, name, hi_bit, lo_bit): | |
| 205 """Adds a column to the table. | |
| 206 | |
| 207 Because we don't use the column information for very much, we don't give | |
| 208 it a type -- we store it as a list of tuples. | |
| 209 | |
| 210 Args: | |
| 211 name: the name of the column (for diagnostic purposes only). | |
| 212 hi_bit: the leftmost bit included. | |
| 213 lo_bit: the rightmost bit included. | |
| 214 """ | |
| 215 self._columns.append( (name, hi_bit, lo_bit) ) | |
| 216 | |
| 217 def add_row(self, patterns, action, arch): | |
| 218 """Adds a row to the table. | |
| 219 Args: | |
| 220 patterns: a list containing a BitPattern for every column in the | |
| 221 table. | |
| 222 action: The action associated with the row. Must either be | |
| 223 a DecoderAction or a DecoderMethod. | |
| 224 arch: a string defining the architectures it applies to. None | |
| 225 implies all. | |
| 226 """ | |
| 227 self.rows.append(Row(patterns, action, arch)) | |
| 228 | |
| 229 def define_pattern(self, pattern, column): | |
| 230 """Converts the given input pattern (for the given column) to the | |
| 231 internal form. Returns None if pattern is bad. | |
| 232 """ | |
| 233 if column >= len(self._columns): return None | |
| 234 col = self._columns[column] | |
| 235 return BitPattern.parse_catch(pattern, col[1], col[2]) | |
| 236 | |
| 237 def action_filter(self, names): | |
| 238 """Returns a table with DecoderActions reduced to the given field names. | |
| 239 Used to optimize out duplicates, depending on context. | |
| 240 """ | |
| 241 table = Table(self.name, self.citation) | |
| 242 table._columns = self._columns | |
| 243 for r in self.rows: | |
| 244 table.add_row(r.patterns, r.action.action_filter(names), r.arch) | |
| 245 return table | |
| 246 | |
| 247 class DecoderAction: | |
| 248 """An action defining a class decoder to apply. | |
| 249 | |
| 250 Corresponds to the parsed decoder action: | |
| 251 decoder_action ::= id (id (word (id)?)?)? | |
| 252 | |
| 253 Fields are: | |
| 254 name - Name of class decoder selected. | |
| 255 rule - Name of the rule in ARM manual that defines | |
| 256 the decoder action. | |
| 257 pattern - The placement of 0/1's within any instruction | |
| 258 that is matched by the corresponding rule. | |
| 259 constraints - Additional constraints that apply to the rule. | |
| 260 """ | |
| 261 def __init__(self, name, rule, pattern, constraints): | |
| 262 self.name = name | |
| 263 self.rule = rule | |
| 264 self.pattern = pattern | |
| 265 self.constraints = constraints | |
| 266 | |
| 267 def action_filter(self, names): | |
| 268 return DecoderAction( | |
| 269 self.name if 'name' in names else None, | |
| 270 self.rule if 'rule' in names else None, | |
| 271 self.pattern if 'pattern' in names else None, | |
| 272 self.constraints if 'constraints' in names else None) | |
| 273 | |
| 274 def __eq__(self, other): | |
| 275 return (other.__class__.__name__ == 'DecoderAction' | |
| 276 and self.name == other.name | |
| 277 and self.rule == other.rule | |
| 278 and self.pattern == other.pattern | |
| 279 and self.constraints == other.constraints) | |
| 280 | |
| 281 def __cmp__(self, other): | |
| 282 # Order lexicographically on type/fields. | |
| 283 value = cmp(other.__class__.__name__, 'DecoderAction') | |
| 284 if value != 0: return value | |
| 285 value = cmp(self.name, other.name) | |
| 286 if value != 0: return value | |
| 287 value = cmp(self.rule, other.rule) | |
| 288 if value != 0: return value | |
| 289 value = cmp(self.pattern, other.pattern) | |
| 290 if value != 0: return value | |
| 291 return cmp(self.constraints, other.constraints) | |
| 292 | |
| 293 def __hash__(self): | |
| 294 return (hash('DecoderAction') + hash(self.name) + hash(self.rule) + | |
| 295 hash(self.pattern) + hash(self.constraints)) | |
| 296 | |
| 297 def __repr__(self): | |
| 298 return '=%s %s %s %s' % (self.name, self.rule, | |
| 299 self.pattern, self.constraints) | |
| 300 | |
| 301 class DecoderMethod(object): | |
| 302 """An action defining a parse method to call. | |
| 303 | |
| 304 Corresponds to the parsed decoder method: | |
| 305 decoder_method ::= '->' id | |
| 306 | |
| 307 Fields are: | |
| 308 name - The name of the corresponding table (i.e. method) that | |
| 309 should be used to continue searching for a matching class | |
| 310 decoder. | |
| 311 """ | |
| 312 def __init__(self, name): | |
| 313 self.name = name | |
| 314 | |
| 315 def action_filter(self, unused_names): | |
| 316 return self | |
| 317 | |
| 318 def __eq__(self, other): | |
| 319 return (self.__class__.__name__ == 'DecoderMethod' | |
| 320 and self.name == other.name) | |
| 321 | |
| 322 def __cmp__(self, other): | |
| 323 # Lexicographically compare types/fields. | |
| 324 value = cmp(other.__class__.__name__, 'DecoderMethod') | |
| 325 if value != 0: return value | |
| 326 return cmp(self.name, other.name) | |
| 327 | |
| 328 def __hash__(self): | |
| 329 return hash('DecoderMethod') + hash(self.name) | |
| 330 | |
| 331 def __repr__(self): | |
| 332 return '->%s' % self.name | |
| 333 | |
| 334 class Row(object): | |
| 335 """ A row in a Table.""" | |
| 336 def __init__(self, patterns, action, arch): | |
| 337 """Initializes a Row. | |
| 338 Args: | |
| 339 patterns: a list of BitPatterns that must match for this Row to | |
| 340 match. | |
| 341 action: the action to be taken if this Row matches. | |
| 342 arch: the minimum architecture that this Row can match. | |
| 343 """ | |
| 344 self.patterns = patterns | |
| 345 self.action = action | |
| 346 self.arch = arch | |
| 347 | |
| 348 self.significant_bits = 0 | |
| 349 for p in patterns: | |
| 350 self.significant_bits += p.significant_bits | |
| 351 | |
| 352 def can_merge(self, other): | |
| 353 """Determines if we can merge two Rows.""" | |
| 354 if self.action != other.action or self.arch != other.arch: | |
| 355 return False | |
| 356 | |
| 357 equal_columns = 0 | |
| 358 compat_columns = 0 | |
| 359 for (a, b) in zip(self.patterns, other.patterns): | |
| 360 if a == b: | |
| 361 equal_columns += 1 | |
| 362 if a.is_strictly_compatible(b): | |
| 363 compat_columns += 1 | |
| 364 | |
| 365 cols = len(self.patterns) | |
| 366 return (equal_columns == cols | |
| 367 or (equal_columns == cols - 1 and compat_columns == 1)) | |
| 368 | |
| 369 def __add__(self, other): | |
| 370 assert self.can_merge(other) # Caller is expected to check! | |
| 371 return Row([a + b for (a, b) in zip(self.patterns, other.patterns)], | |
| 372 self.action, self.arch) | |
| 373 | |
| 374 def __cmp__(self, other): | |
| 375 """Compares two rows, so we can order pattern matches by specificity. | |
| 376 """ | |
| 377 return (cmp(self.patterns, other.patterns) | |
| 378 or cmp(self.action, other.action)) | |
| 379 | |
| 380 def __repr__(self): | |
| 381 return 'Row(%s, %s)' % (repr(self.patterns), repr(self.action)) | |
| 382 | |
| 383 class Decoder(object): | |
| 384 """Defines a class decoder which consists of set of tables. | |
| 385 | |
| 386 A decoder has a primary (i.e. start) table to parse intructions (and | |
| 387 select the proper ClassDecoder), as well as a set of additional | |
| 388 tables to complete the selection of a class decoder. Instances of | |
| 389 this class correspond to the internal representation of parsed | |
| 390 decoder tables recognized by dgen_input.py (see that file for | |
| 391 details). | |
| 392 | |
| 393 Fields are: | |
| 394 primary - The entry parse table to find a class decoder. | |
| 395 tables - The (sorted) set of tables defined by a decoder. | |
| 396 | |
| 397 Note: maintains restriction that tables have unique names. | |
| 398 """ | |
| 399 | |
| 400 def __init__(self): | |
| 401 self.primary = None | |
| 402 self._is_sorted = False | |
| 403 self._tables = [] | |
| 404 | |
| 405 def add(self, table): | |
| 406 """Adds the table to the set of tables. Returns true if successful. | |
| 407 """ | |
| 408 if filter(lambda(t): t.name == table.name, self._tables): | |
| 409 # Table with name already defined, report error. | |
| 410 return False | |
| 411 else: | |
| 412 if not self._tables: | |
| 413 self.primary = table | |
| 414 self._tables.append(table) | |
| 415 self.is_sorted = False | |
| 416 return True | |
| 417 | |
| 418 def tables(self): | |
| 419 """Returns the sorted (by table name) list of tables""" | |
| 420 if self._is_sorted: return self._tables | |
| 421 self._tables = sorted(self._tables, key=lambda(tbl): tbl.name) | |
| 422 self._is_sorted = True | |
| 423 return self._tables | |
| 424 | |
| 425 def action_filter(self, names): | |
| 426 """Returns a new set of tables with actions reduced to the set of | |
| 427 field names. | |
| 428 """ | |
| 429 decoder = Decoder() | |
| 430 decoder._tables = sorted([ t.action_filter(names) for t in self._tables ], | |
| 431 key=lambda(tbl): tbl.name) | |
| 432 decoder.primary = filter( | |
| 433 lambda(t): t.name == self.primary.name, self._tables)[0] | |
| 434 return decoder | |
| 435 | |
| 436 def decoders(self): | |
| 437 """Returns the sorted sequence of DecoderAction's defined in the tables.""" | |
| 438 decoders = set() | |
| 439 for t in self._tables: | |
| 440 for r in t.rows: | |
| 441 if r.action.__class__.__name__ == 'DecoderAction': | |
| 442 decoders.add(r.action) | |
| 443 return sorted(decoders) | |
| 444 | |
| 445 def rules(self): | |
| 446 """Returns the sorted sequence of DecoderActions that define | |
| 447 the rule field. | |
| 448 """ | |
| 449 return sorted(filter(lambda (r): r.rule, self.decoders())) | |
| OLD | NEW |