diff options
Diffstat (limited to 'src/mem/slicc')
-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 | ||||
-rw-r--r-- | src/mem/slicc/parser.py | 25 | ||||
-rw-r--r-- | src/mem/slicc/symbols/Func.py | 4 | ||||
-rw-r--r-- | src/mem/slicc/symbols/StateMachine.py | 241 |
16 files changed, 565 insertions, 71 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 * diff --git a/src/mem/slicc/parser.py b/src/mem/slicc/parser.py index ce665465f..bb958f746 100644 --- a/src/mem/slicc/parser.py +++ b/src/mem/slicc/parser.py @@ -165,12 +165,15 @@ class SLICC(Grammar): 'check_stop_slots' : 'CHECK_STOP_SLOTS', 'static_cast' : 'STATIC_CAST', 'if' : 'IF', + 'is_valid' : 'IS_VALID', + 'is_invalid' : 'IS_INVALID', 'else' : 'ELSE', 'return' : 'RETURN', 'THIS' : 'THIS', 'CHIP' : 'CHIP', 'void' : 'VOID', 'new' : 'NEW', + 'OOD' : 'OOD', } literals = ':[]{}(),=' @@ -576,7 +579,11 @@ class SLICC(Grammar): def p_statement__static_cast(self, p): "aexpr : STATIC_CAST '(' type ',' expr ')'" - p[0] = ast.StaticCastAST(self, p[3], p[5]) + p[0] = ast.StaticCastAST(self, p[3], "ref", p[5]) + + def p_statement__static_cast_ptr(self, p): + "aexpr : STATIC_CAST '(' type ',' STRING ',' expr ')'" + p[0] = ast.StaticCastAST(self, p[3], p[5], p[7]) def p_statement__return(self, p): "statement : RETURN expr SEMI" @@ -603,6 +610,10 @@ class SLICC(Grammar): "aexpr : var" p[0] = p[1] + def p_expr__localvar(self, p): + "aexpr : type ident" + p[0] = ast.LocalVariableAST(self, p[1], p[2]) + def p_expr__literal(self, p): "aexpr : literal" p[0] = p[1] @@ -619,6 +630,10 @@ class SLICC(Grammar): "aexpr : NEW type" p[0] = ast.NewExprAST(self, p[2]) + def p_expr__null(self, p): + "aexpr : OOD" + p[0] = ast.OodAST(self) + # globally access a local chip component and call a method def p_expr__local_chip_method(self, p): "aexpr : THIS DOT var '[' expr ']' DOT var DOT ident '(' exprs ')'" @@ -687,6 +702,14 @@ class SLICC(Grammar): "aexpr : '(' expr ')'" p[0] = p[2] + def p_expr__is_valid_ptr(self, p): + "aexpr : IS_VALID '(' var ')'" + p[0] = ast.IsValidPtrExprAST(self, p[3], True) + + def p_expr__is_invalid_ptr(self, p): + "aexpr : IS_INVALID '(' var ')'" + p[0] = ast.IsValidPtrExprAST(self, p[3], False) + def p_literal__string(self, p): "literal : STRING" p[0] = ast.LiteralExprAST(self, p[1], "std::string") diff --git a/src/mem/slicc/symbols/Func.py b/src/mem/slicc/symbols/Func.py index a5751344a..e1670e3ed 100644 --- a/src/mem/slicc/symbols/Func.py +++ b/src/mem/slicc/symbols/Func.py @@ -60,6 +60,8 @@ class Func(Symbol): void_type = self.symtab.find("void", Type) if "return_by_ref" in self and self.return_type != void_type: return_type += "&" + elif "return_by_pointer" in self and self.return_type != void_type: + return_type += "*" return "%s %s(%s);" % (return_type, self.c_ident, ", ".join(self.param_strings)) @@ -87,6 +89,8 @@ class Func(Symbol): return_type = self.return_type.c_ident if "return_by_ref" in self and self.return_type != void_type: return_type += "&" + if "return_by_pointer" in self and self.return_type != void_type: + return_type += "*" if self.isInternalMachineFunc: klass = "%s_Controller" % self.machineStr diff --git a/src/mem/slicc/symbols/StateMachine.py b/src/mem/slicc/symbols/StateMachine.py index 145284726..b0d663c43 100644 --- a/src/mem/slicc/symbols/StateMachine.py +++ b/src/mem/slicc/symbols/StateMachine.py @@ -46,6 +46,7 @@ class StateMachine(Symbol): super(StateMachine, self).__init__(symtab, ident, location, pairs) self.table = None self.config_parameters = config_parameters + for param in config_parameters: if param.pointer: var = Var(symtab, param.name, location, param.type_ast.type, @@ -62,6 +63,8 @@ class StateMachine(Symbol): self.in_ports = [] self.functions = [] self.objects = [] + self.TBEType = None + self.EntryType = None self.message_buffer_names = [] @@ -107,6 +110,21 @@ class StateMachine(Symbol): def addObject(self, obj): self.objects.append(obj) + def addType(self, type): + type_ident = '%s' % type.c_ident + + if type_ident == "%s_TBE" %self.ident: + if self.TBEType != None: + self.error("Multiple Transaction Buffer types in a " \ + "single machine."); + self.TBEType = type + + elif "interface" in type and "AbstractCacheEntry" == type["interface"]: + if self.EntryType != None: + self.error("Multiple AbstractCacheEntry types in a " \ + "single machine."); + self.EntryType = type + # Needs to be called before accessing the table def buildTable(self): assert self.table is None @@ -264,12 +282,35 @@ private: int m_number_of_TBEs; TransitionResult doTransition(${ident}_Event event, - ${ident}_State state, +''') + + if self.EntryType != None: + code(''' + ${{self.EntryType.c_ident}}* m_cache_entry_ptr, +''') + if self.TBEType != None: + code(''' + ${{self.TBEType.c_ident}}* m_tbe_ptr, +''') + + code(''' const Address& addr); TransitionResult doTransitionWorker(${ident}_Event event, ${ident}_State state, ${ident}_State& next_state, +''') + + if self.TBEType != None: + code(''' + ${{self.TBEType.c_ident}}*& m_tbe_ptr, +''') + if self.EntryType != None: + code(''' + ${{self.EntryType.c_ident}}*& m_cache_entry_ptr, +''') + + code(''' const Address& addr); std::string m_name; @@ -299,13 +340,42 @@ static int m_num_controllers; if proto: code('$proto') + if self.EntryType != None: + code(''' + +// Set and Reset for cache_entry variable +void set_cache_entry(${{self.EntryType.c_ident}}*& m_cache_entry_ptr, AbstractCacheEntry* m_new_cache_entry); +void unset_cache_entry(${{self.EntryType.c_ident}}*& m_cache_entry_ptr); +''') + + if self.TBEType != None: + code(''' + +// Set and Reset for tbe variable +void set_tbe(${{self.TBEType.c_ident}}*& m_tbe_ptr, ${ident}_TBE* m_new_tbe); +void unset_tbe(${{self.TBEType.c_ident}}*& m_tbe_ptr); +''') + code(''' // Actions ''') - for action in self.actions.itervalues(): - code('/** \\brief ${{action.desc}} */') - code('void ${{action.ident}}(const Address& addr);') + if self.TBEType != None and self.EntryType != None: + for action in self.actions.itervalues(): + code('/** \\brief ${{action.desc}} */') + code('void ${{action.ident}}(${{self.TBEType.c_ident}}*& m_tbe_ptr, ${{self.EntryType.c_ident}}*& m_cache_entry_ptr, const Address& addr);') + elif self.TBEType != None: + for action in self.actions.itervalues(): + code('/** \\brief ${{action.desc}} */') + code('void ${{action.ident}}(${{self.TBEType.c_ident}}*& m_tbe_ptr, const Address& addr);') + elif self.EntryType != None: + for action in self.actions.itervalues(): + code('/** \\brief ${{action.desc}} */') + code('void ${{action.ident}}(${{self.EntryType.c_ident}}*& m_cache_entry_ptr, const Address& addr);') + else: + for action in self.actions.itervalues(): + code('/** \\brief ${{action.desc}} */') + code('void ${{action.ident}}(const Address& addr);') # the controller internal variables code(''' @@ -731,15 +801,97 @@ void $c_ident::clearStats() { code(''' m_profiler.clearStats(); } +''') + + if self.EntryType != None: + code(''' + +// Set and Reset for cache_entry variable +void +$c_ident::set_cache_entry(${{self.EntryType.c_ident}}*& m_cache_entry_ptr, AbstractCacheEntry* m_new_cache_entry) +{ + m_cache_entry_ptr = (${{self.EntryType.c_ident}}*)m_new_cache_entry; +} + +void +$c_ident::unset_cache_entry(${{self.EntryType.c_ident}}*& m_cache_entry_ptr) +{ + m_cache_entry_ptr = 0; +} +''') + + if self.TBEType != None: + code(''' + +// Set and Reset for tbe variable +void +$c_ident::set_tbe(${{self.TBEType.c_ident}}*& m_tbe_ptr, ${{self.TBEType.c_ident}}* m_new_tbe) +{ + m_tbe_ptr = m_new_tbe; +} + +void +$c_ident::unset_tbe(${{self.TBEType.c_ident}}*& m_tbe_ptr) +{ + m_tbe_ptr = NULL; +} +''') + + code(''' // Actions ''') + if self.TBEType != None and self.EntryType != None: + for action in self.actions.itervalues(): + if "c_code" not in action: + continue - for action in self.actions.itervalues(): - if "c_code" not in action: - continue + code(''' +/** \\brief ${{action.desc}} */ +void +$c_ident::${{action.ident}}(${{self.TBEType.c_ident}}*& m_tbe_ptr, ${{self.EntryType.c_ident}}*& m_cache_entry_ptr, const Address& addr) +{ + DPRINTF(RubyGenerated, "executing\\n"); + ${{action["c_code"]}} +} - code(''' +''') + elif self.TBEType != None: + for action in self.actions.itervalues(): + if "c_code" not in action: + continue + + code(''' +/** \\brief ${{action.desc}} */ +void +$c_ident::${{action.ident}}(${{self.TBEType.c_ident}}*& m_tbe_ptr, const Address& addr) +{ + DPRINTF(RubyGenerated, "executing\\n"); + ${{action["c_code"]}} +} + +''') + elif self.EntryType != None: + for action in self.actions.itervalues(): + if "c_code" not in action: + continue + + code(''' +/** \\brief ${{action.desc}} */ +void +$c_ident::${{action.ident}}(${{self.EntryType.c_ident}}*& m_cache_entry_ptr, const Address& addr) +{ + DPRINTF(RubyGenerated, "executing\\n"); + ${{action["c_code"]}} +} + +''') + else: + for action in self.actions.itervalues(): + if "c_code" not in action: + continue + + code(''' /** \\brief ${{action.desc}} */ void $c_ident::${{action.ident}}(const Address& addr) @@ -777,9 +929,6 @@ using namespace std; void ${ident}_Controller::wakeup() { - // DEBUG_EXPR(GENERATED_COMP, MedPrio, *this); - // DEBUG_EXPR(GENERATED_COMP, MedPrio, g_eventQueue_ptr->getTime()); - int counter = 0; while (true) { // Some cases will put us into an infinite loop without this limit @@ -850,9 +999,29 @@ ${ident}_Controller::wakeup() TransitionResult ${ident}_Controller::doTransition(${ident}_Event event, - ${ident}_State state, +''') + if self.EntryType != None: + code(''' + ${{self.EntryType.c_ident}}* m_cache_entry_ptr, +''') + if self.TBEType != None: + code(''' + ${{self.TBEType.c_ident}}* m_tbe_ptr, +''') + code(''' const Address &addr) { +''') + if self.TBEType != None and self.EntryType != None: + code('${ident}_State state = ${ident}_getState(m_tbe_ptr, m_cache_entry_ptr, addr);') + elif self.TBEType != None: + code('${ident}_State state = ${ident}_getState(m_tbe_ptr, addr);') + elif self.EntryType != None: + code('${ident}_State state = ${ident}_getState(m_cache_entry_ptr, addr);') + else: + code('${ident}_State state = ${ident}_getState(addr);') + + code(''' ${ident}_State next_state = state; DPRINTF(RubyGenerated, "%s, Time: %lld, state: %s, event: %s, addr: %s\\n", @@ -863,8 +1032,17 @@ ${ident}_Controller::doTransition(${ident}_Event event, addr); TransitionResult result = - doTransitionWorker(event, state, next_state, addr); +''') + if self.TBEType != None and self.EntryType != None: + code('doTransitionWorker(event, state, next_state, m_tbe_ptr, m_cache_entry_ptr, addr);') + elif self.TBEType != None: + code('doTransitionWorker(event, state, next_state, m_tbe_ptr, addr);') + elif self.EntryType != None: + code('doTransitionWorker(event, state, next_state, m_cache_entry_ptr, addr);') + else: + code('doTransitionWorker(event, state, next_state, addr);') + code(''' if (result == TransitionResult_Valid) { DPRINTF(RubyGenerated, "next_state: %s\\n", ${ident}_State_to_string(next_state)); @@ -877,7 +1055,17 @@ ${ident}_Controller::doTransition(${ident}_Event event, addr, GET_TRANSITION_COMMENT()); CLEAR_TRANSITION_COMMENT(); - ${ident}_setState(addr, next_state); +''') + if self.TBEType != None and self.EntryType != None: + code('${ident}_setState(m_tbe_ptr, m_cache_entry_ptr, addr, next_state);') + elif self.TBEType != None: + code('${ident}_setState(m_tbe_ptr, addr, next_state);') + elif self.EntryType != None: + code('${ident}_setState(m_cache_entry_ptr, addr, next_state);') + else: + code('${ident}_setState(addr, next_state);') + + code(''' } else if (result == TransitionResult_ResourceStall) { DPRINTFR(ProtocolTrace, "%7s %3s %10s%20s %6s>%-6s %s %s\\n", g_eventQueue_ptr->getTime(), m_version, "${ident}", @@ -902,6 +1090,17 @@ TransitionResult ${ident}_Controller::doTransitionWorker(${ident}_Event event, ${ident}_State state, ${ident}_State& next_state, +''') + + if self.TBEType != None: + code(''' + ${{self.TBEType.c_ident}}*& m_tbe_ptr, +''') + if self.EntryType != None: + code(''' + ${{self.EntryType.c_ident}}*& m_cache_entry_ptr, +''') + code(''' const Address& addr) { switch(HASH_FUN(state, event)) { @@ -950,8 +1149,18 @@ if (!%s.areNSlotsAvailable(%s)) if stall: case('return TransitionResult_ProtocolStall;') else: - for action in actions: - case('${{action.ident}}(addr);') + if self.TBEType != None and self.EntryType != None: + for action in actions: + case('${{action.ident}}(m_tbe_ptr, m_cache_entry_ptr, addr);') + elif self.TBEType != None: + for action in actions: + case('${{action.ident}}(m_tbe_ptr, addr);') + elif self.EntryType != None: + for action in actions: + case('${{action.ident}}(m_cache_entry_ptr, addr);') + else: + for action in actions: + case('${{action.ident}}(addr);') case('return TransitionResult_Valid;') case = str(case) |