FuncCallExprAST.py revision 7780
111507SCurtis.Dunham@arm.com# Copyright (c) 1999-2008 Mark D. Hill and David A. Wood 211507SCurtis.Dunham@arm.com# Copyright (c) 2009 The Hewlett-Packard Development Company 311507SCurtis.Dunham@arm.com# All rights reserved. 411507SCurtis.Dunham@arm.com# 511507SCurtis.Dunham@arm.com# Redistribution and use in source and binary forms, with or without 611507SCurtis.Dunham@arm.com# modification, are permitted provided that the following conditions are 711507SCurtis.Dunham@arm.com# met: redistributions of source code must retain the above copyright 811507SCurtis.Dunham@arm.com# notice, this list of conditions and the following disclaimer; 911507SCurtis.Dunham@arm.com# redistributions in binary form must reproduce the above copyright 1011507SCurtis.Dunham@arm.com# notice, this list of conditions and the following disclaimer in the 1111507SCurtis.Dunham@arm.com# documentation and/or other materials provided with the distribution; 1211507SCurtis.Dunham@arm.com# neither the name of the copyright holders nor the names of its 1311507SCurtis.Dunham@arm.com# contributors may be used to endorse or promote products derived from 1411507SCurtis.Dunham@arm.com# this software without specific prior written permission. 1511507SCurtis.Dunham@arm.com# 1611507SCurtis.Dunham@arm.com# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1711507SCurtis.Dunham@arm.com# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1811507SCurtis.Dunham@arm.com# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 1911507SCurtis.Dunham@arm.com# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 2011507SCurtis.Dunham@arm.com# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2111507SCurtis.Dunham@arm.com# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 2211507SCurtis.Dunham@arm.com# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2311507SCurtis.Dunham@arm.com# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2411507SCurtis.Dunham@arm.com# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2511507SCurtis.Dunham@arm.com# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 2611507SCurtis.Dunham@arm.com# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2711507SCurtis.Dunham@arm.com 2811507SCurtis.Dunham@arm.comfrom slicc.ast.ExprAST import ExprAST 2911507SCurtis.Dunham@arm.comfrom slicc.symbols import Func, Type 3011507SCurtis.Dunham@arm.com 3111507SCurtis.Dunham@arm.comclass FuncCallExprAST(ExprAST): 3211507SCurtis.Dunham@arm.com def __init__(self, slicc, proc_name, exprs): 3311507SCurtis.Dunham@arm.com super(FuncCallExprAST, self).__init__(slicc) 3411507SCurtis.Dunham@arm.com self.proc_name = proc_name 3511507SCurtis.Dunham@arm.com self.exprs = exprs 3611507SCurtis.Dunham@arm.com 3711507SCurtis.Dunham@arm.com def __repr__(self): 3811507SCurtis.Dunham@arm.com return "[FuncCallExpr: %s %s]" % (self.proc_name, self.exprs) 3911507SCurtis.Dunham@arm.com 4011507SCurtis.Dunham@arm.com def generate(self, code): 4111507SCurtis.Dunham@arm.com machine = self.state_machine 4211507SCurtis.Dunham@arm.com 4311507SCurtis.Dunham@arm.com if self.proc_name == "DPRINTF": 4411507SCurtis.Dunham@arm.com # Code for inserting the location of the DPRINTF() 4511507SCurtis.Dunham@arm.com # statement in the .sm file in the statement it self. 4611507SCurtis.Dunham@arm.com # 'self.exprs[0].location' represents the location. 4711507SCurtis.Dunham@arm.com # 'format' represents the second argument of the 4811507SCurtis.Dunham@arm.com # original DPRINTF() call. It is left unmodified. 4911507SCurtis.Dunham@arm.com # str_list is used for concatenating the argument 5011507SCurtis.Dunham@arm.com # list following the format specifier. A DPRINTF() 5111507SCurtis.Dunham@arm.com # call may or may not contain any arguments following 5211507SCurtis.Dunham@arm.com # the format specifier. These two cases need to be 5311507SCurtis.Dunham@arm.com # handled differently. Hence the check whether or not 5411507SCurtis.Dunham@arm.com # the str_list is empty. 5511507SCurtis.Dunham@arm.com 5611507SCurtis.Dunham@arm.com format = "%s" % (self.exprs[1].inline()) 5711507SCurtis.Dunham@arm.com format_length = len(format) 5811507SCurtis.Dunham@arm.com str_list = [] 5911507SCurtis.Dunham@arm.com 6011507SCurtis.Dunham@arm.com for i in range(2, len(self.exprs)): 6111507SCurtis.Dunham@arm.com str_list.append("%s" % self.exprs[i].inline()) 6211507SCurtis.Dunham@arm.com 6311507SCurtis.Dunham@arm.com if len(str_list) == 0: 6411507SCurtis.Dunham@arm.com code('DPRINTF(RubySlicc, "$0: $1")', 6511507SCurtis.Dunham@arm.com self.exprs[0].location, format[2:format_length-2]) 6611507SCurtis.Dunham@arm.com else: 6711507SCurtis.Dunham@arm.com code('DPRINTF(RubySlicc, "$0: $1", $2)', 6811507SCurtis.Dunham@arm.com self.exprs[0].location, format[2:format_length-2], 6911507SCurtis.Dunham@arm.com ', '.join(str_list)) 7011507SCurtis.Dunham@arm.com 7111507SCurtis.Dunham@arm.com return self.symtab.find("void", Type) 7211507SCurtis.Dunham@arm.com 7311507SCurtis.Dunham@arm.com # hack for adding comments to profileTransition 7411507SCurtis.Dunham@arm.com if self.proc_name == "APPEND_TRANSITION_COMMENT": 7511507SCurtis.Dunham@arm.com # FIXME - check for number of parameters 7611507SCurtis.Dunham@arm.com code("APPEND_TRANSITION_COMMENT($0)", self.exprs[0].inline()) 7711507SCurtis.Dunham@arm.com return self.symtab.find("void", Type) 7811507SCurtis.Dunham@arm.com 7911507SCurtis.Dunham@arm.com # Look up the function in the symbol table 8011507SCurtis.Dunham@arm.com func = self.symtab.find(self.proc_name, Func) 8111507SCurtis.Dunham@arm.com 8211507SCurtis.Dunham@arm.com # Check the types and get the code for the parameters 8311507SCurtis.Dunham@arm.com if func is None: 8411507SCurtis.Dunham@arm.com self.error("Unrecognized function name: '%s'", self.proc_name) 8511507SCurtis.Dunham@arm.com 8611507SCurtis.Dunham@arm.com if len(self.exprs) != len(func.param_types): 8711507SCurtis.Dunham@arm.com self.error("Wrong number of arguments passed to function : '%s'" +\ 8811507SCurtis.Dunham@arm.com " Expected %d, got %d", self.proc_name, 8911507SCurtis.Dunham@arm.com len(func.param_types), len(self.exprs)) 9011507SCurtis.Dunham@arm.com 9111507SCurtis.Dunham@arm.com cvec = [] 9211507SCurtis.Dunham@arm.com for expr,expected_type in zip(self.exprs, func.param_types): 9311507SCurtis.Dunham@arm.com # Check the types of the parameter 9411507SCurtis.Dunham@arm.com actual_type,param_code = expr.inline(True) 9511507SCurtis.Dunham@arm.com if actual_type != expected_type: 9611507SCurtis.Dunham@arm.com expr.error("Type mismatch: expected: %s actual: %s" % \ 9711507SCurtis.Dunham@arm.com (expected_type, actual_type)) 9811507SCurtis.Dunham@arm.com cvec.append(param_code) 9911507SCurtis.Dunham@arm.com 10011507SCurtis.Dunham@arm.com # OK, the semantics of "trigger" here is that, ports in the 10111507SCurtis.Dunham@arm.com # machine have different priorities. We always check the first 10211507SCurtis.Dunham@arm.com # port for doable transitions. If nothing/stalled, we pick one 10311507SCurtis.Dunham@arm.com # from the next port. 10411507SCurtis.Dunham@arm.com # 10511507SCurtis.Dunham@arm.com # One thing we have to be careful as the SLICC protocol 10611507SCurtis.Dunham@arm.com # writter is : If a port have two or more transitions can be 10711507SCurtis.Dunham@arm.com # picked from in one cycle, they must be independent. 10811507SCurtis.Dunham@arm.com # Otherwise, if transition A and B mean to be executed in 10911507SCurtis.Dunham@arm.com # sequential, and A get stalled, transition B can be issued 11011507SCurtis.Dunham@arm.com # erroneously. In practice, in most case, there is only one 11111507SCurtis.Dunham@arm.com # transition should be executed in one cycle for a given 11211507SCurtis.Dunham@arm.com # port. So as most of current protocols. 11311507SCurtis.Dunham@arm.com 11411507SCurtis.Dunham@arm.com if self.proc_name == "trigger": 11511507SCurtis.Dunham@arm.com code(''' 11611507SCurtis.Dunham@arm.com{ 11711507SCurtis.Dunham@arm.com Address addr = ${{cvec[1]}}; 11811507SCurtis.Dunham@arm.com TransitionResult result = doTransition(${{cvec[0]}}, ${machine}_getState(addr), addr); 11911507SCurtis.Dunham@arm.com 12011507SCurtis.Dunham@arm.com if (result == TransitionResult_Valid) { 12111507SCurtis.Dunham@arm.com counter++; 12211507SCurtis.Dunham@arm.com continue; // Check the first port again 12311507SCurtis.Dunham@arm.com } 12411507SCurtis.Dunham@arm.com 12511507SCurtis.Dunham@arm.com if (result == TransitionResult_ResourceStall) { 12611507SCurtis.Dunham@arm.com g_eventQueue_ptr->scheduleEvent(this, 1); 12711507SCurtis.Dunham@arm.com 12811507SCurtis.Dunham@arm.com // Cannot do anything with this transition, go check next doable transition (mostly likely of next port) 12911507SCurtis.Dunham@arm.com } 13011507SCurtis.Dunham@arm.com} 13111507SCurtis.Dunham@arm.com''') 13211507SCurtis.Dunham@arm.com elif self.proc_name == "doubleTrigger": 13311507SCurtis.Dunham@arm.com # NOTE: Use the doubleTrigger call with extreme caution 13411507SCurtis.Dunham@arm.com # the key to double trigger is the second event triggered 13511507SCurtis.Dunham@arm.com # cannot fail becuase the first event cannot be undone 13611507SCurtis.Dunham@arm.com assert len(cvec) == 4 13711507SCurtis.Dunham@arm.com code(''' 13811507SCurtis.Dunham@arm.com{ 13911507SCurtis.Dunham@arm.com Address addr1 = ${{cvec[1]}}; 14011507SCurtis.Dunham@arm.com TransitionResult result1 = 14111507SCurtis.Dunham@arm.com doTransition(${{cvec[0]}}, ${machine}_getState(addr1), addr1); 14211507SCurtis.Dunham@arm.com 14311507SCurtis.Dunham@arm.com if (result1 == TransitionResult_Valid) { 14411507SCurtis.Dunham@arm.com //this second event cannont fail because the first event 14511507SCurtis.Dunham@arm.com // already took effect 14611507SCurtis.Dunham@arm.com Address addr2 = ${{cvec[3]}}; 14711507SCurtis.Dunham@arm.com TransitionResult result2 = doTransition(${{cvec[2]}}, ${machine}_getState(addr2), addr2); 14811507SCurtis.Dunham@arm.com 14911507SCurtis.Dunham@arm.com // ensure the event suceeded 15011507SCurtis.Dunham@arm.com assert(result2 == TransitionResult_Valid); 15111507SCurtis.Dunham@arm.com 15211507SCurtis.Dunham@arm.com counter++; 15311507SCurtis.Dunham@arm.com continue; // Check the first port again 15411507SCurtis.Dunham@arm.com } 15511507SCurtis.Dunham@arm.com 15611507SCurtis.Dunham@arm.com if (result1 == TransitionResult_ResourceStall) { 15711507SCurtis.Dunham@arm.com g_eventQueue_ptr->scheduleEvent(this, 1); 15811507SCurtis.Dunham@arm.com // Cannot do anything with this transition, go check next 15911507SCurtis.Dunham@arm.com // doable transition (mostly likely of next port) 16011507SCurtis.Dunham@arm.com } 16111507SCurtis.Dunham@arm.com} 16211507SCurtis.Dunham@arm.com''') 16311507SCurtis.Dunham@arm.com elif self.proc_name == "error": 16411507SCurtis.Dunham@arm.com code("$0", self.exprs[0].embedError(cvec[0])) 16511507SCurtis.Dunham@arm.com elif self.proc_name == "assert": 16611507SCurtis.Dunham@arm.com error = self.exprs[0].embedError('"assert failure"') 16711507SCurtis.Dunham@arm.com code(''' 16811507SCurtis.Dunham@arm.comif (ASSERT_FLAG && !(${{cvec[0]}})) { 16911507SCurtis.Dunham@arm.com $error 17011507SCurtis.Dunham@arm.com} 17111507SCurtis.Dunham@arm.com''') 17211507SCurtis.Dunham@arm.com 17311507SCurtis.Dunham@arm.com elif self.proc_name == "continueProcessing": 17411507SCurtis.Dunham@arm.com code("counter++;") 17511507SCurtis.Dunham@arm.com code("continue; // Check the first port again") 17611507SCurtis.Dunham@arm.com else: 17711507SCurtis.Dunham@arm.com # Normal function 17811507SCurtis.Dunham@arm.com 17911507SCurtis.Dunham@arm.com # if the func is internal to the chip but not the machine 18011507SCurtis.Dunham@arm.com # then it can only be accessed through the chip pointer 18111507SCurtis.Dunham@arm.com internal = "" 18211507SCurtis.Dunham@arm.com if "external" not in func and not func.isInternalMachineFunc: 18311507SCurtis.Dunham@arm.com internal = "m_chip_ptr->" 18411507SCurtis.Dunham@arm.com 18511507SCurtis.Dunham@arm.com params = ', '.join(str(c) for c in cvec) 18611507SCurtis.Dunham@arm.com fix = code.nofix() 18711507SCurtis.Dunham@arm.com code('(${internal}${{func.c_ident}}($params))') 18811507SCurtis.Dunham@arm.com code.fix(fix) 18911507SCurtis.Dunham@arm.com 19011507SCurtis.Dunham@arm.com return func.return_type 19111507SCurtis.Dunham@arm.com