micro_asm.py revision 5594
14483Sgblack@eecs.umich.edu# Copyright (c) 2003-2005 The Regents of The University of Michigan 24483Sgblack@eecs.umich.edu# All rights reserved. 34483Sgblack@eecs.umich.edu# 44483Sgblack@eecs.umich.edu# Redistribution and use in source and binary forms, with or without 54483Sgblack@eecs.umich.edu# modification, are permitted provided that the following conditions are 64483Sgblack@eecs.umich.edu# met: redistributions of source code must retain the above copyright 74483Sgblack@eecs.umich.edu# notice, this list of conditions and the following disclaimer; 84483Sgblack@eecs.umich.edu# redistributions in binary form must reproduce the above copyright 94483Sgblack@eecs.umich.edu# notice, this list of conditions and the following disclaimer in the 104483Sgblack@eecs.umich.edu# documentation and/or other materials provided with the distribution; 114483Sgblack@eecs.umich.edu# neither the name of the copyright holders nor the names of its 124483Sgblack@eecs.umich.edu# contributors may be used to endorse or promote products derived from 134483Sgblack@eecs.umich.edu# this software without specific prior written permission. 144483Sgblack@eecs.umich.edu# 154483Sgblack@eecs.umich.edu# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 164483Sgblack@eecs.umich.edu# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 174483Sgblack@eecs.umich.edu# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 184483Sgblack@eecs.umich.edu# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 194483Sgblack@eecs.umich.edu# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 204483Sgblack@eecs.umich.edu# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 214483Sgblack@eecs.umich.edu# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 224483Sgblack@eecs.umich.edu# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 234483Sgblack@eecs.umich.edu# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 244483Sgblack@eecs.umich.edu# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 254483Sgblack@eecs.umich.edu# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 264483Sgblack@eecs.umich.edu# 274483Sgblack@eecs.umich.edu# Authors: Gabe Black 284483Sgblack@eecs.umich.edu 294483Sgblack@eecs.umich.eduimport os 304483Sgblack@eecs.umich.eduimport sys 314483Sgblack@eecs.umich.eduimport re 324483Sgblack@eecs.umich.eduimport string 334483Sgblack@eecs.umich.eduimport traceback 344483Sgblack@eecs.umich.edu# get type names 354483Sgblack@eecs.umich.edufrom types import * 364483Sgblack@eecs.umich.edu 374483Sgblack@eecs.umich.edu# Prepend the directory where the PLY lex & yacc modules are found 384483Sgblack@eecs.umich.edu# to the search path. 394483Sgblack@eecs.umich.edusys.path[0:0] = [os.environ['M5_PLY']] 404483Sgblack@eecs.umich.edu 414483Sgblack@eecs.umich.edufrom ply import lex 424483Sgblack@eecs.umich.edufrom ply import yacc 434483Sgblack@eecs.umich.edu 444483Sgblack@eecs.umich.edu########################################################################## 454483Sgblack@eecs.umich.edu# 464483Sgblack@eecs.umich.edu# Base classes for use outside of the assembler 474483Sgblack@eecs.umich.edu# 484483Sgblack@eecs.umich.edu########################################################################## 494483Sgblack@eecs.umich.edu 504483Sgblack@eecs.umich.educlass Micro_Container(object): 514483Sgblack@eecs.umich.edu def __init__(self, name): 524483Sgblack@eecs.umich.edu self.microops = [] 534483Sgblack@eecs.umich.edu self.name = name 544483Sgblack@eecs.umich.edu self.directives = {} 554483Sgblack@eecs.umich.edu self.micro_classes = {} 564483Sgblack@eecs.umich.edu self.labels = {} 574483Sgblack@eecs.umich.edu 585039Sgblack@eecs.umich.edu def add_microop(self, mnemonic, microop): 594483Sgblack@eecs.umich.edu self.microops.append(microop) 604483Sgblack@eecs.umich.edu 614483Sgblack@eecs.umich.edu def __str__(self): 624483Sgblack@eecs.umich.edu string = "%s:\n" % self.name 634483Sgblack@eecs.umich.edu for microop in self.microops: 644483Sgblack@eecs.umich.edu string += " %s\n" % microop 654483Sgblack@eecs.umich.edu return string 664483Sgblack@eecs.umich.edu 674507Sgblack@eecs.umich.educlass Combinational_Macroop(Micro_Container): 684483Sgblack@eecs.umich.edu pass 694483Sgblack@eecs.umich.edu 704507Sgblack@eecs.umich.educlass Rom_Macroop(object): 714507Sgblack@eecs.umich.edu def __init__(self, name, target): 724507Sgblack@eecs.umich.edu self.name = name 734507Sgblack@eecs.umich.edu self.target = target 744507Sgblack@eecs.umich.edu 754508Sgblack@eecs.umich.edu def __str__(self): 764508Sgblack@eecs.umich.edu return "%s: %s\n" % (self.name, self.target) 774508Sgblack@eecs.umich.edu 784483Sgblack@eecs.umich.educlass Rom(Micro_Container): 794483Sgblack@eecs.umich.edu def __init__(self, name): 804483Sgblack@eecs.umich.edu super(Rom, self).__init__(name) 814483Sgblack@eecs.umich.edu self.externs = {} 824483Sgblack@eecs.umich.edu 834483Sgblack@eecs.umich.edu########################################################################## 844483Sgblack@eecs.umich.edu# 854483Sgblack@eecs.umich.edu# Support classes 864483Sgblack@eecs.umich.edu# 874483Sgblack@eecs.umich.edu########################################################################## 884483Sgblack@eecs.umich.edu 894483Sgblack@eecs.umich.educlass Label(object): 904483Sgblack@eecs.umich.edu def __init__(self): 914483Sgblack@eecs.umich.edu self.extern = False 924483Sgblack@eecs.umich.edu self.name = "" 934483Sgblack@eecs.umich.edu 944483Sgblack@eecs.umich.educlass Block(object): 954483Sgblack@eecs.umich.edu def __init__(self): 964483Sgblack@eecs.umich.edu self.statements = [] 974483Sgblack@eecs.umich.edu 984483Sgblack@eecs.umich.educlass Statement(object): 994483Sgblack@eecs.umich.edu def __init__(self): 1004483Sgblack@eecs.umich.edu self.is_microop = False 1014483Sgblack@eecs.umich.edu self.is_directive = False 1024503Sgblack@eecs.umich.edu self.params = "" 1034483Sgblack@eecs.umich.edu 1044483Sgblack@eecs.umich.educlass Microop(Statement): 1054483Sgblack@eecs.umich.edu def __init__(self): 1064483Sgblack@eecs.umich.edu super(Microop, self).__init__() 1074483Sgblack@eecs.umich.edu self.mnemonic = "" 1084483Sgblack@eecs.umich.edu self.labels = [] 1094483Sgblack@eecs.umich.edu self.is_microop = True 1104483Sgblack@eecs.umich.edu 1114483Sgblack@eecs.umich.educlass Directive(Statement): 1124483Sgblack@eecs.umich.edu def __init__(self): 1134483Sgblack@eecs.umich.edu super(Directive, self).__init__() 1144483Sgblack@eecs.umich.edu self.name = "" 1154483Sgblack@eecs.umich.edu self.is_directive = True 1164483Sgblack@eecs.umich.edu 1174483Sgblack@eecs.umich.edu########################################################################## 1184483Sgblack@eecs.umich.edu# 1194483Sgblack@eecs.umich.edu# Functions that handle common tasks 1204483Sgblack@eecs.umich.edu# 1214483Sgblack@eecs.umich.edu########################################################################## 1224483Sgblack@eecs.umich.edu 1234483Sgblack@eecs.umich.edudef print_error(message): 1244483Sgblack@eecs.umich.edu print 1254483Sgblack@eecs.umich.edu print "*** %s" % message 1264483Sgblack@eecs.umich.edu print 1274483Sgblack@eecs.umich.edu 1284483Sgblack@eecs.umich.edudef handle_statement(parser, container, statement): 1294483Sgblack@eecs.umich.edu if statement.is_microop: 1304613Sgblack@eecs.umich.edu if statement.mnemonic not in parser.microops.keys(): 1314613Sgblack@eecs.umich.edu raise Exception, "Unrecognized mnemonic: %s" % statement.mnemonic 1324613Sgblack@eecs.umich.edu parser.symbols["__microopClassFromInsideTheAssembler"] = \ 1334613Sgblack@eecs.umich.edu parser.microops[statement.mnemonic] 1344483Sgblack@eecs.umich.edu try: 1354613Sgblack@eecs.umich.edu microop = eval('__microopClassFromInsideTheAssembler(%s)' % 1364613Sgblack@eecs.umich.edu statement.params, {}, parser.symbols) 1374483Sgblack@eecs.umich.edu except: 1384591Sgblack@eecs.umich.edu print_error("Error creating microop object with mnemonic %s." % \ 1394591Sgblack@eecs.umich.edu statement.mnemonic) 1404483Sgblack@eecs.umich.edu raise 1414483Sgblack@eecs.umich.edu try: 1424483Sgblack@eecs.umich.edu for label in statement.labels: 1435009Sgblack@eecs.umich.edu container.labels[label.text] = microop 1445594Sgblack@eecs.umich.edu if label.is_extern: 1455009Sgblack@eecs.umich.edu container.externs[label.text] = microop 1465039Sgblack@eecs.umich.edu container.add_microop(statement.mnemonic, microop) 1474483Sgblack@eecs.umich.edu except: 1484483Sgblack@eecs.umich.edu print_error("Error adding microop.") 1494483Sgblack@eecs.umich.edu raise 1504483Sgblack@eecs.umich.edu elif statement.is_directive: 1514613Sgblack@eecs.umich.edu if statement.name not in container.directives.keys(): 1524613Sgblack@eecs.umich.edu raise Exception, "Unrecognized directive: %s" % statement.name 1534613Sgblack@eecs.umich.edu parser.symbols["__directiveFunctionFromInsideTheAssembler"] = \ 1544613Sgblack@eecs.umich.edu container.directives[statement.name] 1554483Sgblack@eecs.umich.edu try: 1564613Sgblack@eecs.umich.edu eval('__directiveFunctionFromInsideTheAssembler(%s)' % 1574613Sgblack@eecs.umich.edu statement.params, {}, parser.symbols) 1584483Sgblack@eecs.umich.edu except: 1594483Sgblack@eecs.umich.edu print_error("Error executing directive.") 1604483Sgblack@eecs.umich.edu print container.directives 1614483Sgblack@eecs.umich.edu raise 1624483Sgblack@eecs.umich.edu else: 1634483Sgblack@eecs.umich.edu raise Exception, "Didn't recognize the type of statement", statement 1644483Sgblack@eecs.umich.edu 1654483Sgblack@eecs.umich.edu########################################################################## 1664483Sgblack@eecs.umich.edu# 1674483Sgblack@eecs.umich.edu# Lexer specification 1684483Sgblack@eecs.umich.edu# 1694483Sgblack@eecs.umich.edu########################################################################## 1704483Sgblack@eecs.umich.edu 1714483Sgblack@eecs.umich.edu# Error handler. Just call exit. Output formatted to work under 1724483Sgblack@eecs.umich.edu# Emacs compile-mode. Optional 'print_traceback' arg, if set to True, 1734483Sgblack@eecs.umich.edu# prints a Python stack backtrace too (can be handy when trying to 1744483Sgblack@eecs.umich.edu# debug the parser itself). 1754483Sgblack@eecs.umich.edudef error(lineno, string, print_traceback = False): 1764483Sgblack@eecs.umich.edu # Print a Python stack backtrace if requested. 1774483Sgblack@eecs.umich.edu if (print_traceback): 1784483Sgblack@eecs.umich.edu traceback.print_exc() 1794483Sgblack@eecs.umich.edu if lineno != 0: 1804483Sgblack@eecs.umich.edu line_str = "%d:" % lineno 1814483Sgblack@eecs.umich.edu else: 1824483Sgblack@eecs.umich.edu line_str = "" 1834483Sgblack@eecs.umich.edu sys.exit("%s %s" % (line_str, string)) 1844483Sgblack@eecs.umich.edu 1854483Sgblack@eecs.umich.edureserved = ('DEF', 'MACROOP', 'ROM', 'EXTERN') 1864483Sgblack@eecs.umich.edu 1874483Sgblack@eecs.umich.edutokens = reserved + ( 1884483Sgblack@eecs.umich.edu # identifier 1894483Sgblack@eecs.umich.edu 'ID', 1904483Sgblack@eecs.umich.edu # arguments for microops and directives 1914483Sgblack@eecs.umich.edu 'PARAMS', 1924483Sgblack@eecs.umich.edu 1934483Sgblack@eecs.umich.edu 'LPAREN', 'RPAREN', 1944483Sgblack@eecs.umich.edu 'LBRACE', 'RBRACE', 1954483Sgblack@eecs.umich.edu 'COLON', 'SEMI', 'DOT', 1964483Sgblack@eecs.umich.edu 'NEWLINE' 1974483Sgblack@eecs.umich.edu ) 1984483Sgblack@eecs.umich.edu 1994483Sgblack@eecs.umich.edu# New lines are ignored at the top level, but they end statements in the 2004483Sgblack@eecs.umich.edu# assembler 2014483Sgblack@eecs.umich.edustates = ( 2024483Sgblack@eecs.umich.edu ('asm', 'exclusive'), 2034483Sgblack@eecs.umich.edu ('params', 'exclusive'), 2044483Sgblack@eecs.umich.edu) 2054483Sgblack@eecs.umich.edu 2064483Sgblack@eecs.umich.edureserved_map = { } 2074483Sgblack@eecs.umich.edufor r in reserved: 2084483Sgblack@eecs.umich.edu reserved_map[r.lower()] = r 2094483Sgblack@eecs.umich.edu 2104512Sgblack@eecs.umich.edu# Ignore comments 2114502Sgblack@eecs.umich.edudef t_ANY_COMMENT(t): 2124502Sgblack@eecs.umich.edu r'\#[^\n]*(?=\n)' 2134502Sgblack@eecs.umich.edu 2144502Sgblack@eecs.umich.edudef t_ANY_MULTILINECOMMENT(t): 2154502Sgblack@eecs.umich.edu r'/\*([^/]|((?<!\*)/))*\*/' 2164502Sgblack@eecs.umich.edu 2174512Sgblack@eecs.umich.edu# A colon marks the end of a label. It should follow an ID which will 2184512Sgblack@eecs.umich.edu# put the lexer in the "params" state. Seeing the colon will put it back 2194512Sgblack@eecs.umich.edu# in the "asm" state since it knows it saw a label and not a mnemonic. 2204483Sgblack@eecs.umich.edudef t_params_COLON(t): 2214483Sgblack@eecs.umich.edu r':' 2224483Sgblack@eecs.umich.edu t.lexer.begin('asm') 2234483Sgblack@eecs.umich.edu return t 2244483Sgblack@eecs.umich.edu 2254512Sgblack@eecs.umich.edu# Parameters are a string of text which don't contain an unescaped statement 2264512Sgblack@eecs.umich.edu# statement terminator, ie a newline or semi colon. 2274483Sgblack@eecs.umich.edudef t_params_PARAMS(t): 2284566Sgblack@eecs.umich.edu r'([^\n;\\]|(\\[\n;\\]))+' 2294483Sgblack@eecs.umich.edu t.lineno += t.value.count('\n') 2304566Sgblack@eecs.umich.edu unescapeParamsRE = re.compile(r'(\\[\n;\\])') 2314566Sgblack@eecs.umich.edu def unescapeParams(mo): 2324566Sgblack@eecs.umich.edu val = mo.group(0) 2334566Sgblack@eecs.umich.edu return val[1] 2344566Sgblack@eecs.umich.edu t.value = unescapeParamsRE.sub(unescapeParams, t.value) 2354483Sgblack@eecs.umich.edu t.lexer.begin('asm') 2364483Sgblack@eecs.umich.edu return t 2374483Sgblack@eecs.umich.edu 2384613Sgblack@eecs.umich.edu# An "ID" in the micro assembler is either a label, directive, or mnemonic 2394613Sgblack@eecs.umich.edu# If it's either a directive or a mnemonic, it will be optionally followed by 2404613Sgblack@eecs.umich.edu# parameters. If it's a label, the following colon will make the lexer stop 2414613Sgblack@eecs.umich.edu# looking for parameters. 2424613Sgblack@eecs.umich.edudef t_asm_ID(t): 2434613Sgblack@eecs.umich.edu r'[A-Za-z_]\w*' 2444613Sgblack@eecs.umich.edu t.type = reserved_map.get(t.value, 'ID') 2455593Sgblack@eecs.umich.edu # If the ID is really "extern", we shouldn't start looking for parameters 2465593Sgblack@eecs.umich.edu # yet. The real ID, the label itself, is coming up. 2475593Sgblack@eecs.umich.edu if t.type != 'EXTERN': 2485593Sgblack@eecs.umich.edu t.lexer.begin('params') 2494613Sgblack@eecs.umich.edu return t 2504613Sgblack@eecs.umich.edu 2514613Sgblack@eecs.umich.edu# If there is a label and you're -not- in the assembler (which would be caught 2524613Sgblack@eecs.umich.edu# above), don't start looking for parameters. 2534613Sgblack@eecs.umich.edudef t_ANY_ID(t): 2544613Sgblack@eecs.umich.edu r'[A-Za-z_]\w*' 2554613Sgblack@eecs.umich.edu t.type = reserved_map.get(t.value, 'ID') 2564613Sgblack@eecs.umich.edu return t 2574613Sgblack@eecs.umich.edu 2584512Sgblack@eecs.umich.edu# Braces enter and exit micro assembly 2594483Sgblack@eecs.umich.edudef t_INITIAL_LBRACE(t): 2604483Sgblack@eecs.umich.edu r'\{' 2614483Sgblack@eecs.umich.edu t.lexer.begin('asm') 2624483Sgblack@eecs.umich.edu return t 2634483Sgblack@eecs.umich.edu 2644483Sgblack@eecs.umich.edudef t_asm_RBRACE(t): 2654483Sgblack@eecs.umich.edu r'\}' 2664483Sgblack@eecs.umich.edu t.lexer.begin('INITIAL') 2674483Sgblack@eecs.umich.edu return t 2684483Sgblack@eecs.umich.edu 2694512Sgblack@eecs.umich.edu# At the top level, keep track of newlines only for line counting. 2704483Sgblack@eecs.umich.edudef t_INITIAL_NEWLINE(t): 2714483Sgblack@eecs.umich.edu r'\n+' 2724483Sgblack@eecs.umich.edu t.lineno += t.value.count('\n') 2734483Sgblack@eecs.umich.edu 2744512Sgblack@eecs.umich.edu# In the micro assembler, do line counting but also return a token. The 2754512Sgblack@eecs.umich.edu# token is needed by the parser to detect the end of a statement. 2764483Sgblack@eecs.umich.edudef t_asm_NEWLINE(t): 2774483Sgblack@eecs.umich.edu r'\n+' 2784483Sgblack@eecs.umich.edu t.lineno += t.value.count('\n') 2794483Sgblack@eecs.umich.edu return t 2804483Sgblack@eecs.umich.edu 2814512Sgblack@eecs.umich.edu# A newline or semi colon when looking for params signals that the statement 2824512Sgblack@eecs.umich.edu# is over and the lexer should go back to looking for regular assembly. 2834483Sgblack@eecs.umich.edudef t_params_NEWLINE(t): 2844483Sgblack@eecs.umich.edu r'\n+' 2854483Sgblack@eecs.umich.edu t.lineno += t.value.count('\n') 2864483Sgblack@eecs.umich.edu t.lexer.begin('asm') 2874483Sgblack@eecs.umich.edu return t 2884483Sgblack@eecs.umich.edu 2894483Sgblack@eecs.umich.edudef t_params_SEMI(t): 2904483Sgblack@eecs.umich.edu r';' 2914483Sgblack@eecs.umich.edu t.lexer.begin('asm') 2924483Sgblack@eecs.umich.edu return t 2934483Sgblack@eecs.umich.edu 2944483Sgblack@eecs.umich.edu# Basic regular expressions to pick out simple tokens 2954483Sgblack@eecs.umich.edut_ANY_LPAREN = r'\(' 2964483Sgblack@eecs.umich.edut_ANY_RPAREN = r'\)' 2974483Sgblack@eecs.umich.edut_ANY_SEMI = r';' 2984483Sgblack@eecs.umich.edut_ANY_DOT = r'\.' 2994483Sgblack@eecs.umich.edu 3004483Sgblack@eecs.umich.edut_ANY_ignore = ' \t\x0c' 3014483Sgblack@eecs.umich.edu 3024483Sgblack@eecs.umich.edudef t_ANY_error(t): 3034483Sgblack@eecs.umich.edu error(t.lineno, "illegal character '%s'" % t.value[0]) 3044483Sgblack@eecs.umich.edu t.skip(1) 3054483Sgblack@eecs.umich.edu 3064483Sgblack@eecs.umich.edu########################################################################## 3074483Sgblack@eecs.umich.edu# 3084483Sgblack@eecs.umich.edu# Parser specification 3094483Sgblack@eecs.umich.edu# 3104483Sgblack@eecs.umich.edu########################################################################## 3114483Sgblack@eecs.umich.edu 3124483Sgblack@eecs.umich.edu# Start symbol for a file which may have more than one macroop or rom 3134483Sgblack@eecs.umich.edu# specification. 3144483Sgblack@eecs.umich.edudef p_file(t): 3154483Sgblack@eecs.umich.edu 'file : opt_rom_or_macros' 3164483Sgblack@eecs.umich.edu 3174483Sgblack@eecs.umich.edudef p_opt_rom_or_macros_0(t): 3184483Sgblack@eecs.umich.edu 'opt_rom_or_macros : ' 3194483Sgblack@eecs.umich.edu 3204483Sgblack@eecs.umich.edudef p_opt_rom_or_macros_1(t): 3214483Sgblack@eecs.umich.edu 'opt_rom_or_macros : rom_or_macros' 3224483Sgblack@eecs.umich.edu 3234483Sgblack@eecs.umich.edudef p_rom_or_macros_0(t): 3244483Sgblack@eecs.umich.edu 'rom_or_macros : rom_or_macro' 3254483Sgblack@eecs.umich.edu 3264483Sgblack@eecs.umich.edudef p_rom_or_macros_1(t): 3274483Sgblack@eecs.umich.edu 'rom_or_macros : rom_or_macros rom_or_macro' 3284483Sgblack@eecs.umich.edu 3294483Sgblack@eecs.umich.edudef p_rom_or_macro_0(t): 3304512Sgblack@eecs.umich.edu '''rom_or_macro : rom_block 3314512Sgblack@eecs.umich.edu | macroop_def''' 3324483Sgblack@eecs.umich.edu 3334483Sgblack@eecs.umich.edu# Defines a section of microcode that should go in the current ROM 3344483Sgblack@eecs.umich.edudef p_rom_block(t): 3354483Sgblack@eecs.umich.edu 'rom_block : DEF ROM block SEMI' 3364507Sgblack@eecs.umich.edu if not t.parser.rom: 3374507Sgblack@eecs.umich.edu print_error("Rom block found, but no Rom object specified.") 3384507Sgblack@eecs.umich.edu raise TypeError, "Rom block found, but no Rom object was specified." 3394483Sgblack@eecs.umich.edu for statement in t[3].statements: 3404483Sgblack@eecs.umich.edu handle_statement(t.parser, t.parser.rom, statement) 3414483Sgblack@eecs.umich.edu t[0] = t.parser.rom 3424483Sgblack@eecs.umich.edu 3434483Sgblack@eecs.umich.edu# Defines a macroop that jumps to an external label in the ROM 3444483Sgblack@eecs.umich.edudef p_macroop_def_0(t): 3454502Sgblack@eecs.umich.edu 'macroop_def : DEF MACROOP ID LPAREN ID RPAREN SEMI' 3464507Sgblack@eecs.umich.edu if not t.parser.rom_macroop_type: 3474507Sgblack@eecs.umich.edu print_error("ROM based macroop found, but no ROM macroop class was specified.") 3484507Sgblack@eecs.umich.edu raise TypeError, "ROM based macroop found, but no ROM macroop class was specified." 3494507Sgblack@eecs.umich.edu macroop = t.parser.rom_macroop_type(t[3], t[5]) 3504508Sgblack@eecs.umich.edu t.parser.macroops[t[3]] = macroop 3514507Sgblack@eecs.umich.edu 3524483Sgblack@eecs.umich.edu 3534483Sgblack@eecs.umich.edu# Defines a macroop that is combinationally generated 3544483Sgblack@eecs.umich.edudef p_macroop_def_1(t): 3554483Sgblack@eecs.umich.edu 'macroop_def : DEF MACROOP ID block SEMI' 3564483Sgblack@eecs.umich.edu try: 3574483Sgblack@eecs.umich.edu curop = t.parser.macro_type(t[3]) 3584483Sgblack@eecs.umich.edu except TypeError: 3594483Sgblack@eecs.umich.edu print_error("Error creating macroop object.") 3604483Sgblack@eecs.umich.edu raise 3614483Sgblack@eecs.umich.edu for statement in t[4].statements: 3624483Sgblack@eecs.umich.edu handle_statement(t.parser, curop, statement) 3634502Sgblack@eecs.umich.edu t.parser.macroops[t[3]] = curop 3644483Sgblack@eecs.umich.edu 3654512Sgblack@eecs.umich.edu# A block of statements 3664512Sgblack@eecs.umich.edudef p_block(t): 3674512Sgblack@eecs.umich.edu 'block : LBRACE statements RBRACE' 3684512Sgblack@eecs.umich.edu block = Block() 3694512Sgblack@eecs.umich.edu block.statements = t[2] 3704512Sgblack@eecs.umich.edu t[0] = block 3714512Sgblack@eecs.umich.edu 3724483Sgblack@eecs.umich.edudef p_statements_0(t): 3734483Sgblack@eecs.umich.edu 'statements : statement' 3744483Sgblack@eecs.umich.edu if t[1]: 3754483Sgblack@eecs.umich.edu t[0] = [t[1]] 3764483Sgblack@eecs.umich.edu else: 3774483Sgblack@eecs.umich.edu t[0] = [] 3784483Sgblack@eecs.umich.edu 3794483Sgblack@eecs.umich.edudef p_statements_1(t): 3804483Sgblack@eecs.umich.edu 'statements : statements statement' 3814483Sgblack@eecs.umich.edu if t[2]: 3824483Sgblack@eecs.umich.edu t[1].append(t[2]) 3834483Sgblack@eecs.umich.edu t[0] = t[1] 3844483Sgblack@eecs.umich.edu 3854483Sgblack@eecs.umich.edudef p_statement(t): 3864483Sgblack@eecs.umich.edu 'statement : content_of_statement end_of_statement' 3874483Sgblack@eecs.umich.edu t[0] = t[1] 3884483Sgblack@eecs.umich.edu 3894483Sgblack@eecs.umich.edu# A statement can be a microop or an assembler directive 3904483Sgblack@eecs.umich.edudef p_content_of_statement_0(t): 3914483Sgblack@eecs.umich.edu '''content_of_statement : microop 3924483Sgblack@eecs.umich.edu | directive''' 3934483Sgblack@eecs.umich.edu t[0] = t[1] 3944483Sgblack@eecs.umich.edu 3954512Sgblack@eecs.umich.edu# Ignore empty statements 3964483Sgblack@eecs.umich.edudef p_content_of_statement_1(t): 3974483Sgblack@eecs.umich.edu 'content_of_statement : ' 3984483Sgblack@eecs.umich.edu pass 3994483Sgblack@eecs.umich.edu 4004483Sgblack@eecs.umich.edu# Statements are ended by newlines or a semi colon 4014483Sgblack@eecs.umich.edudef p_end_of_statement(t): 4024483Sgblack@eecs.umich.edu '''end_of_statement : NEWLINE 4034483Sgblack@eecs.umich.edu | SEMI''' 4044483Sgblack@eecs.umich.edu pass 4054483Sgblack@eecs.umich.edu 4064512Sgblack@eecs.umich.edu# Different flavors of microop to avoid shift/reduce errors 4074483Sgblack@eecs.umich.edudef p_microop_0(t): 4084483Sgblack@eecs.umich.edu 'microop : labels ID' 4094483Sgblack@eecs.umich.edu microop = Microop() 4104483Sgblack@eecs.umich.edu microop.labels = t[1] 4114483Sgblack@eecs.umich.edu microop.mnemonic = t[2] 4124483Sgblack@eecs.umich.edu t[0] = microop 4134483Sgblack@eecs.umich.edu 4144483Sgblack@eecs.umich.edudef p_microop_1(t): 4154483Sgblack@eecs.umich.edu 'microop : ID' 4164483Sgblack@eecs.umich.edu microop = Microop() 4174483Sgblack@eecs.umich.edu microop.mnemonic = t[1] 4184483Sgblack@eecs.umich.edu t[0] = microop 4194483Sgblack@eecs.umich.edu 4204483Sgblack@eecs.umich.edudef p_microop_2(t): 4214483Sgblack@eecs.umich.edu 'microop : labels ID PARAMS' 4224483Sgblack@eecs.umich.edu microop = Microop() 4234483Sgblack@eecs.umich.edu microop.labels = t[1] 4244483Sgblack@eecs.umich.edu microop.mnemonic = t[2] 4254483Sgblack@eecs.umich.edu microop.params = t[3] 4264483Sgblack@eecs.umich.edu t[0] = microop 4274483Sgblack@eecs.umich.edu 4284483Sgblack@eecs.umich.edudef p_microop_3(t): 4294483Sgblack@eecs.umich.edu 'microop : ID PARAMS' 4304483Sgblack@eecs.umich.edu microop = Microop() 4314483Sgblack@eecs.umich.edu microop.mnemonic = t[1] 4324483Sgblack@eecs.umich.edu microop.params = t[2] 4334483Sgblack@eecs.umich.edu t[0] = microop 4344483Sgblack@eecs.umich.edu 4354512Sgblack@eecs.umich.edu# Labels in the microcode 4364483Sgblack@eecs.umich.edudef p_labels_0(t): 4374483Sgblack@eecs.umich.edu 'labels : label' 4384483Sgblack@eecs.umich.edu t[0] = [t[1]] 4394483Sgblack@eecs.umich.edu 4404483Sgblack@eecs.umich.edudef p_labels_1(t): 4414483Sgblack@eecs.umich.edu 'labels : labels label' 4424483Sgblack@eecs.umich.edu t[1].append(t[2]) 4434483Sgblack@eecs.umich.edu t[0] = t[1] 4444483Sgblack@eecs.umich.edu 4455009Sgblack@eecs.umich.edu# labels on lines by themselves are attached to the following instruction. 4465009Sgblack@eecs.umich.edudef p_labels_2(t): 4475009Sgblack@eecs.umich.edu 'labels : labels NEWLINE' 4485009Sgblack@eecs.umich.edu t[0] = t[1] 4495009Sgblack@eecs.umich.edu 4504483Sgblack@eecs.umich.edudef p_label_0(t): 4514483Sgblack@eecs.umich.edu 'label : ID COLON' 4524483Sgblack@eecs.umich.edu label = Label() 4534483Sgblack@eecs.umich.edu label.is_extern = False 4544483Sgblack@eecs.umich.edu label.text = t[1] 4554483Sgblack@eecs.umich.edu t[0] = label 4564483Sgblack@eecs.umich.edu 4574483Sgblack@eecs.umich.edudef p_label_1(t): 4584483Sgblack@eecs.umich.edu 'label : EXTERN ID COLON' 4594483Sgblack@eecs.umich.edu label = Label() 4604483Sgblack@eecs.umich.edu label.is_extern = True 4614483Sgblack@eecs.umich.edu label.text = t[2] 4624483Sgblack@eecs.umich.edu t[0] = label 4634483Sgblack@eecs.umich.edu 4644512Sgblack@eecs.umich.edu# Directives for the macroop 4654503Sgblack@eecs.umich.edudef p_directive_0(t): 4664483Sgblack@eecs.umich.edu 'directive : DOT ID' 4674483Sgblack@eecs.umich.edu directive = Directive() 4684483Sgblack@eecs.umich.edu directive.name = t[2] 4694483Sgblack@eecs.umich.edu t[0] = directive 4704483Sgblack@eecs.umich.edu 4714503Sgblack@eecs.umich.edudef p_directive_1(t): 4724503Sgblack@eecs.umich.edu 'directive : DOT ID PARAMS' 4734503Sgblack@eecs.umich.edu directive = Directive() 4744503Sgblack@eecs.umich.edu directive.name = t[2] 4754503Sgblack@eecs.umich.edu directive.params = t[3] 4764503Sgblack@eecs.umich.edu t[0] = directive 4774503Sgblack@eecs.umich.edu 4784483Sgblack@eecs.umich.edu# Parse error handler. Note that the argument here is the offending 4794483Sgblack@eecs.umich.edu# *token*, not a grammar symbol (hence the need to use t.value) 4804483Sgblack@eecs.umich.edudef p_error(t): 4814483Sgblack@eecs.umich.edu if t: 4824483Sgblack@eecs.umich.edu error(t.lineno, "syntax error at '%s'" % t.value) 4834483Sgblack@eecs.umich.edu else: 4844483Sgblack@eecs.umich.edu error(0, "unknown syntax error", True) 4854483Sgblack@eecs.umich.edu 4864483Sgblack@eecs.umich.educlass MicroAssembler(object): 4874483Sgblack@eecs.umich.edu 4884507Sgblack@eecs.umich.edu def __init__(self, macro_type, microops, 4894507Sgblack@eecs.umich.edu rom = None, rom_macroop_type = None): 4904483Sgblack@eecs.umich.edu self.lexer = lex.lex() 4914483Sgblack@eecs.umich.edu self.parser = yacc.yacc() 4924483Sgblack@eecs.umich.edu self.parser.macro_type = macro_type 4934502Sgblack@eecs.umich.edu self.parser.macroops = {} 4944483Sgblack@eecs.umich.edu self.parser.microops = microops 4954483Sgblack@eecs.umich.edu self.parser.rom = rom 4964507Sgblack@eecs.umich.edu self.parser.rom_macroop_type = rom_macroop_type 4974613Sgblack@eecs.umich.edu self.parser.symbols = {} 4984613Sgblack@eecs.umich.edu self.symbols = self.parser.symbols 4994483Sgblack@eecs.umich.edu 5004483Sgblack@eecs.umich.edu def assemble(self, asm): 5014483Sgblack@eecs.umich.edu self.parser.parse(asm, lexer=self.lexer) 5024483Sgblack@eecs.umich.edu macroops = self.parser.macroops 5034502Sgblack@eecs.umich.edu self.parser.macroops = {} 5044483Sgblack@eecs.umich.edu return macroops 505