From 2278363015a2a5cc850b38213833096d33b496e8 Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Tue, 22 Sep 2009 18:12:39 -0700 Subject: slicc: Pure python implementation of slicc. This is simply a translation of the C++ slicc into python with very minimal reorganization of the code. The output can be verified as nearly identical by doing a "diff -wBur". Slicc can easily be run manually by using util/slicc --- src/mem/slicc/symbols/Action.hh | 52 -- src/mem/slicc/symbols/Action.py | 38 + src/mem/slicc/symbols/Event.hh | 45 - src/mem/slicc/symbols/Event.py | 34 + src/mem/slicc/symbols/Func.cc | 143 --- src/mem/slicc/symbols/Func.hh | 96 --- src/mem/slicc/symbols/Func.py | 107 +++ src/mem/slicc/symbols/State.hh | 45 - src/mem/slicc/symbols/State.py | 34 + src/mem/slicc/symbols/StateMachine.cc | 1534 --------------------------------- src/mem/slicc/symbols/StateMachine.hh | 156 ---- src/mem/slicc/symbols/StateMachine.py | 1222 ++++++++++++++++++++++++++ src/mem/slicc/symbols/Symbol.cc | 72 -- src/mem/slicc/symbols/Symbol.hh | 100 --- src/mem/slicc/symbols/Symbol.py | 78 ++ src/mem/slicc/symbols/SymbolTable.cc | 327 ------- src/mem/slicc/symbols/SymbolTable.hh | 121 --- src/mem/slicc/symbols/SymbolTable.py | 218 +++++ src/mem/slicc/symbols/Transition.cc | 173 ---- src/mem/slicc/symbols/Transition.hh | 120 --- src/mem/slicc/symbols/Transition.py | 61 ++ src/mem/slicc/symbols/Type.cc | 779 ----------------- src/mem/slicc/symbols/Type.hh | 155 ---- src/mem/slicc/symbols/Type.py | 650 ++++++++++++++ src/mem/slicc/symbols/Var.cc | 57 -- src/mem/slicc/symbols/Var.hh | 98 --- src/mem/slicc/symbols/Var.py | 50 ++ src/mem/slicc/symbols/__init__.py | 38 + 28 files changed, 2530 insertions(+), 4073 deletions(-) delete mode 100644 src/mem/slicc/symbols/Action.hh create mode 100644 src/mem/slicc/symbols/Action.py delete mode 100644 src/mem/slicc/symbols/Event.hh create mode 100644 src/mem/slicc/symbols/Event.py delete mode 100644 src/mem/slicc/symbols/Func.cc delete mode 100644 src/mem/slicc/symbols/Func.hh create mode 100644 src/mem/slicc/symbols/Func.py delete mode 100644 src/mem/slicc/symbols/State.hh create mode 100644 src/mem/slicc/symbols/State.py delete mode 100644 src/mem/slicc/symbols/StateMachine.cc delete mode 100644 src/mem/slicc/symbols/StateMachine.hh create mode 100644 src/mem/slicc/symbols/StateMachine.py delete mode 100644 src/mem/slicc/symbols/Symbol.cc delete mode 100644 src/mem/slicc/symbols/Symbol.hh create mode 100644 src/mem/slicc/symbols/Symbol.py delete mode 100644 src/mem/slicc/symbols/SymbolTable.cc delete mode 100644 src/mem/slicc/symbols/SymbolTable.hh create mode 100644 src/mem/slicc/symbols/SymbolTable.py delete mode 100644 src/mem/slicc/symbols/Transition.cc delete mode 100644 src/mem/slicc/symbols/Transition.hh create mode 100644 src/mem/slicc/symbols/Transition.py delete mode 100644 src/mem/slicc/symbols/Type.cc delete mode 100644 src/mem/slicc/symbols/Type.hh create mode 100644 src/mem/slicc/symbols/Type.py delete mode 100644 src/mem/slicc/symbols/Var.cc delete mode 100644 src/mem/slicc/symbols/Var.hh create mode 100644 src/mem/slicc/symbols/Var.py create mode 100644 src/mem/slicc/symbols/__init__.py (limited to 'src/mem/slicc/symbols') diff --git a/src/mem/slicc/symbols/Action.hh b/src/mem/slicc/symbols/Action.hh deleted file mode 100644 index dbb0c836a..000000000 --- a/src/mem/slicc/symbols/Action.hh +++ /dev/null @@ -1,52 +0,0 @@ - -/* - * Copyright (c) 1999-2008 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. - */ - -/* - * $Id$ - */ - -#ifndef ACTION_H -#define ACTION_H - -#include "mem/slicc/symbols/Symbol.hh" - -class Action : public Symbol { -public: - Action(string id, - const Map& resources, - const Location& location, - const Map& pairs) : Symbol(id, location, pairs) { m_resources = resources; } - const Map& getResources() const { return m_resources; } - void print(ostream& out) const { out << "[Action: " << getIdent() << "]"; } - -private: - Map m_resources; -}; - -#endif //ACTION_H diff --git a/src/mem/slicc/symbols/Action.py b/src/mem/slicc/symbols/Action.py new file mode 100644 index 000000000..880fab15a --- /dev/null +++ b/src/mem/slicc/symbols/Action.py @@ -0,0 +1,38 @@ +# Copyright (c) 1999-2008 Mark D. Hill and David A. Wood +# Copyright (c) 2009 The Hewlett-Packard Development Company +# 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.symbols.Symbol import Symbol + +class Action(Symbol): + def __init__(self, table, ident, resources, location, pairs): + super(Action, self).__init__(table, ident, location, pairs) + self.resources = resources + + def __repr__(self): + return "[Action: %s]" % self.ident + +__all__ = [ "Action" ] diff --git a/src/mem/slicc/symbols/Event.hh b/src/mem/slicc/symbols/Event.hh deleted file mode 100644 index 40cefc982..000000000 --- a/src/mem/slicc/symbols/Event.hh +++ /dev/null @@ -1,45 +0,0 @@ - -/* - * Copyright (c) 1999-2008 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. - */ - -/* - * $Id$ - */ - -#ifndef EVENT_H -#define EVENT_H - -#include "mem/slicc/symbols/Symbol.hh" - -class Event : public Symbol { -public: - Event(string id, const Location& location, const Map& pairs) : Symbol(id, location, pairs) {} - void print(ostream& out) const { out << "[Event: " << getIdent() << "]"; } -}; - -#endif //EVENT_H diff --git a/src/mem/slicc/symbols/Event.py b/src/mem/slicc/symbols/Event.py new file mode 100644 index 000000000..9ff4d8ba7 --- /dev/null +++ b/src/mem/slicc/symbols/Event.py @@ -0,0 +1,34 @@ +# Copyright (c) 1999-2008 Mark D. Hill and David A. Wood +# Copyright (c) 2009 The Hewlett-Packard Development Company +# 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.symbols.Symbol import Symbol + +class Event(Symbol): + def __repr__(self): + return "[Event: %s]" % self.ident + +__all__ = [ "Event" ] diff --git a/src/mem/slicc/symbols/Func.cc b/src/mem/slicc/symbols/Func.cc deleted file mode 100644 index d29138b38..000000000 --- a/src/mem/slicc/symbols/Func.cc +++ /dev/null @@ -1,143 +0,0 @@ - -/* - * Copyright (c) 1999-2008 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. - */ - -/* - * Func.cc - * - * Description: See Func.hh - * - * $Id$ - * - */ - -#include "mem/slicc/symbols/Func.hh" -#include "mem/slicc/symbols/SymbolTable.hh" -#include "mem/slicc/generator/fileio.hh" -#include "mem/slicc/symbols/StateMachine.hh" - -Func::Func(string id, const Location& location, - Type* type_ptr, const Vector& param_type_vec, - const Vector& param_string_vec, string body, - const Map& pairs, StateMachine* machine_ptr) - : Symbol(id, location, pairs) -{ - m_type_ptr = type_ptr; - m_param_type_vec = param_type_vec; - m_param_string_vec = param_string_vec; - m_body = body; - m_isInternalMachineFunc = false; - - if (machine_ptr == NULL) { - m_c_ident = id; - } else if (existPair("external") || existPair("primitive")) { - m_c_ident = id; - } else { - m_machineStr = machine_ptr->toString(); - m_c_ident = m_machineStr + "_" + id; // Append with machine name - m_isInternalMachineFunc = true; - } -} - -void Func::funcPrototype(string& code) const -{ - if (isExternal()) { - // Do nothing - } else { - string return_type = m_type_ptr->cIdent(); - Type* void_type_ptr = g_sym_table.getType("void"); - if (existPair("return_by_ref") && (m_type_ptr != void_type_ptr)) { - return_type += "&"; - } - code += return_type + " " + cIdent() + "("; - int size = m_param_string_vec.size(); - for(int i=0; icIdent(); - code += return_type; - if (existPair("return_by_ref") && m_type_ptr != void_type_ptr) { - code += "&"; - } - if (!m_isInternalMachineFunc) { - code += " Chip::" + cIdent() + "("; - } else { - code += " " + m_machineStr + "_Controller::" + cIdent() + "("; - } - int size = m_param_type_vec.size(); - for(int i=0; i& param_type_vec, const Vector& param_string_vec, - string body, const Map& pairs, StateMachine* machine_ptr); - - // Destructor - ~Func() {} - - // Public Methods - string cIdent() const { return m_c_ident; } - const Vector& getParamTypes() const { return m_param_type_vec; } - Type* getReturnType() const { return m_type_ptr; } - void writeCFiles(string path) ; - void funcPrototype(string& code) const; - bool isExternal() const { return existPair("external"); } - bool isInternalMachineFunc() const { return m_isInternalMachineFunc; } - void print(ostream& out) const; -private: - // Private Methods - - // Private copy constructor and assignment operator - Func(const Func& obj); - Func& operator=(const Func& obj); - - // Data Members (m_ prefix) - Type* m_type_ptr; - Vector m_param_type_vec; - Vector m_param_string_vec; - string m_body; - string m_c_ident; - string m_machineStr; - bool m_isInternalMachineFunc; -}; - -// Output operator declaration -ostream& operator<<(ostream& out, const Func& obj); - -// ******************* Definitions ******************* - -// Output operator definition -extern inline -ostream& operator<<(ostream& out, const Func& obj) -{ - obj.print(out); - out << flush; - return out; -} - -#endif //FUNC_H diff --git a/src/mem/slicc/symbols/Func.py b/src/mem/slicc/symbols/Func.py new file mode 100644 index 000000000..5c812a96f --- /dev/null +++ b/src/mem/slicc/symbols/Func.py @@ -0,0 +1,107 @@ +# Copyright (c) 1999-2008 Mark D. Hill and David A. Wood +# Copyright (c) 2009 The Hewlett-Packard Development Company +# 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 m5.util import code_formatter + +from slicc.symbols.Symbol import Symbol +from slicc.symbols.Type import Type + +class Func(Symbol): + def __init__(self, table, ident, location, return_type, param_types, + param_strings, body, pairs, machine): + super(Func, self).__init__(table, ident, location, pairs) + self.return_type = return_type + self.param_types = param_types + self.param_strings = param_strings + self.body = body + self.isInternalMachineFunc = False + + if machine is None: + self.c_ident = ident + elif "external" in self or "primitive" in self: + self.c_ident = ident + else: + self.machineStr = str(machine) + # Append with machine name + self.c_ident = "%s_%s" % (self.machineStr, ident) + self.isInternalMachineFunc = True + + def __repr__(self): + return "" + + @property + def prototype(self): + if "external" in self: + return "" + + return_type = self.return_type.c_ident + void_type = self.symtab.find("void", Type) + if "return_by_ref" in self and self.return_type != void_type: + return_type += "&" + + return "%s %s(%s);" % (return_type, self.c_ident, + ", ".join(self.param_strings)) + + def writeCodeFiles(self, path): + '''This write a function of object Chip''' + if "external" in self: + return + + code = code_formatter() + + # Header + code(''' +/** Auto generated C++ code started by $__file__:$__line__ */ + +#include "mem/protocol/Types.hh" +''') + + if self.isInternalMachineFunc: + code('#include "mem/protocol/${{self.machineStr}}_Controller.hh"') + + # Generate function header + void_type = self.symtab.find("void", Type) + return_type = self.return_type.c_ident + if "return_by_ref" in self and self.return_type != void_type: + return_type += "&" + + if self.isInternalMachineFunc: + klass = "%s_Controller" % self.machineStr + else: + klass = "Chip" + + params = ', '.join(self.param_strings) + + code(''' +$return_type ${klass}::${{self.c_ident}}($params) +{ +${{self.body}} +} +''') + code.write(path, "%s.cc" % self.c_ident) + +__all__ = [ "Func" ] diff --git a/src/mem/slicc/symbols/State.hh b/src/mem/slicc/symbols/State.hh deleted file mode 100644 index 39900d506..000000000 --- a/src/mem/slicc/symbols/State.hh +++ /dev/null @@ -1,45 +0,0 @@ - -/* - * Copyright (c) 1999-2008 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. - */ - -/* - * $Id$ - */ - -#ifndef STATE_H -#define STATE_H - -#include "mem/slicc/symbols/Symbol.hh" - -class State : public Symbol { -public: - State(string id, const Location& location, const Map& pairs) : Symbol(id, location, pairs) {} - void print(ostream& out) const { out << "[State: " << getIdent() << "]"; } -}; - -#endif //STATE_H diff --git a/src/mem/slicc/symbols/State.py b/src/mem/slicc/symbols/State.py new file mode 100644 index 000000000..123693256 --- /dev/null +++ b/src/mem/slicc/symbols/State.py @@ -0,0 +1,34 @@ +# Copyright (c) 1999-2008 Mark D. Hill and David A. Wood +# Copyright (c) 2009 The Hewlett-Packard Development Company +# 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.symbols.Symbol import Symbol + +class State(Symbol): + def __repr__(self): + return "[State: %s]" % self.ident + +__all__ = [ "State" ] diff --git a/src/mem/slicc/symbols/StateMachine.cc b/src/mem/slicc/symbols/StateMachine.cc deleted file mode 100644 index 86f92b692..000000000 --- a/src/mem/slicc/symbols/StateMachine.cc +++ /dev/null @@ -1,1534 +0,0 @@ - -/* - * Copyright (c) 1999-2008 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. - */ - -/* - * $Id$ - * - * */ - -#include "mem/slicc/symbols/StateMachine.hh" -#include "mem/slicc/generator/fileio.hh" -#include "mem/slicc/generator/html_gen.hh" -#include "mem/slicc/symbols/Action.hh" -#include "mem/slicc/symbols/Event.hh" -#include "mem/slicc/symbols/State.hh" -#include "mem/slicc/symbols/Transition.hh" -#include "mem/slicc/symbols/Var.hh" -#include "mem/slicc/symbols/SymbolTable.hh" -#include "mem/gems_common/util.hh" -#include "mem/gems_common/Vector.hh" -#include "mem/slicc/ast/FormalParamAST.hh" - -#include - -StateMachine::StateMachine(string ident, const Location& location, const Map& pairs, Vector* config_parameters) - : Symbol(ident, location, pairs) -{ - m_table_built = false; - m_config_parameters = config_parameters; - - for (int i=0; i< m_config_parameters->size(); i++) { - Var* var = new Var(m_config_parameters->ref(i)->getName(), - location, - m_config_parameters->ref(i)->getType(), - "m_"+m_config_parameters->ref(i)->getName(), - Map(), - this); - g_sym_table.registerSym(m_config_parameters->ref(i)->getName(), var); - } -} - -StateMachine::~StateMachine() -{ - // FIXME - // assert(0); -} - -void StateMachine::addState(State* state_ptr) -{ - assert(m_table_built == false); - m_state_map.add(state_ptr, m_states.size()); - m_states.insertAtBottom(state_ptr); -} - -void StateMachine::addEvent(Event* event_ptr) -{ - assert(m_table_built == false); - m_event_map.add(event_ptr, m_events.size()); - m_events.insertAtBottom(event_ptr); -} - -void StateMachine::addAction(Action* action_ptr) -{ - assert(m_table_built == false); - - // Check for duplicate action - int size = m_actions.size(); - for(int i=0; igetIdent() == action_ptr->getIdent()) { - m_actions[i]->warning("Duplicate action definition: " + m_actions[i]->getIdent()); - action_ptr->error("Duplicate action definition: " + action_ptr->getIdent()); - } - if (m_actions[i]->getShorthand() == action_ptr->getShorthand()) { - m_actions[i]->warning("Duplicate action shorthand: " + m_actions[i]->getIdent()); - m_actions[i]->warning(" shorthand = " + m_actions[i]->getShorthand()); - action_ptr->warning("Duplicate action shorthand: " + action_ptr->getIdent()); - action_ptr->error(" shorthand = " + action_ptr->getShorthand()); - } - } - - m_actions.insertAtBottom(action_ptr); -} - -void StateMachine::addTransition(Transition* trans_ptr) -{ - assert(m_table_built == false); - trans_ptr->checkIdents(m_states, m_events, m_actions); - m_transitions.insertAtBottom(trans_ptr); -} - -void StateMachine::addFunc(Func* func_ptr) -{ - // register func in the symbol table - g_sym_table.registerSym(func_ptr->toString(), func_ptr); - m_internal_func_vec.insertAtBottom(func_ptr); -} - -void StateMachine::buildTable() -{ - assert(m_table_built == false); - int numStates = m_states.size(); - int numEvents = m_events.size(); - int numTransitions = m_transitions.size(); - int stateIndex, eventIndex; - - for(stateIndex=0; stateIndex < numStates; stateIndex++) { - m_table.insertAtBottom(Vector()); - for(eventIndex=0; eventIndex < numEvents; eventIndex++) { - m_table[stateIndex].insertAtBottom(NULL); - } - } - - for(int i=0; i actions = trans_ptr->getActions(); - for(int actionIndex=0; actionIndex < actions.size(); actionIndex++) { - actions[actionIndex]->markUsed(); - } - - stateIndex = getStateIndex(trans_ptr->getStatePtr()); - eventIndex = getEventIndex(trans_ptr->getEventPtr()); - if (m_table[stateIndex][eventIndex] != NULL) { - m_table[stateIndex][eventIndex]->warning("Duplicate transition: " + m_table[stateIndex][eventIndex]->toString()); - trans_ptr->error("Duplicate transition: " + trans_ptr->toString()); - } - m_table[stateIndex][eventIndex] = trans_ptr; - } - - // Look at all actions to make sure we used them all - for(int actionIndex=0; actionIndex < m_actions.size(); actionIndex++) { - Action* action_ptr = m_actions[actionIndex]; - if (!action_ptr->wasUsed()) { - string error_msg = "Unused action: " + action_ptr->getIdent(); - if (action_ptr->existPair("desc")) { - error_msg += ", " + action_ptr->getDescription(); - } - action_ptr->warning(error_msg); - } - } - - m_table_built = true; -} - -const Transition* StateMachine::getTransPtr(int stateIndex, int eventIndex) const -{ - return m_table[stateIndex][eventIndex]; -} - -// *********************** // -// ******* C Files ******* // -// *********************** // - -void StateMachine::writeCFiles(string path) -{ - string comp = getIdent(); - string filename; - - // Output the method declarations for the class declaration - { - ostringstream sstr; - printControllerH(sstr, comp); - conditionally_write_file(path + comp + "_Controller.hh", sstr); - } - - // Output switch statement for transition table - { - ostringstream sstr; - printCSwitch(sstr, comp); - conditionally_write_file(path + comp + "_Transitions.cc", sstr); - } - - // Output the actions for performing the actions - { - ostringstream sstr; - printControllerC(sstr, comp); - conditionally_write_file(path + comp + "_Controller.cc", sstr); - } - - // Output the wakeup loop for the events - { - ostringstream sstr; - printCWakeup(sstr, comp); - conditionally_write_file(path + comp + "_Wakeup.cc", sstr); - } - - // Profiling - { - ostringstream sstr; - printProfilerC(sstr, comp); - conditionally_write_file(path + comp + "_Profiler.cc", sstr); - } - { - ostringstream sstr; - printProfilerH(sstr, comp); - conditionally_write_file(path + comp + "_Profiler.hh", sstr); - } - - // Write internal func files - for(int i=0; iwriteCFiles(path); - } - -} - -void StateMachine::printControllerH(ostream& out, string component) -{ - - m_message_buffer_names.clear(); - - out << "/** \\file " << getIdent() << ".hh" << endl; - out << " * " << endl; - out << " * Auto generated C++ code started by "<<__FILE__<<":"<<__LINE__<< endl; - out << " * Created by slicc definition of Module \"" << getShorthand() << "\"" << endl; - out << " */" << endl; - out << endl; - out << "#ifndef " << component << "_CONTROLLER_H" << endl; - out << "#define " << component << "_CONTROLLER_H" << endl; - out << endl; - out << "#include \"mem/ruby/common/Global.hh\"" << endl; - out << "#include \"mem/ruby/common/Consumer.hh\"" << endl; - out << "#include \"mem/ruby/slicc_interface/AbstractController.hh\"" << endl; - out << "#include \"mem/protocol/TransitionResult.hh\"" << endl; - out << "#include \"mem/protocol/Types.hh\"" << endl; - out << "#include \"mem/protocol/" << component << "_Profiler.hh\"" << endl; - - // include object classes - std::set seen_types; - for(int i=0; igetType()->cIdent()) == 0) { - out << "#include \"mem/protocol/" << var->getType()->cIdent() << ".hh\"" << endl; - // out << "class " << var->getType()->cIdent() << ";" << endl; - seen_types.insert(var->getType()->cIdent()); - } - } - - out << endl; - - // for adding information to the protocol debug trace - out << "extern stringstream " << component << "_" << "transitionComment;" << endl; - - out << "class " << component << "_Controller : public AbstractController {" << endl; - - /* the coherence checker needs to call isBlockExclusive() and isBlockShared() - making the Chip a friend class is an easy way to do this for now */ - out << "#ifdef CHECK_COHERENCE" << endl; - out << "#endif /* CHECK_COHERENCE */" << endl; - - out << "public:" << endl; - // out << " " << component << "_Controller(int version, Network* net_ptr);" << endl; - out << " " << component << "_Controller(const string & name);" << endl; - out << " static int getNumControllers();" << endl; - out << " void init(Network* net_ptr, const vector & argv);" << endl; - out << " MessageBuffer* getMandatoryQueue() const;" << endl; - out << " const int & getVersion() const;" << endl; - out << " const string toString() const;" << endl; - out << " const string getName() const;" << endl; - out << " const MachineType getMachineType() const;" << endl; - out << " void print(ostream& out) const;" << endl; - out << " void printConfig(ostream& out) const;" << endl; - out << " void wakeup();" << endl; - out << " void set_atomic(Address addr);" << endl; - out << " void started_writes();" << endl; - out << " void clear_atomic();" << endl; - out << " void printStats(ostream& out) const { s_profiler.dumpStats(out); }" << endl; - out << " void clearStats() { s_profiler.clearStats(); }" << endl; - out << "private:" << endl; -//added by SS -// found_to_mem = 0; - for(int i=0;isize();i++){ - out << " int m_" << m_config_parameters->ref(i)->getName() << ";" << endl; - } - if (strncmp(component.c_str(), "L1Cache", 7) == 0) { - out << " int servicing_atomic;" << endl; - out << " bool started_receiving_writes;" << endl; - out << " Address locked_read_request1;" << endl; - out << " Address locked_read_request2;" << endl; - out << " Address locked_read_request3;" << endl; - out << " Address locked_read_request4;" << endl; - out << " int read_counter;" << endl; - } - out << " int m_number_of_TBEs;" << endl; - - out << " TransitionResult doTransition(" << component << "_Event event, " << component - << "_State state, const Address& addr"; - if(CHECK_INVALID_RESOURCE_STALLS) { - out << ", int priority"; - } - out << "); // in " << component << "_Transitions.cc" << endl; - out << " TransitionResult doTransitionWorker(" << component << "_Event event, " << component - << "_State state, " << component << "_State& next_state, const Address& addr"; - if(CHECK_INVALID_RESOURCE_STALLS) { - out << ", int priority"; - } - out << "); // in " << component << "_Transitions.cc" << endl; - out << " string m_name;" << endl; - out << " int m_transitions_per_cycle;" << endl; - out << " int m_buffer_size;" << endl; - out << " int m_recycle_latency;" << endl; - out << " map< string, string > m_cfg;" << endl; - out << " NodeID m_version;" << endl; - out << " Network* m_net_ptr;" << endl; - out << " MachineID m_machineID;" << endl; - out << " " << component << "_Profiler s_profiler;" << endl; - out << " static int m_num_controllers;" << endl; - - // internal function protypes - out << " // Internal functions" << endl; - for(int i=0; ifuncPrototype(proto); - if (proto != "") { - out << " " << proto; - } - } - - out << " // Actions" << endl; - for(int i=0; i < numActions(); i++) { - const Action& action = getAction(i); - out << "/** \\brief " << action.getDescription() << "*/" << endl; - out << " void " << action.getIdent() << "(const Address& addr);" << endl; - } - - // the controller internal variables - out << " // Object" << endl; - for(int i=0; i < numObjects(); i++) { - const Var* var = m_objs[i]; - string template_hack = ""; - if (var->existPair("template_hack")) { - template_hack = var->lookupPair("template_hack"); - } - out << " " << var->getType()->cIdent() << template_hack << "* m_" - << var->cIdent() << "_ptr;" << endl; - - string str = "m_"+ var->cIdent() + "_ptr"; - if (var->getType()->cIdent() == "MessageBuffer") - m_message_buffer_names.push_back(str); - - } - - - out << "};" << endl; - out << "#endif // " << component << "_CONTROLLER_H" << endl; -} - -void StateMachine::printControllerC(ostream& out, string component) -{ - out << "/** \\file " << getIdent() << ".cc" << endl; - out << " * " << endl; - out << " * Auto generated C++ code started by "<<__FILE__<<":"<<__LINE__<< endl; - out << " * Created by slicc definition of Module \"" << getShorthand() << "\"" << endl; - out << " */" << endl; - out << endl; - out << "#include \"mem/ruby/common/Global.hh\"" << endl; - out << "#include \"mem/ruby/slicc_interface/RubySlicc_includes.hh\"" << endl; - out << "#include \"mem/protocol/" << component << "_Controller.hh\"" << endl; - out << "#include \"mem/protocol/" << component << "_State.hh\"" << endl; - out << "#include \"mem/protocol/" << component << "_Event.hh\"" << endl; - out << "#include \"mem/protocol/Types.hh\"" << endl; - out << "#include \"mem/ruby/system/System.hh\"" << endl; - - // include object classes - std::set seen_types; - for(int i=0; igetType()->cIdent()) == 0) { - out << "#include \"mem/protocol/" << var->getType()->cIdent() << ".hh\"" << endl; - seen_types.insert(var->getType()->cIdent()); - } - - } - - out << endl; - - out << "int " << component << "_Controller::m_num_controllers = 0;" << endl; - - // for adding information to the protocol debug trace - out << "stringstream " << component << "_" << "transitionComment;" << endl; - out << "#define APPEND_TRANSITION_COMMENT(str) (" << component << "_" << "transitionComment << str)" << endl; - - out << "/** \\brief constructor */" << endl; - out << component << "_Controller::" << component - // << "_Controller(int version, Network* net_ptr)" << endl; - << "_Controller(const string & name)" << endl; - out << " : m_name(name)" << endl; - out << "{ " << endl; - if (strncmp(component.c_str(), "L1Cache", 7) == 0) { - out << " servicing_atomic = 0;" << endl; - out << " started_receiving_writes = false;" << endl; - out << " locked_read_request1 = Address(-1);" << endl; - out << " locked_read_request2 = Address(-1);" << endl; - out << " locked_read_request3 = Address(-1);" << endl; - out << " locked_read_request4 = Address(-1);" << endl; - out << " read_counter = 0;" << endl; - } - out << " m_num_controllers++; " << endl; - for(int i=0; i < numObjects(); i++) { - const Var* var = m_objs[i]; - if ( var->cIdent().find("mandatoryQueue") != string::npos) - out << " m_" << var->cIdent() << "_ptr = new " << var->getType()->cIdent() << "();" << endl; - } - out << "}" << endl << endl; - - out << "void " << component << "_Controller::init(Network * net_ptr, const vector & argv)" << endl; - out << "{" << endl; - out << " for (size_t i=0; i < argv.size(); i+=2) {" << endl; -// out << " printf (\"ARG: %s = %s \\n \", argv[i].c_str(), argv[i+1].c_str());"<< endl; - - out << " if (argv[i] == \"version\") " << endl; - out << " m_version = atoi(argv[i+1].c_str());" << endl; - out << " else if (argv[i] == \"transitions_per_cycle\") " << endl; - out << " m_transitions_per_cycle = atoi(argv[i+1].c_str());" << endl; - out << " else if (argv[i] == \"buffer_size\") " << endl; - out << " m_buffer_size = atoi(argv[i+1].c_str());" << endl; -//added by SS - out << " else if (argv[i] == \"recycle_latency\") " << endl; - out << " m_recycle_latency = atoi(argv[i+1].c_str());" << endl; -//added by SS --> for latency -//for loop on latency_vector to check with argv[i] and assign the value to the related m_latency ... - out << " else if (argv[i] == \"number_of_TBEs\") " << endl; - out << " m_number_of_TBEs = atoi(argv[i+1].c_str());" << endl; - - if (m_config_parameters->size()) { - for(int i= 0 ; i < m_config_parameters->size(); i++) { - out << " else if (argv[i] == \"" << m_config_parameters->ref(i)->getName() << "\")" << endl; - if (m_config_parameters->ref(i)->getTypeName() == "int") - out << " m_" << m_config_parameters->ref(i)->getName() << "=" << "atoi(argv[i+1].c_str());" << endl; - else - assert(0); // only int parameters are supported right now - // if (str == "to_mem_ctrl_latency") - // out << " m_" << (*it)->c_str() << "=" << "atoi(argv[i+1].c_str())+(random() % 5);" << endl; - } - } - out << " }" << endl; - out << " m_net_ptr = net_ptr;" << endl; - out << " m_machineID.type = MachineType_" << component << ";" << endl; - out << " m_machineID.num = m_version;" << endl; - - // make configuration array - out << " for (size_t i=0; i < argv.size(); i+=2) {" << endl; - out << " if (argv[i] != \"version\") " << endl; - out << " m_cfg[argv[i]] = argv[i+1];" << endl; - out << " }" << endl; - - out << endl; - - // initialize objects - out << " // Objects" << endl; - out << " s_profiler.setVersion(m_version);" << endl; - for(int i=0; i < numObjects(); i++) { - const Var* var = m_objs[i]; - if (!var->existPair("network")) { - // Not a network port object - if (var->getType()->existPair("primitive")) { - out << " m_" << var->cIdent() << "_ptr = new " << var->getType()->cIdent() << ";\n"; - if (var->existPair("default")) { - out << " (*m_" << var->cIdent() << "_ptr) = " << var->lookupPair("default") << ";\n"; - } - out << " }\n"; - - } else { - // Normal Object - string template_hack = ""; - if (var->existPair("template_hack")) { - template_hack = var->lookupPair("template_hack"); - } -//added by SS - string str = ""; - int found = 0; - if (var->existPair("factory")) { - out << " m_" << var->cIdent() << "_ptr = " << var->lookupPair("factory"); - } else { - if ( var->cIdent().find("mandatoryQueue") == string::npos) { - - str = " m_" + var->cIdent() + "_ptr = new " + var->getType()->cIdent() + template_hack; - out << str; - if (str.find("TBETable")!=string::npos){ - found = 1; - } - - if (!var->getType()->existPair("non_obj") && (!var->getType()->isEnumeration())) { - str = ""; - if (var->existPair("constructor_hack")) { - string constructor_hack = var->lookupPair("constructor_hack"); - str = "(" + constructor_hack + ")"; - } else { - str = "()"; - } - if (found) - str = "(m_number_of_TBEs)"; - out << str; - } - } - } - - out << ";\n"; - out << " assert(m_" << var->cIdent() << "_ptr != NULL);" << endl; - - if (var->existPair("default")) { - out << " (*m_" << var->cIdent() << "_ptr) = " << var->lookupPair("default") - << "; // Object default" << endl; - } else if (var->getType()->hasDefault()) { - out << " (*m_" << var->cIdent() << "_ptr) = " << var->getType()->getDefault() - << "; // Type " << var->getType()->getIdent() << " default" << endl; - } - - // Set ordering - if (var->existPair("ordered") && !var->existPair("trigger_queue")) { - // A buffer - string ordered = var->lookupPair("ordered"); - out << " m_" << var->cIdent() << "_ptr->setOrdering(" << ordered << ");\n"; - } - - // Set randomization - if (var->existPair("random")) { - // A buffer - string value = var->lookupPair("random"); - out << " m_" << var->cIdent() << "_ptr->setRandomization(" << value << ");\n"; - } - - // Set Priority - if (var->getType()->isBuffer() && var->existPair("rank") && !var->existPair("trigger_queue")) { - string rank = var->lookupPair("rank"); - out << " m_" << var->cIdent() << "_ptr->setPriority(" << rank << ");\n"; - } - } - } else { - // Network port object - string network = var->lookupPair("network"); - string ordered = var->lookupPair("ordered"); - string vnet = var->lookupPair("virtual_network"); - - assert (var->getMachine() != NULL); - out << " m_" << var->cIdent() << "_ptr = m_net_ptr->get" - << network << "NetQueue(m_version+MachineType_base_number(string_to_MachineType(\"" - << var->getMachine()->getIdent() << "\")), " - << ordered << ", " << vnet << ");\n"; - out << " assert(m_" << var->cIdent() << "_ptr != NULL);" << endl; - - // Set ordering - if (var->existPair("ordered")) { - // A buffer - string ordered = var->lookupPair("ordered"); - out << " m_" << var->cIdent() << "_ptr->setOrdering(" << ordered << ");\n"; - } - - // Set randomization - if (var->existPair("random")) { - // A buffer - string value = var->lookupPair("random"); - out << " m_" << var->cIdent() << "_ptr->setRandomization(" << value << ");\n"; - } - - // Set Priority - if (var->existPair("rank")) { - string rank = var->lookupPair("rank"); - out << " m_" << var->cIdent() << "_ptr->setPriority(" << rank << ");\n"; - } - - // Set buffer size - if (var->getType()->isBuffer()) { - out << " if (m_buffer_size > 0) {\n"; - out << " m_" << var->cIdent() << "_ptr->setSize(m_buffer_size);\n"; - out << " }\n"; - } - - // set description (may be overriden later by port def) - out << " m_" << var->cIdent() - << "_ptr->setDescription(\"[Version \" + int_to_string(m_version) + \", " - << component << ", name=" << var->cIdent() << "]\");" << endl; - out << endl; - } - } - - // Set the queue consumers - out << endl; - for(int i=0; i < m_in_ports.size(); i++) { - const Var* port = m_in_ports[i]; - out << " " << port->getCode() << ".setConsumer(this);" << endl; - } - - // Set the queue descriptions - out << endl; - for(int i=0; i < m_in_ports.size(); i++) { - const Var* port = m_in_ports[i]; - out << " " << port->getCode() - << ".setDescription(\"[Version \" + int_to_string(m_version) + \", " - << component << ", " << port->toString() << "]\");" << endl; - } - - // Initialize the transition profiling - out << endl; - for(int i=0; i& action_vec = t.getActions(); - int numActions = action_vec.size(); - - // Figure out if we stall - bool stall = false; - for (int i=0; igetIdent() == "z_stall") { - stall = true; - } - } - - // Only possible if it is not a 'z' case - if (!stall) { - out << " s_profiler.possibleTransition(" << component << "_State_" - << t.getStatePtr()->getIdent() << ", " << component << "_Event_" - << t.getEventPtr()->getIdent() << ");" << endl; - } - } - - //added by SS to initialize recycle_latency of message buffers - std::vector::const_iterator it; - for ( it=m_message_buffer_names.begin() ; it != m_message_buffer_names.end(); it++ ){ - out << " "<< (*it).c_str() << "->setRecycleLatency(m_recycle_latency);" << endl; - } - - - out << "}" << endl; - - out << endl; - - bool has_mandatory_q = false; - for(int i=0; i < m_in_ports.size(); i++) { - if (m_in_ports[i]->getCode().find("mandatoryQueue_ptr")!= string::npos) - has_mandatory_q = true; - } - - out << "int " << component << "_Controller::getNumControllers() {" << endl; - out << " return m_num_controllers;" << endl; - out << "}" << endl; - - out << endl; - - out << "MessageBuffer* " << component << "_Controller::getMandatoryQueue() const {" << endl; - if (has_mandatory_q) - out << " return m_" << component << "_mandatoryQueue_ptr;" << endl; - else - out << " return NULL;" << endl; - out << "}" << endl; - - out << endl; - - out << "const int & "<::const_iterator it = m_cfg.begin(); it != m_cfg.end(); it++) {" << endl; - out << " out << \" \" << (*it).first << \": \" << (*it).second << endl;" << endl; - out << " }" << endl; - out << "}" << endl; - - out << endl; - out << "// Actions" << endl; - out << endl; - - for(int i=0; i < numActions(); i++) { - const Action& action = getAction(i); - if (action.existPair("c_code")) { - out << "/** \\brief " << action.getDescription() << "*/" << endl; - out << "void " << component << "_Controller::" - << action.getIdent() << "(const Address& addr)" << endl; - out << "{" << endl; - out << " DEBUG_MSG(GENERATED_COMP, HighPrio,\"executing\");" << endl; -//added by SS -//it should point to m_latency... -//so I should change the string output of this lookup - - - string c_code_string = action.lookupPair("c_code"); - - out << c_code_string; - - out << "}" << endl; - } - out << endl; - } -} - -void StateMachine::printCWakeup(ostream& out, string component) -{ - out << "// Auto generated C++ code started by "<<__FILE__<<":"<<__LINE__<< endl; - out << "// " << getIdent() << ": " << getShorthand() << endl; - out << endl; - out << "#include \"mem/ruby/common/Global.hh\"" << endl; - out << "#include \"mem/ruby/slicc_interface/RubySlicc_includes.hh\"" << endl; - out << "#include \"mem/protocol/" << component << "_Controller.hh\"" << endl; - out << "#include \"mem/protocol/" << component << "_State.hh\"" << endl; - out << "#include \"mem/protocol/" << component << "_Event.hh\"" << endl; - out << "#include \"mem/protocol/Types.hh\"" << endl; - out << "#include \"mem/ruby/system/System.hh\"" << endl; - out << endl; - out << "void " << component << "_Controller::wakeup()" << endl; - out << "{" << endl; - // out << " DEBUG_EXPR(GENERATED_COMP, MedPrio,*this);" << endl; - // out << " DEBUG_EXPR(GENERATED_COMP, MedPrio,g_eventQueue_ptr->getTime());" << endl; - out << endl; - out << "int counter = 0;" << endl; - out << " while (true) {" << endl; - out << " // Some cases will put us into an infinite loop without this limit" << endl; - out << " assert(counter <= m_transitions_per_cycle);" << endl; - out << " if (counter == m_transitions_per_cycle) {" << endl; - out << " g_system_ptr->getProfiler()->controllerBusy(m_machineID); // Count how often we're fully utilized" << endl; - out << " g_eventQueue_ptr->scheduleEvent(this, 1); // Wakeup in another cycle and try again" << endl; - out << " break;" << endl; - out << " }" << endl; - - // InPorts - // - // Find the position of the mandatory queue in the vector so that we can print it out first - int j = -1; - if (strncmp(component.c_str(), "L1Cache", 7) == 0) { - for(int i=0; i < m_in_ports.size(); i++) { - const Var* port = m_in_ports[i]; - assert(port->existPair("c_code_in_port")); - if (port->toString().find("mandatoryQueue_in") != string::npos) { - assert (j == -1); - j = i; - } - else { - cout << port->toString() << endl << flush; - } - } - - assert(j != -1); - - // print out the mandatory queue here - const Var* port = m_in_ports[j]; - assert(port->existPair("c_code_in_port")); - out << " // " - << component << "InPort " << port->toString() - << endl; - string output = port->lookupPair("c_code_in_port"); - string::size_type pos = output.find("TransitionResult result = doTransition((L1Cache_mandatory_request_type_to_event(((*in_msg_ptr)).m_Type)), L1Cache_getState(addr), addr);"); - assert(pos != string::npos); - string atomics_string = "\n \ - if ((((*in_msg_ptr)).m_Type) == CacheRequestType_ATOMIC) { \n \ - if (servicing_atomic == 0) { \n \ - if (locked_read_request1 == Address(-1)) { \n \ - assert(read_counter == 0); \n \ - locked_read_request1 = addr; \n \ - assert(read_counter == 0); \n \ - read_counter++; \n \ - } \n \ - else if (addr == locked_read_request1) { \n \ - ; // do nothing \n\ - } \n \ - else { \n \ - assert(0); // should never be here if servicing one request at a time \n\ - } \n \ - } \n \ - else if (!started_receiving_writes) { \n \ - if (servicing_atomic == 1) { \n \ - if (locked_read_request2 == Address(-1)) { \n \ - assert(locked_read_request1 != Address(-1)); \n \ - assert(read_counter == 1); \n \ - locked_read_request2 = addr; \n \ - assert(read_counter == 1); \n \ - read_counter++; \n \ - } \n \ - else if (addr == locked_read_request2) { \n \ - ; // do nothing \n\ - } \n \ - else { \n \ - assert(0); // should never be here if servicing one request at a time \n\ - } \n \ - } \n \ - else if (servicing_atomic == 2) { \n \ - if (locked_read_request3 == Address(-1)) { \n \ - assert(locked_read_request1 != Address(-1)); \n \ - assert(locked_read_request2 != Address(-1)); \n \ - assert(read_counter == 1); \n \ - locked_read_request3 = addr; \n \ - assert(read_counter == 2); \n \ - read_counter++; \n \ - } \n \ - else if (addr == locked_read_request3) { \n \ - ; // do nothing \n\ - } \n \ - else { \n \ - assert(0); // should never be here if servicing one request at a time \n\ - } \n \ - } \n \ - else if (servicing_atomic == 3) { \n \ - if (locked_read_request4 == Address(-1)) { \n \ - assert(locked_read_request1 != Address(-1)); \n \ - assert(locked_read_request2 != Address(-1)); \n \ - assert(locked_read_request3 != Address(-1)); \n \ - assert(read_counter == 1); \n \ - locked_read_request4 = addr; \n \ - assert(read_counter == 3); \n \ - read_counter++; \n \ - } \n \ - else if (addr == locked_read_request4) { \n \ - ; // do nothing \n\ - } \n \ - else { \n \ - assert(0); // should never be here if servicing one request at a time \n\ - } \n \ - } \n \ - else { \n \ - assert(0); \n \ - } \n \ - } \n \ - } \n \ - else { \n \ - if (servicing_atomic > 0) { \n \ - // reset \n \ - servicing_atomic = 0; \n \ - read_counter = 0; \n \ - started_receiving_writes = false; \n \ - locked_read_request1 = Address(-1); \n \ - locked_read_request2 = Address(-1); \n \ - locked_read_request3 = Address(-1); \n \ - locked_read_request4 = Address(-1); \n \ - } \n \ - } \n \ - "; - output.insert(pos, atomics_string); - /*string foo = "// Cannot do anything with this transition, go check next doable transition (mostly likely of next port)\n"; - string::size_type next_pos = output.find(foo, pos); - next_pos = next_pos + foo.length(); - - assert(next_pos != string::npos); - string complete = " }\n"; - output.insert(next_pos, complete);*/ - //out << port->lookupPair("c_code_in_port"); - out << output; - out << endl; - } - for(int i=0; i < m_in_ports.size(); i++) { - const Var* port = m_in_ports[i]; - // don't print out mandatory queue twice - if (i != j) { - if (strncmp(component.c_str(), "L1Cache", 7) == 0) { - if (port->toString().find("forwardRequestNetwork_in") != string::npos) { - out << " bool postpone = false;" << endl; - out << " if ((((*m_L1Cache_forwardToCache_ptr)).isReady())) {" << endl; - out << " const RequestMsg* in_msg_ptr;" << endl; - out << " in_msg_ptr = dynamic_cast(((*m_L1Cache_forwardToCache_ptr)).peek());" << endl; - out << " if ((((servicing_atomic == 1) && (locked_read_request1 == ((*in_msg_ptr)).m_Address)) || " << endl; - out << " ((servicing_atomic == 2) && (locked_read_request1 == ((*in_msg_ptr)).m_Address || locked_read_request2 == ((*in_msg_ptr)).m_Address)) || " << endl; - out << " ((servicing_atomic == 3) && (locked_read_request1 == ((*in_msg_ptr)).m_Address || locked_read_request2 == ((*in_msg_ptr)).m_Address || locked_read_request3 == ((*in_msg_ptr)).m_Address)) || " << endl; - out << " ((servicing_atomic == 4) && (locked_read_request1 == ((*in_msg_ptr)).m_Address || locked_read_request2 == ((*in_msg_ptr)).m_Address || locked_read_request3 == ((*in_msg_ptr)).m_Address || locked_read_request1 == ((*in_msg_ptr)).m_Address)))) {" << endl; -// out << " (locked_read_request2 == ((*in_msg_ptr)).m_Address) || (locked_read_request3 == ((*in_msg_ptr)).m_Address) || " << endl; -// out << " (locked_read_request4 == ((*in_msg_ptr)).m_Address))) { " << endl; - - out << " postpone = true;" << endl; - out << " }" << endl; - - out << " }" << endl; - out << " if (!postpone) {" << endl; - } - } - assert(port->existPair("c_code_in_port")); - out << " // " - << component << "InPort " << port->toString() - << endl; - out << port->lookupPair("c_code_in_port"); - if (strncmp(component.c_str(), "L1Cache", 7) == 0) { - if (port->toString().find("forwardRequestNetwork_in") != string::npos) { - out << "}" << endl; - } - } - out << endl; - } - } - - out << " break; // If we got this far, we have nothing left todo" << endl; - out << " }" << endl; - // out << " g_eventQueue_ptr->scheduleEvent(this, 1);" << endl; - // out << " DEBUG_NEWLINE(GENERATED_COMP, MedPrio);" << endl; - out << "}" << endl; - out << endl; - - - // tack on two more functions - if (strncmp(component.c_str(), "L1Cache", 7) == 0) { - out << "void " << component << "_Controller::set_atomic(Address addr)" << endl; - out << "{" << endl; - out << " servicing_atomic++; " << endl; - out << "}" << endl; - out << "void " << component << "_Controller::started_writes()" << endl; - out << "{" << endl; - out << " started_receiving_writes = true; " << endl; - out << "}" << endl; - out << "void " << component << "_Controller::clear_atomic()" << endl; - out << "{" << endl; - out << " assert(servicing_atomic > 0); " << endl; - out << " read_counter--; " << endl; - out << " servicing_atomic--; " << endl; - out << " if (read_counter == 0) { " << endl; - out << " servicing_atomic = 0; " << endl; - out << " started_receiving_writes = false; " << endl; - out << " locked_read_request1 = Address(-1); " << endl; - out << " locked_read_request2 = Address(-1); " << endl; - out << " locked_read_request3 = Address(-1); " << endl; - out << " locked_read_request4 = Address(-1); " << endl; - out << " } " << endl; - out << "}" << endl; - } - else { - out << "void " << component << "_Controller::started_writes()" << endl; - out << "{" << endl; - out << " assert(0); " << endl; - out << "}" << endl; - out << "void " << component << "_Controller::set_atomic(Address addr)" << endl; - out << "{" << endl; - out << " assert(0); " << endl; - out << "}" << endl; - - out << "void " << component << "_Controller::clear_atomic()" << endl; - out << "{" << endl; - out << " assert(0); " << endl; - out << "}" << endl; - } - -} - -void StateMachine::printCSwitch(ostream& out, string component) -{ - out << "// Auto generated C++ code started by "<<__FILE__<<":"<<__LINE__<< endl; - out << "// " << getIdent() << ": " << getShorthand() << endl; - out << endl; - out << "#include \"mem/ruby/common/Global.hh\"" << endl; - out << "#include \"mem/protocol/" << component << "_Controller.hh\"" << endl; - out << "#include \"mem/protocol/" << component << "_State.hh\"" << endl; - out << "#include \"mem/protocol/" << component << "_Event.hh\"" << endl; - out << "#include \"mem/protocol/Types.hh\"" << endl; - out << "#include \"mem/ruby/system/System.hh\"" << endl; - out << endl; - out << "#define HASH_FUN(state, event) ((int(state)*" << component - << "_Event_NUM)+int(event))" << endl; - out << endl; - out << "#define GET_TRANSITION_COMMENT() (" << component << "_" << "transitionComment.str())" << endl; - out << "#define CLEAR_TRANSITION_COMMENT() (" << component << "_" << "transitionComment.str(\"\"))" << endl; - out << endl; - out << "TransitionResult " << component << "_Controller::doTransition(" - << component << "_Event event, " - << component << "_State state, " - << "const Address& addr" << endl; - if(CHECK_INVALID_RESOURCE_STALLS) { - out << ", int priority"; - } - out << ")" << endl; - - out << "{" << endl; - out << " " << component << "_State next_state = state;" << endl; - out << endl; - out << " DEBUG_NEWLINE(GENERATED_COMP, MedPrio);" << endl; - out << " DEBUG_MSG(GENERATED_COMP, MedPrio,*this);" << endl; - out << " DEBUG_EXPR(GENERATED_COMP, MedPrio,g_eventQueue_ptr->getTime());" << endl; - out << " DEBUG_EXPR(GENERATED_COMP, MedPrio,state);" << endl; - out << " DEBUG_EXPR(GENERATED_COMP, MedPrio,event);" << endl; - out << " DEBUG_EXPR(GENERATED_COMP, MedPrio,addr);" << endl; - out << endl; - out << " TransitionResult result = doTransitionWorker(event, state, next_state, addr"; - if(CHECK_INVALID_RESOURCE_STALLS) { - out << ", priority"; - } - out << ");" << endl; - out << endl; - out << " if (result == TransitionResult_Valid) {" << endl; - out << " DEBUG_EXPR(GENERATED_COMP, MedPrio, next_state);" << endl; - out << " DEBUG_NEWLINE(GENERATED_COMP, MedPrio);" << endl; - out << " s_profiler.countTransition(state, event);" << endl; - out << " if (Debug::getProtocolTrace()) {" << endl - << " g_system_ptr->getProfiler()->profileTransition(\"" << component - << "\", m_version, addr, " << endl - << " " << component << "_State_to_string(state), " << endl - << " " << component << "_Event_to_string(event), " << endl - << " " << component << "_State_to_string(next_state), GET_TRANSITION_COMMENT());" << endl - << " }" << endl; - out << " CLEAR_TRANSITION_COMMENT();" << endl; - out << " " << component << "_setState(addr, next_state);" << endl; - out << " " << endl; - out << " } else if (result == TransitionResult_ResourceStall) {" << endl; - out << " if (Debug::getProtocolTrace()) {" << endl - << " g_system_ptr->getProfiler()->profileTransition(\"" << component - << "\", m_version, addr, " << endl - << " " << component << "_State_to_string(state), " << endl - << " " << component << "_Event_to_string(event), " << endl - << " " << component << "_State_to_string(next_state), " << endl - << " \"Resource Stall\");" << endl - << " }" << endl; - out << " } else if (result == TransitionResult_ProtocolStall) {" << endl; - out << " DEBUG_MSG(GENERATED_COMP,HighPrio,\"stalling\");" << endl - << " DEBUG_NEWLINE(GENERATED_COMP, MedPrio);" << endl; - out << " if (Debug::getProtocolTrace()) {" << endl - << " g_system_ptr->getProfiler()->profileTransition(\"" << component - << "\", m_version, addr, " << endl - << " " << component << "_State_to_string(state), " << endl - << " " << component << "_Event_to_string(event), " << endl - << " " << component << "_State_to_string(next_state), " << endl - << " \"Protocol Stall\");" << endl - << " }" << endl - << " }" << endl; - out << " return result;" << endl; - out << "}" << endl; - out << endl; - out << "TransitionResult " << component << "_Controller::doTransitionWorker(" - << component << "_Event event, " - << component << "_State state, " - << component << "_State& next_state, " - << "const Address& addr" << endl; - if(CHECK_INVALID_RESOURCE_STALLS) { - out << ", int priority" << endl; - } - out << ")" << endl; - - out << "{" << endl; - out << "" << endl; - - out << " switch(HASH_FUN(state, event)) {" << endl; - - Map > code_map; // This map will allow suppress generating duplicate code - Vector code_vec; - - for(int i=0; igetIdent() - + ", " + component + "_Event_" + t.getEventPtr()->getIdent(); - - string code; - - code += " {\n"; - // Only set next_state if it changes - if (t.getStatePtr() != t.getNextStatePtr()) { - code += " next_state = " + component + "_State_" + t.getNextStatePtr()->getIdent() + ";\n"; - } - - const Vector& action_vec = t.getActions(); - int numActions = action_vec.size(); - - // Check for resources - Vector code_sorter; - const Map& res = t.getResources(); - Vector res_keys = res.keys(); - for (int i=0; igetType()->cIdent() == "DNUCAStopTable") { - temp_code += res.lookup(res_keys[i]); - } else { - temp_code += " if (!" + (res_keys[i]->getCode()) + ".areNSlotsAvailable(" + res.lookup(res_keys[i]) + ")) {\n"; - if(CHECK_INVALID_RESOURCE_STALLS) { - // assert that the resource stall is for a resource of equal or greater priority - temp_code += " assert(priority >= "+ (res_keys[i]->getCode()) + ".getPriority());\n"; - } - temp_code += " return TransitionResult_ResourceStall;\n"; - temp_code += " }\n"; - } - code_sorter.insertAtBottom(temp_code); - } - - // Emit the code sequences in a sorted order. This makes the - // output deterministic (without this the output order can vary - // since Map's keys() on a vector of pointers is not deterministic - code_sorter.sortVector(); - for (int i=0; igetIdent() == "z_stall") { - stall = true; - } - } - - if (stall) { - code += " return TransitionResult_ProtocolStall;\n"; - } else { - for (int i=0; igetIdent() + "(addr);\n"; - } - code += " return TransitionResult_Valid;\n"; - } - code += " }\n"; - - - // Look to see if this transition code is unique. - if (code_map.exist(code)) { - code_map.lookup(code).insertAtBottom(case_string); - } else { - Vector vec; - vec.insertAtBottom(case_string); - code_map.add(code, vec); - code_vec.insertAtBottom(code); - } - } - - // Walk through all of the unique code blocks and spit out the - // corresponding case statement elements - for (int i=0; igetTime());" << endl; - out << " WARN_EXPR(addr);" << endl; - out << " WARN_EXPR(event);" << endl; - out << " WARN_EXPR(state);" << endl; - out << " ERROR_MSG(\"Invalid transition\");" << endl; - out << " }" << endl; - out << " return TransitionResult_Valid;" << endl; - out << "}" << endl; -} - -void StateMachine::printProfilerH(ostream& out, string component) -{ - out << "// Auto generated C++ code started by "<<__FILE__<<":"<<__LINE__<< endl; - out << "// " << getIdent() << ": " << getShorthand() << endl; - out << endl; - out << "#ifndef " << component << "_PROFILER_H" << endl; - out << "#define " << component << "_PROFILER_H" << endl; - out << endl; - out << "#include \"mem/ruby/common/Global.hh\"" << endl; - out << "#include \"mem/protocol/" << component << "_State.hh\"" << endl; - out << "#include \"mem/protocol/" << component << "_Event.hh\"" << endl; - out << endl; - out << "class " << component << "_Profiler {" << endl; - out << "public:" << endl; - out << " " << component << "_Profiler();" << endl; - out << " void setVersion(int version);" << endl; - out << " void countTransition(" << component << "_State state, " << component << "_Event event);" << endl; - out << " void possibleTransition(" << component << "_State state, " << component << "_Event event);" << endl; - out << " void dumpStats(ostream& out) const;" << endl; - out << " void clearStats();" << endl; - out << "private:" << endl; - out << " int m_counters[" << component << "_State_NUM][" << component << "_Event_NUM];" << endl; - out << " int m_event_counters[" << component << "_Event_NUM];" << endl; - out << " bool m_possible[" << component << "_State_NUM][" << component << "_Event_NUM];" << endl; - out << " int m_version;" << endl; - out << "};" << endl; - out << "#endif // " << component << "_PROFILER_H" << endl; -} - -void StateMachine::printProfilerC(ostream& out, string component) -{ - out << "// Auto generated C++ code started by "<<__FILE__<<":"<<__LINE__<< endl; - out << "// " << getIdent() << ": " << getShorthand() << endl; - out << endl; - out << "#include \"mem/protocol/" << component << "_Profiler.hh\"" << endl; - out << endl; - - // Constructor - out << component << "_Profiler::" << component << "_Profiler()" << endl; - out << "{" << endl; - out << " for (int state = 0; state < " << component << "_State_NUM; state++) {" << endl; - out << " for (int event = 0; event < " << component << "_Event_NUM; event++) {" << endl; - out << " m_possible[state][event] = false;" << endl; - out << " m_counters[state][event] = 0;" << endl; - out << " }" << endl; - out << " }" << endl; - out << " for (int event = 0; event < " << component << "_Event_NUM; event++) {" << endl; - out << " m_event_counters[event] = 0;" << endl; - out << " }" << endl; - out << "}" << endl; - - // setVersion - out << "void " << component << "_Profiler::setVersion(int version)" << endl; - out << "{" << endl; - out << " m_version = version;" << endl; - out << "}" << endl; - - // Clearstats - out << "void " << component << "_Profiler::clearStats()" << endl; - out << "{" << endl; - out << " for (int state = 0; state < " << component << "_State_NUM; state++) {" << endl; - out << " for (int event = 0; event < " << component << "_Event_NUM; event++) {" << endl; - out << " m_counters[state][event] = 0;" << endl; - out << " }" << endl; - out << " }" << endl; - out << " for (int event = 0; event < " << component << "_Event_NUM; event++) {" << endl; - out << " m_event_counters[event] = 0;" << endl; - out << " }" << endl; - out << "}" << endl; - - // Count Transition - out << "void " << component << "_Profiler::countTransition(" << component << "_State state, " << component << "_Event event)" << endl; - out << "{" << endl; - out << " assert(m_possible[state][event]);" << endl; - out << " m_counters[state][event]++;" << endl; - out << " m_event_counters[event]++;" << endl; - out << "}" << endl; - - // Possible Transition - out << "void " << component << "_Profiler::possibleTransition(" << component << "_State state, " << component << "_Event event)" << endl; - out << "{" << endl; - out << " m_possible[state][event] = true;" << endl; - out << "}" << endl; - - // dumpStats - out << "void " << component << "_Profiler::dumpStats(ostream& out) const" << endl; - out << "{" << endl; - out << " out << \" --- " << component << " \" << m_version << \" ---\" << endl;" << endl; - out << " out << \" - Event Counts -\" << endl;" << endl; - out << " for (int event = 0; event < " << component << "_Event_NUM; event++) {" << endl; - out << " int count = m_event_counters[event];" << endl; - out << " out << (" << component << "_Event) event << \" \" << count << endl;" << endl; - out << " }" << endl; - out << " out << endl;" << endl; - out << " out << \" - Transitions -\" << endl;" << endl; - out << " for (int state = 0; state < " << component << "_State_NUM; state++) {" << endl; - out << " for (int event = 0; event < " << component << "_Event_NUM; event++) {" << endl; - out << " if (m_possible[state][event]) {" << endl; - out << " int count = m_counters[state][event];" << endl; - out << " out << (" << component << "_State) state << \" \" << (" << component << "_Event) event << \" \" << count;" << endl; - out << " if (count == 0) {" << endl; - out << " out << \" <-- \";" << endl; - out << " }" << endl; - out << " out << endl;" << endl; - out << " }" << endl; - out << " }" << endl; - out << " out << endl;" << endl; - out << " }" << endl; - out << "}" << endl; -} - - - -// ************************** // -// ******* HTML Files ******* // -// ************************** // - -string frameRef(string click_href, string click_target, string over_href, string over_target_num, string text) -{ - string temp; - temp += ""; - return temp; -} - -string frameRef(string href, string target, string target_num, string text) -{ - return frameRef(href, target, href, target_num, text); -} - - -void StateMachine::writeHTMLFiles(string path) -{ - string filename; - string component = getIdent(); - - /* - { - ostringstream out; - out << "" << endl; - out << "" << endl; - out << "" << component << "" << endl; - out << "" << endl; - out << "" << endl; - out << " " << endl; - out << " " << endl; - out << "" << endl; - out << "" << endl; - conditionally_write_file(path + component + ".html", out); - } - */ - - // Create table with no row hilighted - { - ostringstream out; - printHTMLTransitions(out, numStates()+1); - - // -- Write file - filename = component + "_table.html"; - conditionally_write_file(path + filename, out); - } - - // Generate transition tables - for(int i=0; i" << endl; - - // -- Header - out << "

" << formatHTMLShorthand(getShorthand()) << ": " << endl; - Vector machine_vec = g_sym_table.getStateMachines(); - for (int i=0; igetIdent() << endl; - } else { - out << "getIdent() + "_table.html\">" + type->getIdent() + " " << endl; - } - } - out << "

" << endl; - - // -- Table header - out << "" << endl; - - // -- Column headers - out << "" << endl; - - // -- First column header - out << " " << endl; - - for(int event = 0; event < numEvents(); event++ ) { - out << " " << endl; - } - - out << "" << endl; - - // -- Body of table - for(int state = 0; state < numStates(); state++ ) { - out << "" << endl; - - // -- Each row - if (state == active_state) { - out << " " << endl; - - // -- One column for each event - for(int event = 0; event < numEvents(); event++ ) { - const Transition* trans_ptr = getTransPtr(state, event); - - if( trans_ptr != NULL ) { - bool stall_action = false; - string nextState; - string actions_str; - - // -- Get the actions - // actions = trans_ptr->getActionShorthands(); - const Vector actions = trans_ptr->getActions(); - for (int action=0; action < actions.size(); action++) { - if ((actions[action]->getIdent() == "z_stall") || - (actions[action]->getIdent() == "zz_recycleMandatoryQueue")) { - stall_action = true; - } - actions_str += " "; - actions_str += frameRef(getIdent() + "_action_" + actions[action]->getIdent() + ".html", "Status", "1", - formatHTMLShorthand(actions[action]->getShorthand())); - actions_str += "\n"; - } - - // -- Get the next state - if (trans_ptr->getNextStatePtr()->getIdent() != getState(state).getIdent()) { - string click_href = getIdent() + "_table_" + trans_ptr->getNextStatePtr()->getIdent() + ".html"; - nextState = frameRef(click_href, "Table", getIdent() + "_State_" + trans_ptr->getNextStatePtr()->getIdent() + ".html", "1", - formatHTMLShorthand(trans_ptr->getNextStateShorthand())); - } else { - nextState = ""; - } - - // -- Print out "actions/next-state" - if (stall_action) { - if (state == active_state) { - out << " " << endl; - } else { - // This is the no transition case - if (state == active_state) { - out << " " << endl; - } else { - out << " " << endl; - } - } - } - // -- Each row - if (state == active_state) { - out << " " << endl; - - out << "" << endl; - } - - // -- Column footer - out << "" << endl; - out << " " << endl; - - for(int i = 0; i < numEvents(); i++ ) { - out << " " << endl; - } - out << "" << endl; - - // -- Epilog - out << "
"; - out << frameRef(getIdent() + "_Event_" + getEvent(event).getIdent() + ".html", "Status", "1", formatHTMLShorthand(getEvent(event).getShorthand())); - out << "
"; - } else { - out << " "; - } - - string click_href = getIdent() + "_table_" + getState(state).getIdent() + ".html"; - string text = formatHTMLShorthand(getState(state).getShorthand()); - - out << frameRef(click_href, "Table", getIdent() + "_State_" + getState(state).getIdent() + ".html", "1", formatHTMLShorthand(getState(state).getShorthand())); - out << ""; - } else { - out << " "; - } - } else if (active_state < numStates() && (trans_ptr->getNextStatePtr()->getIdent() == getState(active_state).getIdent())) { - out << " "; - } else if (state == active_state) { - out << " "; - } else { - out << " "; - } - - out << actions_str; - if ((nextState.length() != 0) && (actions_str.length() != 0)) { - out << "/"; - } - out << nextState; - out << "  "; - } else { - out << " "; - } - - click_href = getIdent() + "_table_" + getState(state).getIdent() + ".html"; - text = formatHTMLShorthand(getState(state).getShorthand()); - - out << frameRef(click_href, "Table", getIdent() + "_State_" + getState(state).getIdent() + ".html", "1", formatHTMLShorthand(getState(state).getShorthand())); - out << "
"; - out << frameRef(getIdent() + "_Event_" + getEvent(i).getIdent() + ".html", "Status", "1", formatHTMLShorthand(getEvent(i).getShorthand())); - out << "
" << endl; - out << "" << endl; -} - - diff --git a/src/mem/slicc/symbols/StateMachine.hh b/src/mem/slicc/symbols/StateMachine.hh deleted file mode 100644 index f5f3ab073..000000000 --- a/src/mem/slicc/symbols/StateMachine.hh +++ /dev/null @@ -1,156 +0,0 @@ - -/* - * Copyright (c) 1999-2008 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. - */ - -/* - * $Id$ - * - * */ - -#ifndef STATEMACHINE_H -#define STATEMACHINE_H - -#include "mem/slicc/slicc_global.hh" -#include "mem/gems_common/Vector.hh" -#include "mem/gems_common/Map.hh" -#include "mem/slicc/symbols/Symbol.hh" -#include - -using namespace std; - -class Transition; -class Event; -class State; -class Action; -class Var; -class Func; -class FormalParamAST; - -class StateMachine : public Symbol { -public: - // Constructors - StateMachine(string ident, const Location& location, const Map& pairs, Vector* config_parameters); - - // Destructor - ~StateMachine(); - - // Public Methods - - // Add items to the state machine - // void setMachine(string ident, const Map& pairs); - void addState(State* state_ptr); - void addEvent(Event* event_ptr); - void addAction(Action* action_ptr); - void addTransition(Transition* trans_ptr); - void addInPort(Var* var) { m_in_ports.insertAtBottom(var); } - void addFunc(Func* func); - void addObj(Var* obj) { m_objs.insertAtBottom(obj); } - - // Accessors to vectors - const State& getState(int index) const { return *m_states[index]; } - const Event& getEvent(int index) const { return *m_events[index]; } - const Action& getAction(int index) const { return *m_actions[index]; } - const Transition& getTransition(int index) const { return *m_transitions[index]; } - const Transition* getTransPtr(int stateIndex, int eventIndex) const; - const Var& getObject(int index) const { return *m_objs[index]; } - - // Accessors for size of vectors - int numStates() const { return m_states.size(); } - int numEvents() const { return m_events.size(); } - int numActions() const { return m_actions.size(); } - int numTransitions() const { return m_transitions.size(); } - int numObjects() const { return m_objs.size(); } - - void buildTable(); // Needs to be called before accessing the table - - // Code generator methods - void writeCFiles(string path) ; - void writeHTMLFiles(string path) ; - - void print(ostream& out) const { out << "[StateMachine: " << toString() << "]" << endl; } -private: - - Vector* m_config_parameters; - - // Private Methods - void checkForDuplicate(const Symbol& sym) const; - - int getStateIndex(State* state_ptr) const { return m_state_map.lookup(state_ptr); } - int getEventIndex(Event* event_ptr) const { return m_event_map.lookup(event_ptr); } - - // Private copy constructor and assignment operator - // StateMachine(const StateMachine& obj); - // StateMachine& operator=(const StateMachine& obj); - - void printControllerH(ostream& out, string component) ; - void printControllerC(ostream& out, string component) ; - void printCWakeup(ostream& out, string component) ; - void printCSwitch(ostream& out, string component) ; - void printProfilerH(ostream& out, string component) ; - void printProfilerC(ostream& out, string component) ; - - void printHTMLTransitions(ostream& out, int active_state) ; - - // Data Members (m_ prefix) - Vector m_states; - Vector m_events; - Vector m_actions; - Vector m_transitions; - Vector m_internal_func_vec; - - Map m_state_map; - Map m_event_map; - - Vector m_in_ports; - - Vector m_objs; - - // Table variables - bool m_table_built; - Vector > m_table; - - //added by SS - std::vector m_message_buffer_names; - -}; - -// Output operator declaration -ostream& operator<<(ostream& out, const StateMachine& obj); - -// ******************* Definitions ******************* - -// Output operator definition -extern inline -ostream& operator<<(ostream& out, const StateMachine& obj) -{ - obj.print(out); - out << flush; - return out; -} - -#endif //STATEMACHINE_H diff --git a/src/mem/slicc/symbols/StateMachine.py b/src/mem/slicc/symbols/StateMachine.py new file mode 100644 index 000000000..e54d6a435 --- /dev/null +++ b/src/mem/slicc/symbols/StateMachine.py @@ -0,0 +1,1222 @@ +# Copyright (c) 1999-2008 Mark D. Hill and David A. Wood +# Copyright (c) 2009 The Hewlett-Packard Development Company +# 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 m5.util import code_formatter, orderdict + +from slicc.symbols.Symbol import Symbol +from slicc.symbols.Var import Var +import slicc.generate.html as html + +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) + self.symtab.registerSym(param.name, var) + + self.states = orderdict() + self.events = orderdict() + self.actions = orderdict() + self.transitions = [] + self.in_ports = [] + self.functions = [] + self.objects = [] + + self.message_buffer_names = [] + + def __repr__(self): + return "[StateMachine: %s]" % self.ident + + def addState(self, state): + assert self.table is None + self.states[state.ident] = state + + def addEvent(self, event): + assert self.table is None + self.events[event.ident] = event + + def addAction(self, action): + assert self.table is None + + # Check for duplicate action + for other in self.actions.itervalues(): + if action.ident == other.ident: + a.warning("Duplicate action definition: %s" % a.ident) + action.error("Duplicate action definition: %s" % action.ident) + if action.short == other.short: + other.warning("Duplicate action shorthand: %s" % other.ident) + other.warning(" shorthand = %s" % other.short) + action.warning("Duplicate action shorthand: %s" % action.ident) + action.error(" shorthand = %s" % action.short) + + self.actions[action.ident] = action + + def addTransition(self, trans): + assert self.table is None + self.transitions.append(trans) + + def addInPort(self, var): + self.in_ports.append(var) + + def addFunc(self, func): + # register func in the symbol table + self.symtab.registerSym(str(func), func) + self.functions.append(func) + + def addObject(self, obj): + self.objects.append(obj) + + # Needs to be called before accessing the table + def buildTable(self): + assert self.table is None + + table = {} + + for trans in self.transitions: + # Track which actions we touch so we know if we use them + # all -- really this should be done for all symbols as + # part of the symbol table, then only trigger it for + # Actions, States, Events, etc. + + for action in trans.actions: + action.used = True + + index = (trans.state, trans.event) + if index in table: + table[index].warning("Duplicate transition: %s" % table[index]) + trans.error("Duplicate transition: %s" % trans) + table[index] = trans + + # Look at all actions to make sure we used them all + for action in self.actions.itervalues(): + if not action.used: + error_msg = "Unused action: %s" % action.ident + if "desc" in action: + error_msg += ", " + action.desc + action.warning(error_msg) + self.table = table + + def writeCodeFiles(self, path): + self.printControllerHH(path) + self.printControllerCC(path) + self.printCSwitch(path) + self.printCWakeup(path) + self.printProfilerCC(path) + self.printProfilerHH(path) + + for func in self.functions: + func.writeCodeFiles(path) + + def printControllerHH(self, path): + '''Output the method declarations for the class declaration''' + code = code_formatter() + ident = self.ident + c_ident = "%s_Controller" % self.ident + + self.message_buffer_names = [] + + code(''' +/** \\file $ident.hh + * + * Auto generated C++ code started by $__file__:$__line__ + * Created by slicc definition of Module "${{self.short}}" + */ + +#ifndef ${ident}_CONTROLLER_H +#define ${ident}_CONTROLLER_H + +#include "mem/ruby/common/Global.hh" +#include "mem/ruby/common/Consumer.hh" +#include "mem/ruby/slicc_interface/AbstractController.hh" +#include "mem/protocol/TransitionResult.hh" +#include "mem/protocol/Types.hh" +#include "mem/protocol/${ident}_Profiler.hh" +''') + + seen_types = set() + for var in self.objects: + if var.type.ident not in seen_types: + code('#include "mem/protocol/${{var.type.c_ident}}.hh"') + seen_types.add(var.type.ident) + + # for adding information to the protocol debug trace + code(''' +extern stringstream ${ident}_transitionComment; + +class $c_ident : public AbstractController { +#ifdef CHECK_COHERENCE +#endif /* CHECK_COHERENCE */ +public: + $c_ident(const string & name); + static int getNumControllers(); + void init(Network* net_ptr, const vector & argv); + MessageBuffer* getMandatoryQueue() const; + const int & getVersion() const; + const string toString() const; + const string getName() const; + const MachineType getMachineType() const; + void print(ostream& out) const; + void printConfig(ostream& out) const; + void wakeup(); + void set_atomic(Address addr); + void started_writes(); + void clear_atomic(); + void printStats(ostream& out) const { s_profiler.dumpStats(out); } + void clearStats() { s_profiler.clearStats(); } +private: +''') + + code.indent() + # added by SS + for param in self.config_parameters: + code('int m_${{param.ident}};') + + if self.ident == "L1Cache": + code(''' +int servicing_atomic; +bool started_receiving_writes; +Address locked_read_request1; +Address locked_read_request2; +Address locked_read_request3; +Address locked_read_request4; +int read_counter; +''') + + code(''' +int m_number_of_TBEs; + +TransitionResult doTransition(${ident}_Event event, ${ident}_State state, const Address& addr); // in ${ident}_Transitions.cc +TransitionResult doTransitionWorker(${ident}_Event event, ${ident}_State state, ${ident}_State& next_state, const Address& addr); // in ${ident}_Transitions.cc +string m_name; +int m_transitions_per_cycle; +int m_buffer_size; +int m_recycle_latency; +map< string, string > m_cfg; +NodeID m_version; +Network* m_net_ptr; +MachineID m_machineID; +${ident}_Profiler s_profiler; +static int m_num_controllers; +// Internal functions +''') + + for func in self.functions: + proto = func.prototype + if proto: + code('$proto') + + code(''' + +// Actions +''') + for action in self.actions.itervalues(): + code('/** \\brief ${{action.desc}} */') + code('void ${{action.ident}}(const Address& addr);') + + # the controller internal variables + code(''' + +// Object +''') + for var in self.objects: + th = var.get("template_hack", "") + code('${{var.type.c_ident}}$th* m_${{var.c_ident}}_ptr;') + + if var.type.ident == "MessageBuffer": + self.message_buffer_names.append("m_%s_ptr" % var.c_ident) + + code.dedent() + code('};') + code('#endif // ${ident}_CONTROLLER_H') + code.write(path, '%s.hh' % c_ident) + + def printControllerCC(self, path): + '''Output the actions for performing the actions''' + + code = code_formatter() + ident = self.ident + c_ident = "%s_Controller" % self.ident + + code(''' +/** \\file $ident.cc + * + * Auto generated C++ code started by $__file__:$__line__ + * Created by slicc definition of Module "${{self.short}}" + */ + +#include "mem/ruby/common/Global.hh" +#include "mem/ruby/slicc_interface/RubySlicc_includes.hh" +#include "mem/protocol/${ident}_Controller.hh" +#include "mem/protocol/${ident}_State.hh" +#include "mem/protocol/${ident}_Event.hh" +#include "mem/protocol/Types.hh" +#include "mem/ruby/system/System.hh" +''') + + # include object classes + seen_types = set() + for var in self.objects: + if var.type.ident not in seen_types: + code('#include "mem/protocol/${{var.type.c_ident}}.hh"') + seen_types.add(var.type.ident) + + code(''' +int $c_ident::m_num_controllers = 0; + +stringstream ${ident}_transitionComment; +#define APPEND_TRANSITION_COMMENT(str) (${ident}_transitionComment << str) +/** \\brief constructor */ +$c_ident::$c_ident(const string &name) + : m_name(name) +{ +''') + code.indent() + if self.ident == "L1Cache": + code(''' +servicing_atomic = 0; +started_receiving_writes = false; +locked_read_request1 = Address(-1); +locked_read_request2 = Address(-1); +locked_read_request3 = Address(-1); +locked_read_request4 = Address(-1); +read_counter = 0; +''') + + code('m_num_controllers++;') + for var in self.objects: + if var.ident.find("mandatoryQueue") >= 0: + code('m_${{var.c_ident}}_ptr = new ${{var.type.c_ident}}();') + + code.dedent() + code(''' +} + +void $c_ident::init(Network *net_ptr, const vector &argv) +{ + for (size_t i = 0; i < argv.size(); i += 2) { + if (argv[i] == "version") + m_version = atoi(argv[i+1].c_str()); + else if (argv[i] == "transitions_per_cycle") + m_transitions_per_cycle = atoi(argv[i+1].c_str()); + else if (argv[i] == "buffer_size") + m_buffer_size = atoi(argv[i+1].c_str()); + else if (argv[i] == "recycle_latency") + m_recycle_latency = atoi(argv[i+1].c_str()); + else if (argv[i] == "number_of_TBEs") + m_number_of_TBEs = atoi(argv[i+1].c_str()); +''') + + code.indent() + code.indent() + for param in self.config_parameters: + code('else if (argv[i] == "${{param.name}}")') + if param.type_ast.type.ident == "int": + code(' m_${{param.name}} = atoi(argv[i+1].c_str());') + else: + self.error("only int parameters are supported right now") + code.dedent() + code.dedent() + code(''' + } + + m_net_ptr = net_ptr; + m_machineID.type = MachineType_${ident}; + m_machineID.num = m_version; + for (size_t i = 0; i < argv.size(); i += 2) { + if (argv[i] != "version") + m_cfg[argv[i]] = argv[i+1]; + } + + // Objects + s_profiler.setVersion(m_version); +''') + + code.indent() + for var in self.objects: + vtype = var.type + vid = "m_%s_ptr" % var.c_ident + if "network" not in var: + # Not a network port object + if "primitive" in vtype: + code('$vid = new ${{vtype.c_ident}};') + if "default" in var: + code('(*$vid) = ${{var["default"]}};') + else: + # Normal Object + # added by SS + if "factory" in var: + code('$vid = ${{var["factory"]}};') + elif var.ident.find("mandatoryQueue") < 0: + th = var.get("template_hack", "") + expr = "%s = new %s%s" % (vid, vtype.c_ident, th) + + args = "" + if "non_obj" not in vtype and not vtype.isEnumeration: + if expr.find("TBETable") >= 0: + args = "m_number_of_TBEs" + else: + args = var.get("constructor_hack", "") + args = "(%s)" % args + + code('$expr$args;') + else: + code(';') + + code('assert($vid != NULL);') + + if "default" in var: + code('(*$vid) = ${{var["default"]}}; // Object default') + elif "default" in vtype: + code('(*$vid) = ${{vtype["default"]}}; // Type ${{vtype.ident}} default') + + # Set ordering + if "ordered" in var and "trigger_queue" not in var: + # A buffer + code('$vid->setOrdering(${{var["ordered"]}});') + + # Set randomization + if "random" in var: + # A buffer + code('$vid->setRandomization(${{var["random"]}});') + + # Set Priority + if vtype.isBuffer and \ + "rank" in var and "trigger_queue" not in var: + code('$vid->setPriority(${{var["rank"]}});') + else: + # Network port object + network = var["network"] + ordered = var["ordered"] + vnet = var["virtual_network"] + + assert var.machine is not None + code(''' +$vid = m_net_ptr->get${network}NetQueue(m_version+MachineType_base_number(string_to_MachineType("${{var.machine.ident}}")), $ordered, $vnet); +''') + + code('assert($vid != NULL);') + + # Set ordering + if "ordered" in var: + # A buffer + code('$vid->setOrdering(${{var["ordered"]}});') + + # Set randomization + if "random" in var: + # A buffer + code('$vid->setRandomization(${{var["random"]}})') + + # Set Priority + if "rank" in var: + code('$vid->setPriority(${{var["rank"]}})') + + # Set buffer size + if vtype.isBuffer: + code(''' +if (m_buffer_size > 0) { + $vid->setSize(m_buffer_size); +} +''') + + # set description (may be overriden later by port def) + code('$vid->setDescription("[Version " + int_to_string(m_version) + ", ${ident}, name=${{var.c_ident}}]");') + + # Set the queue consumers + code.insert_newline() + for port in self.in_ports: + code('${{port.code}}.setConsumer(this);') + + # Set the queue descriptions + code.insert_newline() + for port in self.in_ports: + code('${{port.code}}.setDescription("[Version " + int_to_string(m_version) + ", $ident, $port]");') + + # Initialize the transition profiling + code.insert_newline() + for trans in self.transitions: + # Figure out if we stall + stall = False + for action in trans.actions: + if action.ident == "z_stall": + stall = True + + # Only possible if it is not a 'z' case + if not stall: + state = "%s_State_%s" % (self.ident, trans.state.ident) + event = "%s_Event_%s" % (self.ident, trans.event.ident) + code('s_profiler.possibleTransition($state, $event);') + + # added by SS to initialize recycle_latency of message buffers + for buf in self.message_buffer_names: + code("$buf->setRecycleLatency(m_recycle_latency);") + + code.dedent() + code('}') + + has_mandatory_q = False + for port in self.in_ports: + if port.code.find("mandatoryQueue_ptr") >= 0: + has_mandatory_q = True + + if has_mandatory_q: + mq_ident = "m_%s_mandatoryQueue_ptr" % self.ident + else: + mq_ident = "NULL" + + code(''' +int $c_ident::getNumControllers() { + return m_num_controllers; +} + +MessageBuffer* $c_ident::getMandatoryQueue() const { + return $mq_ident; +} + +const int & $c_ident::getVersion() const{ + return m_version; +} + +const string $c_ident::toString() const{ + return "$c_ident"; +} + +const string $c_ident::getName() const{ + return m_name; +} +const MachineType $c_ident::getMachineType() const{ + return MachineType_${ident}; +} + +void $c_ident::print(ostream& out) const { out << "[$c_ident " << m_version << "]"; } + +void $c_ident::printConfig(ostream& out) const { + out << "$c_ident config: " << m_name << endl; + out << " version: " << m_version << endl; + for (map::const_iterator it = m_cfg.begin(); it != m_cfg.end(); it++) { + out << " " << (*it).first << ": " << (*it).second << endl; + } +} + +// Actions +''') + + 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) +{ + DEBUG_MSG(GENERATED_COMP, HighPrio, "executing"); + ${{action["c_code"]}} +} + +''') + code.write(path, "%s.cc" % c_ident) + + def printCWakeup(self, path): + '''Output the wakeup loop for the events''' + + code = code_formatter() + ident = self.ident + + code(''' +// Auto generated C++ code started by $__file__:$__line__ +// ${ident}: ${{self.short}} + +#include "mem/ruby/common/Global.hh" +#include "mem/ruby/slicc_interface/RubySlicc_includes.hh" +#include "mem/protocol/${ident}_Controller.hh" +#include "mem/protocol/${ident}_State.hh" +#include "mem/protocol/${ident}_Event.hh" +#include "mem/protocol/Types.hh" +#include "mem/ruby/system/System.hh" + +void ${ident}_Controller::wakeup() +{ + + int counter = 0; + while (true) { + // Some cases will put us into an infinite loop without this limit + assert(counter <= m_transitions_per_cycle); + if (counter == m_transitions_per_cycle) { + g_system_ptr->getProfiler()->controllerBusy(m_machineID); // Count how often we\'re fully utilized + g_eventQueue_ptr->scheduleEvent(this, 1); // Wakeup in another cycle and try again + break; + } +''') + + code.indent() + code.indent() + + # InPorts + # + # Find the position of the mandatory queue in the vector so + # that we can print it out first + + mandatory_q = None + if self.ident == "L1Cache": + for i,port in enumerate(self.in_ports): + assert "c_code_in_port" in port + if str(port).find("mandatoryQueue_in") >= 0: + assert mandatory_q is None + mandatory_q = port + + assert mandatory_q is not None + + # print out the mandatory queue here + port = mandatory_q + code('// ${ident}InPort $port') + output = port["c_code_in_port"] + + pos = output.find("TransitionResult result = doTransition((L1Cache_mandatory_request_type_to_event(((*in_msg_ptr)).m_Type)), L1Cache_getState(addr), addr);") + assert pos >= 0 + atomics_string = ''' +if ((((*in_msg_ptr)).m_Type) == CacheRequestType_ATOMIC) { + if (servicing_atomic == 0) { + if (locked_read_request1 == Address(-1)) { + assert(read_counter == 0); + locked_read_request1 = addr; + assert(read_counter == 0); + read_counter++; + } + else if (addr == locked_read_request1) { + ; // do nothing + } + else { + assert(0); // should never be here if servicing one request at a time + } + } + else if (!started_receiving_writes) { + if (servicing_atomic == 1) { + if (locked_read_request2 == Address(-1)) { + assert(locked_read_request1 != Address(-1)); + assert(read_counter == 1); + locked_read_request2 = addr; + assert(read_counter == 1); + read_counter++; + } + else if (addr == locked_read_request2) { + ; // do nothing + } + else { + assert(0); // should never be here if servicing one request at a time + } + } + else if (servicing_atomic == 2) { + if (locked_read_request3 == Address(-1)) { + assert(locked_read_request1 != Address(-1)); + assert(locked_read_request2 != Address(-1)); + assert(read_counter == 1); + locked_read_request3 = addr; + assert(read_counter == 2); + read_counter++; + } + else if (addr == locked_read_request3) { + ; // do nothing + } + else { + assert(0); // should never be here if servicing one request at a time + } + } + else if (servicing_atomic == 3) { + if (locked_read_request4 == Address(-1)) { + assert(locked_read_request1 != Address(-1)); + assert(locked_read_request2 != Address(-1)); + assert(locked_read_request3 != Address(-1)); + assert(read_counter == 1); + locked_read_request4 = addr; + assert(read_counter == 3); + read_counter++; + } + else if (addr == locked_read_request4) { + ; // do nothing + } + else { + assert(0); // should never be here if servicing one request at a time + } + } + else { + assert(0); + } + } +} +else { + if (servicing_atomic > 0) { + // reset + servicing_atomic = 0; + read_counter = 0; + started_receiving_writes = false; + locked_read_request1 = Address(-1); + locked_read_request2 = Address(-1); + locked_read_request3 = Address(-1); + locked_read_request4 = Address(-1); + } +} +''' + + output = output[:pos] + atomics_string + output[pos:] + code('$output') + + for port in self.in_ports: + # don't print out mandatory queue twice + if port == mandatory_q: + continue + + if ident == "L1Cache": + if str(port).find("forwardRequestNetwork_in") >= 0: + code(''' +bool postpone = false; +if ((((*m_L1Cache_forwardToCache_ptr)).isReady())) { + const RequestMsg* in_msg_ptr; + in_msg_ptr = dynamic_cast(((*m_L1Cache_forwardToCache_ptr)).peek()); + if ((((servicing_atomic == 1) && (locked_read_request1 == ((*in_msg_ptr)).m_Address)) || + ((servicing_atomic == 2) && (locked_read_request1 == ((*in_msg_ptr)).m_Address || locked_read_request2 == ((*in_msg_ptr)).m_Address)) || + ((servicing_atomic == 3) && (locked_read_request1 == ((*in_msg_ptr)).m_Address || locked_read_request2 == ((*in_msg_ptr)).m_Address || locked_read_request3 == ((*in_msg_ptr)).m_Address)) || + ((servicing_atomic == 4) && (locked_read_request1 == ((*in_msg_ptr)).m_Address || locked_read_request2 == ((*in_msg_ptr)).m_Address || locked_read_request3 == ((*in_msg_ptr)).m_Address || locked_read_request1 == ((*in_msg_ptr)).m_Address)))) { + postpone = true; + } +} +if (!postpone) { +''') + code.indent() + code('// ${ident}InPort $port') + code('${{port["c_code_in_port"]}}') + code.dedent() + + if ident == "L1Cache": + if str(port).find("forwardRequestNetwork_in") >= 0: + code.dedent() + code('}') + code.indent() + code('') + + code.dedent() + code.dedent() + code(''' + break; // If we got this far, we have nothing left todo + } +} +''') + + if self.ident == "L1Cache": + code(''' +void ${ident}_Controller::set_atomic(Address addr) +{ + servicing_atomic++; +} + +void ${ident}_Controller::started_writes() +{ + started_receiving_writes = true; +} + +void ${ident}_Controller::clear_atomic() +{ + assert(servicing_atomic > 0); + read_counter--; + servicing_atomic--; + if (read_counter == 0) { + servicing_atomic = 0; + started_receiving_writes = false; + locked_read_request1 = Address(-1); + locked_read_request2 = Address(-1); + locked_read_request3 = Address(-1); + locked_read_request4 = Address(-1); + } +} +''') + else: + code(''' +void ${ident}_Controller::started_writes() +{ + assert(0); +} + +void ${ident}_Controller::set_atomic(Address addr) +{ + assert(0); +} + +void ${ident}_Controller::clear_atomic() +{ + assert(0); +} +''') + + + code.write(path, "%s_Wakeup.cc" % self.ident) + + def printCSwitch(self, path): + '''Output switch statement for transition table''' + + code = code_formatter() + ident = self.ident + + code(''' +// Auto generated C++ code started by $__file__:$__line__ +// ${ident}: ${{self.short}} + +#include "mem/ruby/common/Global.hh" +#include "mem/protocol/${ident}_Controller.hh" +#include "mem/protocol/${ident}_State.hh" +#include "mem/protocol/${ident}_Event.hh" +#include "mem/protocol/Types.hh" +#include "mem/ruby/system/System.hh" + +#define HASH_FUN(state, event) ((int(state)*${ident}_Event_NUM)+int(event)) + +#define GET_TRANSITION_COMMENT() (${ident}_transitionComment.str()) +#define CLEAR_TRANSITION_COMMENT() (${ident}_transitionComment.str("")) + +TransitionResult ${ident}_Controller::doTransition(${ident}_Event event, ${ident}_State state, const Address& addr +) +{ + ${ident}_State next_state = state; + + DEBUG_NEWLINE(GENERATED_COMP, MedPrio); + DEBUG_MSG(GENERATED_COMP, MedPrio, *this); + DEBUG_EXPR(GENERATED_COMP, MedPrio, g_eventQueue_ptr->getTime()); + DEBUG_EXPR(GENERATED_COMP, MedPrio,state); + DEBUG_EXPR(GENERATED_COMP, MedPrio,event); + DEBUG_EXPR(GENERATED_COMP, MedPrio,addr); + + TransitionResult result = doTransitionWorker(event, state, next_state, addr); + + if (result == TransitionResult_Valid) { + DEBUG_EXPR(GENERATED_COMP, MedPrio, next_state); + DEBUG_NEWLINE(GENERATED_COMP, MedPrio); + s_profiler.countTransition(state, event); + if (Debug::getProtocolTrace()) { + g_system_ptr->getProfiler()->profileTransition("${ident}", m_version, addr, + ${ident}_State_to_string(state), + ${ident}_Event_to_string(event), + ${ident}_State_to_string(next_state), GET_TRANSITION_COMMENT()); + } + CLEAR_TRANSITION_COMMENT(); + ${ident}_setState(addr, next_state); + + } else if (result == TransitionResult_ResourceStall) { + if (Debug::getProtocolTrace()) { + g_system_ptr->getProfiler()->profileTransition("${ident}", m_version, addr, + ${ident}_State_to_string(state), + ${ident}_Event_to_string(event), + ${ident}_State_to_string(next_state), + "Resource Stall"); + } + } else if (result == TransitionResult_ProtocolStall) { + DEBUG_MSG(GENERATED_COMP, HighPrio, "stalling"); + DEBUG_NEWLINE(GENERATED_COMP, MedPrio); + if (Debug::getProtocolTrace()) { + g_system_ptr->getProfiler()->profileTransition("${ident}", m_version, addr, + ${ident}_State_to_string(state), + ${ident}_Event_to_string(event), + ${ident}_State_to_string(next_state), + "Protocol Stall"); + } + } + + return result; +} + +TransitionResult ${ident}_Controller::doTransitionWorker(${ident}_Event event, ${ident}_State state, ${ident}_State& next_state, const Address& addr +) +{ + switch(HASH_FUN(state, event)) { +''') + + # This map will allow suppress generating duplicate code + cases = orderdict() + + for trans in self.transitions: + case_string = "%s_State_%s, %s_Event_%s" % \ + (self.ident, trans.state.ident, self.ident, trans.event.ident) + + case = code_formatter() + # Only set next_state if it changes + if trans.state != trans.nextState: + ns_ident = trans.nextState.ident + case('next_state = ${ident}_State_${ns_ident};') + + actions = trans.actions + + # Check for resources + case_sorter = [] + res = trans.resources + for key,val in res.iteritems(): + if key.type.ident != "DNUCAStopTable": + val = ''' +if (!%s.areNSlotsAvailable(%s)) { + return TransitionResult_ResourceStall; +} +''' % (key.code, val) + case_sorter.append(val) + + + # Emit the code sequences in a sorted order. This makes the + # output deterministic (without this the output order can vary + # since Map's keys() on a vector of pointers is not deterministic + for c in sorted(case_sorter): + case("$c") + + # Figure out if we stall + stall = False + for action in actions: + if action.ident == "z_stall": + stall = True + break + + if stall: + case('return TransitionResult_ProtocolStall;') + else: + for action in actions: + case('${{action.ident}}(addr);') + case('return TransitionResult_Valid;') + + case = str(case) + + # Look to see if this transition code is unique. + if case not in cases: + cases[case] = [] + + cases[case].append(case_string) + + # Walk through all of the unique code blocks and spit out the + # corresponding case statement elements + for case,transitions in cases.iteritems(): + # Iterative over all the multiple transitions that share + # the same code + for trans in transitions: + code(' case HASH_FUN($trans):') + code(' {') + code(' $case') + code(' }') + + code(''' + default: + WARN_EXPR(m_version); + WARN_EXPR(g_eventQueue_ptr->getTime()); + WARN_EXPR(addr); + WARN_EXPR(event); + WARN_EXPR(state); + ERROR_MSG(\"Invalid transition\"); + } + return TransitionResult_Valid; +} +''') + code.write(path, "%s_Transitions.cc" % self.ident) + + def printProfilerHH(self, path): + code = code_formatter() + ident = self.ident + + code(''' +// Auto generated C++ code started by $__file__:$__line__ +// ${ident}: ${{self.short}} + +#ifndef ${ident}_PROFILER_H +#define ${ident}_PROFILER_H + +#include "mem/ruby/common/Global.hh" +#include "mem/protocol/${ident}_State.hh" +#include "mem/protocol/${ident}_Event.hh" + +class ${ident}_Profiler { + public: + ${ident}_Profiler(); + void setVersion(int version); + void countTransition(${ident}_State state, ${ident}_Event event); + void possibleTransition(${ident}_State state, ${ident}_Event event); + void dumpStats(ostream& out) const; + void clearStats(); + + private: + int m_counters[${ident}_State_NUM][${ident}_Event_NUM]; + int m_event_counters[${ident}_Event_NUM]; + bool m_possible[${ident}_State_NUM][${ident}_Event_NUM]; + int m_version; +}; + +#endif // ${ident}_PROFILER_H +''') + code.write(path, "%s_Profiler.hh" % self.ident) + + def printProfilerCC(self, path): + code = code_formatter() + ident = self.ident + + code(''' +// Auto generated C++ code started by $__file__:$__line__ +// ${ident}: ${{self.short}} + +#include "mem/protocol/${ident}_Profiler.hh" + +${ident}_Profiler::${ident}_Profiler() +{ + for (int state = 0; state < ${ident}_State_NUM; state++) { + for (int event = 0; event < ${ident}_Event_NUM; event++) { + m_possible[state][event] = false; + m_counters[state][event] = 0; + } + } + for (int event = 0; event < ${ident}_Event_NUM; event++) { + m_event_counters[event] = 0; + } +} +void ${ident}_Profiler::setVersion(int version) +{ + m_version = version; +} +void ${ident}_Profiler::clearStats() +{ + for (int state = 0; state < ${ident}_State_NUM; state++) { + for (int event = 0; event < ${ident}_Event_NUM; event++) { + m_counters[state][event] = 0; + } + } + + for (int event = 0; event < ${ident}_Event_NUM; event++) { + m_event_counters[event] = 0; + } +} +void ${ident}_Profiler::countTransition(${ident}_State state, ${ident}_Event event) +{ + assert(m_possible[state][event]); + m_counters[state][event]++; + m_event_counters[event]++; +} +void ${ident}_Profiler::possibleTransition(${ident}_State state, ${ident}_Event event) +{ + m_possible[state][event] = true; +} +void ${ident}_Profiler::dumpStats(ostream& out) const +{ + out << " --- ${ident} " << m_version << " ---" << endl; + out << " - Event Counts -" << endl; + for (int event = 0; event < ${ident}_Event_NUM; event++) { + int count = m_event_counters[event]; + out << (${ident}_Event) event << " " << count << endl; + } + out << endl; + out << " - Transitions -" << endl; + for (int state = 0; state < ${ident}_State_NUM; state++) { + for (int event = 0; event < ${ident}_Event_NUM; event++) { + if (m_possible[state][event]) { + int count = m_counters[state][event]; + out << (${ident}_State) state << " " << (${ident}_Event) event << " " << count; + if (count == 0) { + out << " <-- "; + } + out << endl; + } + } + out << endl; + } +} +''') + code.write(path, "%s_Profiler.cc" % self.ident) + + # ************************** + # ******* HTML Files ******* + # ************************** + def frameRef(self, click_href, click_target, over_href, over_target_num, + text): + code = code_formatter(fix_newlines=False) + code("""${{html.formatShorthand(text)}}""") + return str(code) + + def writeHTMLFiles(self, path): + # Create table with no row hilighted + self.printHTMLTransitions(path, None) + + # Generate transition tables + for state in self.states.itervalues(): + self.printHTMLTransitions(path, state) + + # Generate action descriptions + for action in self.actions.itervalues(): + name = "%s_action_%s.html" % (self.ident, action.ident) + code = html.createSymbol(action, "Action") + code.write(path, name) + + # Generate state descriptions + for state in self.states.itervalues(): + name = "%s_State_%s.html" % (self.ident, state.ident) + code = html.createSymbol(state, "State") + code.write(path, name) + + # Generate event descriptions + for event in self.events.itervalues(): + name = "%s_Event_%s.html" % (self.ident, event.ident) + code = html.createSymbol(event, "Event") + code.write(path, name) + + def printHTMLTransitions(self, path, active_state): + code = code_formatter() + + code(''' + + +

${{html.formatShorthand(self.short)}}: +''') + code.indent() + for i,machine in enumerate(self.symtab.getAllType(StateMachine)): + mid = machine.ident + if i != 0: + extra = " - " + else: + extra = "" + if machine == self: + code('$extra$mid') + else: + code('$extra$mid') + code.dedent() + + code(""" +

+ + + + +""") + + for event in self.events.itervalues(): + href = "%s_Event_%s.html" % (self.ident, event.ident) + ref = self.frameRef(href, "Status", href, "1", event.short) + code('') + + code('') + # -- Body of table + for state in self.states.itervalues(): + # -- Each row + if state == active_state: + color = "yellow" + else: + color = "white" + + click = "%s_table_%s.html" % (self.ident, state.ident) + over = "%s_State_%s.html" % (self.ident, state.ident) + text = html.formatShorthand(state.short) + ref = self.frameRef(click, "Table", over, "1", state.short) + code(''' + + +''') + + # -- One column for each event + for event in self.events.itervalues(): + trans = self.table.get((state,event), None) + if trans is None: + # This is the no transition case + if state == active_state: + color = "#C0C000" + else: + color = "lightgrey" + + code('') + continue + + next = trans.nextState + stall_action = False + + # -- Get the actions + for action in trans.actions: + if action.ident == "z_stall" or \ + action.ident == "zz_recycleMandatoryQueue": + stall_action = True + + # -- Print out "actions/next-state" + if stall_action: + if state == active_state: + color = "#C0C000" + else: + color = "lightgrey" + + elif active_state and next.ident == active_state.ident: + color = "aqua" + elif state == active_state: + color = "yellow" + else: + color = "white" + + fix = code.nofix() + code('\n") + code.fix(fix) + + # -- Each row + if state == active_state: + color = "yellow" + else: + color = "white" + + click = "%s_table_%s.html" % (self.ident, state.ident) + over = "%s_State_%s.html" % (self.ident, state.ident) + ref = self.frameRef(click, "Table", over, "1", state.short) + code(''' + + +''') + code(''' + + +''') + + for event in self.events.itervalues(): + href = "%s_Event_%s.html" % (self.ident, event.ident) + ref = self.frameRef(href, "Status", href, "1", event.short) + code('') + code(''' + +
$ref
$ref ') + for action in trans.actions: + href = "%s_action_%s.html" % (self.ident, action.ident) + ref = self.frameRef(href, "Status", href, "1", + action.short) + code(' $ref\n') + if next != state: + if trans.actions: + code('/') + click = "%s_table_%s.html" % (self.ident, next.ident) + over = "%s_State_%s.html" % (self.ident, next.ident) + ref = self.frameRef(click, "Table", over, "1", next.short) + code("$ref") + code("$ref
$ref
+ +''') + + + if active_state: + name = "%s_table_%s.html" % (self.ident, active_state.ident) + else: + name = "%s_table.html" % self.ident + code.write(path, name) + +__all__ = [ "StateMachine" ] diff --git a/src/mem/slicc/symbols/Symbol.cc b/src/mem/slicc/symbols/Symbol.cc deleted file mode 100644 index 25af5ad47..000000000 --- a/src/mem/slicc/symbols/Symbol.cc +++ /dev/null @@ -1,72 +0,0 @@ - -/* - * Copyright (c) 1999-2008 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. - */ - -/* - * $Id$ - * - */ - -#include "mem/slicc/symbols/Symbol.hh" - -Symbol::Symbol(string id, const Location& location, const Map& pairs) -{ - m_id = id; - m_location = location; - m_pairs = pairs; - if (!existPair("short")) { - addPair("short", m_id); - } - m_used = false; -} - -Symbol::Symbol(string id, const Location& location) -{ - m_id = id; - m_location = location; - if (!existPair("short")) { - addPair("short", m_id); - } - m_used = false; -} - -const string& Symbol::lookupPair(const string& key) const -{ - if (!existPair(key)) { - error("Value for pair '" + key + "' missing."); - } - return m_pairs.lookup(key); -} - -void Symbol::addPair(const string& key, const string& value) -{ - if (existPair(key)) { - warning("Pair key '" + key + "' re-defined. new: '" + value + "' old: '" + lookupPair(key) + "'"); - } - m_pairs.add(key, value); -} diff --git a/src/mem/slicc/symbols/Symbol.hh b/src/mem/slicc/symbols/Symbol.hh deleted file mode 100644 index 4a1c5e44e..000000000 --- a/src/mem/slicc/symbols/Symbol.hh +++ /dev/null @@ -1,100 +0,0 @@ - -/* - * Copyright (c) 1999-2008 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. - */ - -/* - * $Id$ - */ - -#ifndef SYMBOL_H -#define SYMBOL_H - -#include "mem/slicc/slicc_global.hh" -#include "mem/gems_common/Map.hh" -#include "mem/slicc/ast/Location.hh" - -class Symbol { -public: - // Constructors - Symbol(string id, const Location& location, const Map& pairs); - Symbol(string id, const Location& location); - // Destructor - virtual ~Symbol() { } - - // Public Methods - void error(string err_msg) const { m_location.error(err_msg); } - void warning(string err_msg) const { m_location.warning(err_msg); } - const Location& getLocation() const { return m_location; } - - const string& toString() const { return m_id; } - - const string& getIdent() const { return m_id; } - const string& getShorthand() const { return lookupPair("short"); } - const string& getDescription() const { return lookupPair("desc"); } - - void markUsed() { m_used = true; } - bool wasUsed() { return m_used; } - - bool existPair(const string& key) const { return m_pairs.exist(key); } - const string& lookupPair(const string& key) const; - void addPair(const string& key, const string& value); - - // virtual string getCode() const = 0; - virtual void writeCFiles(string path) {} - virtual void writeHTMLFiles(string path) {} - virtual void print(ostream& out) const { out << "[Symbol: " << getIdent() << "]"; } - -private: - // Private Methods - - // Private copy constructor and assignment operator - // Symbol(const Symbol& obj); - // Symbol& operator=(const Symbol& obj); - - // Data Members (m_ prefix) - string m_id; - Map m_pairs; - Location m_location; - bool m_used; -}; - -// Output operator declaration -ostream& operator<<(ostream& out, const Symbol& obj); - -// ******************* Definitions ******************* - -// Output operator definition -extern inline -ostream& operator<<(ostream& out, const Symbol& obj) -{ - obj.print(out); - out << flush; - return out; -} - -#endif //SYMBOL_H diff --git a/src/mem/slicc/symbols/Symbol.py b/src/mem/slicc/symbols/Symbol.py new file mode 100644 index 000000000..b394fda44 --- /dev/null +++ b/src/mem/slicc/symbols/Symbol.py @@ -0,0 +1,78 @@ +# Copyright (c) 1999-2008 Mark D. Hill and David A. Wood +# Copyright (c) 2009 The Hewlett-Packard Development Company +# 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.util import PairContainer + +class Symbol(PairContainer): + def __init__(self, symtab, ident, location, pairs=None): + super(Symbol, self).__init__() + + from slicc.util import Location + from slicc.symbols import SymbolTable + if not isinstance(symtab, SymbolTable): raise AttributeError + if not isinstance(ident, str): raise AttributeError + if not isinstance(location, Location): raise AttributeError + + self.symtab = symtab + self.ident = ident + self.location = location + if pairs: + self.pairs.update(getattr(pairs, "pairs", pairs)) + if "short" not in self: + self["short"] = self.ident + self.used = False + + def __repr__(self): + return "[Symbol: %s]" % self.ident + + def __str__(self): + return str(self.ident) + + def __setitem__(self, key, value): + if key in self.pairs: + self.warning("Pair key '%s' re-defined. new: '%s' old: '%s'", + key, value, self.pairs[key]) + super(Symbol, self).__setitem__(key, value) + + @property + def short(self): + return self["short"] + + @property + def desc(self): + return self["desc"] + + def error(self, message, *args): + self.location.error(message, *args) + + def warning(self, message, *args): + self.location.warning(message, *args) + + def writeHTMLFiles(self, path): + pass + +__all__ = [ "Symbol" ] diff --git a/src/mem/slicc/symbols/SymbolTable.cc b/src/mem/slicc/symbols/SymbolTable.cc deleted file mode 100644 index 8af3685f8..000000000 --- a/src/mem/slicc/symbols/SymbolTable.cc +++ /dev/null @@ -1,327 +0,0 @@ - -/* - * Copyright (c) 1999-2008 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. - */ - -/* - * SymbolTable.cc - * - * Description: See SymbolTable.hh - * - * $Id$ - * - * */ - -#include "mem/slicc/symbols/SymbolTable.hh" -#include "mem/slicc/generator/fileio.hh" -#include "mem/slicc/generator/html_gen.hh" -#include "mem/slicc/generator/mif_gen.hh" -#include "mem/slicc/symbols/Action.hh" - -SymbolTable g_sym_table; - -SymbolTable::SymbolTable() -{ - m_sym_map_vec.setSize(1); - m_depth = 0; - - { - Map pairs; - pairs.add("enumeration", "yes"); - newSym(new Type("MachineType", Location(), pairs)); - } - - { - Map pairs; - pairs.add("primitive", "yes"); - pairs.add("external", "yes"); - newSym(new Type("void", Location(), pairs)); - } -} - -SymbolTable::~SymbolTable() -{ - int size = m_sym_vec.size(); - for(int i=0; itoString(), sym_ptr); - m_sym_vec.insertAtBottom(sym_ptr); // Holder for the allocated Sym objects. -} - -void SymbolTable::newMachComponentSym(Symbol* sym_ptr) -{ - // used to cheat-- that is, access components in other machines - StateMachine* mach_ptr = getStateMachine("current_machine"); - if (mach_ptr != NULL) { - m_machine_component_map_vec.lookup(mach_ptr->toString()).add(sym_ptr->toString(), sym_ptr); - } -} - -Var* SymbolTable::getMachComponentVar(string mach, string ident) -{ - Symbol* s = m_machine_component_map_vec.lookup(mach).lookup(ident); - return dynamic_cast(s); -} - - -void SymbolTable::registerSym(string id, Symbol* sym_ptr) -{ - - // Check for redeclaration (in the current frame only) - if (m_sym_map_vec[m_depth].exist(id)) { - sym_ptr->error("Symbol '" + id + "' redeclared in same scope."); - } - // FIXME - warn on masking of a declaration in a previous frame - m_sym_map_vec[m_depth].add(id, sym_ptr); -} - -void SymbolTable::registerGlobalSym(string id, Symbol* sym_ptr) -{ - // Check for redeclaration (global frame only) - if (m_sym_map_vec[0].exist(id)) { - sym_ptr->error("Global symbol '" + id + "' redeclared in global scope."); - } - m_sym_map_vec[0].add(id, sym_ptr); -} - -Symbol* SymbolTable::getSym(string ident) const -{ - for (int i=m_depth; i>=0; i--) { - if (m_sym_map_vec[i].exist(ident)) { - return m_sym_map_vec[i].lookup(ident); - } - } - return NULL; -} - -void SymbolTable::newCurrentMachine(StateMachine* sym_ptr) -{ - registerGlobalSym(sym_ptr->toString(), sym_ptr); - registerSym("current_machine", sym_ptr); - m_sym_vec.insertAtBottom(sym_ptr); // Holder for the allocated Sym objects. - - Map m; - m_machine_component_map_vec.add(sym_ptr->toString(),m); - -} - -Type* SymbolTable::getType(string ident) const -{ - return dynamic_cast(getSym(ident)); -} - -Var* SymbolTable::getVar(string ident) const -{ - return dynamic_cast(getSym(ident)); -} - -Func* SymbolTable::getFunc(string ident) const -{ - return dynamic_cast(getSym(ident)); -} - -StateMachine* SymbolTable::getStateMachine(string ident) const -{ - return dynamic_cast(getSym(ident)); -} - -void SymbolTable::pushFrame() -{ - m_depth++; - m_sym_map_vec.expand(1); - m_sym_map_vec[m_depth].clear(); -} - -void SymbolTable::popFrame() -{ - m_depth--; - assert(m_depth >= 0); - m_sym_map_vec.expand(-1); -} - -void SymbolTable::writeCFiles(string path) const -{ - int size = m_sym_vec.size(); - { - // Write the Types.hh include file for the types - ostringstream sstr; - sstr << "/** Auto generated C++ code started by "<<__FILE__<<":"<<__LINE__<< " */" << endl; - sstr << endl; - sstr << "#include \"mem/ruby/slicc_interface/RubySlicc_includes.hh\"" << endl; - for(int i=0; i(m_sym_vec[i]); - if (type != NULL && !type->isPrimitive()) { - sstr << "#include \"mem/protocol/" << type->cIdent() << ".hh" << "\"" << endl; - } - } - conditionally_write_file(path + "/Types.hh", sstr); - } - - // Write all the symbols - for(int i=0; iwriteCFiles(path + '/'); - } - - writeControllerFactory(path); -} - -void SymbolTable::writeControllerFactory(string path) const -{ - ostringstream sstr; - int size = m_sym_vec.size(); - - sstr << "/** \\file ControllerFactory.hh " << endl; - sstr << " * Auto generatred C++ code started by " << __FILE__ << ":" << __LINE__ << endl; - sstr << " */" << endl << endl; - - sstr << "#ifndef CONTROLLERFACTORY_H" << endl; - sstr << "#define CONTROLLERFACTORY_H" << endl; - sstr << endl; - - Vector< string > controller_types; - - // includes - sstr << "#include " << endl; - sstr << "class Network;" << endl; - sstr << "class AbstractController;" << endl; - sstr << endl; - - sstr << "class ControllerFactory {" << endl; - sstr << "public:" << endl; - sstr << " static AbstractController* createController(const std::string & controller_type, const std::string & name);" << endl; - sstr << "};" << endl; - sstr << endl; - - sstr << "#endif // CONTROLLERFACTORY_H" << endl; - conditionally_write_file(path + "/ControllerFactory.hh", sstr); - - // ControllerFactory.cc file - - sstr.str(""); - - sstr << "/** \\file ControllerFactory.cc " << endl; - sstr << " * Auto generatred C++ code started by " << __FILE__ << ":" << __LINE__ << endl; - sstr << " */" << endl << endl; - - // includes - sstr << "#include \"mem/protocol/ControllerFactory.hh\"" << endl; - sstr << "#include \"mem/ruby/slicc_interface/AbstractController.hh\"" << endl; - sstr << "#include \"mem/protocol/MachineType.hh\"" << endl; - for(int i=0; i(m_sym_vec[i]); - if (machine != NULL) { - sstr << "#include \"mem/protocol/" << machine->getIdent() << "_Controller.hh\"" << endl; - controller_types.insertAtBottom(machine->getIdent()); - } - } - sstr << endl; - - sstr << "AbstractController* ControllerFactory::createController(const std::string & controller_type, const std::string & name) {" << endl; - for (int i=0;i SymbolTable::getStateMachines() const -{ - Vector machine_vec; - int size = m_sym_vec.size(); - for(int i=0; i(m_sym_vec[i]); - if (type != NULL) { - machine_vec.insertAtBottom(type); - } - } - return machine_vec; -} - -void SymbolTable::writeHTMLFiles(string path) const -{ - // Create index.html - { - ostringstream out; - createHTMLindex(path, out); - conditionally_write_file(path + "index.html", out); - } - - // Create empty.html - { - ostringstream out; - out << ""; - conditionally_write_file(path + "empty.html", out); - } - - // Write all the symbols - int size = m_sym_vec.size(); - for(int i=0; iwriteHTMLFiles(path); - } -} - -void write_file(string filename, ostringstream& sstr) -{ - ofstream out; - - out.open(filename.c_str()); - out << sstr.str(); - out.close(); -} - -void SymbolTable::writeMIFFiles(string path) const -{ - int size = m_sym_vec.size(); - for(int i=0; i(m_sym_vec[i]); - if (machine != NULL) { - printStateTableMIF(*machine, states); - write_file(path + machine->getIdent() + "_states.mif", states); - printEventTableMIF(*machine, events); - write_file(path + machine->getIdent() + "_events.mif", events); - printActionTableMIF(*machine, actions); - write_file(path + machine->getIdent() + "_actions.mif", actions); - printTransitionTableMIF(*machine, transitions); - write_file(path + machine->getIdent() + "_transitions.mif", transitions); - } - } -} - - -void SymbolTable::print(ostream& out) const -{ - out << "[SymbolTable]"; // FIXME -} diff --git a/src/mem/slicc/symbols/SymbolTable.hh b/src/mem/slicc/symbols/SymbolTable.hh deleted file mode 100644 index 90d3f48c3..000000000 --- a/src/mem/slicc/symbols/SymbolTable.hh +++ /dev/null @@ -1,121 +0,0 @@ - -/* - * Copyright (c) 1999-2008 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. - */ - -/* - * SymbolTable.hh - * - * Description: - * - * $Id$ - * - * */ - -#ifndef SYMBOLTABLE_H -#define SYMBOLTABLE_H - -#include "mem/slicc/slicc_global.hh" -#include "mem/gems_common/Map.hh" -#include "mem/gems_common/Vector.hh" - -#include "mem/slicc/symbols/Symbol.hh" -#include "mem/slicc/symbols/Type.hh" -#include "mem/slicc/symbols/Var.hh" -#include "mem/slicc/symbols/Func.hh" -#include "mem/slicc/symbols/StateMachine.hh" - -class SymbolTable; - -extern SymbolTable g_sym_table; - -class SymbolTable { -public: - // Constructors - SymbolTable(); - - // Destructor - ~SymbolTable(); - - // Public Methods - void newSym(Symbol* sym_ptr); - void registerSym(string id, Symbol* sym_ptr); - Symbol* getSym(string id) const; - - // used to cheat-- that is, access components in other machines - void newMachComponentSym(Symbol* sym_ptr); - Var* getMachComponentVar(string mach, string ident); - - void newCurrentMachine(StateMachine* machine_ptr); - StateMachine* getStateMachine(string ident) const; - StateMachine* getStateMachine() const { return getStateMachine("current_machine"); } - Type* getType(string ident) const; - - Var* getVar(string ident) const; - Func* getFunc(string ident) const; - - void pushFrame(); - void popFrame(); - - Vector getStateMachines() const; - - void writeCFiles(string path) const; - void writeHTMLFiles(string path) const; - void writeMIFFiles(string path) const; - - void print(ostream& out) const; -private: - // Private Methods - void registerGlobalSym(string id, Symbol* sym_ptr); - void writeControllerFactory(string path) const; - - // Private copy constructor and assignment operator - SymbolTable(const SymbolTable& obj); - SymbolTable& operator=(const SymbolTable& obj); - - // Data Members (m_ prefix) - Vector m_sym_vec; - Vector > m_sym_map_vec; - Map > m_machine_component_map_vec; - int m_depth; -}; - -// Output operator declaration -ostream& operator<<(ostream& out, const SymbolTable& obj); - -// ******************* Definitions ******************* - -// Output operator definition -extern inline -ostream& operator<<(ostream& out, const SymbolTable& obj) -{ - obj.print(out); - out << flush; - return out; -} - -#endif //SYMBOLTABLE_H diff --git a/src/mem/slicc/symbols/SymbolTable.py b/src/mem/slicc/symbols/SymbolTable.py new file mode 100644 index 000000000..17d7dfad3 --- /dev/null +++ b/src/mem/slicc/symbols/SymbolTable.py @@ -0,0 +1,218 @@ +# Copyright (c) 1999-2008 Mark D. Hill and David A. Wood +# Copyright (c) 2009 The Hewlett-Packard Development Company +# 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 m5.util import code_formatter + +from slicc.generate import html +from slicc.symbols.StateMachine import StateMachine +from slicc.symbols.Type import Type +from slicc.util import Location + +class SymbolTable(object): + def __init__(self): + self.sym_vec = [] + self.sym_map_vec = [ {} ] + self.machine_components = {} + + pairs = {} + pairs["enumeration"] = "yes" + MachineType = Type(self, "MachineType", Location("init", 0), pairs) + self.newSymbol(MachineType) + + pairs = {} + pairs["primitive"] = "yes" + pairs["external"] = "yes" + void = Type(self, "void", Location("init", 0), pairs) + self.newSymbol(void) + + def __repr__(self): + return "[SymbolTable]" # FIXME + + def newSymbol(self, sym): + self.registerSym(str(sym), sym) + self.sym_vec.append(sym) + + def registerSym(self, id, sym): + # Check for redeclaration (in the current frame only) + if id in self.sym_map_vec[-1]: + sym.error("Symbol '%s' redeclared in same scope.", id) + + # FIXME - warn on masking of a declaration in a previous frame + self.sym_map_vec[-1][id] = sym + + def find(self, ident, types=None): + for sym_map in reversed(self.sym_map_vec): + try: + symbol = sym_map[ident] + except KeyError: + continue + + if types is not None: + assert isinstance(symbol, types) + + return symbol + + return None + + def newMachComponentSym(self, symbol): + # used to cheat-- that is, access components in other machines + machine = self.find("current_machine", StateMachine) + if machine: + self.machine_components[str(machine)][str(symbol)] = symbol + + def newCurrentMachine(self, sym): + self.registerGlobalSym(str(sym), sym) + self.registerSym("current_machine", sym) + self.sym_vec.append(sym) + + self.machine_components[str(sym)] = {} + + @property + def state_machine(self): + return self.find("current_machine", StateMachine) + + def pushFrame(self): + self.sym_map_vec.append({}) + + def popFrame(self): + assert len(self.sym_map_vec) > 0 + self.sym_map_vec.pop() + + def registerGlobalSym(self, ident, symbol): + # Check for redeclaration (global frame only) + if ident in self.sym_map_vec[0]: + symbol.error("Symbol '%s' redeclared in global scope." % ident) + + self.sym_map_vec[0][ident] = symbol + + def getAllType(self, type): + for symbol in self.sym_vec: + if isinstance(symbol, type): + yield symbol + + def writeCodeFiles(self, path): + code = code_formatter() + code(''' +/** Auto generated C++ code started by $__file__:$__line__ */ + +#include "mem/ruby/slicc_interface/RubySlicc_includes.hh" +''') + for symbol in self.sym_vec: + if isinstance(symbol, Type) and not symbol.isPrimitive: + code('#include "mem/protocol/${{symbol.c_ident}}.hh"') + + code.write(path, "Types.hh") + + for symbol in self.sym_vec: + symbol.writeCodeFiles(path) + + self.writeControllerFactory(path) + + def writeControllerFactory(self, path): + code = code_formatter() + + code(''' +/** \\file ControllerFactory.hh + * Auto generatred C++ code started by $__file__:$__line__ + */ + +#ifndef CONTROLLERFACTORY_H +#define CONTROLLERFACTORY_H + +#include +class Network; +class AbstractController; + +class ControllerFactory { + public: + static AbstractController *createController(const std::string &controller_type, const std::string &name); +}; +#endif // CONTROLLERFACTORY_H''') + code.write(path, "ControllerFactory.hh") + + code = code_formatter() + code(''' +/** \\file ControllerFactory.cc + * Auto generatred C++ code started by $__file__:$__line__ + */ + +#include "mem/protocol/ControllerFactory.hh" +#include "mem/ruby/slicc_interface/AbstractController.hh" +#include "mem/protocol/MachineType.hh" +''') + + controller_types = [] + for symbol in self.getAllType(StateMachine): + code('#include "mem/protocol/${{symbol.ident}}_Controller.hh"') + controller_types.append(symbol.ident) + + code(''' +AbstractController *ControllerFactory::createController(const std::string &controller_type, const std::string &name) { +''') + + for ct in controller_types: + code(''' + if (controller_type == "$ct") + return new ${ct}_Controller(name); +''') + + code(''' + assert(0); // invalid controller type + return NULL; +} +''') + code.write(path, "ControllerFactory.cc") + + def writeHTMLFiles(self, path): + machines = list(self.getAllType(StateMachine)) + if len(machines) > 1: + name = "%s_table.html" % machines[0].ident + else: + name = "empty.html" + + code = code_formatter() + code(''' + + +$path + + + + + + +''') + code.write(path, "index.html") + + code = code_formatter() + code("") + code.write(path, "empty.html") + + for symbol in self.sym_vec: + symbol.writeHTMLFiles(path) + +__all__ = [ "SymbolTable" ] diff --git a/src/mem/slicc/symbols/Transition.cc b/src/mem/slicc/symbols/Transition.cc deleted file mode 100644 index d6d348166..000000000 --- a/src/mem/slicc/symbols/Transition.cc +++ /dev/null @@ -1,173 +0,0 @@ - -/* - * Copyright (c) 1999-2008 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. - */ - -/* - * $Id$ - * - * */ - -#include "mem/slicc/symbols/Transition.hh" -#include "mem/slicc/symbols/State.hh" -#include "mem/slicc/symbols/Event.hh" -#include "mem/slicc/symbols/Action.hh" -#include "mem/gems_common/util.hh" -#include "mem/slicc/symbols/Var.hh" - -Transition::Transition(string state, string event, string nextState, - const Vector& actionList, - const Location& location, - const Map& pairMap) - : Symbol(state + "|" + event, location, pairMap) -{ - m_state = state; - m_event = event; - m_nextState = nextState; - m_actionList = actionList; - - // Ptrs are undefined at this point - m_statePtr = NULL; - m_eventPtr = NULL; - m_nextStatePtr = NULL; - m_actionPtrsValid = false; -} - -void Transition::checkIdents(const Vector& states, - const Vector& events, - const Vector& actions) -{ - m_statePtr = findIndex(states, m_state); - m_eventPtr = findIndex(events, m_event); - m_nextStatePtr = findIndex(states, m_nextState); - - for(int i=0; i < m_actionList.size(); i++) { - Action* action_ptr = findIndex(actions, m_actionList[i]); - int size = action_ptr->getResources().keys().size(); - for (int j=0; j < size; j++) { - Var* var_ptr = action_ptr->getResources().keys()[j]; - if (var_ptr->getType()->cIdent() != "DNUCAStopTable") { - int num = atoi((action_ptr->getResources().lookup(var_ptr)).c_str()); - if (m_resources.exist(var_ptr)) { - num += atoi((m_resources.lookup(var_ptr)).c_str()); - } - m_resources.add(var_ptr, int_to_string(num)); - } else { - m_resources.add(var_ptr, action_ptr->getResources().lookup(var_ptr)); - } - } - m_actionPtrs.insertAtBottom(action_ptr); - } - m_actionPtrsValid = true; -} - -const string& Transition::getStateShorthand() const -{ - assert(m_statePtr != NULL); - return m_statePtr->getShorthand(); -} - -const string& Transition::getEventShorthand() const -{ - assert(m_eventPtr != NULL); - return m_eventPtr->getShorthand(); -} - -const string& Transition::getNextStateShorthand() const -{ - assert(m_nextStatePtr != NULL); - return m_nextStatePtr->getShorthand(); -} - -string Transition::getActionShorthands() const -{ - assert(m_actionPtrsValid); - string str; - int numActions = m_actionPtrs.size(); - for (int i=0; igetShorthand(); - } - return str; -} - -void Transition::print(ostream& out) const -{ - out << "[Transition: "; - out << "(" << m_state; - if (m_statePtr != NULL) { - out << ":" << *m_statePtr; - } - out << ", " << m_event; - if (m_eventPtr != NULL) { - out << ":" << *m_eventPtr; - } - out << ") -> "; - out << m_nextState; - if (m_nextStatePtr != NULL) { - out << ":" << *m_nextStatePtr; - } - out << ", "; - out << m_actionList; - out << "]"; -} - -Event* Transition::findIndex(const Vector& vec, string ident) -{ - int size = vec.size(); - for(int i=0; igetIdent()) { - return vec[i]; - } - } - error("Event not found: " + ident); - return NULL; -} - -State* Transition::findIndex(const Vector& vec, string ident) -{ - int size = vec.size(); - for(int i=0; igetIdent()) { - return vec[i]; - } - } - error("State not found: " + ident); - return NULL; -} - -Action* Transition::findIndex(const Vector& vec, string ident) -{ - int size = vec.size(); - for(int i=0; igetIdent()) { - return vec[i]; - } - } - error("Action not found: " + ident); - return NULL; -} - diff --git a/src/mem/slicc/symbols/Transition.hh b/src/mem/slicc/symbols/Transition.hh deleted file mode 100644 index 75d6da4e9..000000000 --- a/src/mem/slicc/symbols/Transition.hh +++ /dev/null @@ -1,120 +0,0 @@ - -/* - * Copyright (c) 1999-2008 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. - */ - -/* - * Transition.hh - * - * Description: - * - * $Id$ - * - * */ - -#ifndef TRANSITION_H -#define TRANSITION_H - -#include "mem/slicc/slicc_global.hh" -#include "mem/gems_common/Vector.hh" -#include "mem/slicc/symbols/Symbol.hh" - -class State; -class Event; -class Action; -class Var; - -class Transition : public Symbol { -public: - // Constructors - Transition(string state, string event, string nextState, - const Vector& actionList, - const Location& location, - const Map& pairMap); - // Destructor - ~Transition() { } - - // Public Methods - State* getStatePtr() const { assert(m_statePtr != NULL); return m_statePtr; } - Event* getEventPtr() const { assert(m_eventPtr != NULL); return m_eventPtr; } - State* getNextStatePtr() const { assert(m_nextStatePtr != NULL); return m_nextStatePtr; } - - // int getStateIndex() const { assert(m_statePtr != NULL); return m_statePtr->getIndex(); } - // int getEventIndex() const { assert(m_eventPtr != NULL); return m_eventPtr->getIndex(); } - // int getNextStateIndex() const { assert(m_nextStatePtr != NULL); return m_nextStatePtr->getIndex(); } - void checkIdents(const Vector& states, - const Vector& events, - const Vector& actions); - - const string& getStateShorthand() const; - const string& getEventShorthand() const; - const string& getNextStateShorthand() const; - string getActionShorthands() const; - const Vector& getActions() const { assert(m_actionPtrsValid); return m_actionPtrs; } - const Map& getResources() const { assert(m_actionPtrsValid); return m_resources; } - - void print(ostream& out) const; - - // Default copy constructor and assignment operator - // Transition(const Transition& obj); - // Transition& operator=(const Transition& obj); -private: - // Private Methods - Event* findIndex(const Vector& vec, string ident); - State* findIndex(const Vector& vec, string ident); - Action* findIndex(const Vector& vec, string ident); - - // Data Members (m_ prefix) - string m_state; - string m_event; - string m_nextState; - - State* m_statePtr; - Event* m_eventPtr; - State* m_nextStatePtr; - - Vector m_actionList; - Vector m_actionPtrs; - Map m_resources; - bool m_actionPtrsValid; -}; - -// Output operator declaration -ostream& operator<<(ostream& out, const Transition& obj); - -// ******************* Definitions ******************* - -// Output operator definition -extern inline -ostream& operator<<(ostream& out, const Transition& obj) -{ - obj.print(out); - out << flush; - return out; -} - -#endif //TRANSITION_H diff --git a/src/mem/slicc/symbols/Transition.py b/src/mem/slicc/symbols/Transition.py new file mode 100644 index 000000000..1bf09048a --- /dev/null +++ b/src/mem/slicc/symbols/Transition.py @@ -0,0 +1,61 @@ +# Copyright (c) 1999-2008 Mark D. Hill and David A. Wood +# Copyright (c) 2009 The Hewlett-Packard Development Company +# 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.symbols.Symbol import Symbol + +class Transition(Symbol): + def __init__(self, table, machine, state, event, nextState, actions, + location, pairs): + ident = "%s|%s" % (state, event) + super(Transition, self).__init__(table, ident, location, pairs) + + self.state = machine.states[state] + self.event = machine.events[event] + self.nextState = machine.states[nextState] + self.actions = [ machine.actions[a] for a in actions ] + self.resources = {} + + for action in self.actions: + for var,value in action.resources.iteritems(): + if var.type.ident != "DNUCAStopTable": + num = int(value) + if var in self.resources: + num += int(value) + self.resources[var] = str(num) + else: + self.resources[var] = value + + def __repr__(self): + return "[Transition: (%r, %r) -> %r, %r]" % \ + (self.state, self.event, self.nextState, self.actions) + + def getActionShorthands(self): + assert self.actions + + return ''.join(a.short for a in self.actions) + +__all__ = [ "Transition" ] diff --git a/src/mem/slicc/symbols/Type.cc b/src/mem/slicc/symbols/Type.cc deleted file mode 100644 index 5afe53423..000000000 --- a/src/mem/slicc/symbols/Type.cc +++ /dev/null @@ -1,779 +0,0 @@ - -/* - * Copyright (c) 1999-2008 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. - */ - -/* - * Type.cc - * - * Description: See Type.hh - * - * $Id$ - * */ - -#include "mem/slicc/symbols/Type.hh" -#include "mem/slicc/generator/fileio.hh" -#include "mem/gems_common/Map.hh" -#include "mem/slicc/symbols/StateMachine.hh" - -Type::Type(string id, const Location& location, - const Map& pairs, - StateMachine* machine_ptr) - : Symbol(id, location, pairs) -{ - if (machine_ptr == NULL) { - m_c_id = id; - } else if (isExternal() || isPrimitive()) { - if (existPair("external_name")) { - m_c_id = lookupPair("external_name"); - } else { - m_c_id = id; - } - } else { - m_c_id = machine_ptr->toString() + "_" + id; // Append with machine name - } - - if(existPair("desc")){ - m_desc = lookupPair("desc"); - } else { - m_desc = "No description avaliable"; - } - - // check for interface that this Type implements - if(existPair("interface")) { - string interface = lookupPair("interface"); - if(interface == "Message" || interface == "NetworkMessage") { - addPair("message", "yes"); - } - if(interface == "NetworkMessage") { - addPair("networkmessage", "yes"); - } - } - - // FIXME - all of the following id comparisons are fragile hacks - if ((getIdent() == "CacheMemory") || (getIdent() == "NewCacheMemory") || - (getIdent() == "TLCCacheMemory") || (getIdent() == "DNUCACacheMemory") || - (getIdent() == "DNUCABankCacheMemory") || (getIdent() == "L2BankCacheMemory") || - (getIdent() == "CompressedCacheMemory") || (getIdent() == "PrefetchCacheMemory")) { - addPair("cache", "yes"); - } - - if ((getIdent() == "TBETable") || (getIdent() == "DNUCATBETable") || (getIdent() == "DNUCAStopTable")) { - addPair("tbe", "yes"); - } - - if ((getIdent() == "NewTBETable")) { - addPair("newtbe", "yes"); - } - - if ((getIdent() == "TimerTable")) { - addPair("timer", "yes"); - } - - if ((getIdent() == "DirectoryMemory")) { - addPair("dir", "yes"); - } - - if ((getIdent() == "PersistentTable")) { - addPair("persistent", "yes"); - } - - if ((getIdent() == "Prefetcher")) { - addPair("prefetcher", "yes"); - } - - if ((getIdent() == "DNUCA_Movement")) { - addPair("mover", "yes"); - } - - if (id == "MachineType") { - m_isMachineType = true; - } else { - m_isMachineType = false; - } -} - -// Return false on error -bool Type::dataMemberAdd(string id, Type* type_ptr, Map& pairs, - string* init_code) -{ - if (dataMemberExist(id)) { - return false; // Error - } else { - m_data_member_map.add(id, type_ptr); - m_data_member_ident_vec.insertAtBottom(id); - m_data_member_type_vec.insertAtBottom(type_ptr); - m_data_member_pairs_vec.insertAtBottom(pairs); - m_data_member_init_code_vec.insertAtBottom(init_code); - } - - return true; -} - -string Type::methodId(string name, - const Vector& param_type_vec) -{ - string paramStr = ""; - for (int i = 0; i < param_type_vec.size(); i++) { - paramStr += "_"+param_type_vec[i]->cIdent(); - } - return name+paramStr; -} - -bool Type::methodAdd(string name, - Type* return_type_ptr, - const Vector& param_type_vec) -{ - string id = methodId(name, param_type_vec); - if (methodExist(id)) { - return false; // Error - } else { - m_method_return_type_map.add(id, return_type_ptr); - m_method_param_type_map.add(id, param_type_vec); - return true; - } -} - -bool Type::enumAdd(string id, Map pairs_map) -{ - if (enumExist(id)) { - return false; - } else { - m_enum_map.add(id, true); - m_enum_vec.insertAtBottom(id); - m_enum_pairs.insertAtBottom(pairs_map); - - // Add default - if (!existPair("default")) { - addPair("default", cIdent()+"_NUM"); - } - - return true; - } -} - -void Type::writeCFiles(string path) -{ - if (isExternal()) { - // Do nothing - } else if (isEnumeration()) { - printEnumH(path); - printEnumC(path); - } else { // User defined structs and messages - printTypeH(path); - printTypeC(path); - } -} - -void Type::printTypeH(string path) const -{ - ostringstream out; - int size = m_data_member_type_vec.size(); - string type_name = cIdent(); // Identifier for the type in C - - // Header - out << "/** \\file " << type_name << ".hh" << endl; - out << " * " << endl; - out << " * Auto generated C++ code started by "<<__FILE__<<":"<<__LINE__<< endl; - out << " */" << endl; - out << endl; - out << "#ifndef " << type_name << "_H" << endl; - out << "#define " << type_name << "_H" << endl; - out << endl; - - // Include all of the #includes needed - out << "#include \"mem/ruby/common/Global.hh\"" << endl; - out << "#include \"mem/gems_common/Allocator.hh\"" << endl; - for (int i=0; i < size; i++) { - Type* type = m_data_member_type_vec[i]; - if (!type->isPrimitive()) { - out << "#include \"mem/protocol/" << type->cIdent() << ".hh" << "\"" << endl; - } - } - string interface = ""; - if(existPair("interface")) { - interface = lookupPair("interface"); - out << "#include \"mem/protocol/" << interface << ".hh\"" << endl; - } - - // Class definition - out << "class " << type_name; - - if(interface != "") { - out << " : public " << interface ; - } - - out << " {" << endl; - out << "public:" << endl; - - // ******** Default constructor ******** - - out << " " << type_name << "() " << endl; - - // Call superclass constructor - if (interface != "") { - out << " : " << interface << "()" << endl; - } - - out << " {" << endl; - - if(!isGlobal()) { - for (int i=0; i < size; i++) { - - Type* type_ptr = m_data_member_type_vec[i]; - string id = m_data_member_ident_vec[i]; - if (m_data_member_pairs_vec[i].exist("default")) { - // look for default value - string default_value = m_data_member_pairs_vec[i].lookup("default"); - out << " m_" << id << " = " << default_value << "; // default for this field " << endl; - } else if (type_ptr->hasDefault()) { - // Look for the type default - string default_value = type_ptr->getDefault(); - out << " m_" << id << " = " << default_value << "; // default value of " << type_ptr->cIdent() << endl; - } else { - out << " // m_" << id << " has no default" << endl; - } - } - } // end of if(!isGlobal()) - out << " }" << endl; - - // ******** Default destructor ******** - out << " "; - out << "~" << type_name << "() { };" << endl; - - // ******** Full init constructor ******** - if(! isGlobal()) { - out << " " << type_name << "("; - - for (int i=0; i < size; i++) { - if (i != 0) { - out << ", "; - } - Type* type = m_data_member_type_vec[i]; - string id = m_data_member_ident_vec[i]; - out << "const " << type->cIdent() << "& local_" << id; - } - - if (isMessage()) { - out << ", const unsigned local_proc_id" << flush; - } - - out << ")" << endl; - - // Call superclass constructor - if (interface != "") { - out << " : " << interface << "()" << endl; - } - - out << " {" << endl; - for (int i=0; i < size; i++) { - Type* type_ptr = m_data_member_type_vec[i]; - string id = m_data_member_ident_vec[i]; - out << " m_" << id << " = local_" << id << ";" << endl; - if (m_data_member_pairs_vec[i].exist("nextLineCallHack")) { - string next_line_value = m_data_member_pairs_vec[i].lookup("nextLineCallHack"); - out << " m_" << id << next_line_value << ";" << endl; - } - } - if (isMessage()) { - out << " proc_id = local_proc_id;" << endl << flush; - } - out << " }" << endl; - } // end of if(!isGlobal()) - - // create a static factory method - if (interface != "") { - out << " static " << interface << "* create() {" << endl; - out << " return new " << type_name << "(); " << endl; - out << " }" << endl; - } - - // bobba - - //******** Partial init constructor ******** - //** Constructor needs only the first n-1 data members for init - //** HACK to create objects with partially specified data members - //** Need to get rid of this and use hierarchy instead -// if(! isGlobal()) { -// out << " " << type_name << "("; - -// for (int i=0; i < size-1; i++) { -// if (i != 0) { -// out << ", "; -// } -// Type* type = m_data_member_type_vec[i]; -// string id = m_data_member_ident_vec[i]; -// out << "const " << type->cIdent() << "& local_" << id; -// } -// out << ")" << endl; - -// // Call superclass constructor -// if (interface != "") { -// out << " : " << interface << "()" << endl; -// } - -// out << " {" << endl; -// for (int i=0; i < size-1; i++) { -// Type* type_ptr = m_data_member_type_vec[i]; -// string id = m_data_member_ident_vec[i]; -// out << " m_" << id << " = local_" << id << ";" << endl; -// if (m_data_member_pairs_vec[i].exist("nextLineCallHack")) { -// string next_line_value = m_data_member_pairs_vec[i].lookup("nextLineCallHack"); -// out << " m_" << id << next_line_value << ";" << endl; -// } - -// } -// out << " }" << endl; -// } // end of if(!isGlobal()) - - // ******** Message member functions ******** - // FIXME: those should be moved into slicc file, slicc should support more of - // the c++ class inheritance - - if (isMessage()) { - out << " Message* clone() const { checkAllocator(); return s_allocator_ptr->allocate(*this); }" << endl; - out << " void destroy() { checkAllocator(); s_allocator_ptr->deallocate(this); }" << endl; - out << " static Allocator<" << type_name << ">* s_allocator_ptr;" << endl; - out << " static void checkAllocator() { if (s_allocator_ptr == NULL) { s_allocator_ptr = new Allocator<" << type_name << ">; }}" << endl; - } - - if(!isGlobal()) { - // const Get methods for each field - out << " // Const accessors methods for each field" << endl; - for (int i=0; i < size; i++) { - Type* type_ptr = m_data_member_type_vec[i]; - string type = type_ptr->cIdent(); - string id = m_data_member_ident_vec[i]; - out << "/** \\brief Const accessor method for " << id << " field." << endl; - out << " * \\return " << id << " field" << endl; - out << " */" << endl; - out << " const " << type << "& get" << id - << "() const { return m_" << id << "; }" << endl; - } - - out << endl; - - // Non-const Get methods for each field - out << " // Non const Accessors methods for each field" << endl; - for (int i=0; i < size; i++) { - Type* type_ptr = m_data_member_type_vec[i]; - string type = type_ptr->cIdent(); - string id = m_data_member_ident_vec[i]; - out << "/** \\brief Non-const accessor method for " << id << " field." << endl; - out << " * \\return " << id << " field" << endl; - out << " */" << endl; - out << " " << type << "& get" << id - << "() { return m_" << id << "; }" << endl; - } - - out << endl; - - // Set methods for each field - out << " // Mutator methods for each field" << endl; - for (int i=0; i < size; i++) { - Type* type_ptr = m_data_member_type_vec[i]; - string type = type_ptr->cIdent(); - string id = m_data_member_ident_vec[i]; - out << "/** \\brief Mutator method for " << id << " field */" << endl; - out << " void set" << id << "(const " << type << "& local_" - << id << ") { m_" << id << " = local_" << id << "; }" << endl; - } - - out << endl; - } // end of if(!isGlobal()) - - out << " void print(ostream& out) const;" << endl; - out << "//private:" << endl; - - // Data members for each field - for (int i=0; i < size; i++) { - if (!m_data_member_pairs_vec[i].exist("abstract")) { - out << " "; - // global structure - if(isGlobal()) out << "static const "; - - Type* type = m_data_member_type_vec[i]; - string id = m_data_member_ident_vec[i]; - out << type->cIdent() << " m_" << id; - - // init value - string* init_code = m_data_member_init_code_vec[i]; - if(init_code) { - // only global structure can have init value here - assert(isGlobal()); - out << " = " << *init_code << " "; - } - out << ";"; - if (m_data_member_pairs_vec[i].exist("desc")) { - string desc = m_data_member_pairs_vec[i].lookup("desc"); - out << " /**< " << desc << "*/"; - } - out << endl; - } - } - - if (isMessage()) { - out << " unsigned proc_id;" << endl << flush; - } - - out << "};" << endl; // End class - - out << "// Output operator declaration" << endl; - out << "ostream& operator<<(ostream& out, const " << type_name << "& obj);" << endl; - out << endl; - out << "// Output operator definition" << endl; - out << "extern inline" << endl; - out << "ostream& operator<<(ostream& out, const " << type_name << "& obj)" << endl; - out << "{" << endl; - out << " obj.print(out);" << endl; - out << " out << flush;" << endl; - out << " return out;" << endl; - out << "}" << endl; - out << endl; - out << "#endif // " << type_name << "_H" << endl; - - // Write it out - conditionally_write_file(path + type_name + ".hh", out); -} - -void Type::printTypeC(string path) const -{ - ostringstream out; - int size = m_data_member_type_vec.size(); - string type_name = cIdent(); // Identifier for the type in C - - // Header - out << "/** \\file " << type_name << ".cc" << endl; - out << " * " << endl; - out << " * Auto generated C++ code started by "<<__FILE__<<":"<<__LINE__<< endl; - out << " */" << endl; - out << endl; - out << "#include \"mem/protocol/" << type_name << ".hh\"" << endl; - out << endl; - if (isMessage()) { - out << "Allocator<" << type_name << ">* " << type_name << "::s_allocator_ptr = NULL;" << endl; - } - out << "/** \\brief Print the state of this object */" << endl; - out << "void " << type_name << "::print(ostream& out) const" << endl; - out << "{" << endl; - out << " out << \"[" << type_name << ": \";" << endl; - - // For each field - for (int i=0; i < size; i++) { - string id = m_data_member_ident_vec[i]; - out << " out << \"" << id << "=\" << m_" << id << " << \" \";" << endl; - } - - if (isMessage()) { - out << " out << \"" << "Time" << "=\" << getTime()" << " << \" \";" << endl; - } - - // Trailer - out << " out << \"]\";" << endl; - out << "}" << endl; - - // Write it out - conditionally_write_file(path + type_name + ".cc", out); -} - -void Type::printEnumH(string path) const -{ - ostringstream out; - int size = m_enum_vec.size(); - string type_name = cIdent(); // Identifier for the type in C - string type_desc = desc(); - - // Header - out << "/** \\file " << type_name << ".hh" << endl; - out << " * " << endl; - out << " * Auto generated C++ code started by "<<__FILE__<<":"<<__LINE__<< endl; - out << " */" << endl; - - out << "#ifndef " << type_name << "_H" << endl; - out << "#define " << type_name << "_H" << endl; - out << endl; - // Include all of the #includes needed - out << "#include \"mem/ruby/common/Global.hh\"" << endl; - out << endl; - - // Class definition - out << "/** \\enum " << type_name << endl; - out << " * \\brief " << type_desc << endl; - out << " */" << endl; - out << "enum " << type_name << " {" << endl; - - out << " " << type_name << "_FIRST," << endl; - - // For each field - for(int i = 0; i < size; i++ ) { - string id = m_enum_vec[i]; - string description; - if(m_enum_pairs[i].exist("desc")){ - description = m_enum_pairs[i].lookup("desc"); - } else { - description = "No description avaliable"; - } - if (i == 0) { - out << " " << type_name << "_" << id << " = " << type_name << "_FIRST, /**< " << description << " */" << endl; - } - else { - out << " " << type_name << "_" << id << ", /**< " << description << " */" << endl; - } - } - out << " " << type_name << "_NUM" << endl; - out << "};" << endl; - - // Code to convert from a string to the enumeration - out << type_name << " string_to_" << type_name << "(const string& str);" << endl; - - // Code to convert state to a string - out << "string " << type_name << "_to_string(const " << type_name << "& obj);" << endl; - - // Code to increment an enumeration type - out << type_name << " &operator++( " << type_name << " &e);" << endl; - - // MachineType hack used to set the base component id for each Machine - if (m_isMachineType) { - out << "int " << type_name << "_base_level(const " << type_name << "& obj);" << endl; - out << "MachineType " << type_name << "_from_base_level(int);" << endl; - out << "int " << type_name << "_base_number(const " << type_name << "& obj);" << endl; - out << "int " << type_name << "_base_count(const " << type_name << "& obj);" << endl; - // out << "int " << type_name << "_chip_count(const " << type_name << "& obj, int chipID);" << endl; - - for(int i = 0; i < size; i++ ) { - string id = m_enum_vec[i]; - out << "#define MACHINETYPE_" << id << " 1" << endl; - } - cout << endl; - } - - // Trailer - out << "ostream& operator<<(ostream& out, const " << type_name << "& obj);" << endl; - out << endl; - out << "#endif // " << type_name << "_H" << endl; - - // Write the file - conditionally_write_file(path + type_name + ".hh", out); -} - -void Type::printEnumC(string path) const -{ - ostringstream out; - int size = m_enum_vec.size(); - string type_name = cIdent(); // Identifier for the type in C - - // Header - out << "/** \\file " << type_name << ".hh" << endl; - out << " * " << endl; - out << " * Auto generated C++ code started by "<<__FILE__<<":"<<__LINE__<< endl; - out << " */" << endl; - - out << endl; - out << "#include \"mem/protocol/" << type_name << ".hh\"" << endl; - if (m_isMachineType) { - out << "#include \"mem/protocol/ControllerFactory.hh\"" << endl; - for( int i = 0; i MachineNames; - for( int i = 0; i& pairs, - StateMachine* machine_ptr = NULL); - - // Destructor - ~Type() {} - - // Public Methods - string cIdent() const { return m_c_id; } - string desc() const { return m_desc; } - - bool isPrimitive() const { return existPair("primitive"); } - bool isNetworkMessage() const { return existPair("networkmessage"); } - bool isMessage() const { return existPair("message"); } - bool isBuffer() const { return existPair("buffer"); } - bool isInPort() const { return existPair("inport"); } - bool isOutPort() const { return existPair("outport"); } - bool isEnumeration() const { return existPair("enumeration"); } - bool isExternal() const { return existPair("external"); } - bool isGlobal() const { return existPair("global"); } - bool isInterface() const { return existPair("interface"); } - - // The data members of this type - only valid for messages and SLICC - // declared structures - // Return false on error - bool dataMemberAdd(string id, Type* type_ptr, Map& pairs, - string* init_code); - bool dataMemberExist(string id) const { return m_data_member_map.exist(id); } - Type* dataMemberType(string id) const { return m_data_member_map.lookup(id); } - - // The methods of this type - only valid for external types - // Return false on error - bool methodAdd(string name, Type* return_type_ptr, const Vector& param_type_vec); - bool methodExist(string id) const { return m_method_return_type_map.exist(id); } - - string methodId(string name, const Vector& param_type_vec); - Type* methodReturnType(string id) const { return m_method_return_type_map.lookup(id); } - const Vector& methodParamType(string id) const { return m_method_param_type_map.lookup(id); } - - // The enumeration idents of this type - only valid for enums - // Return false on error - bool enumAdd(string id, Map pairs); - bool enumExist(string id) const { return m_enum_map.exist(id); } - - // Write the C output files - void writeCFiles(string path) ; - - bool hasDefault() const { return existPair("default"); } - string getDefault() const { return lookupPair("default"); } - - void print(ostream& out) const {} -private: - // Private Methods - - void printTypeH(string path) const; - void printTypeC(string path) const; - void printEnumC(string path) const; - void printEnumH(string path) const; - - // Private copy constructor and assignment operator - Type(const Type& obj); - Type& operator=(const Type& obj); - - // Data Members (m_ prefix) - string m_c_id; - string m_desc; - - // Data Members - Map m_data_member_map; - Vector m_data_member_ident_vec; - Vector m_data_member_type_vec; - Vector > m_data_member_pairs_vec; - Vector m_data_member_init_code_vec; - // Needs pairs here - - // Methods - Map m_method_return_type_map; - Map > m_method_param_type_map; - // Needs pairs here - - // Enum - Map m_enum_map; - Vector m_enum_vec; - Vector< Map < string, string > > m_enum_pairs; - - // MachineType Hack - bool m_isMachineType; - -}; - -// Output operator declaration -ostream& operator<<(ostream& out, const Type& obj); - -// ******************* Definitions ******************* - -// Output operator definition -extern inline -ostream& operator<<(ostream& out, const Type& obj) -{ - obj.print(out); - out << flush; - return out; -} - -#endif //TYPE_H diff --git a/src/mem/slicc/symbols/Type.py b/src/mem/slicc/symbols/Type.py new file mode 100644 index 000000000..2541296dc --- /dev/null +++ b/src/mem/slicc/symbols/Type.py @@ -0,0 +1,650 @@ +# Copyright (c) 1999-2008 Mark D. Hill and David A. Wood +# Copyright (c) 2009 The Hewlett-Packard Development Company +# 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 m5.util import code_formatter, orderdict + +from slicc.util import PairContainer +from slicc.symbols.Symbol import Symbol + +class DataMember(PairContainer): + def __init__(self, ident, type, pairs, init_code): + super(DataMember, self).__init__(pairs) + self.ident = ident + self.type = type + self.init_code = init_code + +class Enumeration(PairContainer): + def __init__(self, ident, pairs): + super(Enumeration, self).__init__(pairs) + self.ident = ident + +class Method(object): + def __init__(self, return_type, param_types): + self.return_type = return_type + self.param_types = param_types + +class Type(Symbol): + def __init__(self, table, ident, location, pairs, machine=None): + super(Type, self).__init__(table, ident, location, pairs) + self.c_ident = ident + if machine: + if self.isExternal or self.isPrimitive: + if "external_name" in self: + self.c_ident = self["external_name"] + else: + # Append with machine name + self.c_ident = "%s_%s" % (machine, ident) + + self.pairs.setdefault("desc", "No description avaliable") + + # check for interface that this Type implements + if "interface" in self: + interface = self["interface"] + if interface in ("Message", "NetworkMessage"): + self["message"] = "yes" + if interface == "NetworkMessage": + self["networkmessage"] = "yes" + + # FIXME - all of the following id comparisons are fragile hacks + if self.ident in ("CacheMemory", "NewCacheMemory", + "TLCCacheMemory", "DNUCACacheMemory", + "DNUCABankCacheMemory", "L2BankCacheMemory", + "CompressedCacheMemory", "PrefetchCacheMemory"): + self["cache"] = "yes" + + if self.ident in ("TBETable", "DNUCATBETable", "DNUCAStopTable"): + self["tbe"] = "yes" + + if self.ident == "NewTBETable": + self["newtbe"] = "yes" + + if self.ident == "TimerTable": + self["timer"] = "yes" + + if self.ident == "DirectoryMemory": + self["dir"] = "yes" + + if self.ident == "PersistentTable": + self["persistent"] = "yes" + + if self.ident == "Prefetcher": + self["prefetcher"] = "yes" + + if self.ident == "DNUCA_Movement": + self["mover"] = "yes" + + self.isMachineType = (ident == "MachineType") + + self.data_members = orderdict() + + # Methods + self.methods = {} + + # Enums + self.enums = orderdict() + + @property + def isPrimitive(self): + return "primitive" in self + @property + def isNetworkMessage(self): + return "networkmessage" in self + @property + def isMessage(self): + return "message" in self + @property + def isBuffer(self): + return "buffer" in self + @property + def isInPort(self): + return "inport" in self + @property + def isOutPort(self): + return "outport" in self + @property + def isEnumeration(self): + return "enumeration" in self + @property + def isExternal(self): + return "external" in self + @property + def isGlobal(self): + return "global" in self + @property + def isInterface(self): + return "interface" in self + + # Return false on error + def dataMemberAdd(self, ident, type, pairs, init_code): + if ident in self.data_members: + return False + + member = DataMember(ident, type, pairs, init_code) + self.data_members[ident] = member + + return True + + def dataMemberType(self, ident): + return self.data_members[ident].type + + def methodId(self, name, param_type_vec): + return '_'.join([name] + [ pt.c_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: + return False + + self.methods[ident] = Method(return_type, param_type_vec) + return True + + def enumAdd(self, ident, pairs): + if ident in self.enums: + return False + + self.enums[ident] = Enumeration(ident, pairs) + + # Add default + if "default" not in self: + self["default"] = "%s_NUM" % self.c_ident + + return True + + def writeCodeFiles(self, path): + if self.isExternal: + # Do nothing + pass + elif self.isEnumeration: + self.printEnumHH(path) + self.printEnumCC(path) + else: + # User defined structs and messages + self.printTypeHH(path) + self.printTypeCC(path) + + def printTypeHH(self, path): + code = code_formatter() + code(''' +/** \\file ${{self.c_ident}}.hh + * + * + * Auto generated C++ code started by $__file__:$__line__ + */ + +#ifndef ${{self.c_ident}}_H +#define ${{self.c_ident}}_H + +#include "mem/ruby/common/Global.hh" +#include "mem/gems_common/Allocator.hh" +''') + + for dm in self.data_members.values(): + if not dm.type.isPrimitive: + code('#include "mem/protocol/$0.hh"', dm.type.c_ident) + + parent = "" + if "interface" in self: + code('#include "mem/protocol/$0.hh"', self["interface"]) + parent = " : public %s" % self["interface"] + + code(''' +$klass ${{self.c_ident}}$parent { + public: + ${{self.c_ident}}() +''', klass="class") + + # Call superclass constructor + if "interface" in self: + code(' : ${{self["interface"]}}()') + + code.indent() + code("{") + if not self.isGlobal: + code.indent() + for dm in self.data_members.values(): + ident = dm.ident + if "default" in dm: + # look for default value + code('m_$ident = ${{dm["default"]}}; // default for this field') + elif "default" in dm.type: + # Look for the type default + tid = dm.type.c_ident + code('m_$ident = ${{dm.type["default"]}}; // default value of $tid') + else: + code('// m_$ident has no default') + code.dedent() + code('}') + + # ******** Default destructor ******** + code('~${{self.c_ident}}() { };') + + # ******** Full init constructor ******** + if not self.isGlobal: + params = [ 'const %s& local_%s' % (dm.type.c_ident, dm.ident) \ + for dm in self.data_members.itervalues() ] + + if self.isMessage: + params.append('const unsigned local_proc_id') + + params = ', '.join(params) + code('${{self.c_ident}}($params)') + + # Call superclass constructor + if "interface" in self: + code(' : ${{self["interface"]}}()') + + code('{') + code.indent() + for dm in self.data_members.values(): + code('m_${{dm.ident}} = local_${{dm.ident}};') + if "nextLineCallHack" in dm: + code('m_${{dm.ident}}${{dm["nextLineCallHack"]}};') + + if self.isMessage: + code('proc_id = local_proc_id;') + + code.dedent() + code('}') + + # create a static factory method + if "interface" in self: + code(''' +static ${{self["interface"]}}* create() { + return new ${{self.c_ident}}(); +} +''') + + # ******** Message member functions ******** + # FIXME: those should be moved into slicc file, slicc should + # support more of the c++ class inheritance + + if self.isMessage: + code(''' +Message* clone() const { checkAllocator(); return s_allocator_ptr->allocate(*this); } +void destroy() { checkAllocator(); s_allocator_ptr->deallocate(this); } +static Allocator<${{self.c_ident}}>* s_allocator_ptr; +static void checkAllocator() { if (s_allocator_ptr == NULL) { s_allocator_ptr = new Allocator<${{self.c_ident}}>; }} +''') + + if not self.isGlobal: + # const Get methods for each field + code('// Const accessors methods for each field') + for dm in self.data_members.values(): + code(''' +/** \\brief Const accessor method for ${{dm.ident}} field. + * \\return ${{dm.ident}} field + */ +const ${{dm.type.c_ident}}& get${{dm.ident}}() const { return m_${{dm.ident}}; } +''') + + # Non-const Get methods for each field + code('// Non const Accessors methods for each field') + for dm in self.data_members.values(): + code(''' +/** \\brief Non-const accessor method for ${{dm.ident}} field. + * \\return ${{dm.ident}} field + */ +${{dm.type.c_ident}}& get${{dm.ident}}() { return m_${{dm.ident}}; } +''') + + #Set methods for each field + code('// Mutator methods for each field') + for dm in self.data_members.values(): + code(''' +/** \\brief Mutator method for ${{dm.ident}} field */ +void set${{dm.ident}}(const ${{dm.type.c_ident}}& local_${{dm.ident}}) { m_${{dm.ident}} = local_${{dm.ident}}; } +''') + + code('void print(ostream& out) const;') + code.dedent() + code(' //private:') + code.indent() + + # Data members for each field + for dm in self.data_members.values(): + if "abstract" not in dm: + const = "" + init = "" + + # global structure + if self.isGlobal: + const = "static const " + + # init value + if dm.init_code: + # only global structure can have init value here + assert self.isGlobal + init = " = %s" % (dm.init_code) + + desc = "" + if "desc" in dm: + desc = '/**< %s */' % dm["desc"] + + code('$const${{dm.type.c_ident}} m_${{dm.ident}}$init; $desc') + + if self.isMessage: + code('unsigned proc_id;') + + code.dedent() + code('};') + + code(''' +// Output operator declaration +ostream& operator<<(ostream& out, const ${{self.c_ident}}& obj); + +// Output operator definition +extern inline +ostream& operator<<(ostream& out, const ${{self.c_ident}}& obj) +{ + obj.print(out); + out << flush; + return out; +} + +#endif // ${{self.c_ident}}_H +''') + + code.write(path, "%s.hh" % self.c_ident) + + def printTypeCC(self, path): + code = code_formatter() + + code(''' +/** \\file ${{self.c_ident}}.cc + * + * Auto generated C++ code started by $__file__:$__line__ + */ + +#include "mem/protocol/${{self.c_ident}}.hh" +''') + + if self.isMessage: + code('Allocator<${{self.c_ident}}>* ${{self.c_ident}}::s_allocator_ptr = NULL;') + code(''' +/** \\brief Print the state of this object */ +void ${{self.c_ident}}::print(ostream& out) const +{ + out << "[${{self.c_ident}}: "; +''') + + # For each field + code.indent() + for dm in self.data_members.values(): + code('out << "${{dm.ident}} = " << m_${{dm.ident}} << " ";''') + + if self.isMessage: + code('out << "Time = " << getTime() << " ";') + code.dedent() + + # Trailer + code(''' + out << "]"; +}''') + + code.write(path, "%s.cc" % self.c_ident) + + def printEnumHH(self, path): + code = code_formatter() + code(''' +/** \\file ${{self.c_ident}}.hh + * + * Auto generated C++ code started by $__file__:$__line__ + */ +#ifndef ${{self.c_ident}}_H +#define ${{self.c_ident}}_H + +#include "mem/ruby/common/Global.hh" + +/** \\enum ${{self.c_ident}} + * \\brief ${{self.desc}} + */ +enum ${{self.c_ident}} { + ${{self.c_ident}}_FIRST, +''') + + code.indent() + # For each field + for i,(ident,enum) in enumerate(self.enums.iteritems()): + desc = enum.get("desc", "No description avaliable") + init = ' = %s_FIRST' % self.c_ident if i == 0 else '' + + code('${{self.c_ident}}_${{enum.ident}}$init, /**< $desc */') + code.dedent() + code(''' + ${{self.c_ident}}_NUM +}; +${{self.c_ident}} string_to_${{self.c_ident}}(const string& str); +string ${{self.c_ident}}_to_string(const ${{self.c_ident}}& obj); +${{self.c_ident}} &operator++(${{self.c_ident}} &e); +''') + + # MachineType hack used to set the base component id for each Machine + if self.isMachineType: + code(''' +int ${{self.c_ident}}_base_level(const ${{self.c_ident}}& obj); +MachineType ${{self.c_ident}}_from_base_level(int); +int ${{self.c_ident}}_base_number(const ${{self.c_ident}}& obj); +int ${{self.c_ident}}_base_count(const ${{self.c_ident}}& obj); +''') + + for enum in self.enums.itervalues(): + code('#define MACHINETYPE_${{enum.ident}} 1') + + # Trailer + code(''' +ostream& operator<<(ostream& out, const ${{self.c_ident}}& obj); + +#endif // ${{self.c_ident}}_H +''') + + code.write(path, "%s.hh" % self.c_ident) + + def printEnumCC(self, path): + code = code_formatter() + code(''' +/** \\file ${{self.c_ident}}.hh + * + * Auto generated C++ code started by $__file__:$__line__ + */ + +#include "mem/protocol/${{self.c_ident}}.hh" + +''') + + if self.isMachineType: + code('#include "mem/protocol/ControllerFactory.hh"') + for enum in self.enums.itervalues(): + code('#include "mem/protocol/${{enum.ident}}_Controller.hh"') + + code(''' +ostream& operator<<(ostream& out, const ${{self.c_ident}}& obj) +{ + out << ${{self.c_ident}}_to_string(obj); + out << flush; + return out; +} + +string ${{self.c_ident}}_to_string(const ${{self.c_ident}}& obj) +{ + switch(obj) { +''') + + # For each field + code.indent() + for enum in self.enums.itervalues(): + code(' case ${{self.c_ident}}_${{enum.ident}}:') + code(' return "${{enum.ident}}";') + code.dedent() + + # Trailer + code(''' + default: + ERROR_MSG("Invalid range for type ${{self.c_ident}}"); + return ""; + } +} + +${{self.c_ident}} string_to_${{self.c_ident}}(const string& str) +{ +''') + + # For each field + code.indent() + code("if (false) {") + start = "} else " + for enum in self.enums.itervalues(): + code('${start}if (str == "${{enum.ident}}") {') + code(' return ${{self.c_ident}}_${{enum.ident}};') + code.dedent() + + code(''' + } else { + WARN_EXPR(str); + ERROR_MSG("Invalid string conversion for type ${{self.c_ident}}"); + } +} + +${{self.c_ident}}& operator++(${{self.c_ident}}& e) { + assert(e < ${{self.c_ident}}_NUM); + return e = ${{self.c_ident}}(e+1); +} +''') + + # MachineType hack used to set the base level and number of + # components for each Machine + if self.isMachineType: + code(''' +/** \\brief returns the base vector index for each machine type to be used by NetDest + * + * \\return the base vector index for each machine type to be used by NetDest + * \\see NetDest.hh + */ +int ${{self.c_ident}}_base_level(const ${{self.c_ident}}& obj) +{ + switch(obj) { +''') + + # For each field + code.indent() + for i,enum in enumerate(self.enums.itervalues()): + code(' case ${{self.c_ident}}_${{enum.ident}}:') + code(' return $i;') + code.dedent() + + # total num + code(''' + case ${{self.c_ident}}_NUM: + return ${{len(self.enums)}}; + + default: + ERROR_MSG("Invalid range for type ${{self.c_ident}}"); + return -1; + } +} + +/** \\brief returns the machine type for each base vector index used by NetDest + * + * \\return the MachineTYpe + */ +MachineType ${{self.c_ident}}_from_base_level(int type) +{ + switch(type) { +''') + + # For each field + code.indent() + for i,enum in enumerate(self.enums.itervalues()): + code(' case $i:') + code(' return ${{self.c_ident}}_${{enum.ident}};') + code.dedent() + + # Trailer + code(''' + default: + ERROR_MSG("Invalid range for type ${{self.c_ident}}"); + return MachineType_NUM; + } +} + +/** \\brief The return value indicates the number of components created + * before a particular machine\'s components + * + * \\return the base number of components for each machine + */ +int ${{self.c_ident}}_base_number(const ${{self.c_ident}}& obj) +{ + int base = 0; + switch(obj) { +''') + + # For each field + code.indent() + code(' case ${{self.c_ident}}_NUM:') + for enum in reversed(self.enums.values()): + code(' base += ${{enum.ident}}_Controller::getNumControllers();') + code(' case ${{self.c_ident}}_${{enum.ident}}:') + code(' break;') + code.dedent() + + code(''' + default: + ERROR_MSG("Invalid range for type ${{self.c_ident}}"); + return -1; + } + + return base; +} + +/** \\brief returns the total number of components for each machine + * \\return the total number of components for each machine + */ +int ${{self.c_ident}}_base_count(const ${{self.c_ident}}& obj) +{ + switch(obj) { +''') + + # For each field + for enum in self.enums.itervalues(): + code(''' + case ${{self.c_ident}}_${{enum.ident}}: + return ${{enum.ident}}_Controller::getNumControllers(); +''') + + # total num + code(''' + case ${{self.c_ident}}_NUM: + default: + ERROR_MSG("Invalid range for type ${{self.c_ident}}"); + return -1; + } +} +''') + + # Write the file + code.write(path, "%s.cc" % self.c_ident) + +__all__ = [ "Type" ] diff --git a/src/mem/slicc/symbols/Var.cc b/src/mem/slicc/symbols/Var.cc deleted file mode 100644 index a6e8dfd55..000000000 --- a/src/mem/slicc/symbols/Var.cc +++ /dev/null @@ -1,57 +0,0 @@ - -/* - * Copyright (c) 1999-2008 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. - */ - -/* - * $Id$ - * - * */ - -#include "mem/slicc/symbols/Var.hh" -#include "mem/slicc/symbols/StateMachine.hh" - -Var::Var(string id, const Location& location, - Type* type_ptr, string code, - const Map& pairs, - StateMachine* machine_ptr) : Symbol(id, location, pairs) -{ - if (machine_ptr == NULL) { - m_c_id = id; - } else { - m_c_id = machine_ptr->toString() + "_" + id; // Append with machine name - } - - m_machine_ptr = machine_ptr; - m_type_ptr = type_ptr; - m_code = code; -} - -void Var::print(ostream& out) const -{ - out << "[Var id: " << m_c_id << "]" << endl; -} diff --git a/src/mem/slicc/symbols/Var.hh b/src/mem/slicc/symbols/Var.hh deleted file mode 100644 index 4cb504296..000000000 --- a/src/mem/slicc/symbols/Var.hh +++ /dev/null @@ -1,98 +0,0 @@ - -/* - * Copyright (c) 1999-2008 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. - */ - -/* - * Var.hh - * - * Description: - * - * $Id$ - * - * */ - -#ifndef VAR_H -#define VAR_H - -#include "mem/slicc/slicc_global.hh" -#include "mem/slicc/symbols/Symbol.hh" -#include "mem/slicc/symbols/Type.hh" - -class StateMachine; - -class Var : public Symbol { -public: - // Constructors - Var(string id, const Location& location, - Type* type_ptr, string code, - const Map& pairs, - StateMachine* machine_ptr = NULL); - - // Var(string id, const Location& location, - // Type* type_ptr, string code) : Symbol(id, location) { m_type_ptr = type_ptr; m_code = code; } - - // Destructor - ~Var() {} - - // Public Methods - string cIdent() const { return m_c_id; } - void writeCFiles(string path) {} - string getCode() const { return m_code; } - Type* getType() const { return m_type_ptr; } - StateMachine* getMachine() const { return m_machine_ptr; } - - void print(ostream& out) const; -private: - // Private Methods - - // Private copy constructor and assignment operator - Var(const Var& obj); - Var& operator=(const Var& obj); - - // Data Members (m_ prefix) - string m_c_id; - Type* m_type_ptr; - string m_code; - StateMachine* m_machine_ptr; -}; - -// Output operator declaration -ostream& operator<<(ostream& out, const Var& obj); - -// ******************* Definitions ******************* - -// Output operator definition -extern inline -ostream& operator<<(ostream& out, const Var& obj) -{ - obj.print(out); - out << flush; - return out; -} - -#endif //VAR_H diff --git a/src/mem/slicc/symbols/Var.py b/src/mem/slicc/symbols/Var.py new file mode 100644 index 000000000..87a101f65 --- /dev/null +++ b/src/mem/slicc/symbols/Var.py @@ -0,0 +1,50 @@ +# Copyright (c) 1999-2008 Mark D. Hill and David A. Wood +# Copyright (c) 2009 The Hewlett-Packard Development Company +# 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.symbols.Symbol import Symbol + +class Var(Symbol): + def __init__(self, symtab, ident, location, type, code, pairs, + machine=None): + super(Var, self).__init__(symtab, ident, location, pairs) + + if machine: + self.c_ident = "%s_%s" % (machine, ident) + else: + self.c_ident = ident + + self.machine = machine + self.type = type + self.code = code + + def __repr__(self): + return "[Var id: %s]" % (self.c_ident) + + def writeCodeFiles(self, path): + pass + +__all__ = [ "Var" ] diff --git a/src/mem/slicc/symbols/__init__.py b/src/mem/slicc/symbols/__init__.py new file mode 100644 index 000000000..43388a5fe --- /dev/null +++ b/src/mem/slicc/symbols/__init__.py @@ -0,0 +1,38 @@ +# Copyright (c) 2009 The Hewlett-Packard Development Company +# 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. +# +# Authors: Nathan Binkert + +from slicc.symbols.Action import Action +from slicc.symbols.Event import Event +from slicc.symbols.Func import Func +from slicc.symbols.State import State +from slicc.symbols.StateMachine import StateMachine +from slicc.symbols.Symbol import Symbol +from slicc.symbols.SymbolTable import SymbolTable +from slicc.symbols.Transition import Transition +from slicc.symbols.Type import Type +from slicc.symbols.Var import Var -- cgit v1.2.3