diff options
Diffstat (limited to 'src/mem/slicc/ast')
-rw-r--r-- | src/mem/slicc/ast/ActionDeclAST.py | 19 | ||||
-rw-r--r-- | src/mem/slicc/ast/FormalParamAST.py | 16 | ||||
-rw-r--r-- | src/mem/slicc/ast/FuncCallExprAST.py | 53 | ||||
-rw-r--r-- | src/mem/slicc/ast/IfStatementAST.py | 4 | ||||
-rw-r--r-- | src/mem/slicc/ast/InPortDeclAST.py | 14 | ||||
-rw-r--r-- | src/mem/slicc/ast/IsValidPtrExprAST.py | 53 | ||||
-rw-r--r-- | src/mem/slicc/ast/LocalVariableAST.py | 54 | ||||
-rw-r--r-- | src/mem/slicc/ast/MethodCallExprAST.py | 95 | ||||
-rw-r--r-- | src/mem/slicc/ast/OodAST.py | 40 | ||||
-rw-r--r-- | src/mem/slicc/ast/ReturnStatementAST.py | 2 | ||||
-rw-r--r-- | src/mem/slicc/ast/StaticCastAST.py | 8 | ||||
-rw-r--r-- | src/mem/slicc/ast/TypeDeclAST.py | 5 | ||||
-rw-r--r-- | src/mem/slicc/ast/__init__.py | 3 |
13 files changed, 312 insertions, 54 deletions
diff --git a/src/mem/slicc/ast/ActionDeclAST.py b/src/mem/slicc/ast/ActionDeclAST.py index e85aa25b8..2a8fb0639 100644 --- a/src/mem/slicc/ast/ActionDeclAST.py +++ b/src/mem/slicc/ast/ActionDeclAST.py @@ -39,6 +39,11 @@ class ActionDeclAST(DeclAST): def generate(self): resources = {} + + machine = self.symtab.state_machine + if machine is None: + self.error("Action declaration not part of a machine.") + if self.statement_list: # Add new local vars self.symtab.pushFrame() @@ -52,6 +57,16 @@ class ActionDeclAST(DeclAST): "addr", self.pairs) self.symtab.newSymbol(var) + if machine.TBEType != None: + var = Var(self.symtab, "tbe", self.location, machine.TBEType, + "(*m_tbe_ptr)", self.pairs) + self.symtab.newSymbol(var) + + if machine.EntryType != None: + var = Var(self.symtab, "cache_entry", self.location, + machine.EntryType, "(*m_cache_entry_ptr)", self.pairs) + self.symtab.newSymbol(var) + # Do not allows returns in actions code = self.slicc.codeFormatter() self.statement_list.generate(code, None) @@ -61,10 +76,6 @@ class ActionDeclAST(DeclAST): self.symtab.popFrame() - machine = self.symtab.state_machine - if machine is None: - self.error("Action declaration not part of a machine.") - action = Action(self.symtab, self.ident, resources, self.location, self.pairs) machine.addAction(action) diff --git a/src/mem/slicc/ast/FormalParamAST.py b/src/mem/slicc/ast/FormalParamAST.py index c64731196..142e837cc 100644 --- a/src/mem/slicc/ast/FormalParamAST.py +++ b/src/mem/slicc/ast/FormalParamAST.py @@ -48,7 +48,17 @@ class FormalParamAST(AST): param = "param_%s" % self.ident # Add to symbol table - v = Var(self.symtab, self.ident, self.location, type, param, - self.pairs) - self.symtab.newSymbol(v) + if self.pointer or str(type) == "TBE" or ( + "interface" in type and type["interface"] == "AbstractCacheEntry"): + + v = Var(self.symtab, self.ident, self.location, type, + "(*%s)" % param, self.pairs) + self.symtab.newSymbol(v) + return type, "%s* %s" % (type.c_ident, param) + + else: + v = Var(self.symtab, self.ident, self.location, type, param, + self.pairs) + self.symtab.newSymbol(v) + return type, "%s %s" % (type.c_ident, param) diff --git a/src/mem/slicc/ast/FuncCallExprAST.py b/src/mem/slicc/ast/FuncCallExprAST.py index 829203d53..2c5e9ea4d 100644 --- a/src/mem/slicc/ast/FuncCallExprAST.py +++ b/src/mem/slicc/ast/FuncCallExprAST.py @@ -89,6 +89,7 @@ class FuncCallExprAST(ExprAST): len(func.param_types), len(self.exprs)) cvec = [] + type_vec = [] for expr,expected_type in zip(self.exprs, func.param_types): # Check the types of the parameter actual_type,param_code = expr.inline(True) @@ -96,6 +97,7 @@ class FuncCallExprAST(ExprAST): expr.error("Type mismatch: expected: %s actual: %s" % \ (expected_type, actual_type)) cvec.append(param_code) + type_vec.append(expected_type) # OK, the semantics of "trigger" here is that, ports in the # machine have different priorities. We always check the first @@ -115,8 +117,25 @@ class FuncCallExprAST(ExprAST): code(''' { Address addr = ${{cvec[1]}}; - TransitionResult result = doTransition(${{cvec[0]}}, ${machine}_getState(addr), addr); +''') + if machine.TBEType != None and machine.EntryType != None: + code(''' + TransitionResult result = doTransition(${{cvec[0]}}, ${{cvec[2]}}, ${{cvec[3]}}, addr); +''') + elif machine.TBEType != None: + code(''' + TransitionResult result = doTransition(${{cvec[0]}}, ${{cvec[2]}}, addr); +''') + elif machine.EntryType != None: + code(''' + TransitionResult result = doTransition(${{cvec[0]}}, ${{cvec[2]}}, addr); +''') + else: + code(''' + TransitionResult result = doTransition(${{cvec[0]}}, addr); +''') + code(''' if (result == TransitionResult_Valid) { counter++; continue; // Check the first port again @@ -175,6 +194,16 @@ if (!(${{cvec[0]}})) { elif self.proc_name == "continueProcessing": code("counter++;") code("continue; // Check the first port again") + + elif self.proc_name == "set_cache_entry": + code("set_cache_entry(m_cache_entry_ptr, %s);" %(cvec[0])); + elif self.proc_name == "unset_cache_entry": + code("unset_cache_entry(m_cache_entry_ptr);"); + elif self.proc_name == "set_tbe": + code("set_tbe(m_tbe_ptr, %s);" %(cvec[0])); + elif self.proc_name == "unset_tbe": + code("unset_tbe(m_tbe_ptr);"); + else: # Normal function @@ -184,7 +213,27 @@ if (!(${{cvec[0]}})) { if "external" not in func and not func.isInternalMachineFunc: internal = "m_chip_ptr->" - params = ', '.join(str(c) for c in cvec) + params = "" + first_param = True + + for (param_code, type) in zip(cvec, type_vec): + if str(type) == "TBE" or ("interface" in type and + type["interface"] == "AbstractCacheEntry"): + + if first_param: + params = str(param_code).replace('*','') + first_param = False + else: + params += ', ' + params += str(param_code).replace('*',''); + else: + if first_param: + params = str(param_code) + first_param = False + else: + params += ', ' + params += str(param_code); + fix = code.nofix() code('(${internal}${{func.c_ident}}($params))') code.fix(fix) diff --git a/src/mem/slicc/ast/IfStatementAST.py b/src/mem/slicc/ast/IfStatementAST.py index 359173203..0e023195c 100644 --- a/src/mem/slicc/ast/IfStatementAST.py +++ b/src/mem/slicc/ast/IfStatementAST.py @@ -55,13 +55,17 @@ class IfStatementAST(StatementAST): code('if ($cond_code) {') # Then part code.indent() + self.symtab.pushFrame() self.then.generate(code, return_type) + self.symtab.popFrame() code.dedent() # Else part if self.else_: code('} else {') code.indent() + self.symtab.pushFrame() self.else_.generate(code, return_type) + self.symtab.popFrame() code.dedent() code('}') # End scope diff --git a/src/mem/slicc/ast/InPortDeclAST.py b/src/mem/slicc/ast/InPortDeclAST.py index 5aa27bae8..c6fadb9e7 100644 --- a/src/mem/slicc/ast/InPortDeclAST.py +++ b/src/mem/slicc/ast/InPortDeclAST.py @@ -51,6 +51,10 @@ class InPortDeclAST(DeclAST): symtab = self.symtab void_type = symtab.find("void", Type) + machine = symtab.state_machine + if machine is None: + self.error("InPort declaration not part of a machine.") + code = self.slicc.codeFormatter() queue_type = self.var_expr.generate(code) if not queue_type.isInPort: @@ -79,6 +83,11 @@ class InPortDeclAST(DeclAST): param_types.append(type) + if machine.EntryType != None: + param_types.append(machine.EntryType) + if machine.TBEType != None: + param_types.append(machine.TBEType) + # Add the trigger method - FIXME, this is a bit dirty pairs = { "external" : "yes" } func = Func(self.symtab, "trigger", self.location, void_type, @@ -123,13 +132,10 @@ class InPortDeclAST(DeclAST): rcode.indent() self.statements.generate(rcode, None) in_port["c_code_in_port"] = str(rcode) + symtab.popFrame() # Add port to state machine - machine = symtab.state_machine - if machine is None: - self.error("InPort declaration not part of a machine.") - machine.addInPort(in_port) # Include max_rank to be used by StateMachine.py diff --git a/src/mem/slicc/ast/IsValidPtrExprAST.py b/src/mem/slicc/ast/IsValidPtrExprAST.py new file mode 100644 index 000000000..850f45e96 --- /dev/null +++ b/src/mem/slicc/ast/IsValidPtrExprAST.py @@ -0,0 +1,53 @@ +# +# Copyright (c) 2011 Mark D. Hill and David A. Wood +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +from slicc.ast.ExprAST import ExprAST +from slicc.symbols import Type + +class IsValidPtrExprAST(ExprAST): + def __init__(self, slicc, variable, flag): + super(IsValidPtrExprAST, self).__init__(slicc) + self.variable = variable + self.flag = flag + + def __repr__(self): + return "[IsValidPtrExprAST: %r]" % self.variable + + def generate(self, code): + # Make sure the variable is valid + fix = code.nofix() + code("(") + var_type, var_code = self.variable.inline(True); + var_code_str = str(var_code).replace('*','') + if self.flag: + code("${var_code_str} != NULL)") + else: + code("${var_code_str} == NULL)") + code.fix(fix) + type = self.symtab.find("bool", Type) + return type diff --git a/src/mem/slicc/ast/LocalVariableAST.py b/src/mem/slicc/ast/LocalVariableAST.py new file mode 100644 index 000000000..82e73ba7a --- /dev/null +++ b/src/mem/slicc/ast/LocalVariableAST.py @@ -0,0 +1,54 @@ +# +# Copyright (c) 2011 Mark D. Hill and David A. Wood +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +from slicc.ast.StatementAST import StatementAST +from slicc.symbols import Var + +class LocalVariableAST(StatementAST): + def __init__(self, slicc, type_ast, ident): + super(LocalVariableAST, self).__init__(slicc) + self.type_ast = type_ast + self.ident = ident + + def __repr__(self): + return "[LocalVariableAST: %r %r]" % (self.type_ast, self.ident) + + @property + def name(self): + return self.var_name + + def generate(self, code): + type = self.type_ast.type; + ident = "%s" % self.ident; + + # Add to symbol table + v = Var(self.symtab, self.ident, self.location, type, ident, + self.pairs) + self.symtab.newSymbol(v) + code += "%s* %s" % (type.c_ident, ident) + return type diff --git a/src/mem/slicc/ast/MethodCallExprAST.py b/src/mem/slicc/ast/MethodCallExprAST.py index 84009c076..6a2977533 100644 --- a/src/mem/slicc/ast/MethodCallExprAST.py +++ b/src/mem/slicc/ast/MethodCallExprAST.py @@ -97,48 +97,67 @@ class MemberMethodCallExprAST(MethodCallExprAST): prefix = "" implements_interface = False - if methodId not in obj_type.methods: - # - # The initial method check has failed, but before generating an - # error we must check whether any of the paramTypes implement - # an interface. If so, we must check if the method ids using - # the inherited types exist. - # - # This code is a temporary fix and only checks for the methodId - # where all paramTypes are converted to their inherited type. The - # right way to do this is to replace slicc's simple string - # comparison for determining the correct overloaded method, with a - # more robust param by param check. + + if methodId in obj_type.methods: + return_type = obj_type.methods[methodId].return_type + + else: # - implemented_paramTypes = [] - for paramType in paramTypes: - implemented_paramType = paramType - if paramType.isInterface: - implements_interface = True - implemented_paramType.abstract_ident = paramType["interface"] + # Check whether the method is implemented by the super class + if "interface" in obj_type: + interface_type = self.symtab.find(obj_type["interface"]); + + if methodId in interface_type.methods: + return_type = interface_type.methods[methodId].return_type + obj_type = interface_type + else: - implemented_paramType.abstract_ident = paramType.c_ident - - implemented_paramTypes.append(implemented_paramType) + self.error("Invalid method call: " \ + "Type '%s' does not have a method %s, '%s'", + obj_type, self.proc_name, methodId) - if implements_interface: - implementedMethodId = obj_type.methodIdAbstract(self.proc_name, - implemented_paramTypes) else: - implementedMethodId = "" - - if implementedMethodId not in obj_type.methods: - self.error("Invalid method call: " \ - "Type '%s' does not have a method '%s' nor '%s'", - obj_type, methodId, implementedMethodId) - else: - # - # Replace the methodId with the implementedMethodId found in - # the method list. - # - methodId = implementedMethodId - - return_type = obj_type.methods[methodId].return_type + # + # The initial method check has failed, but before generating an + # error we must check whether any of the paramTypes implement + # an interface. If so, we must check if the method ids using + # the inherited types exist. + # + # This code is a temporary fix and only checks for the methodId + # where all paramTypes are converted to their inherited type. The + # right way to do this is to replace slicc's simple string + # comparison for determining the correct overloaded method, with a + # more robust param by param check. + # + implemented_paramTypes = [] + for paramType in paramTypes: + implemented_paramType = paramType + if paramType.isInterface: + implements_interface = True + implemented_paramType.abstract_ident = paramType["interface"] + else: + implemented_paramType.abstract_ident = paramType.c_ident + + implemented_paramTypes.append(implemented_paramType) + + if implements_interface: + implementedMethodId = obj_type.methodIdAbstract(self.proc_name, + implemented_paramTypes) + else: + implementedMethodId = "" + + if implementedMethodId not in obj_type.methods: + self.error("Invalid method call: " \ + "Type '%s' does not have a method %s, '%s' nor '%s'", + obj_type, self.proc_name, methodId, implementedMethodId) + else: + # + # Replace the methodId with the implementedMethodId found in + # the method list. + # + methodId = implementedMethodId + return_type = obj_type.methods[methodId].return_type + if return_type.isInterface: prefix = "static_cast<%s &>" % return_type.c_ident prefix = "%s((%s)." % (prefix, code) diff --git a/src/mem/slicc/ast/OodAST.py b/src/mem/slicc/ast/OodAST.py new file mode 100644 index 000000000..0f4cf141c --- /dev/null +++ b/src/mem/slicc/ast/OodAST.py @@ -0,0 +1,40 @@ +# +# Copyright (c) 2011 Mark D. Hill and David A. Wood +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +from slicc.ast.ExprAST import ExprAST + +class OodAST(ExprAST): + def __init__(self, slicc): + super(OodAST, self).__init__(slicc) + + def __repr__(self): + return "[Ood:]" + + def generate(self, code): + code += "NULL" + return "OOD" diff --git a/src/mem/slicc/ast/ReturnStatementAST.py b/src/mem/slicc/ast/ReturnStatementAST.py index f1aff1c32..754bb4c9f 100644 --- a/src/mem/slicc/ast/ReturnStatementAST.py +++ b/src/mem/slicc/ast/ReturnStatementAST.py @@ -45,7 +45,7 @@ class ReturnStatementAST(StatementAST): self.error("Invalid 'return' statement") # The return type must match - if return_type != actual_type: + if actual_type != "OOD" and return_type != actual_type: self.expr_ast.error("Return type miss-match, expected return " + "type is '%s', actual is '%s'", return_type, actual_type) diff --git a/src/mem/slicc/ast/StaticCastAST.py b/src/mem/slicc/ast/StaticCastAST.py index 3a48f398e..71280ba67 100644 --- a/src/mem/slicc/ast/StaticCastAST.py +++ b/src/mem/slicc/ast/StaticCastAST.py @@ -27,18 +27,22 @@ from slicc.ast.ExprAST import ExprAST class StaticCastAST(ExprAST): - def __init__(self, slicc, type_ast, expr_ast): + def __init__(self, slicc, type_ast, type_modifier, expr_ast): super(StaticCastAST, self).__init__(slicc) self.type_ast = type_ast self.expr_ast = expr_ast + self.type_modifier = type_modifier def __repr__(self): return "[StaticCastAST: %r]" % self.expr_ast def generate(self, code): actual_type, ecode = self.expr_ast.inline(True) - code('static_cast<${{self.type_ast.type.c_ident}} &>($ecode)') + if self.type_modifier == "pointer": + code('static_cast<${{self.type_ast.type.c_ident}} *>($ecode)') + else: + code('static_cast<${{self.type_ast.type.c_ident}} &>($ecode)') if not "interface" in self.type_ast.type: self.expr_ast.error("static cast only premitted for those types " \ diff --git a/src/mem/slicc/ast/TypeDeclAST.py b/src/mem/slicc/ast/TypeDeclAST.py index ecdb5949b..983e86882 100644 --- a/src/mem/slicc/ast/TypeDeclAST.py +++ b/src/mem/slicc/ast/TypeDeclAST.py @@ -50,10 +50,15 @@ class TypeDeclAST(DeclAST): def generate(self): ident = str(self.type_ast) + machine = self.symtab.state_machine # Make the new type new_type = Type(self.symtab, ident, self.location, self.pairs, self.state_machine) + + if machine: + machine.addType(new_type) + self.symtab.newSymbol(new_type) # Add all of the fields of the type to it diff --git a/src/mem/slicc/ast/__init__.py b/src/mem/slicc/ast/__init__.py index b854612be..ae797ecd3 100644 --- a/src/mem/slicc/ast/__init__.py +++ b/src/mem/slicc/ast/__init__.py @@ -46,11 +46,14 @@ from slicc.ast.FuncDeclAST import * from slicc.ast.IfStatementAST import * from slicc.ast.InPortDeclAST import * from slicc.ast.InfixOperatorExprAST import * +from slicc.ast.IsValidPtrExprAST import * from slicc.ast.LiteralExprAST import * +from slicc.ast.LocalVariableAST import * from slicc.ast.MachineAST import * from slicc.ast.MemberExprAST import * from slicc.ast.MethodCallExprAST import * from slicc.ast.NewExprAST import * +from slicc.ast.OodAST import * from slicc.ast.ObjDeclAST import * from slicc.ast.OutPortDeclAST import * from slicc.ast.PairAST import * |