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 {{...}}' (C++ code blocks) are copied
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 ---