summaryrefslogtreecommitdiff
path: root/src/mem/slicc
diff options
context:
space:
mode:
Diffstat (limited to 'src/mem/slicc')
-rw-r--r--src/mem/slicc/ast/ActionDeclAST.py19
-rw-r--r--src/mem/slicc/ast/FormalParamAST.py16
-rw-r--r--src/mem/slicc/ast/FuncCallExprAST.py53
-rw-r--r--src/mem/slicc/ast/IfStatementAST.py4
-rw-r--r--src/mem/slicc/ast/InPortDeclAST.py14
-rw-r--r--src/mem/slicc/ast/IsValidPtrExprAST.py53
-rw-r--r--src/mem/slicc/ast/LocalVariableAST.py54
-rw-r--r--src/mem/slicc/ast/MethodCallExprAST.py95
-rw-r--r--src/mem/slicc/ast/OodAST.py40
-rw-r--r--src/mem/slicc/ast/ReturnStatementAST.py2
-rw-r--r--src/mem/slicc/ast/StaticCastAST.py8
-rw-r--r--src/mem/slicc/ast/TypeDeclAST.py5
-rw-r--r--src/mem/slicc/ast/__init__.py3
-rw-r--r--src/mem/slicc/parser.py25
-rw-r--r--src/mem/slicc/symbols/Func.py4
-rw-r--r--src/mem/slicc/symbols/StateMachine.py241
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)