PageRenderTime 68ms CodeModel.GetById 29ms RepoModel.GetById 0ms app.codeStats 0ms

/src/arch/isa_parser.py

https://bitbucket.org/musleh123/ece565
Python | 2134 lines | 1906 code | 61 blank | 167 comment | 25 complexity | deaee43123c658f3ec074c09f35813f1 MD5 | raw file
Possible License(s): BSD-3-Clause, LGPL-2.1, WTFPL

Large files files are truncated, but you can click here to view the full file

  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
  9. # notice, this list of conditions and the following disclaimer in the
  10. # documentation and/or other materials provided with the distribution;
  11. # neither the name of the copyright holders nor the names of its
  12. # contributors may be used to endorse or promote products derived from
  13. # this software without specific prior written permission.
  14. #
  15. # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  16. # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  17. # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  18. # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  19. # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  20. # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  21. # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  22. # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  23. # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  24. # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  25. # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  26. #
  27. # Authors: Steve Reinhardt
  28. import os
  29. import sys
  30. import re
  31. import string
  32. import inspect, traceback
  33. # get type names
  34. from types import *
  35. from m5.util.grammar import Grammar
  36. debug=False
  37. ###################
  38. # Utility functions
  39. #
  40. # Indent every line in string 's' by two spaces
  41. # (except preprocessor directives).
  42. # Used to make nested code blocks look pretty.
  43. #
  44. def indent(s):
  45. return re.sub(r'(?m)^(?!#)', ' ', s)
  46. #
  47. # Munge a somewhat arbitrarily formatted piece of Python code
  48. # (e.g. from a format 'let' block) into something whose indentation
  49. # will get by the Python parser.
  50. #
  51. # The two keys here are that Python will give a syntax error if
  52. # there's any whitespace at the beginning of the first line, and that
  53. # all lines at the same lexical nesting level must have identical
  54. # indentation. Unfortunately the way code literals work, an entire
  55. # let block tends to have some initial indentation. Rather than
  56. # trying to figure out what that is and strip it off, we prepend 'if
  57. # 1:' to make the let code the nested block inside the if (and have
  58. # the parser automatically deal with the indentation for us).
  59. #
  60. # We don't want to do this if (1) the code block is empty or (2) the
  61. # first line of the block doesn't have any whitespace at the front.
  62. def fixPythonIndentation(s):
  63. # get rid of blank lines first
  64. s = re.sub(r'(?m)^\s*\n', '', s);
  65. if (s != '' and re.match(r'[ \t]', s[0])):
  66. s = 'if 1:\n' + s
  67. return s
  68. class ISAParserError(Exception):
  69. """Error handler for parser errors"""
  70. def __init__(self, first, second=None):
  71. if second is None:
  72. self.lineno = 0
  73. self.string = first
  74. else:
  75. if hasattr(first, 'lexer'):
  76. first = first.lexer.lineno
  77. self.lineno = first
  78. self.string = second
  79. def display(self, filename_stack, print_traceback=debug):
  80. # Output formatted to work under Emacs compile-mode. Optional
  81. # 'print_traceback' arg, if set to True, prints a Python stack
  82. # backtrace too (can be handy when trying to debug the parser
  83. # itself).
  84. spaces = ""
  85. for (filename, line) in filename_stack[:-1]:
  86. print "%sIn file included from %s:" % (spaces, filename)
  87. spaces += " "
  88. # Print a Python stack backtrace if requested.
  89. if print_traceback or not self.lineno:
  90. traceback.print_exc()
  91. line_str = "%s:" % (filename_stack[-1][0], )
  92. if self.lineno:
  93. line_str += "%d:" % (self.lineno, )
  94. return "%s%s %s" % (spaces, line_str, self.string)
  95. def exit(self, filename_stack, print_traceback=debug):
  96. # Just call exit.
  97. sys.exit(self.display(filename_stack, print_traceback))
  98. def error(*args):
  99. raise ISAParserError(*args)
  100. ####################
  101. # Template objects.
  102. #
  103. # Template objects are format strings that allow substitution from
  104. # the attribute spaces of other objects (e.g. InstObjParams instances).
  105. labelRE = re.compile(r'(?<!%)%\(([^\)]+)\)[sd]')
  106. class Template(object):
  107. def __init__(self, parser, t):
  108. self.parser = parser
  109. self.template = t
  110. def subst(self, d):
  111. myDict = None
  112. # Protect non-Python-dict substitutions (e.g. if there's a printf
  113. # in the templated C++ code)
  114. template = self.parser.protectNonSubstPercents(self.template)
  115. # CPU-model-specific substitutions are handled later (in GenCode).
  116. template = self.parser.protectCpuSymbols(template)
  117. # Build a dict ('myDict') to use for the template substitution.
  118. # Start with the template namespace. Make a copy since we're
  119. # going to modify it.
  120. myDict = self.parser.templateMap.copy()
  121. if isinstance(d, InstObjParams):
  122. # If we're dealing with an InstObjParams object, we need
  123. # to be a little more sophisticated. The instruction-wide
  124. # parameters are already formed, but the parameters which
  125. # are only function wide still need to be generated.
  126. compositeCode = ''
  127. myDict.update(d.__dict__)
  128. # The "operands" and "snippets" attributes of the InstObjParams
  129. # objects are for internal use and not substitution.
  130. del myDict['operands']
  131. del myDict['snippets']
  132. snippetLabels = [l for l in labelRE.findall(template)
  133. if d.snippets.has_key(l)]
  134. snippets = dict([(s, self.parser.mungeSnippet(d.snippets[s]))
  135. for s in snippetLabels])
  136. myDict.update(snippets)
  137. compositeCode = ' '.join(map(str, snippets.values()))
  138. # Add in template itself in case it references any
  139. # operands explicitly (like Mem)
  140. compositeCode += ' ' + template
  141. operands = SubOperandList(self.parser, compositeCode, d.operands)
  142. myDict['op_decl'] = operands.concatAttrStrings('op_decl')
  143. if operands.readPC or operands.setPC:
  144. myDict['op_decl'] += 'TheISA::PCState __parserAutoPCState;\n'
  145. # In case there are predicated register reads and write, declare
  146. # the variables for register indicies. It is being assumed that
  147. # all the operands in the OperandList are also in the
  148. # SubOperandList and in the same order. Otherwise, it is
  149. # expected that predication would not be used for the operands.
  150. if operands.predRead:
  151. myDict['op_decl'] += 'uint8_t _sourceIndex = 0;\n'
  152. if operands.predWrite:
  153. myDict['op_decl'] += 'uint8_t M5_VAR_USED _destIndex = 0;\n'
  154. is_src = lambda op: op.is_src
  155. is_dest = lambda op: op.is_dest
  156. myDict['op_src_decl'] = \
  157. operands.concatSomeAttrStrings(is_src, 'op_src_decl')
  158. myDict['op_dest_decl'] = \
  159. operands.concatSomeAttrStrings(is_dest, 'op_dest_decl')
  160. if operands.readPC:
  161. myDict['op_src_decl'] += \
  162. 'TheISA::PCState __parserAutoPCState;\n'
  163. if operands.setPC:
  164. myDict['op_dest_decl'] += \
  165. 'TheISA::PCState __parserAutoPCState;\n'
  166. myDict['op_rd'] = operands.concatAttrStrings('op_rd')
  167. if operands.readPC:
  168. myDict['op_rd'] = '__parserAutoPCState = xc->pcState();\n' + \
  169. myDict['op_rd']
  170. # Compose the op_wb string. If we're going to write back the
  171. # PC state because we changed some of its elements, we'll need to
  172. # do that as early as possible. That allows later uncoordinated
  173. # modifications to the PC to layer appropriately.
  174. reordered = list(operands.items)
  175. reordered.reverse()
  176. op_wb_str = ''
  177. pcWbStr = 'xc->pcState(__parserAutoPCState);\n'
  178. for op_desc in reordered:
  179. if op_desc.isPCPart() and op_desc.is_dest:
  180. op_wb_str = op_desc.op_wb + pcWbStr + op_wb_str
  181. pcWbStr = ''
  182. else:
  183. op_wb_str = op_desc.op_wb + op_wb_str
  184. myDict['op_wb'] = op_wb_str
  185. elif isinstance(d, dict):
  186. # if the argument is a dictionary, we just use it.
  187. myDict.update(d)
  188. elif hasattr(d, '__dict__'):
  189. # if the argument is an object, we use its attribute map.
  190. myDict.update(d.__dict__)
  191. else:
  192. raise TypeError, "Template.subst() arg must be or have dictionary"
  193. return template % myDict
  194. # Convert to string. This handles the case when a template with a
  195. # CPU-specific term gets interpolated into another template or into
  196. # an output block.
  197. def __str__(self):
  198. return self.parser.expandCpuSymbolsToString(self.template)
  199. ################
  200. # Format object.
  201. #
  202. # A format object encapsulates an instruction format. It must provide
  203. # a defineInst() method that generates the code for an instruction
  204. # definition.
  205. class Format(object):
  206. def __init__(self, id, params, code):
  207. self.id = id
  208. self.params = params
  209. label = 'def format ' + id
  210. self.user_code = compile(fixPythonIndentation(code), label, 'exec')
  211. param_list = string.join(params, ", ")
  212. f = '''def defInst(_code, _context, %s):
  213. my_locals = vars().copy()
  214. exec _code in _context, my_locals
  215. return my_locals\n''' % param_list
  216. c = compile(f, label + ' wrapper', 'exec')
  217. exec c
  218. self.func = defInst
  219. def defineInst(self, parser, name, args, lineno):
  220. parser.updateExportContext()
  221. context = parser.exportContext.copy()
  222. if len(name):
  223. Name = name[0].upper()
  224. if len(name) > 1:
  225. Name += name[1:]
  226. context.update({ 'name' : name, 'Name' : Name })
  227. try:
  228. vars = self.func(self.user_code, context, *args[0], **args[1])
  229. except Exception, exc:
  230. if debug:
  231. raise
  232. error(lineno, 'error defining "%s": %s.' % (name, exc))
  233. for k in vars.keys():
  234. if k not in ('header_output', 'decoder_output',
  235. 'exec_output', 'decode_block'):
  236. del vars[k]
  237. return GenCode(parser, **vars)
  238. # Special null format to catch an implicit-format instruction
  239. # definition outside of any format block.
  240. class NoFormat(object):
  241. def __init__(self):
  242. self.defaultInst = ''
  243. def defineInst(self, parser, name, args, lineno):
  244. error(lineno,
  245. 'instruction definition "%s" with no active format!' % name)
  246. ###############
  247. # GenCode class
  248. #
  249. # The GenCode class encapsulates generated code destined for various
  250. # output files. The header_output and decoder_output attributes are
  251. # strings containing code destined for decoder.hh and decoder.cc
  252. # respectively. The decode_block attribute contains code to be
  253. # incorporated in the decode function itself (that will also end up in
  254. # decoder.cc). The exec_output attribute is a dictionary with a key
  255. # for each CPU model name; the value associated with a particular key
  256. # is the string of code for that CPU model's exec.cc file. The
  257. # has_decode_default attribute is used in the decode block to allow
  258. # explicit default clauses to override default default clauses.
  259. class GenCode(object):
  260. # Constructor. At this point we substitute out all CPU-specific
  261. # symbols. For the exec output, these go into the per-model
  262. # dictionary. For all other output types they get collapsed into
  263. # a single string.
  264. def __init__(self, parser,
  265. header_output = '', decoder_output = '', exec_output = '',
  266. decode_block = '', has_decode_default = False):
  267. self.parser = parser
  268. self.header_output = parser.expandCpuSymbolsToString(header_output)
  269. self.decoder_output = parser.expandCpuSymbolsToString(decoder_output)
  270. if isinstance(exec_output, dict):
  271. self.exec_output = exec_output
  272. elif isinstance(exec_output, str):
  273. # If the exec_output arg is a single string, we replicate
  274. # it for each of the CPU models, substituting and
  275. # %(CPU_foo)s params appropriately.
  276. self.exec_output = parser.expandCpuSymbolsToDict(exec_output)
  277. self.decode_block = parser.expandCpuSymbolsToString(decode_block)
  278. self.has_decode_default = has_decode_default
  279. # Override '+' operator: generate a new GenCode object that
  280. # concatenates all the individual strings in the operands.
  281. def __add__(self, other):
  282. exec_output = {}
  283. for cpu in self.parser.cpuModels:
  284. n = cpu.name
  285. exec_output[n] = self.exec_output[n] + other.exec_output[n]
  286. return GenCode(self.parser,
  287. self.header_output + other.header_output,
  288. self.decoder_output + other.decoder_output,
  289. exec_output,
  290. self.decode_block + other.decode_block,
  291. self.has_decode_default or other.has_decode_default)
  292. # Prepend a string (typically a comment) to all the strings.
  293. def prepend_all(self, pre):
  294. self.header_output = pre + self.header_output
  295. self.decoder_output = pre + self.decoder_output
  296. self.decode_block = pre + self.decode_block
  297. for cpu in self.parser.cpuModels:
  298. self.exec_output[cpu.name] = pre + self.exec_output[cpu.name]
  299. # Wrap the decode block in a pair of strings (e.g., 'case foo:'
  300. # and 'break;'). Used to build the big nested switch statement.
  301. def wrap_decode_block(self, pre, post = ''):
  302. self.decode_block = pre + indent(self.decode_block) + post
  303. #####################################################################
  304. #
  305. # Bitfield Operator Support
  306. #
  307. #####################################################################
  308. bitOp1ArgRE = re.compile(r'<\s*(\w+)\s*:\s*>')
  309. bitOpWordRE = re.compile(r'(?<![\w\.])([\w\.]+)<\s*(\w+)\s*:\s*(\w+)\s*>')
  310. bitOpExprRE = re.compile(r'\)<\s*(\w+)\s*:\s*(\w+)\s*>')
  311. def substBitOps(code):
  312. # first convert single-bit selectors to two-index form
  313. # i.e., <n> --> <n:n>
  314. code = bitOp1ArgRE.sub(r'<\1:\1>', code)
  315. # simple case: selector applied to ID (name)
  316. # i.e., foo<a:b> --> bits(foo, a, b)
  317. code = bitOpWordRE.sub(r'bits(\1, \2, \3)', code)
  318. # if selector is applied to expression (ending in ')'),
  319. # we need to search backward for matching '('
  320. match = bitOpExprRE.search(code)
  321. while match:
  322. exprEnd = match.start()
  323. here = exprEnd - 1
  324. nestLevel = 1
  325. while nestLevel > 0:
  326. if code[here] == '(':
  327. nestLevel -= 1
  328. elif code[here] == ')':
  329. nestLevel += 1
  330. here -= 1
  331. if here < 0:
  332. sys.exit("Didn't find '('!")
  333. exprStart = here+1
  334. newExpr = r'bits(%s, %s, %s)' % (code[exprStart:exprEnd+1],
  335. match.group(1), match.group(2))
  336. code = code[:exprStart] + newExpr + code[match.end():]
  337. match = bitOpExprRE.search(code)
  338. return code
  339. #####################################################################
  340. #
  341. # Code Parser
  342. #
  343. # The remaining code is the support for automatically extracting
  344. # instruction characteristics from pseudocode.
  345. #
  346. #####################################################################
  347. # Force the argument to be a list. Useful for flags, where a caller
  348. # can specify a singleton flag or a list of flags. Also usful for
  349. # converting tuples to lists so they can be modified.
  350. def makeList(arg):
  351. if isinstance(arg, list):
  352. return arg
  353. elif isinstance(arg, tuple):
  354. return list(arg)
  355. elif not arg:
  356. return []
  357. else:
  358. return [ arg ]
  359. class Operand(object):
  360. '''Base class for operand descriptors. An instance of this class
  361. (or actually a class derived from this one) represents a specific
  362. operand for a code block (e.g, "Rc.sq" as a dest). Intermediate
  363. derived classes encapsulates the traits of a particular operand
  364. type (e.g., "32-bit integer register").'''
  365. def buildReadCode(self, func = None):
  366. subst_dict = {"name": self.base_name,
  367. "func": func,
  368. "reg_idx": self.reg_spec,
  369. "ctype": self.ctype}
  370. if hasattr(self, 'src_reg_idx'):
  371. subst_dict['op_idx'] = self.src_reg_idx
  372. code = self.read_code % subst_dict
  373. return '%s = %s;\n' % (self.base_name, code)
  374. def buildWriteCode(self, func = None):
  375. subst_dict = {"name": self.base_name,
  376. "func": func,
  377. "reg_idx": self.reg_spec,
  378. "ctype": self.ctype,
  379. "final_val": self.base_name}
  380. if hasattr(self, 'dest_reg_idx'):
  381. subst_dict['op_idx'] = self.dest_reg_idx
  382. code = self.write_code % subst_dict
  383. return '''
  384. {
  385. %s final_val = %s;
  386. %s;
  387. if (traceData) { traceData->setData(final_val); }
  388. }''' % (self.dflt_ctype, self.base_name, code)
  389. def __init__(self, parser, full_name, ext, is_src, is_dest):
  390. self.full_name = full_name
  391. self.ext = ext
  392. self.is_src = is_src
  393. self.is_dest = is_dest
  394. # The 'effective extension' (eff_ext) is either the actual
  395. # extension, if one was explicitly provided, or the default.
  396. if ext:
  397. self.eff_ext = ext
  398. elif hasattr(self, 'dflt_ext'):
  399. self.eff_ext = self.dflt_ext
  400. if hasattr(self, 'eff_ext'):
  401. self.ctype = parser.operandTypeMap[self.eff_ext]
  402. # Finalize additional fields (primarily code fields). This step
  403. # is done separately since some of these fields may depend on the
  404. # register index enumeration that hasn't been performed yet at the
  405. # time of __init__(). The register index enumeration is affected
  406. # by predicated register reads/writes. Hence, we forward the flags
  407. # that indicate whether or not predication is in use.
  408. def finalize(self, predRead, predWrite):
  409. self.flags = self.getFlags()
  410. self.constructor = self.makeConstructor(predRead, predWrite)
  411. self.op_decl = self.makeDecl()
  412. if self.is_src:
  413. self.op_rd = self.makeRead(predRead)
  414. self.op_src_decl = self.makeDecl()
  415. else:
  416. self.op_rd = ''
  417. self.op_src_decl = ''
  418. if self.is_dest:
  419. self.op_wb = self.makeWrite(predWrite)
  420. self.op_dest_decl = self.makeDecl()
  421. else:
  422. self.op_wb = ''
  423. self.op_dest_decl = ''
  424. def isMem(self):
  425. return 0
  426. def isReg(self):
  427. return 0
  428. def isFloatReg(self):
  429. return 0
  430. def isIntReg(self):
  431. return 0
  432. def isControlReg(self):
  433. return 0
  434. def isPCState(self):
  435. return 0
  436. def isPCPart(self):
  437. return self.isPCState() and self.reg_spec
  438. def hasReadPred(self):
  439. return self.read_predicate != None
  440. def hasWritePred(self):
  441. return self.write_predicate != None
  442. def getFlags(self):
  443. # note the empty slice '[:]' gives us a copy of self.flags[0]
  444. # instead of a reference to it
  445. my_flags = self.flags[0][:]
  446. if self.is_src:
  447. my_flags += self.flags[1]
  448. if self.is_dest:
  449. my_flags += self.flags[2]
  450. return my_flags
  451. def makeDecl(self):
  452. # Note that initializations in the declarations are solely
  453. # to avoid 'uninitialized variable' errors from the compiler.
  454. return self.ctype + ' ' + self.base_name + ' = 0;\n';
  455. class IntRegOperand(Operand):
  456. def isReg(self):
  457. return 1
  458. def isIntReg(self):
  459. return 1
  460. def makeConstructor(self, predRead, predWrite):
  461. c_src = ''
  462. c_dest = ''
  463. if self.is_src:
  464. c_src = '\n\t_srcRegIdx[_numSrcRegs++] = %s;' % (self.reg_spec)
  465. if self.hasReadPred():
  466. c_src = '\n\tif (%s) {%s\n\t}' % \
  467. (self.read_predicate, c_src)
  468. if self.is_dest:
  469. c_dest = '\n\t_destRegIdx[_numDestRegs++] = %s;' % \
  470. (self.reg_spec)
  471. c_dest += '\n\t_numIntDestRegs++;'
  472. if self.hasWritePred():
  473. c_dest = '\n\tif (%s) {%s\n\t}' % \
  474. (self.write_predicate, c_dest)
  475. return c_src + c_dest
  476. def makeRead(self, predRead):
  477. if (self.ctype == 'float' or self.ctype == 'double'):
  478. error('Attempt to read integer register as FP')
  479. if self.read_code != None:
  480. return self.buildReadCode('readIntRegOperand')
  481. int_reg_val = ''
  482. if predRead:
  483. int_reg_val = 'xc->readIntRegOperand(this, _sourceIndex++)'
  484. if self.hasReadPred():
  485. int_reg_val = '(%s) ? %s : 0' % \
  486. (self.read_predicate, int_reg_val)
  487. else:
  488. int_reg_val = 'xc->readIntRegOperand(this, %d)' % self.src_reg_idx
  489. return '%s = %s;\n' % (self.base_name, int_reg_val)
  490. def makeWrite(self, predWrite):
  491. if (self.ctype == 'float' or self.ctype == 'double'):
  492. error('Attempt to write integer register as FP')
  493. if self.write_code != None:
  494. return self.buildWriteCode('setIntRegOperand')
  495. if predWrite:
  496. wp = 'true'
  497. if self.hasWritePred():
  498. wp = self.write_predicate
  499. wcond = 'if (%s)' % (wp)
  500. windex = '_destIndex++'
  501. else:
  502. wcond = ''
  503. windex = '%d' % self.dest_reg_idx
  504. wb = '''
  505. %s
  506. {
  507. %s final_val = %s;
  508. xc->setIntRegOperand(this, %s, final_val);\n
  509. if (traceData) { traceData->setData(final_val); }
  510. }''' % (wcond, self.ctype, self.base_name, windex)
  511. return wb
  512. class FloatRegOperand(Operand):
  513. def isReg(self):
  514. return 1
  515. def isFloatReg(self):
  516. return 1
  517. def makeConstructor(self, predRead, predWrite):
  518. c_src = ''
  519. c_dest = ''
  520. if self.is_src:
  521. c_src = '\n\t_srcRegIdx[_numSrcRegs++] = %s + FP_Base_DepTag;' % \
  522. (self.reg_spec)
  523. if self.is_dest:
  524. c_dest = \
  525. '\n\t_destRegIdx[_numDestRegs++] = %s + FP_Base_DepTag;' % \
  526. (self.reg_spec)
  527. c_dest += '\n\t_numFPDestRegs++;'
  528. return c_src + c_dest
  529. def makeRead(self, predRead):
  530. bit_select = 0
  531. if (self.ctype == 'float' or self.ctype == 'double'):
  532. func = 'readFloatRegOperand'
  533. else:
  534. func = 'readFloatRegOperandBits'
  535. if self.read_code != None:
  536. return self.buildReadCode(func)
  537. if predRead:
  538. rindex = '_sourceIndex++'
  539. else:
  540. rindex = '%d' % self.src_reg_idx
  541. return '%s = xc->%s(this, %s);\n' % \
  542. (self.base_name, func, rindex)
  543. def makeWrite(self, predWrite):
  544. if (self.ctype == 'float' or self.ctype == 'double'):
  545. func = 'setFloatRegOperand'
  546. else:
  547. func = 'setFloatRegOperandBits'
  548. if self.write_code != None:
  549. return self.buildWriteCode(func)
  550. if predWrite:
  551. wp = '_destIndex++'
  552. else:
  553. wp = '%d' % self.dest_reg_idx
  554. wp = 'xc->%s(this, %s, final_val);' % (func, wp)
  555. wb = '''
  556. {
  557. %s final_val = %s;
  558. %s\n
  559. if (traceData) { traceData->setData(final_val); }
  560. }''' % (self.ctype, self.base_name, wp)
  561. return wb
  562. class ControlRegOperand(Operand):
  563. def isReg(self):
  564. return 1
  565. def isControlReg(self):
  566. return 1
  567. def makeConstructor(self, predRead, predWrite):
  568. c_src = ''
  569. c_dest = ''
  570. if self.is_src:
  571. c_src = \
  572. '\n\t_srcRegIdx[_numSrcRegs++] = %s + Ctrl_Base_DepTag;' % \
  573. (self.reg_spec)
  574. if self.is_dest:
  575. c_dest = \
  576. '\n\t_destRegIdx[_numDestRegs++] = %s + Ctrl_Base_DepTag;' % \
  577. (self.reg_spec)
  578. return c_src + c_dest
  579. def makeRead(self, predRead):
  580. bit_select = 0
  581. if (self.ctype == 'float' or self.ctype == 'double'):
  582. error('Attempt to read control register as FP')
  583. if self.read_code != None:
  584. return self.buildReadCode('readMiscRegOperand')
  585. if predRead:
  586. rindex = '_sourceIndex++'
  587. else:
  588. rindex = '%d' % self.src_reg_idx
  589. return '%s = xc->readMiscRegOperand(this, %s);\n' % \
  590. (self.base_name, rindex)
  591. def makeWrite(self, predWrite):
  592. if (self.ctype == 'float' or self.ctype == 'double'):
  593. error('Attempt to write control register as FP')
  594. if self.write_code != None:
  595. return self.buildWriteCode('setMiscRegOperand')
  596. if predWrite:
  597. windex = '_destIndex++'
  598. else:
  599. windex = '%d' % self.dest_reg_idx
  600. wb = 'xc->setMiscRegOperand(this, %s, %s);\n' % \
  601. (windex, self.base_name)
  602. wb += 'if (traceData) { traceData->setData(%s); }' % \
  603. self.base_name
  604. return wb
  605. class MemOperand(Operand):
  606. def isMem(self):
  607. return 1
  608. def makeConstructor(self, predRead, predWrite):
  609. return ''
  610. def makeDecl(self):
  611. # Note that initializations in the declarations are solely
  612. # to avoid 'uninitialized variable' errors from the compiler.
  613. # Declare memory data variable.
  614. return '%s %s = 0;\n' % (self.ctype, self.base_name)
  615. def makeRead(self, predRead):
  616. if self.read_code != None:
  617. return self.buildReadCode()
  618. return ''
  619. def makeWrite(self, predWrite):
  620. if self.write_code != None:
  621. return self.buildWriteCode()
  622. return ''
  623. class PCStateOperand(Operand):
  624. def makeConstructor(self, predRead, predWrite):
  625. return ''
  626. def makeRead(self, predRead):
  627. if self.reg_spec:
  628. # A component of the PC state.
  629. return '%s = __parserAutoPCState.%s();\n' % \
  630. (self.base_name, self.reg_spec)
  631. else:
  632. # The whole PC state itself.
  633. return '%s = xc->pcState();\n' % self.base_name
  634. def makeWrite(self, predWrite):
  635. if self.reg_spec:
  636. # A component of the PC state.
  637. return '__parserAutoPCState.%s(%s);\n' % \
  638. (self.reg_spec, self.base_name)
  639. else:
  640. # The whole PC state itself.
  641. return 'xc->pcState(%s);\n' % self.base_name
  642. def makeDecl(self):
  643. ctype = 'TheISA::PCState'
  644. if self.isPCPart():
  645. ctype = self.ctype
  646. return "%s %s;\n" % (ctype, self.base_name)
  647. def isPCState(self):
  648. return 1
  649. class OperandList(object):
  650. '''Find all the operands in the given code block. Returns an operand
  651. descriptor list (instance of class OperandList).'''
  652. def __init__(self, parser, code):
  653. self.items = []
  654. self.bases = {}
  655. # delete strings and comments so we don't match on operands inside
  656. for regEx in (stringRE, commentRE):
  657. code = regEx.sub('', code)
  658. # search for operands
  659. next_pos = 0
  660. while 1:
  661. match = parser.operandsRE.search(code, next_pos)
  662. if not match:
  663. # no more matches: we're done
  664. break
  665. op = match.groups()
  666. # regexp groups are operand full name, base, and extension
  667. (op_full, op_base, op_ext) = op
  668. # if the token following the operand is an assignment, this is
  669. # a destination (LHS), else it's a source (RHS)
  670. is_dest = (assignRE.match(code, match.end()) != None)
  671. is_src = not is_dest
  672. # see if we've already seen this one
  673. op_desc = self.find_base(op_base)
  674. if op_desc:
  675. if op_desc.ext != op_ext:
  676. error('Inconsistent extensions for operand %s' % \
  677. op_base)
  678. op_desc.is_src = op_desc.is_src or is_src
  679. op_desc.is_dest = op_desc.is_dest or is_dest
  680. else:
  681. # new operand: create new descriptor
  682. op_desc = parser.operandNameMap[op_base](parser,
  683. op_full, op_ext, is_src, is_dest)
  684. self.append(op_desc)
  685. # start next search after end of current match
  686. next_pos = match.end()
  687. self.sort()
  688. # enumerate source & dest register operands... used in building
  689. # constructor later
  690. self.numSrcRegs = 0
  691. self.numDestRegs = 0
  692. self.numFPDestRegs = 0
  693. self.numIntDestRegs = 0
  694. self.numMiscDestRegs = 0
  695. self.memOperand = None
  696. # Flags to keep track if one or more operands are to be read/written
  697. # conditionally.
  698. self.predRead = False
  699. self.predWrite = False
  700. for op_desc in self.items:
  701. if op_desc.isReg():
  702. if op_desc.is_src:
  703. op_desc.src_reg_idx = self.numSrcRegs
  704. self.numSrcRegs += 1
  705. if op_desc.is_dest:
  706. op_desc.dest_reg_idx = self.numDestRegs
  707. self.numDestRegs += 1
  708. if op_desc.isFloatReg():
  709. self.numFPDestRegs += 1
  710. elif op_desc.isIntReg():
  711. self.numIntDestRegs += 1
  712. elif op_desc.isControlReg():
  713. self.numMiscDestRegs += 1
  714. elif op_desc.isMem():
  715. if self.memOperand:
  716. error("Code block has more than one memory operand.")
  717. self.memOperand = op_desc
  718. # Check if this operand has read/write predication. If true, then
  719. # the microop will dynamically index source/dest registers.
  720. self.predRead = self.predRead or op_desc.hasReadPred()
  721. self.predWrite = self.predWrite or op_desc.hasWritePred()
  722. if parser.maxInstSrcRegs < self.numSrcRegs:
  723. parser.maxInstSrcRegs = self.numSrcRegs
  724. if parser.maxInstDestRegs < self.numDestRegs:
  725. parser.maxInstDestRegs = self.numDestRegs
  726. if parser.maxMiscDestRegs < self.numMiscDestRegs:
  727. parser.maxMiscDestRegs = self.numMiscDestRegs
  728. # now make a final pass to finalize op_desc fields that may depend
  729. # on the register enumeration
  730. for op_desc in self.items:
  731. op_desc.finalize(self.predRead, self.predWrite)
  732. def __len__(self):
  733. return len(self.items)
  734. def __getitem__(self, index):
  735. return self.items[index]
  736. def append(self, op_desc):
  737. self.items.append(op_desc)
  738. self.bases[op_desc.base_name] = op_desc
  739. def find_base(self, base_name):
  740. # like self.bases[base_name], but returns None if not found
  741. # (rather than raising exception)
  742. return self.bases.get(base_name)
  743. # internal helper function for concat[Some]Attr{Strings|Lists}
  744. def __internalConcatAttrs(self, attr_name, filter, result):
  745. for op_desc in self.items:
  746. if filter(op_desc):
  747. result += getattr(op_desc, attr_name)
  748. return result
  749. # return a single string that is the concatenation of the (string)
  750. # values of the specified attribute for all operands
  751. def concatAttrStrings(self, attr_name):
  752. return self.__internalConcatAttrs(attr_name, lambda x: 1, '')
  753. # like concatAttrStrings, but only include the values for the operands
  754. # for which the provided filter function returns true
  755. def concatSomeAttrStrings(self, filter, attr_name):
  756. return self.__internalConcatAttrs(attr_name, filter, '')
  757. # return a single list that is the concatenation of the (list)
  758. # values of the specified attribute for all operands
  759. def concatAttrLists(self, attr_name):
  760. return self.__internalConcatAttrs(attr_name, lambda x: 1, [])
  761. # like concatAttrLists, but only include the values for the operands
  762. # for which the provided filter function returns true
  763. def concatSomeAttrLists(self, filter, attr_name):
  764. return self.__internalConcatAttrs(attr_name, filter, [])
  765. def sort(self):
  766. self.items.sort(lambda a, b: a.sort_pri - b.sort_pri)
  767. class SubOperandList(OperandList):
  768. '''Find all the operands in the given code block. Returns an operand
  769. descriptor list (instance of class OperandList).'''
  770. def __init__(self, parser, code, master_list):
  771. self.items = []
  772. self.bases = {}
  773. # delete strings and comments so we don't match on operands inside
  774. for regEx in (stringRE, commentRE):
  775. code = regEx.sub('', code)
  776. # search for operands
  777. next_pos = 0
  778. while 1:
  779. match = parser.operandsRE.search(code, next_pos)
  780. if not match:
  781. # no more matches: we're done
  782. break
  783. op = match.groups()
  784. # regexp groups are operand full name, base, and extension
  785. (op_full, op_base, op_ext) = op
  786. # find this op in the master list
  787. op_desc = master_list.find_base(op_base)
  788. if not op_desc:
  789. error('Found operand %s which is not in the master list!' \
  790. ' This is an internal error' % op_base)
  791. else:
  792. # See if we've already found this operand
  793. op_desc = self.find_base(op_base)
  794. if not op_desc:
  795. # if not, add a reference to it to this sub list
  796. self.append(master_list.bases[op_base])
  797. # start next search after end of current match
  798. next_pos = match.end()
  799. self.sort()
  800. self.memOperand = None
  801. # Whether the whole PC needs to be read so parts of it can be accessed
  802. self.readPC = False
  803. # Whether the whole PC needs to be written after parts of it were
  804. # changed
  805. self.setPC = False
  806. # Whether this instruction manipulates the whole PC or parts of it.
  807. # Mixing the two is a bad idea and flagged as an error.
  808. self.pcPart = None
  809. # Flags to keep track if one or more operands are to be read/written
  810. # conditionally.
  811. self.predRead = False
  812. self.predWrite = False
  813. for op_desc in self.items:
  814. if op_desc.isPCPart():
  815. self.readPC = True
  816. if op_desc.is_dest:
  817. self.setPC = True
  818. if op_desc.isPCState():
  819. if self.pcPart is not None:
  820. if self.pcPart and not op_desc.isPCPart() or \
  821. not self.pcPart and op_desc.isPCPart():
  822. error("Mixed whole and partial PC state operands.")
  823. self.pcPart = op_desc.isPCPart()
  824. if op_desc.isMem():
  825. if self.memOperand:
  826. error("Code block has more than one memory operand.")
  827. self.memOperand = op_desc
  828. # Check if this operand has read/write predication. If true, then
  829. # the microop will dynamically index source/dest registers.
  830. self.predRead = self.predRead or op_desc.hasReadPred()
  831. self.predWrite = self.predWrite or op_desc.hasWritePred()
  832. # Regular expression object to match C++ strings
  833. stringRE = re.compile(r'"([^"\\]|\\.)*"')
  834. # Regular expression object to match C++ comments
  835. # (used in findOperands())
  836. commentRE = re.compile(r'(^)?[^\S\n]*/(?:\*(.*?)\*/[^\S\n]*|/[^\n]*)($)?',
  837. re.DOTALL | re.MULTILINE)
  838. # Regular expression object to match assignment statements
  839. # (used in findOperands())
  840. assignRE = re.compile(r'\s*=(?!=)', re.MULTILINE)
  841. def makeFlagConstructor(flag_list):
  842. if len(flag_list) == 0:
  843. return ''
  844. # filter out repeated flags
  845. flag_list.sort()
  846. i = 1
  847. while i < len(flag_list):
  848. if flag_list[i] == flag_list[i-1]:
  849. del flag_list[i]
  850. else:
  851. i += 1
  852. pre = '\n\tflags['
  853. post = '] = true;'
  854. code = pre + string.join(flag_list, post + pre) + post
  855. return code
  856. # Assume all instruction flags are of the form 'IsFoo'
  857. instFlagRE = re.compile(r'Is.*')
  858. # OpClass constants end in 'Op' except No_OpClass
  859. opClassRE = re.compile(r'.*Op|No_OpClass')
  860. class InstObjParams(object):
  861. def __init__(self, parser, mnem, class_name, base_class = '',
  862. snippets = {}, opt_args = []):
  863. self.mnemonic = mnem
  864. self.class_name = class_name
  865. self.base_class = base_class
  866. if not isinstance(snippets, dict):
  867. snippets = {'code' : snippets}
  868. compositeCode = ' '.join(map(str, snippets.values()))
  869. self.snippets = snippets
  870. self.operands = OperandList(parser, compositeCode)
  871. # The header of the constructor declares the variables to be used
  872. # in the body of the constructor.
  873. header = ''
  874. header += '\n\t_numSrcRegs = 0;'
  875. header += '\n\t_numDestRegs = 0;'
  876. header += '\n\t_numFPDestRegs = 0;'
  877. header += '\n\t_numIntDestRegs = 0;'
  878. self.constructor = header + \
  879. self.operands.concatAttrStrings('constructor')
  880. self.flags = self.operands.concatAttrLists('flags')
  881. # Make a basic guess on the operand class (function unit type).
  882. # These are good enough for most cases, and can be overridden
  883. # later otherwise.
  884. if 'IsStore' in self.flags:
  885. self.op_class = 'MemWriteOp'
  886. elif 'IsLoad' in self.flags or 'IsPrefetch' in self.flags:
  887. self.op_class = 'MemReadOp'
  888. elif 'IsFloating' in self.flags:
  889. self.op_class = 'FloatAddOp'
  890. else:
  891. self.op_class = 'IntAluOp'
  892. # Optional arguments are assumed to be either StaticInst flags
  893. # or an OpClass value. To avoid having to import a complete
  894. # list of these values to match against, we do it ad-hoc
  895. # with regexps.
  896. for oa in opt_args:
  897. if instFlagRE.match(oa):
  898. self.flags.append(oa)
  899. elif opClassRE.match(oa):
  900. self.op_class = oa
  901. else:
  902. error('InstObjParams: optional arg "%s" not recognized '
  903. 'as StaticInst::Flag or OpClass.' % oa)
  904. # add flag initialization to contructor here to include
  905. # any flags added via opt_args
  906. self.constructor += makeFlagConstructor(self.flags)
  907. # if 'IsFloating' is set, add call to the FP enable check
  908. # function (which should be provided by isa_desc via a declare)
  909. if 'IsFloating' in self.flags:
  910. self.fp_enable_check = 'fault = checkFpEnableFault(xc);'
  911. else:
  912. self.fp_enable_check = ''
  913. ##############
  914. # Stack: a simple stack object. Used for both formats (formatStack)
  915. # and default cases (defaultStack). Simply wraps a list to give more
  916. # stack-like syntax and enable initialization with an argument list
  917. # (as opposed to an argument that's a list).
  918. class Stack(list):
  919. def __init__(self, *items):
  920. list.__init__(self, items)
  921. def push(self, item):
  922. self.append(item);
  923. def top(self):
  924. return self[-1]
  925. #######################
  926. #
  927. # Output file template
  928. #
  929. file_template = '''
  930. /*
  931. * DO NOT EDIT THIS FILE!!!
  932. *
  933. * It was automatically generated from the ISA description in %(filename)s
  934. */
  935. %(includes)s
  936. %(global_output)s
  937. namespace %(namespace)s {
  938. %(namespace_output)s
  939. } // namespace %(namespace)s
  940. %(decode_function)s
  941. '''
  942. max_inst_regs_template = '''
  943. /*
  944. * DO NOT EDIT THIS FILE!!!
  945. *
  946. * It was automatically generated from the ISA description in %(filename)s
  947. */
  948. namespace %(namespace)s {
  949. const int MaxInstSrcRegs = %(MaxInstSrcRegs)d;
  950. const int MaxInstDestRegs = %(MaxInstDestRegs)d;
  951. const int MaxMiscDestRegs = %(MaxMiscDestRegs)d;
  952. } // namespace %(namespace)s
  953. '''
  954. class ISAParser(Grammar):
  955. def __init__(self, output_dir, cpu_models):
  956. super(ISAParser, self).__init__()
  957. self.output_dir = output_dir
  958. self.cpuModels = cpu_models
  959. # variable to hold templates
  960. self.templateMap = {}
  961. # This dictionary maps format name strings to Format objects.
  962. self.formatMap = {}
  963. # The format stack.
  964. self.formatStack = Stack(NoFormat())
  965. # The default case stack.
  966. self.defaultStack = Stack(None)
  967. # Stack that tracks current file and line number. Each
  968. # element is a tuple (filename, lineno) that records the
  969. # *current* filename and the line number in the *previous*
  970. # file where it was included.
  971. self.fileNameStack = Stack()
  972. symbols = ('makeList', 're', 'string')
  973. self.exportContext = dict([(s, eval(s)) for s in symbols])
  974. self.maxInstSrcRegs = 0
  975. self.maxInstDestRegs = 0
  976. self.maxMiscDestRegs = 0
  977. #####################################################################
  978. #
  979. # Lexer
  980. #
  981. # The PLY lexer module takes two things as input:
  982. # - A list of token names (the string list 'tokens')
  983. # - A regular expression describing a match for each token. The
  984. # regexp for token FOO can be provided in two ways:
  985. # - as a string variable named t_FOO
  986. # - as the doc string for a function named t_FOO. In this case,
  987. # the function is also executed, allowing an action to be
  988. # associated with each token match.
  989. #
  990. #####################################################################
  991. # Reserved words. These are listed separately as they are matched
  992. # using the same regexp as generic IDs, but distinguished in the
  993. # t_ID() function. The PLY documentation suggests this approach.
  994. reserved = (
  995. 'BITFIELD', 'DECODE', 'DECODER', 'DEFAULT', 'DEF', 'EXEC', 'FORMAT',
  996. 'HEADER', 'LET', 'NAMESPACE', 'OPERAND_TYPES', 'OPERANDS',
  997. 'OUTPUT', 'SIGNED', 'TEMPLATE'
  998. )
  999. # List of tokens. The lex module requires this.
  1000. tokens = reserved + (
  1001. # identifier
  1002. 'ID',
  1003. # integer literal
  1004. 'INTLIT',
  1005. # string literal
  1006. 'STRLIT',
  1007. # code literal
  1008. 'CODELIT',
  1009. # ( ) [ ] { } < > , ; . : :: *
  1010. 'LPAREN', 'RPAREN',
  1011. 'LBRACKET', 'RBRACKET',
  1012. 'LBRACE', 'RBRACE',
  1013. 'LESS', 'GREATER', 'EQUALS',
  1014. 'COMMA', 'SEMI', 'DOT', 'COLON', 'DBLCOLON',
  1015. 'ASTERISK',
  1016. # C preprocessor directives
  1017. 'CPPDIRECTIVE'
  1018. # The following are matched but never returned. commented out to
  1019. # suppress PLY warning
  1020. # newfile directive
  1021. # 'NEWFILE',
  1022. # endfile directive
  1023. # 'ENDFILE'
  1024. )
  1025. # Regular expressions for token matching
  1026. t_LPAREN = r'\('
  1027. t_RPAREN = r'\)'
  1028. t_LBRACKET = r'\['
  1029. t_RBRACKET = r'\]'
  1030. t_LBRACE = r'\{'
  1031. t_RBRACE = r'\}'
  1032. t_LESS = r'\<'
  1033. t_GREATER = r'\>'
  1034. t_EQUALS = r'='
  1035. t_COMMA = r','
  1036. t_SEMI = r';'
  1037. t_DOT = r'\.'
  1038. t_COLON = r':'
  1039. t_DBLCOLON = r'::'
  1040. t_ASTERISK = r'\*'
  1041. # Identifiers and reserved words
  1042. reserved_map = { }
  1043. for r in reserved:
  1044. reserved_map[r.lower()] = r
  1045. def t_ID(self, t):
  1046. r'[A-Za-z_]\w*'
  1047. t.type = self.reserved_map.get(t.value, 'ID')
  1048. return t
  1049. # Integer literal
  1050. def t_INTLIT(self, t):
  1051. r'-?(0x[\da-fA-F]+)|\d+'
  1052. try:
  1053. t.value = int(t.value,0)
  1054. except ValueError:
  1055. error(t, 'Integer value "%s" too large' % t.value)
  1056. t.value = 0
  1057. return t
  1058. # String literal. Note that these use only single quotes, and
  1059. # can span multiple lines.
  1060. def t_STRLIT(self, t):
  1061. r"(?m)'([^'])+'"
  1062. # strip off quotes
  1063. t.value = t.value[1:-1]
  1064. t.lexer.lineno += t.value.count('\n')
  1065. return t
  1066. # "Code literal"... like a string literal, but delimiters are
  1067. # '{{' and '}}' so they get formatted nicely under emacs c-mode
  1068. def t_CODELIT(self, t):
  1069. r"(?m)\{\{([^\}]|}(?!\}))+\}\}"
  1070. # strip off {{ & }}
  1071. t.value = t.value[2:-2]
  1072. t.lexer.lineno += t.value.count('\n')
  1073. return t
  1074. def t_CPPDIRECTIVE(self, t):
  1075. r'^\#[^\#].*\n'
  1076. t.lexer.lineno += t.value.count('\n')
  1077. return t
  1078. def t_NEWFILE(self, t):
  1079. r'^\#\#newfile\s+"[^"]*"'
  1080. self.fileNameStack.push((t.value[11:-1], t.lexer.lineno))
  1081. t.lexer.lineno = 0
  1082. def t_ENDFILE(self, t):
  1083. r'^\#\#endfile'
  1084. (old_filename, t.lexer.lineno) = self.fileNameStack.pop()
  1085. #
  1086. # The functions t_NEWLINE, t_ignore, and t_error are
  1087. # special for the lex module.
  1088. #
  1089. # Newlines
  1090. def t_NEWLINE(self, t):
  1091. r'\n+'
  1092. t.lexer.lineno += t.value.count('\n')
  1093. # Comments
  1094. def t_comment(self, t):
  1095. r'//.*'
  1096. # Completely ignored characters
  1097. t_ignore = ' \t\x0c'
  1098. # Error handler
  1099. def t_error(self, t):
  1100. error(t, "illegal character '%s'" % t.value[0])
  1101. t.skip(1)
  1102. #####################################################################
  1103. #
  1104. # Parser
  1105. #
  1106. # Every function whose name starts with 'p_' defines a grammar
  1107. # rule. The rule is encoded in the function's doc string, while
  1108. # the function body provides the action taken when the rule is
  1109. # matched. The argument to each function is a list of the values
  1110. # of the rule's symbols: t[0] for the LHS, and t[1..n] for the
  1111. # symbols on the RHS. For tokens, the value is copied from the
  1112. # t.value attribute provided by the lexer. For non-terminals, the
  1113. # value is assigned by the producing rule; i.e., the job of the
  1114. # grammar rule function is to set the value for the non-terminal
  1115. # on the LHS (by assigning to t[0]).
  1116. #####################################################################
  1117. # The LHS of the first grammar rule is used as the start symbol
  1118. # (in this case, 'specification'). Note that this rule enforces
  1119. # that there will be exactly one namespace declaration, with 0 or
  1120. # more global defs/decls before and after it. The defs & decls
  1121. # before the namespace decl will be outside the namespace; those
  1122. # after will be inside. The decoder function is always inside the
  1123. # namespace.
  1124. def p_specification(self, t):
  1125. 'specification : opt_defs_and_outputs name_decl opt_defs_and_outputs decode_block'
  1126. global_code = t[1]
  1127. isa_name = t[2]
  1128. namespace = isa_name + "Inst"
  1129. # wrap the decode block as a function definition
  1130. t[4].wrap_decode_block('''
  1131. StaticInstPtr
  1132. %(isa_name)s::Decoder::decodeInst(%(isa_name)s::ExtMachInst machInst)
  1133. {
  1134. using namespace %(namespace)s;
  1135. ''' % vars(), '}')
  1136. # both the latter output blocks and the decode block are in
  1137. # the namespace
  1138. namespace_code = t[3] + t[4]
  1139. # pass it all back to the caller of yacc.parse()
  1140. t[0] = (isa_name, namespace, global_code, namespace_code)
  1141. # ISA name declaration looks like "namespace <foo>;"
  1142. def p_name_decl(self, t):
  1143. 'name_decl : NAMESPACE ID SEMI'
  1144. t[0] = t[2]
  1145. # 'opt_defs_and_outputs' is a possibly empty sequence of
  1146. # def and/or output statements.
  1147. def p_opt_defs_and_outputs_0(self, t):
  1148. 'opt_defs_and_outputs : empty'
  1149. t[0] = GenCode(self)
  1150. def p_opt_defs_and_outputs_1(self, t):
  1151. 'opt_defs_and_outputs : defs_and_outputs'
  1152. t[0] = t[1]
  1153. def p_defs_and_outputs_0(self, t):
  1154. 'defs_and_outputs : def_or_output'
  1155. t[0] = t[1]
  1156. def p_defs_and_outputs_1(self, t):
  1157. 'defs_and_outputs : defs_and_outputs def_or_output'
  1158. t[0] = t[1] + t[2]
  1159. # The list of possible definition/output statements.
  1160. def p_def_or_output(self, t):
  1161. '''def_or_output : def_format
  1162. | def_bitfield
  1163. | def_bitfield_struct
  1164. | def_template
  1165. | def_operand_types
  1166. | def_operands
  1167. | output_header
  1168. | output_decoder
  1169. | output_exec
  1170. | global_let'''
  1171. t[0] = t[1]
  1172. # Output blocks 'output <foo> {{...}}' (C++ code blocks) are copied
  1173. # directly to the appropriate output section.
  1174. # Massage output block by substituting in template definitions and
  1175. # bit operators. We handle '%'s embedded in the string that don't
  1176. # indicate template substitutions (or CPU-specific symbols, which
  1177. # get handled in GenCode) by doubling them first so that the
  1178. # format operation will reduce them back to single '%'s.

Large files files are truncated, but you can click here to view the full file