isa_parser.py (6655:380a32b43336) | isa_parser.py (6661:9bc3e4611009) |
---|---|
1# Copyright (c) 2003-2005 The Regents of The University of Michigan 2# All rights reserved. 3# 4# Redistribution and use in source and binary forms, with or without 5# modification, are permitted provided that the following conditions are 6# met: redistributions of source code must retain the above copyright 7# notice, this list of conditions and the following disclaimer; 8# redistributions in binary form must reproduce the above copyright --- 20 unchanged lines hidden (view full) --- 29import os 30import sys 31import re 32import string 33import traceback 34# get type names 35from types import * 36 | 1# Copyright (c) 2003-2005 The Regents of The University of Michigan 2# All rights reserved. 3# 4# Redistribution and use in source and binary forms, with or without 5# modification, are permitted provided that the following conditions are 6# met: redistributions of source code must retain the above copyright 7# notice, this list of conditions and the following disclaimer; 8# redistributions in binary form must reproduce the above copyright --- 20 unchanged lines hidden (view full) --- 29import os 30import sys 31import re 32import string 33import traceback 34# get type names 35from types import * 36 |
37from ply import lex 38from ply import yacc | 37from m5.util.grammar import Grammar |
39 | 38 |
40##################################################################### 41# 42# Lexer 43# 44# The PLY lexer module takes two things as input: 45# - A list of token names (the string list 'tokens') 46# - A regular expression describing a match for each token. The 47# regexp for token FOO can be provided in two ways: 48# - as a string variable named t_FOO 49# - as the doc string for a function named t_FOO. In this case, 50# the function is also executed, allowing an action to be 51# associated with each token match. 52# 53##################################################################### | 39class ISAParser(Grammar): 40 def __init__(self, *args, **kwargs): 41 super(ISAParser, self).__init__(*args, **kwargs) 42 self.templateMap = {} |
54 | 43 |
55# Reserved words. These are listed separately as they are matched 56# using the same regexp as generic IDs, but distinguished in the 57# t_ID() function. The PLY documentation suggests this approach. 58reserved = ( 59 'BITFIELD', 'DECODE', 'DECODER', 'DEFAULT', 'DEF', 'EXEC', 'FORMAT', 60 'HEADER', 'LET', 'NAMESPACE', 'OPERAND_TYPES', 'OPERANDS', 61 'OUTPUT', 'SIGNED', 'TEMPLATE' 62 ) | 44 ##################################################################### 45 # 46 # Lexer 47 # 48 # The PLY lexer module takes two things as input: 49 # - A list of token names (the string list 'tokens') 50 # - A regular expression describing a match for each token. The 51 # regexp for token FOO can be provided in two ways: 52 # - as a string variable named t_FOO 53 # - as the doc string for a function named t_FOO. In this case, 54 # the function is also executed, allowing an action to be 55 # associated with each token match. 56 # 57 ##################################################################### |
63 | 58 |
64# List of tokens. The lex module requires this. 65tokens = reserved + ( 66 # identifier 67 'ID', | 59 # Reserved words. These are listed separately as they are matched 60 # using the same regexp as generic IDs, but distinguished in the 61 # t_ID() function. The PLY documentation suggests this approach. 62 reserved = ( 63 'BITFIELD', 'DECODE', 'DECODER', 'DEFAULT', 'DEF', 'EXEC', 'FORMAT', 64 'HEADER', 'LET', 'NAMESPACE', 'OPERAND_TYPES', 'OPERANDS', 65 'OUTPUT', 'SIGNED', 'TEMPLATE' 66 ) |
68 | 67 |
69 # integer literal 70 'INTLIT', | 68 # List of tokens. The lex module requires this. 69 tokens = reserved + ( 70 # identifier 71 'ID', |
71 | 72 |
72 # string literal 73 'STRLIT', | 73 # integer literal 74 'INTLIT', |
74 | 75 |
75 # code literal 76 'CODELIT', | 76 # string literal 77 'STRLIT', |
77 | 78 |
78 # ( ) [ ] { } < > , ; . : :: * 79 'LPAREN', 'RPAREN', 80 'LBRACKET', 'RBRACKET', 81 'LBRACE', 'RBRACE', 82 'LESS', 'GREATER', 'EQUALS', 83 'COMMA', 'SEMI', 'DOT', 'COLON', 'DBLCOLON', 84 'ASTERISK', | 79 # code literal 80 'CODELIT', |
85 | 81 |
86 # C preprocessor directives 87 'CPPDIRECTIVE' | 82 # ( ) [ ] { } < > , ; . : :: * 83 'LPAREN', 'RPAREN', 84 'LBRACKET', 'RBRACKET', 85 'LBRACE', 'RBRACE', 86 'LESS', 'GREATER', 'EQUALS', 87 'COMMA', 'SEMI', 'DOT', 'COLON', 'DBLCOLON', 88 'ASTERISK', |
88 | 89 |
89# The following are matched but never returned. commented out to 90# suppress PLY warning 91 # newfile directive 92# 'NEWFILE', | 90 # C preprocessor directives 91 'CPPDIRECTIVE' |
93 | 92 |
94 # endfile directive 95# 'ENDFILE' 96) | 93 # The following are matched but never returned. commented out to 94 # suppress PLY warning 95 # newfile directive 96 # 'NEWFILE', |
97 | 97 |
98# Regular expressions for token matching 99t_LPAREN = r'\(' 100t_RPAREN = r'\)' 101t_LBRACKET = r'\[' 102t_RBRACKET = r'\]' 103t_LBRACE = r'\{' 104t_RBRACE = r'\}' 105t_LESS = r'\<' 106t_GREATER = r'\>' 107t_EQUALS = r'=' 108t_COMMA = r',' 109t_SEMI = r';' 110t_DOT = r'\.' 111t_COLON = r':' 112t_DBLCOLON = r'::' 113t_ASTERISK = r'\*' | 98 # endfile directive 99 # 'ENDFILE' 100 ) |
114 | 101 |
115# Identifiers and reserved words 116reserved_map = { } 117for r in reserved: 118 reserved_map[r.lower()] = r | 102 # Regular expressions for token matching 103 t_LPAREN = r'\(' 104 t_RPAREN = r'\)' 105 t_LBRACKET = r'\[' 106 t_RBRACKET = r'\]' 107 t_LBRACE = r'\{' 108 t_RBRACE = r'\}' 109 t_LESS = r'\<' 110 t_GREATER = r'\>' 111 t_EQUALS = r'=' 112 t_COMMA = r',' 113 t_SEMI = r';' 114 t_DOT = r'\.' 115 t_COLON = r':' 116 t_DBLCOLON = r'::' 117 t_ASTERISK = r'\*' |
119 | 118 |
120def t_ID(t): 121 r'[A-Za-z_]\w*' 122 t.type = reserved_map.get(t.value,'ID') 123 return t | 119 # Identifiers and reserved words 120 reserved_map = { } 121 for r in reserved: 122 reserved_map[r.lower()] = r |
124 | 123 |
125# Integer literal 126def t_INTLIT(t): 127 r'(0x[\da-fA-F]+)|\d+' 128 try: 129 t.value = int(t.value,0) 130 except ValueError: 131 error(t.lexer.lineno, 'Integer value "%s" too large' % t.value) 132 t.value = 0 133 return t | 124 def t_ID(self, t): 125 r'[A-Za-z_]\w*' 126 t.type = self.reserved_map.get(t.value, 'ID') 127 return t |
134 | 128 |
135# String literal. Note that these use only single quotes, and 136# can span multiple lines. 137def t_STRLIT(t): 138 r"(?m)'([^'])+'" 139 # strip off quotes 140 t.value = t.value[1:-1] 141 t.lexer.lineno += t.value.count('\n') 142 return t | 129 # Integer literal 130 def t_INTLIT(self, t): 131 r'(0x[\da-fA-F]+)|\d+' 132 try: 133 t.value = int(t.value,0) 134 except ValueError: 135 error(t.lexer.lineno, 'Integer value "%s" too large' % t.value) 136 t.value = 0 137 return t |
143 | 138 |
139 # String literal. Note that these use only single quotes, and 140 # can span multiple lines. 141 def t_STRLIT(self, t): 142 r"(?m)'([^'])+'" 143 # strip off quotes 144 t.value = t.value[1:-1] 145 t.lexer.lineno += t.value.count('\n') 146 return t |
|
144 | 147 |
145# "Code literal"... like a string literal, but delimiters are 146# '{{' and '}}' so they get formatted nicely under emacs c-mode 147def t_CODELIT(t): 148 r"(?m)\{\{([^\}]|}(?!\}))+\}\}" 149 # strip off {{ & }} 150 t.value = t.value[2:-2] 151 t.lexer.lineno += t.value.count('\n') 152 return t | |
153 | 148 |
154def t_CPPDIRECTIVE(t): 155 r'^\#[^\#].*\n' 156 t.lexer.lineno += t.value.count('\n') 157 return t | 149 # "Code literal"... like a string literal, but delimiters are 150 # '{{' and '}}' so they get formatted nicely under emacs c-mode 151 def t_CODELIT(self, t): 152 r"(?m)\{\{([^\}]|}(?!\}))+\}\}" 153 # strip off {{ & }} 154 t.value = t.value[2:-2] 155 t.lexer.lineno += t.value.count('\n') 156 return t |
158 | 157 |
159def t_NEWFILE(t): 160 r'^\#\#newfile\s+"[\w/.-]*"' 161 fileNameStack.push((t.value[11:-1], t.lexer.lineno)) 162 t.lexer.lineno = 0 | 158 def t_CPPDIRECTIVE(self, t): 159 r'^\#[^\#].*\n' 160 t.lexer.lineno += t.value.count('\n') 161 return t |
163 | 162 |
164def t_ENDFILE(t): 165 r'^\#\#endfile' 166 (old_filename, t.lexer.lineno) = fileNameStack.pop() | 163 def t_NEWFILE(self, t): 164 r'^\#\#newfile\s+"[\w/.-]*"' 165 fileNameStack.push((t.value[11:-1], t.lexer.lineno)) 166 t.lexer.lineno = 0 |
167 | 167 |
168# 169# The functions t_NEWLINE, t_ignore, and t_error are 170# special for the lex module. 171# | 168 def t_ENDFILE(self, t): 169 r'^\#\#endfile' 170 (old_filename, t.lexer.lineno) = fileNameStack.pop() |
172 | 171 |
173# Newlines 174def t_NEWLINE(t): 175 r'\n+' 176 t.lexer.lineno += t.value.count('\n') | 172 # 173 # The functions t_NEWLINE, t_ignore, and t_error are 174 # special for the lex module. 175 # |
177 | 176 |
178# Comments 179def t_comment(t): 180 r'//.*' | 177 # Newlines 178 def t_NEWLINE(self, t): 179 r'\n+' 180 t.lexer.lineno += t.value.count('\n') |
181 | 181 |
182# Completely ignored characters 183t_ignore = ' \t\x0c' | 182 # Comments 183 def t_comment(self, t): 184 r'//.*' |
184 | 185 |
185# Error handler 186def t_error(t): 187 error(t.lexer.lineno, "illegal character '%s'" % t.value[0]) 188 t.skip(1) | 186 # Completely ignored characters 187 t_ignore = ' \t\x0c' |
189 | 188 |
190# Build the lexer 191lexer = lex.lex() | 189 # Error handler 190 def t_error(self, t): 191 error(t.lexer.lineno, "illegal character '%s'" % t.value[0]) 192 t.skip(1) |
192 | 193 |
193##################################################################### 194# 195# Parser 196# 197# Every function whose name starts with 'p_' defines a grammar rule. 198# The rule is encoded in the function's doc string, while the 199# function body provides the action taken when the rule is matched. 200# The argument to each function is a list of the values of the 201# rule's symbols: t[0] for the LHS, and t[1..n] for the symbols 202# on the RHS. For tokens, the value is copied from the t.value 203# attribute provided by the lexer. For non-terminals, the value 204# is assigned by the producing rule; i.e., the job of the grammar 205# rule function is to set the value for the non-terminal on the LHS 206# (by assigning to t[0]). 207##################################################################### | 194 ##################################################################### 195 # 196 # Parser 197 # 198 # Every function whose name starts with 'p_' defines a grammar 199 # rule. The rule is encoded in the function's doc string, while 200 # the function body provides the action taken when the rule is 201 # matched. The argument to each function is a list of the values 202 # of the rule's symbols: t[0] for the LHS, and t[1..n] for the 203 # symbols on the RHS. For tokens, the value is copied from the 204 # t.value attribute provided by the lexer. For non-terminals, the 205 # value is assigned by the producing rule; i.e., the job of the 206 # grammar rule function is to set the value for the non-terminal 207 # on the LHS (by assigning to t[0]). 208 ##################################################################### |
208 | 209 |
209# The LHS of the first grammar rule is used as the start symbol 210# (in this case, 'specification'). Note that this rule enforces 211# that there will be exactly one namespace declaration, with 0 or more 212# global defs/decls before and after it. The defs & decls before 213# the namespace decl will be outside the namespace; those after 214# will be inside. The decoder function is always inside the namespace. 215def p_specification(t): 216 'specification : opt_defs_and_outputs name_decl opt_defs_and_outputs decode_block' 217 global_code = t[1] 218 isa_name = t[2] 219 namespace = isa_name + "Inst" 220 # wrap the decode block as a function definition 221 t[4].wrap_decode_block(''' | 210 # The LHS of the first grammar rule is used as the start symbol 211 # (in this case, 'specification'). Note that this rule enforces 212 # that there will be exactly one namespace declaration, with 0 or 213 # more global defs/decls before and after it. The defs & decls 214 # before the namespace decl will be outside the namespace; those 215 # after will be inside. The decoder function is always inside the 216 # namespace. 217 def p_specification(self, t): 218 'specification : opt_defs_and_outputs name_decl opt_defs_and_outputs decode_block' 219 global_code = t[1] 220 isa_name = t[2] 221 namespace = isa_name + "Inst" 222 # wrap the decode block as a function definition 223 t[4].wrap_decode_block(''' |
222StaticInstPtr 223%(isa_name)s::decodeInst(%(isa_name)s::ExtMachInst machInst) 224{ 225 using namespace %(namespace)s; 226''' % vars(), '}') | 224StaticInstPtr 225%(isa_name)s::decodeInst(%(isa_name)s::ExtMachInst machInst) 226{ 227 using namespace %(namespace)s; 228''' % vars(), '}') |
227 # both the latter output blocks and the decode block are in the namespace 228 namespace_code = t[3] + t[4] 229 # pass it all back to the caller of yacc.parse() 230 t[0] = (isa_name, namespace, global_code, namespace_code) | 229 # both the latter output blocks and the decode block are in 230 # the namespace 231 namespace_code = t[3] + t[4] 232 # pass it all back to the caller of yacc.parse() 233 t[0] = (isa_name, namespace, global_code, namespace_code) |
231 | 234 |
232# ISA name declaration looks like "namespace 233def p_name_decl(t): 234 'name_decl : NAMESPACE ID SEMI' 235 t[0] = t[2] | 235 # ISA name declaration looks like "namespace <foo>;" 236 def p_name_decl(self, t): 237 'name_decl : NAMESPACE ID SEMI' 238 t[0] = t[2] |
236 | 239 |
237# 'opt_defs_and_outputs' is a possibly empty sequence of 238# def and/or output statements. 239def p_opt_defs_and_outputs_0(t): 240 'opt_defs_and_outputs : empty' 241 t[0] = GenCode() | 240 # 'opt_defs_and_outputs' is a possibly empty sequence of 241 # def and/or output statements. 242 def p_opt_defs_and_outputs_0(self, t): 243 'opt_defs_and_outputs : empty' 244 t[0] = GenCode() |
242 | 245 |
243def p_opt_defs_and_outputs_1(t): 244 'opt_defs_and_outputs : defs_and_outputs' 245 t[0] = t[1] | 246 def p_opt_defs_and_outputs_1(self, t): 247 'opt_defs_and_outputs : defs_and_outputs' 248 t[0] = t[1] |
246 | 249 |
247def p_defs_and_outputs_0(t): 248 'defs_and_outputs : def_or_output' 249 t[0] = t[1] | 250 def p_defs_and_outputs_0(self, t): 251 'defs_and_outputs : def_or_output' 252 t[0] = t[1] |
250 | 253 |
251def p_defs_and_outputs_1(t): 252 'defs_and_outputs : defs_and_outputs def_or_output' 253 t[0] = t[1] + t[2] | 254 def p_defs_and_outputs_1(self, t): 255 'defs_and_outputs : defs_and_outputs def_or_output' 256 t[0] = t[1] + t[2] |
254 | 257 |
255# The list of possible definition/output statements. 256def p_def_or_output(t): 257 '''def_or_output : def_format 258 | def_bitfield 259 | def_bitfield_struct 260 | def_template 261 | def_operand_types 262 | def_operands 263 | output_header 264 | output_decoder 265 | output_exec 266 | global_let''' 267 t[0] = t[1] | 258 # The list of possible definition/output statements. 259 def p_def_or_output(self, t): 260 '''def_or_output : def_format 261 | def_bitfield 262 | def_bitfield_struct 263 | def_template 264 | def_operand_types 265 | def_operands 266 | output_header 267 | output_decoder 268 | output_exec 269 | global_let''' 270 t[0] = t[1] |
268 | 271 |
269# Output blocks 'output 270# directly to the appropriate output section. | 272 # Output blocks 'output <foo> {{...}}' (C++ code blocks) are copied 273 # directly to the appropriate output section. |
271 | 274 |
275 # Massage output block by substituting in template definitions and 276 # bit operators. We handle '%'s embedded in the string that don't 277 # indicate template substitutions (or CPU-specific symbols, which 278 # get handled in GenCode) by doubling them first so that the 279 # format operation will reduce them back to single '%'s. 280 def process_output(self, s): 281 s = protect_non_subst_percents(s) 282 # protects cpu-specific symbols too 283 s = protect_cpu_symbols(s) 284 return substBitOps(s % self.templateMap) |
|
272 | 285 |
273# Protect any non-dict-substitution '%'s in a format string 274# (i.e. those not followed by '(') 275def protect_non_subst_percents(s): 276 return re.sub(r'%(?!\()', '%%', s) | 286 def p_output_header(self, t): 287 'output_header : OUTPUT HEADER CODELIT SEMI' 288 t[0] = GenCode(header_output = self.process_output(t[3])) |
277 | 289 |
278# Massage output block by substituting in template definitions and bit 279# operators. We handle '%'s embedded in the string that don't 280# indicate template substitutions (or CPU-specific symbols, which get 281# handled in GenCode) by doubling them first so that the format 282# operation will reduce them back to single '%'s. 283def process_output(s): 284 s = protect_non_subst_percents(s) 285 # protects cpu-specific symbols too 286 s = protect_cpu_symbols(s) 287 return substBitOps(s % templateMap) | 290 def p_output_decoder(self, t): 291 'output_decoder : OUTPUT DECODER CODELIT SEMI' 292 t[0] = GenCode(decoder_output = self.process_output(t[3])) |
288 | 293 |
289def p_output_header(t): 290 'output_header : OUTPUT HEADER CODELIT SEMI' 291 t[0] = GenCode(header_output = process_output(t[3])) | 294 def p_output_exec(self, t): 295 'output_exec : OUTPUT EXEC CODELIT SEMI' 296 t[0] = GenCode(exec_output = self.process_output(t[3])) |
292 | 297 |
293def p_output_decoder(t): 294 'output_decoder : OUTPUT DECODER CODELIT SEMI' 295 t[0] = GenCode(decoder_output = process_output(t[3])) | 298 # global let blocks 'let {{...}}' (Python code blocks) are 299 # executed directly when seen. Note that these execute in a 300 # special variable context 'exportContext' to prevent the code 301 # from polluting this script's namespace. 302 def p_global_let(self, t): 303 'global_let : LET CODELIT SEMI' 304 updateExportContext() 305 exportContext["header_output"] = '' 306 exportContext["decoder_output"] = '' 307 exportContext["exec_output"] = '' 308 exportContext["decode_block"] = '' 309 try: 310 exec fixPythonIndentation(t[2]) in exportContext 311 except Exception, exc: 312 error(t.lexer.lineno, 313 'error: %s in global let block "%s".' % (exc, t[2])) 314 t[0] = GenCode(header_output = exportContext["header_output"], 315 decoder_output = exportContext["decoder_output"], 316 exec_output = exportContext["exec_output"], 317 decode_block = exportContext["decode_block"]) |
296 | 318 |
297def p_output_exec(t): 298 'output_exec : OUTPUT EXEC CODELIT SEMI' 299 t[0] = GenCode(exec_output = process_output(t[3])) | 319 # Define the mapping from operand type extensions to C++ types and 320 # bit widths (stored in operandTypeMap). 321 def p_def_operand_types(self, t): 322 'def_operand_types : DEF OPERAND_TYPES CODELIT SEMI' 323 try: 324 userDict = eval('{' + t[3] + '}') 325 except Exception, exc: 326 error(t.lexer.lineno, 327 'error: %s in def operand_types block "%s".' % (exc, t[3])) 328 buildOperandTypeMap(userDict, t.lexer.lineno) 329 t[0] = GenCode() # contributes nothing to the output C++ file |
300 | 330 |
301# global let blocks 'let {{...}}' (Python code blocks) are executed 302# directly when seen. Note that these execute in a special variable 303# context 'exportContext' to prevent the code from polluting this 304# script's namespace. 305def p_global_let(t): 306 'global_let : LET CODELIT SEMI' 307 updateExportContext() 308 exportContext["header_output"] = '' 309 exportContext["decoder_output"] = '' 310 exportContext["exec_output"] = '' 311 exportContext["decode_block"] = '' 312 try: 313 exec fixPythonIndentation(t[2]) in exportContext 314 except Exception, exc: 315 error(t.lexer.lineno, 316 'error: %s in global let block "%s".' % (exc, t[2])) 317 t[0] = GenCode(header_output = exportContext["header_output"], 318 decoder_output = exportContext["decoder_output"], 319 exec_output = exportContext["exec_output"], 320 decode_block = exportContext["decode_block"]) | 331 # Define the mapping from operand names to operand classes and 332 # other traits. Stored in operandNameMap. 333 def p_def_operands(self, t): 334 'def_operands : DEF OPERANDS CODELIT SEMI' 335 if not globals().has_key('operandTypeMap'): 336 error(t.lexer.lineno, 337 'error: operand types must be defined before operands') 338 try: 339 userDict = eval('{' + t[3] + '}', exportContext) 340 except Exception, exc: 341 error(t.lexer.lineno, 342 'error: %s in def operands block "%s".' % (exc, t[3])) 343 buildOperandNameMap(userDict, t.lexer.lineno) 344 t[0] = GenCode() # contributes nothing to the output C++ file |
321 | 345 |
322# Define the mapping from operand type extensions to C++ types and bit 323# widths (stored in operandTypeMap). 324def p_def_operand_types(t): 325 'def_operand_types : DEF OPERAND_TYPES CODELIT SEMI' 326 try: 327 userDict = eval('{' + t[3] + '}') 328 except Exception, exc: 329 error(t.lexer.lineno, 330 'error: %s in def operand_types block "%s".' % (exc, t[3])) 331 buildOperandTypeMap(userDict, t.lexer.lineno) 332 t[0] = GenCode() # contributes nothing to the output C++ file | 346 # A bitfield definition looks like: 347 # 'def [signed] bitfield <ID> [<first>:<last>]' 348 # This generates a preprocessor macro in the output file. 349 def p_def_bitfield_0(self, t): 350 'def_bitfield : DEF opt_signed BITFIELD ID LESS INTLIT COLON INTLIT GREATER SEMI' 351 expr = 'bits(machInst, %2d, %2d)' % (t[6], t[8]) 352 if (t[2] == 'signed'): 353 expr = 'sext<%d>(%s)' % (t[6] - t[8] + 1, expr) 354 hash_define = '#undef %s\n#define %s\t%s\n' % (t[4], t[4], expr) 355 t[0] = GenCode(header_output = hash_define) |
333 | 356 |
334# Define the mapping from operand names to operand classes and other 335# traits. Stored in operandNameMap. 336def p_def_operands(t): 337 'def_operands : DEF OPERANDS CODELIT SEMI' 338 if not globals().has_key('operandTypeMap'): 339 error(t.lexer.lineno, 340 'error: operand types must be defined before operands') 341 try: 342 userDict = eval('{' + t[3] + '}', exportContext) 343 except Exception, exc: 344 error(t.lexer.lineno, 345 'error: %s in def operands block "%s".' % (exc, t[3])) 346 buildOperandNameMap(userDict, t.lexer.lineno) 347 t[0] = GenCode() # contributes nothing to the output C++ file | 357 # alternate form for single bit: 'def [signed] bitfield <ID> [<bit>]' 358 def p_def_bitfield_1(self, t): 359 'def_bitfield : DEF opt_signed BITFIELD ID LESS INTLIT GREATER SEMI' 360 expr = 'bits(machInst, %2d, %2d)' % (t[6], t[6]) 361 if (t[2] == 'signed'): 362 expr = 'sext<%d>(%s)' % (1, expr) 363 hash_define = '#undef %s\n#define %s\t%s\n' % (t[4], t[4], expr) 364 t[0] = GenCode(header_output = hash_define) |
348 | 365 |
349# A bitfield definition looks like: 350# 'def [signed] bitfield <ID> [<first>:<last>]' 351# This generates a preprocessor macro in the output file. 352def p_def_bitfield_0(t): 353 'def_bitfield : DEF opt_signed BITFIELD ID LESS INTLIT COLON INTLIT GREATER SEMI' 354 expr = 'bits(machInst, %2d, %2d)' % (t[6], t[8]) 355 if (t[2] == 'signed'): 356 expr = 'sext<%d>(%s)' % (t[6] - t[8] + 1, expr) 357 hash_define = '#undef %s\n#define %s\t%s\n' % (t[4], t[4], expr) 358 t[0] = GenCode(header_output = hash_define) | 366 # alternate form for structure member: 'def bitfield <ID> <ID>' 367 def p_def_bitfield_struct(self, t): 368 'def_bitfield_struct : DEF opt_signed BITFIELD ID id_with_dot SEMI' 369 if (t[2] != ''): 370 error(t.lexer.lineno, 371 'error: structure bitfields are always unsigned.') 372 expr = 'machInst.%s' % t[5] 373 hash_define = '#undef %s\n#define %s\t%s\n' % (t[4], t[4], expr) 374 t[0] = GenCode(header_output = hash_define) |
359 | 375 |
360# alternate form for single bit: 'def [signed] bitfield <ID> [<bit>]' 361def p_def_bitfield_1(t): 362 'def_bitfield : DEF opt_signed BITFIELD ID LESS INTLIT GREATER SEMI' 363 expr = 'bits(machInst, %2d, %2d)' % (t[6], t[6]) 364 if (t[2] == 'signed'): 365 expr = 'sext<%d>(%s)' % (1, expr) 366 hash_define = '#undef %s\n#define %s\t%s\n' % (t[4], t[4], expr) 367 t[0] = GenCode(header_output = hash_define) | 376 def p_id_with_dot_0(self, t): 377 'id_with_dot : ID' 378 t[0] = t[1] |
368 | 379 |
369# alternate form for structure member: 'def bitfield <ID> <ID>' 370def p_def_bitfield_struct(t): 371 'def_bitfield_struct : DEF opt_signed BITFIELD ID id_with_dot SEMI' 372 if (t[2] != ''): 373 error(t.lexer.lineno, 'error: structure bitfields are always unsigned.') 374 expr = 'machInst.%s' % t[5] 375 hash_define = '#undef %s\n#define %s\t%s\n' % (t[4], t[4], expr) 376 t[0] = GenCode(header_output = hash_define) | 380 def p_id_with_dot_1(self, t): 381 'id_with_dot : ID DOT id_with_dot' 382 t[0] = t[1] + t[2] + t[3] |
377 | 383 |
378def p_id_with_dot_0(t): 379 'id_with_dot : ID' 380 t[0] = t[1] | 384 def p_opt_signed_0(self, t): 385 'opt_signed : SIGNED' 386 t[0] = t[1] |
381 | 387 |
382def p_id_with_dot_1(t): 383 'id_with_dot : ID DOT id_with_dot' 384 t[0] = t[1] + t[2] + t[3] | 388 def p_opt_signed_1(self, t): 389 'opt_signed : empty' 390 t[0] = '' |
385 | 391 |
386def p_opt_signed_0(t): 387 'opt_signed : SIGNED' 388 t[0] = t[1] | 392 def p_def_template(self, t): 393 'def_template : DEF TEMPLATE ID CODELIT SEMI' 394 self.templateMap[t[3]] = Template(t[4]) 395 t[0] = GenCode() |
389 | 396 |
390def p_opt_signed_1(t): 391 'opt_signed : empty' 392 t[0] = '' | 397 # An instruction format definition looks like 398 # "def format <fmt>(<params>) {{...}};" 399 def p_def_format(self, t): 400 'def_format : DEF FORMAT ID LPAREN param_list RPAREN CODELIT SEMI' 401 (id, params, code) = (t[3], t[5], t[7]) 402 defFormat(id, params, code, t.lexer.lineno) 403 t[0] = GenCode() |
393 | 404 |
394# Global map variable to hold templates 395templateMap = {} | 405 # The formal parameter list for an instruction format is a 406 # possibly empty list of comma-separated parameters. Positional 407 # (standard, non-keyword) parameters must come first, followed by 408 # keyword parameters, followed by a '*foo' parameter that gets 409 # excess positional arguments (as in Python). Each of these three 410 # parameter categories is optional. 411 # 412 # Note that we do not support the '**foo' parameter for collecting 413 # otherwise undefined keyword args. Otherwise the parameter list 414 # is (I believe) identical to what is supported in Python. 415 # 416 # The param list generates a tuple, where the first element is a 417 # list of the positional params and the second element is a dict 418 # containing the keyword params. 419 def p_param_list_0(self, t): 420 'param_list : positional_param_list COMMA nonpositional_param_list' 421 t[0] = t[1] + t[3] |
396 | 422 |
397def p_def_template(t): 398 'def_template : DEF TEMPLATE ID CODELIT SEMI' 399 templateMap[t[3]] = Template(t[4]) 400 t[0] = GenCode() | 423 def p_param_list_1(self, t): 424 '''param_list : positional_param_list 425 | nonpositional_param_list''' 426 t[0] = t[1] |
401 | 427 |
402# An instruction format definition looks like 403# "def format <fmt>(<params>) {{...}};" 404def p_def_format(t): 405 'def_format : DEF FORMAT ID LPAREN param_list RPAREN CODELIT SEMI' 406 (id, params, code) = (t[3], t[5], t[7]) 407 defFormat(id, params, code, t.lexer.lineno) 408 t[0] = GenCode() | 428 def p_positional_param_list_0(self, t): 429 'positional_param_list : empty' 430 t[0] = [] |
409 | 431 |
410# The formal parameter list for an instruction format is a possibly 411# empty list of comma-separated parameters. Positional (standard, 412# non-keyword) parameters must come first, followed by keyword 413# parameters, followed by a '*foo' parameter that gets excess 414# positional arguments (as in Python). Each of these three parameter 415# categories is optional. 416# 417# Note that we do not support the '**foo' parameter for collecting 418# otherwise undefined keyword args. Otherwise the parameter list is 419# (I believe) identical to what is supported in Python. 420# 421# The param list generates a tuple, where the first element is a list of 422# the positional params and the second element is a dict containing the 423# keyword params. 424def p_param_list_0(t): 425 'param_list : positional_param_list COMMA nonpositional_param_list' 426 t[0] = t[1] + t[3] | 432 def p_positional_param_list_1(self, t): 433 'positional_param_list : ID' 434 t[0] = [t[1]] |
427 | 435 |
428def p_param_list_1(t): 429 '''param_list : positional_param_list 430 | nonpositional_param_list''' 431 t[0] = t[1] | 436 def p_positional_param_list_2(self, t): 437 'positional_param_list : positional_param_list COMMA ID' 438 t[0] = t[1] + [t[3]] |
432 | 439 |
433def p_positional_param_list_0(t): 434 'positional_param_list : empty' 435 t[0] = [] | 440 def p_nonpositional_param_list_0(self, t): 441 'nonpositional_param_list : keyword_param_list COMMA excess_args_param' 442 t[0] = t[1] + t[3] |
436 | 443 |
437def p_positional_param_list_1(t): 438 'positional_param_list : ID' 439 t[0] = [t[1]] | 444 def p_nonpositional_param_list_1(self, t): 445 '''nonpositional_param_list : keyword_param_list 446 | excess_args_param''' 447 t[0] = t[1] |
440 | 448 |
441def p_positional_param_list_2(t): 442 'positional_param_list : positional_param_list COMMA ID' 443 t[0] = t[1] + [t[3]] | 449 def p_keyword_param_list_0(self, t): 450 'keyword_param_list : keyword_param' 451 t[0] = [t[1]] |
444 | 452 |
445def p_nonpositional_param_list_0(t): 446 'nonpositional_param_list : keyword_param_list COMMA excess_args_param' 447 t[0] = t[1] + t[3] | 453 def p_keyword_param_list_1(self, t): 454 'keyword_param_list : keyword_param_list COMMA keyword_param' 455 t[0] = t[1] + [t[3]] |
448 | 456 |
449def p_nonpositional_param_list_1(t): 450 '''nonpositional_param_list : keyword_param_list 451 | excess_args_param''' 452 t[0] = t[1] | 457 def p_keyword_param(self, t): 458 'keyword_param : ID EQUALS expr' 459 t[0] = t[1] + ' = ' + t[3].__repr__() |
453 | 460 |
454def p_keyword_param_list_0(t): 455 'keyword_param_list : keyword_param' 456 t[0] = [t[1]] | 461 def p_excess_args_param(self, t): 462 'excess_args_param : ASTERISK ID' 463 # Just concatenate them: '*ID'. Wrap in list to be consistent 464 # with positional_param_list and keyword_param_list. 465 t[0] = [t[1] + t[2]] |
457 | 466 |
458def p_keyword_param_list_1(t): 459 'keyword_param_list : keyword_param_list COMMA keyword_param' 460 t[0] = t[1] + [t[3]] | 467 # End of format definition-related rules. 468 ############## |
461 | 469 |
462def p_keyword_param(t): 463 'keyword_param : ID EQUALS expr' 464 t[0] = t[1] + ' = ' + t[3].__repr__() | 470 # 471 # A decode block looks like: 472 # decode <field1> [, <field2>]* [default <inst>] { ... } 473 # 474 def p_decode_block(self, t): 475 'decode_block : DECODE ID opt_default LBRACE decode_stmt_list RBRACE' 476 default_defaults = defaultStack.pop() 477 codeObj = t[5] 478 # use the "default defaults" only if there was no explicit 479 # default statement in decode_stmt_list 480 if not codeObj.has_decode_default: 481 codeObj += default_defaults 482 codeObj.wrap_decode_block('switch (%s) {\n' % t[2], '}\n') 483 t[0] = codeObj |
465 | 484 |
466def p_excess_args_param(t): 467 'excess_args_param : ASTERISK ID' 468 # Just concatenate them: '*ID'. Wrap in list to be consistent 469 # with positional_param_list and keyword_param_list. 470 t[0] = [t[1] + t[2]] | 485 # The opt_default statement serves only to push the "default 486 # defaults" onto defaultStack. This value will be used by nested 487 # decode blocks, and used and popped off when the current 488 # decode_block is processed (in p_decode_block() above). 489 def p_opt_default_0(self, t): 490 'opt_default : empty' 491 # no default specified: reuse the one currently at the top of 492 # the stack 493 defaultStack.push(defaultStack.top()) 494 # no meaningful value returned 495 t[0] = None |
471 | 496 |
472# End of format definition-related rules. 473############## | 497 def p_opt_default_1(self, t): 498 'opt_default : DEFAULT inst' 499 # push the new default 500 codeObj = t[2] 501 codeObj.wrap_decode_block('\ndefault:\n', 'break;\n') 502 defaultStack.push(codeObj) 503 # no meaningful value returned 504 t[0] = None |
474 | 505 |
475# 476# A decode block looks like: 477# decode <field1> [, <field2>]* [default <inst>] { ... } 478# 479def p_decode_block(t): 480 'decode_block : DECODE ID opt_default LBRACE decode_stmt_list RBRACE' 481 default_defaults = defaultStack.pop() 482 codeObj = t[5] 483 # use the "default defaults" only if there was no explicit 484 # default statement in decode_stmt_list 485 if not codeObj.has_decode_default: 486 codeObj += default_defaults 487 codeObj.wrap_decode_block('switch (%s) {\n' % t[2], '}\n') 488 t[0] = codeObj | 506 def p_decode_stmt_list_0(self, t): 507 'decode_stmt_list : decode_stmt' 508 t[0] = t[1] |
489 | 509 |
490# The opt_default statement serves only to push the "default defaults" 491# onto defaultStack. This value will be used by nested decode blocks, 492# and used and popped off when the current decode_block is processed 493# (in p_decode_block() above). 494def p_opt_default_0(t): 495 'opt_default : empty' 496 # no default specified: reuse the one currently at the top of the stack 497 defaultStack.push(defaultStack.top()) 498 # no meaningful value returned 499 t[0] = None | 510 def p_decode_stmt_list_1(self, t): 511 'decode_stmt_list : decode_stmt decode_stmt_list' 512 if (t[1].has_decode_default and t[2].has_decode_default): 513 error(t.lexer.lineno, 'Two default cases in decode block') 514 t[0] = t[1] + t[2] |
500 | 515 |
501def p_opt_default_1(t): 502 'opt_default : DEFAULT inst' 503 # push the new default 504 codeObj = t[2] 505 codeObj.wrap_decode_block('\ndefault:\n', 'break;\n') 506 defaultStack.push(codeObj) 507 # no meaningful value returned 508 t[0] = None | 516 # 517 # Decode statement rules 518 # 519 # There are four types of statements allowed in a decode block: 520 # 1. Format blocks 'format <foo> { ... }' 521 # 2. Nested decode blocks 522 # 3. Instruction definitions. 523 # 4. C preprocessor directives. |
509 | 524 |
510def p_decode_stmt_list_0(t): 511 'decode_stmt_list : decode_stmt' 512 t[0] = t[1] | |
513 | 525 |
514def p_decode_stmt_list_1(t): 515 'decode_stmt_list : decode_stmt decode_stmt_list' 516 if (t[1].has_decode_default and t[2].has_decode_default): 517 error(t.lexer.lineno, 'Two default cases in decode block') 518 t[0] = t[1] + t[2] | 526 # Preprocessor directives found in a decode statement list are 527 # passed through to the output, replicated to all of the output 528 # code streams. This works well for ifdefs, so we can ifdef out 529 # both the declarations and the decode cases generated by an 530 # instruction definition. Handling them as part of the grammar 531 # makes it easy to keep them in the right place with respect to 532 # the code generated by the other statements. 533 def p_decode_stmt_cpp(self, t): 534 'decode_stmt : CPPDIRECTIVE' 535 t[0] = GenCode(t[1], t[1], t[1], t[1]) |
519 | 536 |
520# 521# Decode statement rules 522# 523# There are four types of statements allowed in a decode block: 524# 1. Format blocks 'format <foo> { ... }' 525# 2. Nested decode blocks 526# 3. Instruction definitions. 527# 4. C preprocessor directives. | 537 # A format block 'format <foo> { ... }' sets the default 538 # instruction format used to handle instruction definitions inside 539 # the block. This format can be overridden by using an explicit 540 # format on the instruction definition or with a nested format 541 # block. 542 def p_decode_stmt_format(self, t): 543 'decode_stmt : FORMAT push_format_id LBRACE decode_stmt_list RBRACE' 544 # The format will be pushed on the stack when 'push_format_id' 545 # is processed (see below). Once the parser has recognized 546 # the full production (though the right brace), we're done 547 # with the format, so now we can pop it. 548 formatStack.pop() 549 t[0] = t[4] |
528 | 550 |
551 # This rule exists so we can set the current format (& push the 552 # stack) when we recognize the format name part of the format 553 # block. 554 def p_push_format_id(self, t): 555 'push_format_id : ID' 556 try: 557 formatStack.push(formatMap[t[1]]) 558 t[0] = ('', '// format %s' % t[1]) 559 except KeyError: 560 error(t.lexer.lineno, 561 'instruction format "%s" not defined.' % t[1]) |
|
529 | 562 |
530# Preprocessor directives found in a decode statement list are passed 531# through to the output, replicated to all of the output code 532# streams. This works well for ifdefs, so we can ifdef out both the 533# declarations and the decode cases generated by an instruction 534# definition. Handling them as part of the grammar makes it easy to 535# keep them in the right place with respect to the code generated by 536# the other statements. 537def p_decode_stmt_cpp(t): 538 'decode_stmt : CPPDIRECTIVE' 539 t[0] = GenCode(t[1], t[1], t[1], t[1]) | 563 # Nested decode block: if the value of the current field matches 564 # the specified constant, do a nested decode on some other field. 565 def p_decode_stmt_decode(self, t): 566 'decode_stmt : case_label COLON decode_block' 567 label = t[1] 568 codeObj = t[3] 569 # just wrap the decoding code from the block as a case in the 570 # outer switch statement. 571 codeObj.wrap_decode_block('\n%s:\n' % label) 572 codeObj.has_decode_default = (label == 'default') 573 t[0] = codeObj |
540 | 574 |
541# A format block 'format <foo> { ... }' sets the default instruction 542# format used to handle instruction definitions inside the block. 543# This format can be overridden by using an explicit format on the 544# instruction definition or with a nested format block. 545def p_decode_stmt_format(t): 546 'decode_stmt : FORMAT push_format_id LBRACE decode_stmt_list RBRACE' 547 # The format will be pushed on the stack when 'push_format_id' is 548 # processed (see below). Once the parser has recognized the full 549 # production (though the right brace), we're done with the format, 550 # so now we can pop it. 551 formatStack.pop() 552 t[0] = t[4] | 575 # Instruction definition (finally!). 576 def p_decode_stmt_inst(self, t): 577 'decode_stmt : case_label COLON inst SEMI' 578 label = t[1] 579 codeObj = t[3] 580 codeObj.wrap_decode_block('\n%s:' % label, 'break;\n') 581 codeObj.has_decode_default = (label == 'default') 582 t[0] = codeObj |
553 | 583 |
554# This rule exists so we can set the current format (& push the stack) 555# when we recognize the format name part of the format block. 556def p_push_format_id(t): 557 'push_format_id : ID' 558 try: 559 formatStack.push(formatMap[t[1]]) 560 t[0] = ('', '// format %s' % t[1]) 561 except KeyError: 562 error(t.lexer.lineno, 'instruction format "%s" not defined.' % t[1]) | 584 # The case label is either a list of one or more constants or 585 # 'default' 586 def p_case_label_0(self, t): 587 'case_label : intlit_list' 588 t[0] = ': '.join(map(lambda a: 'case %#x' % a, t[1])) |
563 | 589 |
564# Nested decode block: if the value of the current field matches the 565# specified constant, do a nested decode on some other field. 566def p_decode_stmt_decode(t): 567 'decode_stmt : case_label COLON decode_block' 568 label = t[1] 569 codeObj = t[3] 570 # just wrap the decoding code from the block as a case in the 571 # outer switch statement. 572 codeObj.wrap_decode_block('\n%s:\n' % label) 573 codeObj.has_decode_default = (label == 'default') 574 t[0] = codeObj | 590 def p_case_label_1(self, t): 591 'case_label : DEFAULT' 592 t[0] = 'default' |
575 | 593 |
576# Instruction definition (finally!). 577def p_decode_stmt_inst(t): 578 'decode_stmt : case_label COLON inst SEMI' 579 label = t[1] 580 codeObj = t[3] 581 codeObj.wrap_decode_block('\n%s:' % label, 'break;\n') 582 codeObj.has_decode_default = (label == 'default') 583 t[0] = codeObj | 594 # 595 # The constant list for a decode case label must be non-empty, but 596 # may have one or more comma-separated integer literals in it. 597 # 598 def p_intlit_list_0(self, t): 599 'intlit_list : INTLIT' 600 t[0] = [t[1]] |
584 | 601 |
585# The case label is either a list of one or more constants or 'default' 586def p_case_label_0(t): 587 'case_label : intlit_list' 588 t[0] = ': '.join(map(lambda a: 'case %#x' % a, t[1])) | 602 def p_intlit_list_1(self, t): 603 'intlit_list : intlit_list COMMA INTLIT' 604 t[0] = t[1] 605 t[0].append(t[3]) |
589 | 606 |
590def p_case_label_1(t): 591 'case_label : DEFAULT' 592 t[0] = 'default' | 607 # Define an instruction using the current instruction format 608 # (specified by an enclosing format block). 609 # "<mnemonic>(<args>)" 610 def p_inst_0(self, t): 611 'inst : ID LPAREN arg_list RPAREN' 612 # Pass the ID and arg list to the current format class to deal with. 613 currentFormat = formatStack.top() 614 codeObj = currentFormat.defineInst(t[1], t[3], t.lexer.lineno) 615 args = ','.join(map(str, t[3])) 616 args = re.sub('(?m)^', '//', args) 617 args = re.sub('^//', '', args) 618 comment = '\n// %s::%s(%s)\n' % (currentFormat.id, t[1], args) 619 codeObj.prepend_all(comment) 620 t[0] = codeObj |
593 | 621 |
594# 595# The constant list for a decode case label must be non-empty, but may have 596# one or more comma-separated integer literals in it. 597# 598def p_intlit_list_0(t): 599 'intlit_list : INTLIT' 600 t[0] = [t[1]] | 622 # Define an instruction using an explicitly specified format: 623 # "<fmt>::<mnemonic>(<args>)" 624 def p_inst_1(self, t): 625 'inst : ID DBLCOLON ID LPAREN arg_list RPAREN' 626 try: 627 format = formatMap[t[1]] 628 except KeyError: 629 error(t.lexer.lineno, 630 'instruction format "%s" not defined.' % t[1]) 631 codeObj = format.defineInst(t[3], t[5], t.lexer.lineno) 632 comment = '\n// %s::%s(%s)\n' % (t[1], t[3], t[5]) 633 codeObj.prepend_all(comment) 634 t[0] = codeObj |
601 | 635 |
602def p_intlit_list_1(t): 603 'intlit_list : intlit_list COMMA INTLIT' 604 t[0] = t[1] 605 t[0].append(t[3]) | 636 # The arg list generates a tuple, where the first element is a 637 # list of the positional args and the second element is a dict 638 # containing the keyword args. 639 def p_arg_list_0(self, t): 640 'arg_list : positional_arg_list COMMA keyword_arg_list' 641 t[0] = ( t[1], t[3] ) |
606 | 642 |
607# Define an instruction using the current instruction format (specified 608# by an enclosing format block). 609# "<mnemonic>(<args>)" 610def p_inst_0(t): 611 'inst : ID LPAREN arg_list RPAREN' 612 # Pass the ID and arg list to the current format class to deal with. 613 currentFormat = formatStack.top() 614 codeObj = currentFormat.defineInst(t[1], t[3], t.lexer.lineno) 615 args = ','.join(map(str, t[3])) 616 args = re.sub('(?m)^', '//', args) 617 args = re.sub('^//', '', args) 618 comment = '\n// %s::%s(%s)\n' % (currentFormat.id, t[1], args) 619 codeObj.prepend_all(comment) 620 t[0] = codeObj | 643 def p_arg_list_1(self, t): 644 'arg_list : positional_arg_list' 645 t[0] = ( t[1], {} ) |
621 | 646 |
622# Define an instruction using an explicitly specified format: 623# "<fmt>::<mnemonic>(<args>)" 624def p_inst_1(t): 625 'inst : ID DBLCOLON ID LPAREN arg_list RPAREN' 626 try: 627 format = formatMap[t[1]] 628 except KeyError: 629 error(t.lexer.lineno, 'instruction format "%s" not defined.' % t[1]) 630 codeObj = format.defineInst(t[3], t[5], t.lexer.lineno) 631 comment = '\n// %s::%s(%s)\n' % (t[1], t[3], t[5]) 632 codeObj.prepend_all(comment) 633 t[0] = codeObj | 647 def p_arg_list_2(self, t): 648 'arg_list : keyword_arg_list' 649 t[0] = ( [], t[1] ) |
634 | 650 |
635# The arg list generates a tuple, where the first element is a list of 636# the positional args and the second element is a dict containing the 637# keyword args. 638def p_arg_list_0(t): 639 'arg_list : positional_arg_list COMMA keyword_arg_list' 640 t[0] = ( t[1], t[3] ) | 651 def p_positional_arg_list_0(self, t): 652 'positional_arg_list : empty' 653 t[0] = [] |
641 | 654 |
642def p_arg_list_1(t): 643 'arg_list : positional_arg_list' 644 t[0] = ( t[1], {} ) | 655 def p_positional_arg_list_1(self, t): 656 'positional_arg_list : expr' 657 t[0] = [t[1]] |
645 | 658 |
646def p_arg_list_2(t): 647 'arg_list : keyword_arg_list' 648 t[0] = ( [], t[1] ) | 659 def p_positional_arg_list_2(self, t): 660 'positional_arg_list : positional_arg_list COMMA expr' 661 t[0] = t[1] + [t[3]] |
649 | 662 |
650def p_positional_arg_list_0(t): 651 'positional_arg_list : empty' 652 t[0] = [] | 663 def p_keyword_arg_list_0(self, t): 664 'keyword_arg_list : keyword_arg' 665 t[0] = t[1] |
653 | 666 |
654def p_positional_arg_list_1(t): 655 'positional_arg_list : expr' 656 t[0] = [t[1]] | 667 def p_keyword_arg_list_1(self, t): 668 'keyword_arg_list : keyword_arg_list COMMA keyword_arg' 669 t[0] = t[1] 670 t[0].update(t[3]) |
657 | 671 |
658def p_positional_arg_list_2(t): 659 'positional_arg_list : positional_arg_list COMMA expr' 660 t[0] = t[1] + [t[3]] | 672 def p_keyword_arg(self, t): 673 'keyword_arg : ID EQUALS expr' 674 t[0] = { t[1] : t[3] } |
661 | 675 |
662def p_keyword_arg_list_0(t): 663 'keyword_arg_list : keyword_arg' 664 t[0] = t[1] | 676 # 677 # Basic expressions. These constitute the argument values of 678 # "function calls" (i.e. instruction definitions in the decode 679 # block) and default values for formal parameters of format 680 # functions. 681 # 682 # Right now, these are either strings, integers, or (recursively) 683 # lists of exprs (using Python square-bracket list syntax). Note 684 # that bare identifiers are trated as string constants here (since 685 # there isn't really a variable namespace to refer to). 686 # 687 def p_expr_0(self, t): 688 '''expr : ID 689 | INTLIT 690 | STRLIT 691 | CODELIT''' 692 t[0] = t[1] |
665 | 693 |
666def p_keyword_arg_list_1(t): 667 'keyword_arg_list : keyword_arg_list COMMA keyword_arg' 668 t[0] = t[1] 669 t[0].update(t[3]) | 694 def p_expr_1(self, t): 695 '''expr : LBRACKET list_expr RBRACKET''' 696 t[0] = t[2] |
670 | 697 |
671def p_keyword_arg(t): 672 'keyword_arg : ID EQUALS expr' 673 t[0] = { t[1] : t[3] } | 698 def p_list_expr_0(self, t): 699 'list_expr : expr' 700 t[0] = [t[1]] |
674 | 701 |
675# 676# Basic expressions. These constitute the argument values of 677# "function calls" (i.e. instruction definitions in the decode block) 678# and default values for formal parameters of format functions. 679# 680# Right now, these are either strings, integers, or (recursively) 681# lists of exprs (using Python square-bracket list syntax). Note that 682# bare identifiers are trated as string constants here (since there 683# isn't really a variable namespace to refer to). 684# 685def p_expr_0(t): 686 '''expr : ID 687 | INTLIT 688 | STRLIT 689 | CODELIT''' 690 t[0] = t[1] | 702 def p_list_expr_1(self, t): 703 'list_expr : list_expr COMMA expr' 704 t[0] = t[1] + [t[3]] |
691 | 705 |
692def p_expr_1(t): 693 '''expr : LBRACKET list_expr RBRACKET''' 694 t[0] = t[2] | 706 def p_list_expr_2(self, t): 707 'list_expr : empty' 708 t[0] = [] |
695 | 709 |
696def p_list_expr_0(t): 697 'list_expr : expr' 698 t[0] = [t[1]] | 710 # 711 # Empty production... use in other rules for readability. 712 # 713 def p_empty(self, t): 714 'empty :' 715 pass |
699 | 716 |
700def p_list_expr_1(t): 701 'list_expr : list_expr COMMA expr' 702 t[0] = t[1] + [t[3]] | 717 # Parse error handler. Note that the argument here is the 718 # offending *token*, not a grammar symbol (hence the need to use 719 # t.value) 720 def p_error(self, t): 721 if t: 722 error(t.lexer.lineno, "syntax error at '%s'" % t.value) 723 else: 724 error(0, "unknown syntax error", True) |
703 | 725 |
704def p_list_expr_2(t): 705 'list_expr : empty' 706 t[0] = [] | 726 # END OF GRAMMAR RULES |
707 | 727 |
708# 709# Empty production... use in other rules for readability. 710# 711def p_empty(t): 712 'empty :' 713 pass 714 715# Parse error handler. Note that the argument here is the offending 716# *token*, not a grammar symbol (hence the need to use t.value) 717def p_error(t): 718 if t: 719 error(t.lexer.lineno, "syntax error at '%s'" % t.value) 720 else: 721 error(0, "unknown syntax error", True) 722 723# END OF GRAMMAR RULES 724# | |
725# Now build the parser. | 728# Now build the parser. |
726parser = yacc.yacc() | 729parser = ISAParser() |
727 | 730 |
728 | |
729##################################################################### 730# 731# Support Classes 732# 733##################################################################### 734 735# Expand template with CPU-specific references into a dictionary with 736# an entry for each CPU model name. The entry key is the model name --- 19 unchanged lines hidden (view full) --- 756 return template 757 758# Protect CPU-specific references by doubling the corresponding '%'s 759# (in preparation for substituting a different set of references into 760# the template). 761def protect_cpu_symbols(template): 762 return re.sub(r'%(?=\(CPU_)', '%%', template) 763 | 731##################################################################### 732# 733# Support Classes 734# 735##################################################################### 736 737# Expand template with CPU-specific references into a dictionary with 738# an entry for each CPU model name. The entry key is the model name --- 19 unchanged lines hidden (view full) --- 758 return template 759 760# Protect CPU-specific references by doubling the corresponding '%'s 761# (in preparation for substituting a different set of references into 762# the template). 763def protect_cpu_symbols(template): 764 return re.sub(r'%(?=\(CPU_)', '%%', template) 765 |
766# Protect any non-dict-substitution '%'s in a format string 767# (i.e. those not followed by '(') 768def protect_non_subst_percents(s): 769 return re.sub(r'%(?!\()', '%%', s) 770 |
|
764############### 765# GenCode class 766# 767# The GenCode class encapsulates generated code destined for various 768# output files. The header_output and decoder_output attributes are 769# strings containing code destined for decoder.hh and decoder.cc 770# respectively. The decode_block attribute contains code to be 771# incorporated in the decode function itself (that will also end up in --- 57 unchanged lines hidden (view full) --- 829# definition. 830 831exportContextSymbols = ('InstObjParams', 'makeList', 're', 'string') 832 833exportContext = {} 834 835def updateExportContext(): 836 exportContext.update(exportDict(*exportContextSymbols)) | 771############### 772# GenCode class 773# 774# The GenCode class encapsulates generated code destined for various 775# output files. The header_output and decoder_output attributes are 776# strings containing code destined for decoder.hh and decoder.cc 777# respectively. The decode_block attribute contains code to be 778# incorporated in the decode function itself (that will also end up in --- 57 unchanged lines hidden (view full) --- 836# definition. 837 838exportContextSymbols = ('InstObjParams', 'makeList', 're', 'string') 839 840exportContext = {} 841 842def updateExportContext(): 843 exportContext.update(exportDict(*exportContextSymbols)) |
837 exportContext.update(templateMap) | 844 exportContext.update(parser.templateMap) |
838 839def exportDict(*symNames): 840 return dict([(s, eval(s)) for s in symNames]) 841 842 843class Format: 844 def __init__(self, id, params, code): 845 # constructor: just save away arguments --- 193 unchanged lines hidden (view full) --- 1039 # in the templated C++ code) 1040 template = protect_non_subst_percents(self.template) 1041 # CPU-model-specific substitutions are handled later (in GenCode). 1042 template = protect_cpu_symbols(template) 1043 1044 # Build a dict ('myDict') to use for the template substitution. 1045 # Start with the template namespace. Make a copy since we're 1046 # going to modify it. | 845 846def exportDict(*symNames): 847 return dict([(s, eval(s)) for s in symNames]) 848 849 850class Format: 851 def __init__(self, id, params, code): 852 # constructor: just save away arguments --- 193 unchanged lines hidden (view full) --- 1046 # in the templated C++ code) 1047 template = protect_non_subst_percents(self.template) 1048 # CPU-model-specific substitutions are handled later (in GenCode). 1049 template = protect_cpu_symbols(template) 1050 1051 # Build a dict ('myDict') to use for the template substitution. 1052 # Start with the template namespace. Make a copy since we're 1053 # going to modify it. |
1047 myDict = templateMap.copy() | 1054 myDict = parser.templateMap.copy() |
1048 1049 if isinstance(d, InstObjParams): 1050 # If we're dealing with an InstObjParams object, we need 1051 # to be a little more sophisticated. The instruction-wide 1052 # parameters are already formed, but the parameters which 1053 # are only function wide still need to be generated. 1054 compositeCode = '' 1055 --- 909 unchanged lines hidden (view full) --- 1965 # PLY requires that the input be in a single string so we have to 1966 # do this up front. 1967 isa_desc = read_and_flatten(isa_desc_file) 1968 1969 # Initialize filename stack with outer file. 1970 fileNameStack.push((isa_desc_file, 0)) 1971 1972 # Parse it. | 1055 1056 if isinstance(d, InstObjParams): 1057 # If we're dealing with an InstObjParams object, we need 1058 # to be a little more sophisticated. The instruction-wide 1059 # parameters are already formed, but the parameters which 1060 # are only function wide still need to be generated. 1061 compositeCode = '' 1062 --- 909 unchanged lines hidden (view full) --- 1972 # PLY requires that the input be in a single string so we have to 1973 # do this up front. 1974 isa_desc = read_and_flatten(isa_desc_file) 1975 1976 # Initialize filename stack with outer file. 1977 fileNameStack.push((isa_desc_file, 0)) 1978 1979 # Parse it. |
1973 (isa_name, namespace, global_code, namespace_code) = \ 1974 parser.parse(isa_desc, lexer=lexer) | 1980 (isa_name, namespace, global_code, namespace_code) = parser.parse(isa_desc) |
1975 1976 # grab the last three path components of isa_desc_file to put in 1977 # the output 1978 filename = '/'.join(isa_desc_file.split('/')[-3:]) 1979 1980 # generate decoder.hh 1981 includes = '#include "base/bitfield.hh" // for bitfield support' 1982 global_output = global_code.header_output --- 41 unchanged lines hidden --- | 1981 1982 # grab the last three path components of isa_desc_file to put in 1983 # the output 1984 filename = '/'.join(isa_desc_file.split('/')[-3:]) 1985 1986 # generate decoder.hh 1987 includes = '#include "base/bitfield.hh" // for bitfield support' 1988 global_output = global_code.header_output --- 41 unchanged lines hidden --- |