From 3e607f146f4c8acac6b42e61a0e6295f52f408a4 Mon Sep 17 00:00:00 2001 From: Nilay Vaish Date: Mon, 15 Oct 2012 17:27:16 -0500 Subject: [PATCH] ruby: allow function definition in slicc structs This patch adds support for function definitions to appear in slicc structs. This is required for supporting functional accesses for different types of messages. Subsequent patches will use this to development. --- src/mem/protocol/RubySlicc_Types.sm | 2 -- src/mem/slicc/ast/EnumDeclAST.py | 2 +- src/mem/slicc/ast/FuncDeclAST.py | 13 +++++++++--- src/mem/slicc/ast/InPortDeclAST.py | 6 +++--- src/mem/slicc/ast/MachineAST.py | 2 +- src/mem/slicc/ast/StateDeclAST.py | 4 ++-- src/mem/slicc/ast/TypeFieldEnumAST.py | 2 +- src/mem/slicc/ast/TypeFieldMemberAST.py | 2 +- src/mem/slicc/ast/TypeFieldMethodAST.py | 6 ++++-- src/mem/slicc/ast/TypeFieldStateAST.py | 2 +- src/mem/slicc/parser.py | 19 ++++++++++++++--- src/mem/slicc/symbols/Func.py | 16 +++----------- src/mem/slicc/symbols/Type.py | 28 ++++++++++++++++++++++--- 13 files changed, 68 insertions(+), 36 deletions(-) diff --git a/src/mem/protocol/RubySlicc_Types.sm b/src/mem/protocol/RubySlicc_Types.sm index a14af946c4..9b18aa417e 100644 --- a/src/mem/protocol/RubySlicc_Types.sm +++ b/src/mem/protocol/RubySlicc_Types.sm @@ -51,8 +51,6 @@ structure(InPort, external = "yes", primitive="yes") { external_type(NodeID, default="0", primitive="yes"); external_type(MachineID); -MessageBuffer getMandatoryQueue(int core_id); - structure (Set, external = "yes", non_obj="yes") { void setSize(int); void add(NodeID); diff --git a/src/mem/slicc/ast/EnumDeclAST.py b/src/mem/slicc/ast/EnumDeclAST.py index da07a0165c..acddcb91f4 100644 --- a/src/mem/slicc/ast/EnumDeclAST.py +++ b/src/mem/slicc/ast/EnumDeclAST.py @@ -67,5 +67,5 @@ class EnumDeclAST(DeclAST): pairs = { "external" : "yes" } func = Func(self.symtab, func_id, self.location, self.symtab.find("std::string", Type), [ t ], [], "", - pairs, None) + pairs) self.symtab.newSymbol(func) diff --git a/src/mem/slicc/ast/FuncDeclAST.py b/src/mem/slicc/ast/FuncDeclAST.py index 54b0f2c595..1d7e2c3ffe 100644 --- a/src/mem/slicc/ast/FuncDeclAST.py +++ b/src/mem/slicc/ast/FuncDeclAST.py @@ -43,7 +43,7 @@ class FuncDeclAST(DeclAST): def files(self, parent=None): return set() - def generate(self): + def generate(self, parent = None): types = [] params = [] void_type = self.symtab.find("void", Type) @@ -71,9 +71,16 @@ class FuncDeclAST(DeclAST): machine = self.state_machine func = Func(self.symtab, self.ident, self.location, return_type, - types, params, str(body), self.pairs, machine) + types, params, str(body), self.pairs) - if machine is not None: + if parent is not None: + if not parent.addFunc(func): + self.error("Duplicate method: %s:%s()" % (parent, self.ident)) + func.class_name = parent.c_ident + + elif machine is not None: machine.addFunc(func) + func.isInternalMachineFunc = True + func.class_name = "%s_Controller" % machine else: self.symtab.newSymbol(func) diff --git a/src/mem/slicc/ast/InPortDeclAST.py b/src/mem/slicc/ast/InPortDeclAST.py index c6fadb9e7f..376315eeda 100644 --- a/src/mem/slicc/ast/InPortDeclAST.py +++ b/src/mem/slicc/ast/InPortDeclAST.py @@ -91,7 +91,7 @@ class InPortDeclAST(DeclAST): # Add the trigger method - FIXME, this is a bit dirty pairs = { "external" : "yes" } func = Func(self.symtab, "trigger", self.location, void_type, - param_types, [], "", pairs, None) + param_types, [], "", pairs) symtab.newSymbol(func) param_types = [] @@ -117,13 +117,13 @@ class InPortDeclAST(DeclAST): # checks before calling double trigger to ensure that won't # happen func = Func(self.symtab, "doubleTrigger", self.location, void_type, - param_types, [], "", pairs, None) + param_types, [], "", pairs) symtab.newSymbol(func) # Add the continueProcessing method - this hack supports # messages that don't trigger events func = Func(self.symtab, "continueProcessing", self.location, - void_type, [], [], "", pairs, None) + void_type, [], [], "", pairs) symtab.newSymbol(func) if self.statements is not None: diff --git a/src/mem/slicc/ast/MachineAST.py b/src/mem/slicc/ast/MachineAST.py index 6cefe83748..c48d2aef17 100644 --- a/src/mem/slicc/ast/MachineAST.py +++ b/src/mem/slicc/ast/MachineAST.py @@ -76,7 +76,7 @@ class MachineAST(DeclAST): def findMachines(self): # Add to MachineType enumeration machine_type = self.symtab.find("MachineType", Type) - if not machine_type.enumAdd(self.ident, self.pairs_ast.pairs): + if not machine_type.addEnum(self.ident, self.pairs_ast.pairs): self.error("Duplicate machine name: %s:%s" % (machine_type, self.ident)) diff --git a/src/mem/slicc/ast/StateDeclAST.py b/src/mem/slicc/ast/StateDeclAST.py index a1bbd74aef..2bca54d092 100644 --- a/src/mem/slicc/ast/StateDeclAST.py +++ b/src/mem/slicc/ast/StateDeclAST.py @@ -66,7 +66,7 @@ class StateDeclAST(DeclAST): pairs = { "external" : "yes" } func = Func(self.symtab, func_id, self.location, self.symtab.find("std::string", Type), [ t ], [], "", - pairs, None) + pairs) self.symtab.newSymbol(func) # Add the State_to_permission method @@ -75,5 +75,5 @@ class StateDeclAST(DeclAST): pairs = { "external" : "yes" } func = Func(self.symtab, func_id, self.location, self.symtab.find("AccessPermission", Type), [ t ], [], "", - pairs, None) + pairs) self.symtab.newSymbol(func) diff --git a/src/mem/slicc/ast/TypeFieldEnumAST.py b/src/mem/slicc/ast/TypeFieldEnumAST.py index 1255c972aa..5ebb516d3e 100644 --- a/src/mem/slicc/ast/TypeFieldEnumAST.py +++ b/src/mem/slicc/ast/TypeFieldEnumAST.py @@ -43,7 +43,7 @@ class TypeFieldEnumAST(TypeFieldAST): self.error("States must in a State Declaration, not a normal enum.") # Add enumeration - if not type.enumAdd(self.field_id, self.pairs_ast.pairs): + if not type.addEnum(self.field_id, self.pairs_ast.pairs): self.error("Duplicate enumeration: %s:%s" % (type, self.field_id)) # Fill machine info diff --git a/src/mem/slicc/ast/TypeFieldMemberAST.py b/src/mem/slicc/ast/TypeFieldMemberAST.py index a601536643..26d3ab2c67 100644 --- a/src/mem/slicc/ast/TypeFieldMemberAST.py +++ b/src/mem/slicc/ast/TypeFieldMemberAST.py @@ -51,7 +51,7 @@ class TypeFieldMemberAST(TypeFieldAST): (field_type, rvalue_type)) # Add data member to the parent type - if not type.dataMemberAdd(self.field_id, field_type, self.pairs, + if not type.addDataMember(self.field_id, field_type, self.pairs, init_code): self.error("Duplicate data member: %s:%s" % (type_ptr, field_id)) diff --git a/src/mem/slicc/ast/TypeFieldMethodAST.py b/src/mem/slicc/ast/TypeFieldMethodAST.py index 2c8cf3f7be..b89f7f97eb 100644 --- a/src/mem/slicc/ast/TypeFieldMethodAST.py +++ b/src/mem/slicc/ast/TypeFieldMethodAST.py @@ -28,12 +28,14 @@ from slicc.ast.TypeFieldAST import TypeFieldAST class TypeFieldMethodAST(TypeFieldAST): - def __init__(self, slicc, return_type_ast, ident, type_asts, pairs): + def __init__(self, slicc, return_type_ast, ident, type_asts, pairs, + statements = None): super(TypeFieldMethodAST, self).__init__(slicc, pairs) self.return_type_ast = return_type_ast self.ident = ident self.type_asts = type_asts + self.statements = statements def __repr__(self): return "" @@ -46,5 +48,5 @@ class TypeFieldMethodAST(TypeFieldAST): types = [ t.type for t in self.type_asts ] # Add method - if not type.methodAdd(self.ident, return_type, types): + if not type.addMethod(self.ident, return_type, types): self.error("Duplicate method: %s:%s()" % (type, self.ident)) diff --git a/src/mem/slicc/ast/TypeFieldStateAST.py b/src/mem/slicc/ast/TypeFieldStateAST.py index aafa241ddb..d2b2532182 100644 --- a/src/mem/slicc/ast/TypeFieldStateAST.py +++ b/src/mem/slicc/ast/TypeFieldStateAST.py @@ -45,7 +45,7 @@ class TypeFieldStateAST(TypeFieldAST): self.error("State Declaration must be of type State.") # Add enumeration - if not type.enumAdd(self.field_id, self.pairs_ast.pairs): + if not type.addEnum(self.field_id, self.pairs_ast.pairs): self.error("Duplicate enumeration: %s:%s" % (type, self.field_id)) # Fill machine info diff --git a/src/mem/slicc/parser.py b/src/mem/slicc/parser.py index 6b6a1aaef2..78b842f748 100644 --- a/src/mem/slicc/parser.py +++ b/src/mem/slicc/parser.py @@ -315,14 +315,23 @@ class SLICC(Grammar): "decl : type ident pairs SEMI" p[0] = ast.ObjDeclAST(self, p[1], p[2], p[3]) + # Function definition and declaration def p_decl__func_decl(self, p): - """decl : void ident '(' params ')' pairs SEMI + "decl : func_decl" + p[0] = p[1] + + def p_func_decl__0(self, p): + """func_decl : void ident '(' params ')' pairs SEMI | type ident '(' params ')' pairs SEMI""" p[0] = ast.FuncDeclAST(self, p[1], p[2], p[4], p[6], None) def p_decl__func_def(self, p): - """decl : void ident '(' params ')' pairs statements - | type ident '(' params ')' pairs statements""" + "decl : func_def" + p[0] = p[1] + + def p_func_def__0(self, p): + """func_def : void ident '(' params ')' pairs statements + | type ident '(' params ')' pairs statements""" p[0] = ast.FuncDeclAST(self, p[1], p[2], p[4], p[6], p[7]) # Type fields @@ -338,6 +347,10 @@ class SLICC(Grammar): "type_member : type_or_void ident '(' types ')' pairs SEMI" p[0] = ast.TypeFieldMethodAST(self, p[1], p[2], p[4], p[6]) + def p_type_method__1(self, p): + "type_member : type_or_void ident '(' params ')' pairs statements" + p[0] = ast.FuncDeclAST(self, p[1], p[2], p[4], p[6], p[7]) + def p_type_member__1(self, p): "type_member : type_or_void ident pairs SEMI" p[0] = ast.TypeFieldMemberAST(self, p[1], p[2], p[3], None) diff --git a/src/mem/slicc/symbols/Func.py b/src/mem/slicc/symbols/Func.py index 8e137d0449..a52b6bbcc1 100644 --- a/src/mem/slicc/symbols/Func.py +++ b/src/mem/slicc/symbols/Func.py @@ -30,7 +30,7 @@ from slicc.symbols.Type import Type class Func(Symbol): def __init__(self, table, ident, location, return_type, param_types, - param_strings, body, pairs, machine): + param_strings, body, pairs): super(Func, self).__init__(table, ident, location, pairs) self.return_type = return_type self.param_types = param_types @@ -38,12 +38,7 @@ class Func(Symbol): self.body = body self.isInternalMachineFunc = False self.c_ident = ident - - if machine is None or "external" in self or "primitive" in self: - pass - else: - self.machineStr = str(machine) - self.isInternalMachineFunc = True + self.class_name = "" def __repr__(self): return "" @@ -81,16 +76,11 @@ class Func(Symbol): if "return_by_pointer" in self and self.return_type != void_type: return_type += "*" - if self.isInternalMachineFunc: - klass = "%s_Controller" % self.machineStr - else: - self.error("No class found for the function %s" % self.ident) - params = ', '.join(self.param_strings) code(''' $return_type -${klass}::${{self.c_ident}}($params) +${{self.class_name}}::${{self.c_ident}}($params) { ${{self.body}} } diff --git a/src/mem/slicc/symbols/Type.py b/src/mem/slicc/symbols/Type.py index aec05a6787..3832919110 100644 --- a/src/mem/slicc/symbols/Type.py +++ b/src/mem/slicc/symbols/Type.py @@ -107,6 +107,7 @@ class Type(Symbol): # Methods self.methods = {} + self.functions = {} # Enums self.enums = orderdict() @@ -143,7 +144,7 @@ class Type(Symbol): return "interface" in self # Return false on error - def dataMemberAdd(self, ident, type, pairs, init_code): + def addDataMember(self, ident, type, pairs, init_code): if ident in self.data_members: return False @@ -164,7 +165,7 @@ class Type(Symbol): def statePermPairAdd(self, state_name, perm_name): self.statePermPairs.append([state_name, perm_name]) - def methodAdd(self, name, return_type, param_type_vec): + def addMethod(self, name, return_type, param_type_vec): ident = self.methodId(name, param_type_vec) if ident in self.methods: return False @@ -172,7 +173,18 @@ class Type(Symbol): self.methods[ident] = Method(return_type, param_type_vec) return True - def enumAdd(self, ident, pairs): + # Ideally either this function or the one above should exist. But + # methods and functions have different structures right now. + # Hence, these are different, at least for the time being. + def addFunc(self, func): + ident = self.methodId(func.ident, func.param_types) + if ident in self.functions: + return False + + self.functions[ident] = func + return True + + def addEnum(self, ident, pairs): if ident in self.enums: return False @@ -368,6 +380,12 @@ set${{dm.ident}}(const ${{dm.type.c_ident}}& local_${{dm.ident}}) code('$const${{dm.type.c_ident}} m_${{dm.ident}}$init;') + # Prototypes for functions defined for the Type + for item in self.functions: + proto = self.functions[item].prototype + if proto: + code('$proto') + code.dedent() code('};') @@ -423,6 +441,10 @@ ${{self.c_ident}}::print(ostream& out) const out << "]"; }''') + # print the code for the functions in the type + for item in self.functions: + code(self.functions[item].generateCode()) + code.write(path, "%s.cc" % self.c_ident) def printEnumHH(self, path):