Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 #!/usr/bin/python | 1 #!/usr/bin/python |
| 2 # | 2 # |
| 3 # Copyright 2009 The Native Client Authors. All rights reserved. | 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 | 4 # Use of this source code is governed by a BSD-style license that can be |
| 5 # be found in the LICENSE file. | 5 # found in the LICENSE file. |
| 6 # Copyright 2009, Google Inc. | |
| 7 # | 6 # |
| 8 | 7 |
| 9 """ | 8 """ |
| 10 The core object model for the Decoder Generator. The dg_input and dg_output | 9 The core object model for the Decoder Generator. The dg_input and dg_output |
| 11 modules both operate in terms of these classes. | 10 modules both operate in terms of these classes. |
| 12 """ | 11 """ |
| 13 | 12 |
| 14 import re | |
| 15 | |
| 16 def _popcount(int): | 13 def _popcount(int): |
| 17 """Returns the number of 1 bits in the input.""" | 14 """Returns the number of 1 bits in the input.""" |
| 18 count = 0 | 15 count = 0 |
| 19 for bit in range(0, 32): | 16 for bit in range(0, 32): |
| 20 count = count + ((int >> bit) & 1) | 17 count = count + ((int >> bit) & 1) |
| 21 return count | 18 return count |
| 22 | 19 |
| 23 | 20 |
| 24 class BitPattern(object): | 21 class BitPattern(object): |
| 25 """A pattern for matching strings of bits. See parse() for syntax.""" | 22 """A pattern for matching strings of bits. See parse() for syntax.""" |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 78 elif c == 'x' or c == 'X': | 75 elif c == 'x' or c == 'X': |
| 79 mask = mask << 1 | 76 mask = mask << 1 |
| 80 value = value << 1 | 77 value = value << 1 |
| 81 else: | 78 else: |
| 82 raise Exception('Invalid characters in pattern %s' % pattern) | 79 raise Exception('Invalid characters in pattern %s' % pattern) |
| 83 | 80 |
| 84 mask = mask << lo_bit | 81 mask = mask << lo_bit |
| 85 value = value << lo_bit | 82 value = value << lo_bit |
| 86 return BitPattern(mask, value, op) | 83 return BitPattern(mask, value, op) |
| 87 | 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 | |
| 88 def __init__(self, mask, value, op): | 96 def __init__(self, mask, value, op): |
| 89 """Initializes a BitPattern. | 97 """Initializes a BitPattern. |
| 90 | 98 |
| 91 Args: | 99 Args: |
| 92 mask: an integer with 1s in the bit positions we care about (e.g. | 100 mask: an integer with 1s in the bit positions we care about (e.g. |
| 93 those that are not X) | 101 those that are not X) |
| 94 value: an integer that would match our pattern, subject to the mask. | 102 value: an integer that would match our pattern, subject to the mask. |
| 95 op: either '==' or '!=', if the pattern is positive or negative, | 103 op: either '==' or '!=', if the pattern is positive or negative, |
| 96 respectively. | 104 respectively. |
| 97 """ | 105 """ |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 199 Because we don't use the column information for very much, we don't give | 207 Because we don't use the column information for very much, we don't give |
| 200 it a type -- we store it as a list of tuples. | 208 it a type -- we store it as a list of tuples. |
| 201 | 209 |
| 202 Args: | 210 Args: |
| 203 name: the name of the column (for diagnostic purposes only). | 211 name: the name of the column (for diagnostic purposes only). |
| 204 hi_bit: the leftmost bit included. | 212 hi_bit: the leftmost bit included. |
| 205 lo_bit: the rightmost bit included. | 213 lo_bit: the rightmost bit included. |
| 206 """ | 214 """ |
| 207 self._columns.append( (name, hi_bit, lo_bit) ) | 215 self._columns.append( (name, hi_bit, lo_bit) ) |
| 208 | 216 |
| 209 def add_row(self, col_patterns, action_string): | 217 def add_row(self, patterns, action, arch): |
| 210 """Adds a row to the table. | 218 """Adds a row to the table. |
| 211 Args: | 219 Args: |
| 212 col_patterns: a list containing a BitPattern for every column in the | 220 patterns: a list containing a BitPattern for every column in the |
| 213 table. | 221 table. |
| 214 action_string: a string indicating the action to take; must begin | 222 action_string: a string indicating the action to take; must begin |
| 215 with '=' for a terminal instruction class, or '->' for a | 223 with '=' for a terminal instruction class, or '->' for a |
| 216 table-change. The action may end with an arch revision in | 224 table-change. |
| 217 parentheses. | 225 arg: a string defining the architectures it applies to. None |
| 226 implies all. | |
| 218 """ | 227 """ |
| 219 arch = None | 228 self.rows.append(Row(patterns, action, arch)) |
| 220 m = re.match(r'^(=[A-Za-z0-9_]+)\(([^)]+)\)$', action_string) | |
| 221 if m: | |
| 222 action_string = m.group(1) | |
| 223 arch = m.group(2) | |
| 224 | 229 |
| 225 parsed = [] | 230 def define_pattern(self, pattern, column): |
| 226 for i in range(0, len(col_patterns)): | 231 """Converts the given input pattern (for the given column) to the |
| 227 col = self._columns[i] | 232 internal form. Returns None if pattern is bad. |
| 228 parsed.append(BitPattern.parse(col_patterns[i], col[1], col[2])) | 233 """ |
| 229 self.rows.append(Row(parsed, action_string, arch)) | 234 if column >= len(self._columns): return None |
| 235 col = self._columns[column] | |
| 236 return BitPattern.parse_catch(pattern, col[1], col[2]) | |
| 230 | 237 |
| 238 def action_filter(self, names): | |
| 239 """Returns a table with DecoderActions reduced to the given field names. | |
| 240 Used to optimize out duplicates, depending on context. | |
| 241 """ | |
| 242 table = Table(self.name, self.citation) | |
| 243 table._columns = self._columns | |
| 244 for r in self.rows: | |
| 245 table.add_row(r.patterns, r.action.action_filter(names), r.arch) | |
| 246 return table | |
| 247 | |
| 248 class DecoderAction: | |
| 249 """An action defining a class decoder to apply.""" | |
| 250 def __init__(self, name, rule, pattern, constraints): | |
| 251 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.
| |
| 252 self.rule = rule | |
| 253 self.pattern = pattern | |
| 254 self.constraints = constraints | |
| 255 | |
| 256 def action_filter(self, names): | |
| 257 return DecoderAction( | |
| 258 self.name if 'name' in names else None, | |
| 259 self.rule if 'rule' in names else None, | |
| 260 self.pattern if 'pattern' in names else None, | |
| 261 self.constraints if 'constraints' in names else None) | |
| 262 | |
| 263 def __eq__(self, other): | |
| 264 return (other.__class__.__name__ == 'DecoderAction' | |
| 265 and self.name == other.name | |
| 266 and self.rule == other.rule | |
| 267 and self.pattern == other.pattern | |
| 268 and self.constraints == other.constraints) | |
| 269 | |
| 270 def __cmp__(self, other): | |
| 271 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.
| |
| 272 if value != 0: return value | |
| 273 value = cmp(self.name, other.name) | |
| 274 if value != 0: return value | |
| 275 value = cmp(self.rule, other.rule) | |
| 276 if value != 0: return value | |
| 277 value = cmp(self.pattern, other.pattern) | |
| 278 if value != 0: return value | |
| 279 return cmp(self.constraints, other.constraints) | |
| 280 | |
| 281 def __hash__(self): | |
| 282 return (hash('DecoderAction') + hash(self.name) + hash(self.rule) + | |
| 283 hash(self.pattern) + hash(self.constraints)) | |
| 284 | |
| 285 def __repr__(self): | |
| 286 return '=%s %s %s %s' % (self.name, self.rule, | |
| 287 self.pattern, self.constraints) | |
| 288 | |
| 289 class DecoderMethod(object): | |
| 290 """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.
| |
| 291 def __init__(self, name): | |
| 292 self.name = name | |
| 293 | |
| 294 def action_filter(self, unused_names): | |
| 295 return self | |
| 296 | |
| 297 def __eq__(self, other): | |
| 298 return (self.__class__.__name__ == 'DecoderMethod' | |
| 299 and self.name == other.name) | |
| 300 | |
| 301 def __cmp__(self, other): | |
| 302 value = cmp(other.__class__.__name__, 'DecoderMethod') | |
| 303 if value != 0: return value | |
| 304 return cmp(self.name, other.name) | |
| 305 | |
| 306 def __hash__(self): | |
| 307 return hash('DecoderMethod') + hash(self.name) | |
| 308 | |
| 309 def __repr__(self): | |
| 310 return '->%s' % self.name | |
| 231 | 311 |
| 232 class Row(object): | 312 class Row(object): |
| 233 """ A row in a Table.""" | 313 """ A row in a Table.""" |
| 234 def __init__(self, patterns, action, arch): | 314 def __init__(self, patterns, action, arch): |
| 235 """Initializes a Row. | 315 """Initializes a Row. |
| 236 Args: | 316 Args: |
| 237 patterns: a list of BitPatterns that must match for this Row to | 317 patterns: a list of BitPatterns that must match for this Row to |
| 238 match. | 318 match. |
| 239 action: the action to be taken if this Row matches. | 319 action: the action to be taken if this Row matches. |
| 240 arch: the minimum architecture that this Row can match. | 320 arch: the minimum architecture that this Row can match. |
| (...skipping 29 matching lines...) Expand all Loading... | |
| 270 self.action, self.arch) | 350 self.action, self.arch) |
| 271 | 351 |
| 272 def __cmp__(self, other): | 352 def __cmp__(self, other): |
| 273 """Compares two rows, so we can order pattern matches by specificity. | 353 """Compares two rows, so we can order pattern matches by specificity. |
| 274 """ | 354 """ |
| 275 return (cmp(self.patterns, other.patterns) | 355 return (cmp(self.patterns, other.patterns) |
| 276 or cmp(self.action, other.action)) | 356 or cmp(self.action, other.action)) |
| 277 | 357 |
| 278 def __repr__(self): | 358 def __repr__(self): |
| 279 return 'Row(%s, %s)' % (repr(self.patterns), repr(self.action)) | 359 return 'Row(%s, %s)' % (repr(self.patterns), repr(self.action)) |
| 360 | |
| 361 class Decoder(object): | |
| 362 """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.
| |
| 363 (i.e. start) table to parse intructions and select the proper ClassDecoder | |
| 364 to use. Note: maintains restriction that tables have unique names. | |
| 365 """ | |
| 366 | |
| 367 def __init__(self): | |
| 368 self.primary = None | |
| 369 self._is_sorted = False | |
| 370 self._tables = [] | |
| 371 | |
| 372 def add(self, table): | |
| 373 """Adds the table to the set of tables. Returns true if successful. | |
| 374 """ | |
| 375 if filter(lambda(t): t.name == table.name, self._tables): | |
| 376 # Table with name already defined, report error. | |
| 377 return False | |
| 378 else: | |
| 379 if not self._tables: | |
| 380 self.primary = table | |
| 381 self._tables.append(table) | |
| 382 self.is_sorted = False | |
| 383 return True | |
| 384 | |
| 385 def tables(self): | |
| 386 """Returns the sorted (by table name) list of tables""" | |
| 387 if self._is_sorted: return self._tables | |
| 388 self._tables = sorted(self._tables, key=lambda(tbl): tbl.name) | |
| 389 self._is_sorted = True | |
| 390 return self._tables | |
| 391 | |
| 392 def action_filter(self, names): | |
| 393 """Returns a new set of tables with actions reduced to the set of | |
| 394 field names. | |
| 395 """ | |
| 396 decoder = Decoder() | |
| 397 decoder._tables = sorted([ t.action_filter(names) for t in self._tables ], | |
| 398 key=lambda(tbl): tbl.name) | |
| 399 decoder.primary = filter( | |
| 400 lambda(t): t.name == self.primary.name, self._tables)[0] | |
| 401 return decoder | |
| 402 | |
| 403 def decoders(self): | |
| 404 """Returns the sorted sequence of DecoderAction's defined in the tables.""" | |
| 405 decoders = set() | |
| 406 for t in self._tables: | |
| 407 for r in t.rows: | |
| 408 if r.action.__class__.__name__ == 'DecoderAction': | |
| 409 decoders.add(r.action) | |
| 410 return sorted(decoders) | |
| 411 | |
| 412 def rules(self): | |
| 413 """Returns the sorted sequence of DecoderActions that define | |
| 414 the rule field. | |
| 415 """ | |
| 416 return sorted(filter(lambda (r): r.rule, self.decoders())) | |
| OLD | NEW |