summaryrefslogtreecommitdiff
path: root/src/mem/slicc
diff options
context:
space:
mode:
Diffstat (limited to 'src/mem/slicc')
-rw-r--r--src/mem/slicc/ast/FormalParamAST.py3
-rw-r--r--src/mem/slicc/ast/MethodCallExprAST.py46
-rw-r--r--src/mem/slicc/ast/StaticCastAST.py54
-rw-r--r--src/mem/slicc/ast/__init__.py1
-rw-r--r--src/mem/slicc/parser.py9
-rw-r--r--src/mem/slicc/symbols/StateMachine.py58
-rw-r--r--src/mem/slicc/symbols/Type.py4
7 files changed, 166 insertions, 9 deletions
diff --git a/src/mem/slicc/ast/FormalParamAST.py b/src/mem/slicc/ast/FormalParamAST.py
index b821dc197..c64731196 100644
--- a/src/mem/slicc/ast/FormalParamAST.py
+++ b/src/mem/slicc/ast/FormalParamAST.py
@@ -29,11 +29,12 @@ from slicc.ast.AST import AST
from slicc.symbols import Var
class FormalParamAST(AST):
- def __init__(self, slicc, type_ast, ident, default = None):
+ def __init__(self, slicc, type_ast, ident, default = None, pointer = False):
super(FormalParamAST, self).__init__(slicc)
self.type_ast = type_ast
self.ident = ident
self.default = default
+ self.pointer = pointer
def __repr__(self):
return "[FormalParamAST: %s]" % self.ident
diff --git a/src/mem/slicc/ast/MethodCallExprAST.py b/src/mem/slicc/ast/MethodCallExprAST.py
index 3f9b250c1..150f391bc 100644
--- a/src/mem/slicc/ast/MethodCallExprAST.py
+++ b/src/mem/slicc/ast/MethodCallExprAST.py
@@ -68,7 +68,8 @@ class MethodCallExprAST(ExprAST):
for actual_type, expected_type in \
zip(paramTypes, obj_type.methods[methodId].param_types):
- if actual_type != expected_type:
+ if actual_type != expected_type and \
+ str(actual_type["interface"]) != str(expected_type):
self.error("Type mismatch: expected: %s actual: %s",
expected_type, actual_type)
@@ -97,9 +98,48 @@ class MemberMethodCallExprAST(MethodCallExprAST):
methodId = obj_type.methodId(self.proc_name, paramTypes)
prefix = ""
+ implements_interface = False
if methodId not in obj_type.methods:
- self.error("Invalid method call: Type '%s' does not have a method '%s'",
- obj_type, methodId)
+ #
+ # 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' 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
if return_type.isInterface:
prefix = "static_cast<%s &>" % return_type.c_ident
diff --git a/src/mem/slicc/ast/StaticCastAST.py b/src/mem/slicc/ast/StaticCastAST.py
new file mode 100644
index 000000000..3a48f398e
--- /dev/null
+++ b/src/mem/slicc/ast/StaticCastAST.py
@@ -0,0 +1,54 @@
+# Copyright (c) 2009 Advanced Micro Devices, Inc.
+# 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 StaticCastAST(ExprAST):
+ def __init__(self, slicc, type_ast, expr_ast):
+ super(StaticCastAST, self).__init__(slicc)
+
+ self.type_ast = type_ast
+ self.expr_ast = expr_ast
+
+ 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 not "interface" in self.type_ast.type:
+ self.expr_ast.error("static cast only premitted for those types " \
+ "that implement inherit an interface")
+
+ # The interface type should match
+ if str(actual_type) != str(self.type_ast.type["interface"]):
+ self.expr_ast.error("static cast miss-match, type is '%s'," \
+ "but inherited type is '%s'",
+ actual_type, self.type_ast.type["interface"])
+
+ return self.type_ast.type
+
diff --git a/src/mem/slicc/ast/__init__.py b/src/mem/slicc/ast/__init__.py
index de50cbd49..cc5f02b84 100644
--- a/src/mem/slicc/ast/__init__.py
+++ b/src/mem/slicc/ast/__init__.py
@@ -59,6 +59,7 @@ from slicc.ast.PeekStatementAST import *
from slicc.ast.ReturnStatementAST import *
from slicc.ast.StatementAST import *
from slicc.ast.StatementListAST import *
+from slicc.ast.StaticCastAST import *
from slicc.ast.TransitionDeclAST import *
from slicc.ast.TypeAST import *
from slicc.ast.TypeDeclAST import *
diff --git a/src/mem/slicc/parser.py b/src/mem/slicc/parser.py
index 891f22973..4db034bab 100644
--- a/src/mem/slicc/parser.py
+++ b/src/mem/slicc/parser.py
@@ -154,6 +154,7 @@ class SLICC(Grammar):
'copy_head' : 'COPY_HEAD',
'check_allocate' : 'CHECK_ALLOCATE',
'check_stop_slots' : 'CHECK_STOP_SLOTS',
+ 'static_cast' : 'STATIC_CAST',
'if' : 'IF',
'else' : 'ELSE',
'return' : 'RETURN',
@@ -416,6 +417,10 @@ class SLICC(Grammar):
"param : type ident"
p[0] = ast.FormalParamAST(self, p[1], p[2])
+ def p_param__pointer(self, p):
+ "param : type STAR ident"
+ p[0] = ast.FormalParamAST(self, p[1], p[3], None, True)
+
def p_param__default(self, p):
"param : type ident '=' NUMBER"
p[0] = ast.FormalParamAST(self, p[1], p[2], p[4])
@@ -531,6 +536,10 @@ class SLICC(Grammar):
"statement : CHECK_STOP_SLOTS '(' var ',' STRING ',' STRING ')' SEMI"
p[0] = ast.CheckStopStatementAST(self, p[3], p[5], p[7])
+ def p_statement__static_cast(self, p):
+ "aexpr : STATIC_CAST '(' type ',' expr ')'"
+ p[0] = ast.StaticCastAST(self, p[3], p[5])
+
def p_statement__return(self, p):
"statement : RETURN expr SEMI"
p[0] = ast.ReturnStatementAST(self, p[2])
diff --git a/src/mem/slicc/symbols/StateMachine.py b/src/mem/slicc/symbols/StateMachine.py
index 2f6e023ce..867886436 100644
--- a/src/mem/slicc/symbols/StateMachine.py
+++ b/src/mem/slicc/symbols/StateMachine.py
@@ -31,14 +31,27 @@ from slicc.symbols.Symbol import Symbol
from slicc.symbols.Var import Var
import slicc.generate.html as html
+python_class_map = {"int": "Int",
+ "string": "String",
+ "bool": "Bool",
+ "CacheMemory": "RubyCache",
+ "Sequencer": "RubySequencer",
+ "DirectoryMemory": "RubyDirectoryMemory",
+ "MemoryControl": "RubyMemoryControl",
+ }
+
class StateMachine(Symbol):
def __init__(self, symtab, ident, location, pairs, config_parameters):
super(StateMachine, self).__init__(symtab, ident, location, pairs)
self.table = None
self.config_parameters = config_parameters
for param in config_parameters:
- var = Var(symtab, param.name, location, param.type_ast.type,
- "m_%s" % param.name, {}, self)
+ if param.pointer:
+ var = Var(symtab, param.name, location, param.type_ast.type,
+ "(*m_%s_ptr)" % param.name, {}, self)
+ else:
+ var = Var(symtab, param.name, location, param.type_ast.type,
+ "m_%s" % param.name, {}, self)
self.symtab.registerSym(param.name, var)
self.states = orderdict()
@@ -153,7 +166,13 @@ class $py_ident(RubyController):
dflt_str = ''
if param.default is not None:
dflt_str = str(param.default) + ', '
- code('${{param.name}} = Param.Int(${dflt_str}"")')
+ if python_class_map.has_key(param.type_ast.type.c_ident):
+ python_type = python_class_map[param.type_ast.type.c_ident]
+ code('${{param.name}} = Param.${{python_type}}(${dflt_str}"")')
+ else:
+ self.error("Unknown c++ to python class conversion for c++ " \
+ "type: '%s'. Please update the python_class_map " \
+ "in StateMachine.py", param.type_ast.type.c_ident)
code.dedent()
code.write(path, '%s.py' % py_ident)
@@ -223,7 +242,10 @@ private:
code.indent()
# added by SS
for param in self.config_parameters:
- code('int m_${{param.ident}};')
+ if param.pointer:
+ code('${{param.type_ast.type}}* m_${{param.ident}}_ptr;')
+ else:
+ code('${{param.type_ast.type}} m_${{param.ident}};')
code('''
int m_number_of_TBEs;
@@ -328,8 +350,34 @@ $c_ident::$c_ident(const Params *p)
m_number_of_TBEs = p->number_of_TBEs;
''')
code.indent()
+
+ #
+ # After initializing the universal machine parameters, initialize the
+ # this machines config parameters. Also detemine if these configuration
+ # params include a sequencer. This information will be used later for
+ # contecting the sequencer back to the L1 cache controller.
+ #
+ contains_sequencer = False
for param in self.config_parameters:
- code('m_${{param.name}} = p->${{param.name}};')
+ if param.name == "sequencer":
+ contains_sequencer = True
+ if param.pointer:
+ code('m_${{param.name}}_ptr = p->${{param.name}};')
+ else:
+ code('m_${{param.name}} = p->${{param.name}};')
+
+ #
+ # For the l1 cache controller, add the special atomic support which
+ # includes passing the sequencer a pointer to the controller.
+ #
+ if self.ident == "L1Cache":
+ if not contains_sequencer:
+ self.error("The L1Cache controller must include the sequencer " \
+ "configuration parameter")
+
+ code('''
+m_sequencer_ptr->setController(this);
+''')
code('m_num_controllers++;')
for var in self.objects:
diff --git a/src/mem/slicc/symbols/Type.py b/src/mem/slicc/symbols/Type.py
index fc45c59df..41032e233 100644
--- a/src/mem/slicc/symbols/Type.py
+++ b/src/mem/slicc/symbols/Type.py
@@ -51,6 +51,7 @@ class Type(Symbol):
def __init__(self, table, ident, location, pairs, machine=None):
super(Type, self).__init__(table, ident, location, pairs)
self.c_ident = ident
+ self.abstract_ident = ""
if machine:
if self.isExternal or self.isPrimitive:
if "external_name" in self:
@@ -154,6 +155,9 @@ class Type(Symbol):
def methodId(self, name, param_type_vec):
return '_'.join([name] + [ pt.c_ident for pt in param_type_vec ])
+ def methodIdAbstract(self, name, param_type_vec):
+ return '_'.join([name] + [ pt.abstract_ident for pt in param_type_vec ])
+
def methodAdd(self, name, return_type, param_type_vec):
ident = self.methodId(name, param_type_vec)
if ident in self.methods: