diff options
Diffstat (limited to 'src/mem/slicc/symbols')
-rw-r--r-- | src/mem/slicc/symbols/Action.hh | 52 | ||||
-rw-r--r-- | src/mem/slicc/symbols/Event.hh | 45 | ||||
-rw-r--r-- | src/mem/slicc/symbols/Func.cc | 144 | ||||
-rw-r--r-- | src/mem/slicc/symbols/Func.hh | 96 | ||||
-rw-r--r-- | src/mem/slicc/symbols/State.hh | 45 | ||||
-rw-r--r-- | src/mem/slicc/symbols/StateMachine.cc | 993 | ||||
-rw-r--r-- | src/mem/slicc/symbols/StateMachine.hh | 141 | ||||
-rw-r--r-- | src/mem/slicc/symbols/Symbol.cc | 72 | ||||
-rw-r--r-- | src/mem/slicc/symbols/Symbol.hh | 100 | ||||
-rw-r--r-- | src/mem/slicc/symbols/SymbolTable.cc | 934 | ||||
-rw-r--r-- | src/mem/slicc/symbols/SymbolTable.hh | 121 | ||||
-rw-r--r-- | src/mem/slicc/symbols/Transition.cc | 173 | ||||
-rw-r--r-- | src/mem/slicc/symbols/Transition.hh | 120 | ||||
-rw-r--r-- | src/mem/slicc/symbols/Type.cc | 746 | ||||
-rw-r--r-- | src/mem/slicc/symbols/Type.hh | 154 | ||||
-rw-r--r-- | src/mem/slicc/symbols/Var.cc | 57 | ||||
-rw-r--r-- | src/mem/slicc/symbols/Var.hh | 98 |
17 files changed, 4091 insertions, 0 deletions
diff --git a/src/mem/slicc/symbols/Action.hh b/src/mem/slicc/symbols/Action.hh new file mode 100644 index 000000000..dbb0c836a --- /dev/null +++ b/src/mem/slicc/symbols/Action.hh @@ -0,0 +1,52 @@ + +/* + * 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<Var*, string>& resources, + const Location& location, + const Map<string, string>& pairs) : Symbol(id, location, pairs) { m_resources = resources; } + const Map<Var*, string>& getResources() const { return m_resources; } + void print(ostream& out) const { out << "[Action: " << getIdent() << "]"; } + +private: + Map<Var*, string> m_resources; +}; + +#endif //ACTION_H diff --git a/src/mem/slicc/symbols/Event.hh b/src/mem/slicc/symbols/Event.hh new file mode 100644 index 000000000..40cefc982 --- /dev/null +++ b/src/mem/slicc/symbols/Event.hh @@ -0,0 +1,45 @@ + +/* + * 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<string, string>& pairs) : Symbol(id, location, pairs) {} + void print(ostream& out) const { out << "[Event: " << getIdent() << "]"; } +}; + +#endif //EVENT_H diff --git a/src/mem/slicc/symbols/Func.cc b/src/mem/slicc/symbols/Func.cc new file mode 100644 index 000000000..0ccca7598 --- /dev/null +++ b/src/mem/slicc/symbols/Func.cc @@ -0,0 +1,144 @@ + +/* + * 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.C + * + * Description: See Func.h + * + * $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<Type*>& param_type_vec, + const Vector<string>& param_string_vec, string body, + const Map<string, string>& 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; i<size; i++) { + // Generate code + if (i != 0) { + code += ", "; + } + code += m_param_string_vec[i]; + } + code += ");\n"; + } +} + +// This write a function of object Chip +void Func::writeCFiles(string path) const +{ + if (isExternal()) { + // Do nothing + } else { + ostringstream out; + + // Header + out << "/** Auto generated C++ code started by "<<__FILE__<<":"<<__LINE__<< " */" << endl; + out << endl; + out << "#include \"mem/protocol/Types.hh\"" << endl; + out << "#include \"mem/protocol/Chip.hh\"" << endl; + if (m_isInternalMachineFunc) { + out << "#include \"" << m_machineStr << "_Controller.hh\"" << endl; + } + out << endl; + + // Generate function header + string code; + Type* void_type_ptr = g_sym_table.getType("void"); + string return_type = m_type_ptr->cIdent(); + 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<size; i++) { + // Generate code + if (i != 0) { + code += ", "; + } + code += m_param_string_vec[i]; + } + code += ")"; + + // Function body + code += "\n{\n"; + code += m_body; + code += "}\n"; + out << code << endl; + + // Write it out + conditionally_write_file(path + cIdent() + ".cc", out); + } +} + +void Func::print(ostream& out) const +{ +} diff --git a/src/mem/slicc/symbols/Func.hh b/src/mem/slicc/symbols/Func.hh new file mode 100644 index 000000000..c7e78838e --- /dev/null +++ b/src/mem/slicc/symbols/Func.hh @@ -0,0 +1,96 @@ + +/* + * 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.h + * + * Description: + * + * $Id$ + * + */ + +#ifndef FUNC_H +#define FUNC_H + +#include "mem/slicc/slicc_global.hh" +#include "mem/slicc/symbols/Type.hh" +class StateMachine; + +class Func : public Symbol { +public: + // Constructors + Func(string id, const Location& location, + Type* type_ptr, const Vector<Type*>& param_type_vec, const Vector<string>& param_string_vec, + string body, const Map<string, string>& pairs, StateMachine* machine_ptr); + + // Destructor + ~Func() {} + + // Public Methods + string cIdent() const { return m_c_ident; } + const Vector<Type*>& getParamTypes() const { return m_param_type_vec; } + Type* getReturnType() const { return m_type_ptr; } + void writeCFiles(string path) const; + 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<Type*> m_param_type_vec; + Vector<string> 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/State.hh b/src/mem/slicc/symbols/State.hh new file mode 100644 index 000000000..39900d506 --- /dev/null +++ b/src/mem/slicc/symbols/State.hh @@ -0,0 +1,45 @@ + +/* + * 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<string, string>& pairs) : Symbol(id, location, pairs) {} + void print(ostream& out) const { out << "[State: " << getIdent() << "]"; } +}; + +#endif //STATE_H diff --git a/src/mem/slicc/symbols/StateMachine.cc b/src/mem/slicc/symbols/StateMachine.cc new file mode 100644 index 000000000..6aaa0ebca --- /dev/null +++ b/src/mem/slicc/symbols/StateMachine.cc @@ -0,0 +1,993 @@ + +/* + * 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" + +StateMachine::StateMachine(string ident, const Location& location, const Map<string, string>& pairs) + : Symbol(ident, location, pairs) +{ + m_table_built = false; +} + +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; i<size; i++) { + if (m_actions[i]->getIdent() == 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<Transition*>()); + for(eventIndex=0; eventIndex < numEvents; eventIndex++) { + m_table[stateIndex].insertAtBottom(NULL); + } + } + + for(int i=0; i<numTransitions; i++) { + Transition* trans_ptr = m_transitions[i]; + + // 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. + + Vector<Action*> 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) const +{ + string comp = getIdent(); + string filename; + + // 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 method declarations for the class declaration + { + ostringstream sstr; + printControllerH(sstr, comp); + conditionally_write_file(path + comp + "_Controller.hh", 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; i<m_internal_func_vec.size(); i++) { + m_internal_func_vec[i]->writeCFiles(path); + } + +} + +void StateMachine::printControllerH(ostream& out, string component) const +{ + 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/protocol/TransitionResult.hh\"" << endl; + out << "#include \"mem/protocol/Types.hh\"" << endl; + out << "#include \"mem/protocol/" << component << "_Profiler.hh\"" << endl; + out << endl; + + // for adding information to the protocol debug trace + out << "extern stringstream " << component << "_" << "transitionComment;" << endl; + + out << "class " << component << "_Controller : public Consumer {" << 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 << " friend class Chip;" << endl; + out << "#endif /* CHECK_COHERENCE */" << endl; + + out << "public:" << endl; + out << " " << component << "_Controller(Chip* chip_ptr, int version);" << endl; + out << " void print(ostream& out) const;" << endl; + out << " void wakeup();" << endl; + out << " static void dumpStats(ostream& out) { s_profiler.dumpStats(out); }" << endl; + out << " static void clearStats() { s_profiler.clearStats(); }" << endl; + out << "private:" << 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 << " Chip* m_chip_ptr;" << endl; + out << " NodeID m_id;" << endl; + out << " NodeID m_version;" << endl; + out << " MachineID m_machineID;" << endl; + out << " static " << component << "_Profiler s_profiler;" << endl; + + // internal function protypes + out << " // Internal functions" << endl; + for(int i=0; i<m_internal_func_vec.size(); i++) { + Func* func = m_internal_func_vec[i]; + string proto; + func->funcPrototype(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; + } + out << "};" << endl; + out << "#endif // " << component << "_CONTROLLER_H" << endl; +} + +void StateMachine::printControllerC(ostream& out, string component) const +{ + 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; + out << "#include \"mem/protocol/Chip.hh\"" << endl; + out << 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 static profiler defn */" << endl; + out << component << "_Profiler " << component << "_Controller::s_profiler;" << endl; + out << endl; + + out << "/** \\brief constructor */" << endl; + out << component << "_Controller::" << component + << "_Controller(Chip* chip_ptr, int version)" << endl; + out << "{" << endl; + out << " m_chip_ptr = chip_ptr;" << endl; + out << " m_id = m_chip_ptr->getID();" << endl; + out << " m_version = version;" << endl; + out << " m_machineID.type = MachineType_" << component << ";" << endl; + out << " m_machineID.num = m_id*RubyConfig::numberOf"<< component << "PerChip()+m_version;" << endl; + + // Set the queue consumers + for(int i=0; i < m_in_ports.size(); i++) { + const Var* port = m_in_ports[i]; + out << " " << port->getCode() << ".setConsumer(this);" << endl; + } + + out << endl; + // Set the queue descriptions + for(int i=0; i < m_in_ports.size(); i++) { + const Var* port = m_in_ports[i]; + out << " " << port->getCode() + << ".setDescription(\"[Chip \" + int_to_string(m_chip_ptr->getID()) + \" \" + int_to_string(m_version) + \", " + << component << ", " << port->toString() << "]\");" << endl; + } + + // Initialize the transition profiling + out << endl; + for(int i=0; i<numTransitions(); i++) { + const Transition& t = getTransition(i); + const Vector<Action*>& action_vec = t.getActions(); + int numActions = action_vec.size(); + + // Figure out if we stall + bool stall = false; + for (int i=0; i<numActions; i++) { + if(action_vec[i]->getIdent() == "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; + } + } + + out << "}" << endl; + + out << endl; + + out << "void " << component << "_Controller::print(ostream& out) const { out << \"[" << component + << "_Controller \" << m_chip_ptr->getID() << \" \" << m_version << \"]\"; }" << 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; + out << action.lookupPair("c_code"); + out << "}" << endl; + } + out << endl; + } +} + +void StateMachine::printCWakeup(ostream& out, string component) const +{ + 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 << "#include \"mem/protocol/Chip.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 <= RubyConfig::" << getIdent() << "TransitionsPerCycle());" << endl; + out << " if (counter == RubyConfig::" << getIdent() << "TransitionsPerCycle()) {" << 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 + for(int i=0; i < m_in_ports.size(); i++) { + const Var* port = m_in_ports[i]; + assert(port->existPair("c_code_in_port")); + out << " // " + << component << "InPort " << port->toString() + << endl; + out << port->lookupPair("c_code_in_port"); + 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; +} + +void StateMachine::printCSwitch(ostream& out, string component) const +{ + 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 << "#include \"mem/protocol/Chip.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 (PROTOCOL_DEBUG_TRACE) {" << endl + << " g_system_ptr->getProfiler()->profileTransition(\"" << component + << "\", m_chip_ptr->getID(), 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 (PROTOCOL_DEBUG_TRACE) {" << endl + << " g_system_ptr->getProfiler()->profileTransition(\"" << component + << "\", m_chip_ptr->getID(), 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 (PROTOCOL_DEBUG_TRACE) {" << endl + << " g_system_ptr->getProfiler()->profileTransition(\"" << component + << "\", m_chip_ptr->getID(), 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<string, Vector<string> > code_map; // This map will allow suppress generating duplicate code + Vector<string> code_vec; + + for(int i=0; i<numTransitions(); i++) { + const Transition& t = getTransition(i); + string case_string = component + "_State_" + t.getStatePtr()->getIdent() + + ", " + 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*>& action_vec = t.getActions(); + int numActions = action_vec.size(); + + // Check for resources + Vector<string> code_sorter; + const Map<Var*, string>& res = t.getResources(); + Vector<Var*> res_keys = res.keys(); + for (int i=0; i<res_keys.size(); i++) { + string temp_code; + if (res_keys[i]->getType()->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; i<code_sorter.size(); i++) { + code += code_sorter[i]; + } + + // Figure out if we stall + bool stall = false; + for (int i=0; i<numActions; i++) { + if(action_vec[i]->getIdent() == "z_stall") { + stall = true; + } + } + + if (stall) { + code += " return TransitionResult_ProtocolStall;\n"; + } else { + for (int i=0; i<numActions; i++) { + code += " " + action_vec[i]->getIdent() + "(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<string> 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; i<code_vec.size(); i++) { + string code = code_vec[i]; + + // Iterative over all the multiple transitions that share the same code + for (int case_num=0; case_num<code_map.lookup(code).size(); case_num++) { + string case_string = code_map.lookup(code)[case_num]; + out << " case HASH_FUN(" << case_string << "):" << endl; + } + out << code; + } + + out << " default:" << endl; + out << " WARN_EXPR(m_id);" << endl; + out << " WARN_EXPR(m_version);" << endl; + out << " WARN_EXPR(g_eventQueue_ptr->getTime());" << 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) const +{ + 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 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 << "};" << endl; + out << "#endif // " << component << "_PROFILER_H" << endl; +} + +void StateMachine::printProfilerC(ostream& out, string component) const +{ + 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; + + // 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 << " ---\" << 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 += "<A href=\"" + click_href + "\" "; + temp += "target=\"" + click_target + "\" "; + string javascript = "if (parent.frames[" + over_target_num + "].location != parent.location + '" + over_href + "') { parent.frames[" + over_target_num + "].location='" + over_href + "' }"; + // string javascript = "parent." + target + ".location='" + href + "'"; + temp += "onMouseOver=\"" + javascript + "\" "; + temp += ">" + text + "</A>"; + 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) const +{ + string filename; + string component = getIdent(); + + /* + { + ostringstream out; + out << "<html>" << endl; + out << "<head>" << endl; + out << "<title>" << component << "</title>" << endl; + out << "</head>" << endl; + out << "<frameset rows=\"30,30,*\" frameborder=\"1\">" << endl; + out << " <frame name=\"Status\" src=\"empty.html\" marginheight=\"1\">" << endl; + out << " <frame name=\"Table\" src=\"" << component << "_table.html\" marginheight=\"1\">" << endl; + out << "</frameset>" << endl; + out << "</html>" << 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<numStates(); i++) { + ostringstream out; + printHTMLTransitions(out, i); + + // -- Write file + filename = component + "_table_" + getState(i).getIdent() + ".html"; + conditionally_write_file(path + filename, out); + } + + // Generate action descriptions + for(int i=0; i<numActions(); i++) { + ostringstream out; + createHTMLSymbol(getAction(i), "Action", out); + + // -- Write file + filename = component + "_action_" + getAction(i).getIdent() + ".html"; + conditionally_write_file(path + filename, out); + } + + // Generate state descriptions + for(int i=0; i<numStates(); i++) { + ostringstream out; + createHTMLSymbol(getState(i), "State", out); + + // -- Write file + filename = component + "_State_" + getState(i).getIdent() + ".html"; + conditionally_write_file(path + filename, out); + } + + // Generate event descriptions + for(int i=0; i<numEvents(); i++) { + ostringstream out; + createHTMLSymbol(getEvent(i), "Event", out); + + // -- Write file + filename = component + "_Event_" + getEvent(i).getIdent() + ".html"; + conditionally_write_file(path + filename, out); + } +} + +void StateMachine::printHTMLTransitions(ostream& out, int active_state) const +{ + // -- Prolog + out << "<HTML><BODY link=\"blue\" vlink=\"blue\">" << endl; + + // -- Header + out << "<H1 align=\"center\">" << formatHTMLShorthand(getShorthand()) << ": " << endl; + Vector<StateMachine*> machine_vec = g_sym_table.getStateMachines(); + for (int i=0; i<machine_vec.size(); i++) { + StateMachine* type = machine_vec[i]; + if (i != 0) { + out << " - "; + } + if (type == this) { + out << type->getIdent() << endl; + } else { + out << "<A target=\"Table\"href=\"" + type->getIdent() + "_table.html\">" + type->getIdent() + "</A> " << endl; + } + } + out << "</H1>" << endl; + + // -- Table header + out << "<TABLE border=1>" << endl; + + // -- Column headers + out << "<TR>" << endl; + + // -- First column header + out << " <TH> </TH>" << endl; + + for(int event = 0; event < numEvents(); event++ ) { + out << " <TH bgcolor=white>"; + out << frameRef(getIdent() + "_Event_" + getEvent(event).getIdent() + ".html", "Status", "1", formatHTMLShorthand(getEvent(event).getShorthand())); + out << "</TH>" << endl; + } + + out << "</TR>" << endl; + + // -- Body of table + for(int state = 0; state < numStates(); state++ ) { + out << "<TR>" << endl; + + // -- Each row + if (state == active_state) { + out << " <TH bgcolor=yellow>"; + } else { + out << " <TH bgcolor=white>"; + } + + 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 << "</TH>" << 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<Action*> 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 << " <TD bgcolor=#C0C000>"; + } else { + out << " <TD bgcolor=lightgrey>"; + } + } else if (active_state < numStates() && (trans_ptr->getNextStatePtr()->getIdent() == getState(active_state).getIdent())) { + out << " <TD bgcolor=aqua>"; + } else if (state == active_state) { + out << " <TD bgcolor=yellow>"; + } else { + out << " <TD bgcolor=white>"; + } + + out << actions_str; + if ((nextState.length() != 0) && (actions_str.length() != 0)) { + out << "/"; + } + out << nextState; + out << "</TD>" << endl; + } else { + // This is the no transition case + if (state == active_state) { + out << " <TD bgcolor=#C0C000> </TD>" << endl; + } else { + out << " <TD bgcolor=lightgrey> </TD>" << endl; + } + } + } + // -- Each row + if (state == active_state) { + out << " <TH bgcolor=yellow>"; + } else { + out << " <TH bgcolor=white>"; + } + + 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 << "</TH>" << endl; + + out << "</TR>" << endl; + } + + // -- Column footer + out << "<TR>" << endl; + out << " <TH> </TH>" << endl; + + for(int i = 0; i < numEvents(); i++ ) { + out << " <TH bgcolor=white>"; + out << frameRef(getIdent() + "_Event_" + getEvent(i).getIdent() + ".html", "Status", "1", formatHTMLShorthand(getEvent(i).getShorthand())); + out << "</TH>" << endl; + } + out << "</TR>" << endl; + + // -- Epilog + out << "</TABLE>" << endl; + out << "</BODY></HTML>" << endl; +} + + diff --git a/src/mem/slicc/symbols/StateMachine.hh b/src/mem/slicc/symbols/StateMachine.hh new file mode 100644 index 000000000..02ab12881 --- /dev/null +++ b/src/mem/slicc/symbols/StateMachine.hh @@ -0,0 +1,141 @@ + +/* + * 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" + +class Transition; +class Event; +class State; +class Action; +class Var; +class Func; + +class StateMachine : public Symbol { +public: + // Constructors + StateMachine(string ident, const Location& location, const Map<string, string>& pairs); + + // Destructor + ~StateMachine(); + + // Public Methods + + // Add items to the state machine + // void setMachine(string ident, const Map<string, string>& 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); + + // 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; + + // 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(); } + + void buildTable(); // Needs to be called before accessing the table + + // Code generator methods + void writeCFiles(string path) const; + void writeHTMLFiles(string path) const; + + void print(ostream& out) const { out << "[StateMachine: " << toString() << "]" << endl; } +private: + // 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) const; + void printControllerC(ostream& out, string component) const; + void printCWakeup(ostream& out, string component) const; + void printCSwitch(ostream& out, string component) const; + void printProfilerH(ostream& out, string component) const; + void printProfilerC(ostream& out, string component) const; + + void printHTMLTransitions(ostream& out, int active_state) const; + + // Data Members (m_ prefix) + Vector<State*> m_states; + Vector<Event*> m_events; + Vector<Action*> m_actions; + Vector<Transition*> m_transitions; + Vector<Func*> m_internal_func_vec; + + Map<State*, int> m_state_map; + Map<Event*, int> m_event_map; + + Vector<Var*> m_in_ports; + + // Table variables + bool m_table_built; + Vector<Vector<Transition*> > m_table; + +}; + +// 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/Symbol.cc b/src/mem/slicc/symbols/Symbol.cc new file mode 100644 index 000000000..25af5ad47 --- /dev/null +++ b/src/mem/slicc/symbols/Symbol.cc @@ -0,0 +1,72 @@ + +/* + * 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<string, string>& 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 new file mode 100644 index 000000000..1b4bd517a --- /dev/null +++ b/src/mem/slicc/symbols/Symbol.hh @@ -0,0 +1,100 @@ + +/* + * 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<string, string>& 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) const {} + virtual void writeHTMLFiles(string path) const {} + 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<string, string> 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/SymbolTable.cc b/src/mem/slicc/symbols/SymbolTable.cc new file mode 100644 index 000000000..70391f838 --- /dev/null +++ b/src/mem/slicc/symbols/SymbolTable.cc @@ -0,0 +1,934 @@ + +/* + * 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. + */ + +#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<string, string> pairs; + pairs.add("enumeration", "yes"); + newSym(new Type("MachineType", Location(), pairs)); + } + + { + Map<string, string> 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; i<size; i++) { + delete m_sym_vec[i]; + } +} + +void SymbolTable::newSym(Symbol* sym_ptr) +{ + registerSym(sym_ptr->toString(), 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<Var*>(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<string, Symbol*> m; + m_machine_component_map_vec.add(sym_ptr->toString(),m); + +} + +Type* SymbolTable::getType(string ident) const +{ + return dynamic_cast<Type*>(getSym(ident)); +} + +Var* SymbolTable::getVar(string ident) const +{ + return dynamic_cast<Var*>(getSym(ident)); +} + +Func* SymbolTable::getFunc(string ident) const +{ + return dynamic_cast<Func*>(getSym(ident)); +} + +StateMachine* SymbolTable::getStateMachine(string ident) const +{ + return dynamic_cast<StateMachine*>(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 mem/protocol/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<size; i++) { + Type* type = dynamic_cast<Type*>(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; i<size; i++) { + m_sym_vec[i]->writeCFiles(path + '/'); + } + + writeChipFiles(path); +} + +void SymbolTable::writeChipFiles(string path) const +{ + // Create Chip.cc and mem/protocol/Chip.hh + + // FIXME - Note: this method is _really_ ugly. Most of this + // functionality should be pushed into each type of symbol and use + // virtual methods to get the right behavior for each type of + // symbol. This is also more flexible, and much cleaner. + + int size = m_sym_vec.size(); + + // Create Chip.h + { + ostringstream sstr; + sstr << "/** \\file Chip.h " << endl; + sstr << " * Auto generated C++ code started by "<<__FILE__<<":"<<__LINE__<<endl; + sstr << " */ " <<endl<<endl; + + sstr << "#ifndef CHIP_H" << endl; + sstr << "#define CHIP_H" << endl; + sstr << endl; + + // Includes + sstr << "#include \"mem/ruby/common/Global.hh\"" << endl; + sstr << "#include \"mem/protocol/Types.hh\"" << endl; + sstr << "#include \"mem/ruby/slicc_interface/AbstractChip.hh\"" << endl; + sstr << "class Network;" << endl; + sstr << endl; + + // Class declarations for all Machines/Controllers + for(int i=0; i<size; i++) { + StateMachine* machine = dynamic_cast<StateMachine*>(m_sym_vec[i]); + if (machine != NULL) { + sstr << "class " << machine->getIdent() << "_Controller;" << endl; + } + } + + sstr << "class Chip : public AbstractChip {" << endl; + sstr << "public:" << endl; + sstr << endl; + sstr << " // Constructors" << endl; + sstr << " Chip(NodeID chip_number, Network* net_ptr);" << endl; + sstr << endl; + sstr << " // Destructor" << endl; + sstr << " ~Chip();" << endl; + sstr << endl; + sstr << " // Public Methods" << endl; + sstr << " void recordCacheContents(CacheRecorder& tr) const;" << endl; + sstr << " void dumpCaches(ostream& out) const;" << endl; + sstr << " void dumpCacheData(ostream& out) const;" << endl; + sstr << " static void printStats(ostream& out);" << endl; + sstr << " static void clearStats();" << endl; + sstr << " void printConfig(ostream& out);" << endl; + sstr << " void print(ostream& out) const;" << endl; + + // Used by coherence checker + sstr << "#ifdef CHECK_COHERENCE" << endl; + sstr << " bool isBlockShared(const Address& addr) const;" << endl; + sstr << " bool isBlockExclusive(const Address& addr) const;" << endl; + sstr << "#endif /* CHECK_COHERENCE */" << endl; + + sstr << endl; + sstr << "private:" << endl; + sstr << " // Private copy constructor and assignment operator" << endl; + sstr << " Chip(const Chip& obj);" << endl; + sstr << " Chip& operator=(const Chip& obj);" << endl; + sstr << endl; + sstr << "public: // FIXME - these should not be public" << endl; + sstr << " // Data Members (m_ prefix)" << endl; + sstr << endl; + sstr << " Chip* m_chip_ptr;" << endl; + sstr << endl; + sstr << " // SLICC object variables" << endl; + sstr << endl; + + // Look at all 'Vars' + for(int i=0; i<size; i++) { + Var* var = dynamic_cast<Var*>(m_sym_vec[i]); + if (var != NULL) { + if (var->existPair("chip_object")) { + if (var->existPair("no_chip_object")) { + // Do nothing + } else { + string template_hack = ""; + if (var->existPair("template_hack")) { + template_hack = var->lookupPair("template_hack"); + } + if (// var->existPair("network") || var->getType()->existPair("cache") || +// var->getType()->existPair("tbe") || var->getType()->existPair("newtbe") || +// var->getType()->existPair("dir") || var->getType()->existPair("persistent") || +// var->getType()->existPair("filter") || var->getType()->existPair("timer") || +// var->existPair("trigger_queue") + var->existPair("no_vector") + ) { + sstr << " " << var->getType()->cIdent() << template_hack << "* m_" + << var->cIdent() << "_ptr;" << endl; + } else { + // create pointer except those created in AbstractChip + if (!(var->existPair("abstract_chip_ptr"))) { + sstr << " Vector < " << var->getType()->cIdent() << template_hack + << "* > m_" << var->cIdent() << "_vec;" << endl; + } + } + } + } + } + } + + sstr << endl; + sstr << " // SLICC machine/controller variables" << endl; + + // Look at all 'Machines' + for(int i=0; i<size; i++) { + StateMachine* machine = dynamic_cast<StateMachine*>(m_sym_vec[i]); + if (machine != NULL) { + string ident = machine->getIdent() + "_Controller"; + sstr << " Vector < " << ident << "* > m_" << ident << "_vec;\n"; + } + } + + sstr << endl; + + sstr << " // machine external SLICC function decls\n"; + + // Look at all 'Functions' + for(int i=0; i<size; i++) { + Func* func = dynamic_cast<Func*>(m_sym_vec[i]); + if (func != NULL) { + string proto; + func->funcPrototype(proto); + if (proto != "") { + sstr << " " << proto; + } + } + } + + sstr << "};" << endl; + sstr << endl; + sstr << "#endif // CHIP_H" << endl; + + conditionally_write_file(path + "/Chip.hh", sstr); + } + // Create Chip.cc + { + ostringstream sstr; + sstr << "// Auto generated C++ code started by "<<__FILE__<<":"<<__LINE__<<endl<<endl; + sstr << "#include \"mem/protocol/Chip.hh\"" << endl; + sstr << "#include \"mem/ruby/network/Network.hh\"" << endl; + sstr << "#include \"mem/ruby/recorder/CacheRecorder.hh\"" << endl; + sstr << "" << endl; + + sstr << "// Includes for controllers" << endl; + for(int i=0; i<size; i++) { + StateMachine* machine = dynamic_cast<StateMachine*>(m_sym_vec[i]); + if (machine != NULL) { + sstr << "#include \"mem/protocol/" << machine->getIdent() << "_Controller.hh\"" << endl; + } + } + + sstr << "" << endl; + sstr << "Chip::Chip(NodeID id, Network* net_ptr):AbstractChip(id, net_ptr)" << endl; + sstr << "{" << endl; + sstr << " m_chip_ptr = this;" << endl; + + // FIXME - WHY IS THIS LOOP HERE? + // WE SEEM TO BE CREATING A SEQUENCER HERE THEN OVERWRITTING THAT INSTANITATION + // IN THE NEXT LOOP +// // find sequencer's type +// for(int i=0; i<size; i++) { +// Var* var = dynamic_cast<Var*>(m_sym_vec[i]); +// if(var && var->cIdent() == "sequencer") +// sstr << " m_sequencer_ptr = new " << var->getType()->cIdent() << "(this);\n"; +// } + + // Look at all 'Vars' + for(int i=0; i<size; i++) { + Var* var = dynamic_cast<Var*>(m_sym_vec[i]); + if (var != NULL && var->existPair("chip_object") && !var->existPair("no_chip_object")) { + + sstr << " // " << var->cIdent() << endl; + if (!var->existPair("network")) { + // Not a network port object + if (var->getType()->existPair("primitive")) { + // Normal non-object + // sstr << " m_" << var->cIdent() << "_ptr = new " << var->getType()->cIdent() << ";\n"; + + sstr << " m_" << var->cIdent(); + sstr << "_vec.setSize(RubyConfig::numberOf"; + sstr << var->getMachine()->getIdent() << "PerChip(m_id));" << endl; + sstr << " for (int i = 0; i < RubyConfig::numberOf" << var->getMachine()->getIdent() + << "PerChip(m_id); i++) {" << endl; + sstr << " m_" << var->cIdent() << "_vec[i] = new " << var->getType()->cIdent() << ";\n"; + if (var->existPair("default")) { + sstr << " *(m_" << var->cIdent() << "_vec[i]) = " << var->lookupPair("default") << ";\n"; + } + sstr << " }\n"; + + } else { + + // Normal Object + string template_hack = ""; + if (var->existPair("template_hack")) { + template_hack = var->lookupPair("template_hack"); + } + if (// var->getType()->existPair("cache") || var->getType()->existPair("tbe") || +// var->getType()->existPair("newtbe") || var->getType()->existPair("timer") || +// var->getType()->existPair("dir") || var->getType()->existPair("persistent") || +// var->getType()->existPair("filter") || var->existPair("trigger_queue") + var->existPair("no_vector")) { + sstr << " m_" << var->cIdent() << "_ptr = new " << var->getType()->cIdent() << template_hack; + if (!var->getType()->existPair("non_obj") && (!var->getType()->isEnumeration())) { + if (var->existPair("constructor_hack")) { + string constructor_hack = var->lookupPair("constructor_hack"); + sstr << "(this, " << constructor_hack << ")"; + } else { + sstr << "(this)"; + } + } + sstr << ";\n"; + sstr << " assert(m_" << var->cIdent() << "_ptr != NULL);" << endl; + + if (var->existPair("default")) { + sstr << " (*m_" << var->cIdent() << "_ptr) = " << var->lookupPair("default") + << "; // Object default" << endl; + } else if (var->getType()->hasDefault()) { + sstr << " (*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"); + sstr << " m_" << var->cIdent() << "_ptr->setOrdering(" << ordered << ");\n"; + } + + // Set randomization + if (var->existPair("random")) { + // A buffer + string value = var->lookupPair("random"); + sstr << " 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"); + sstr << " m_" << var->cIdent() << "_ptr->setPriority(" << rank << ");\n"; + } + } else if ((var->getType()->existPair("mover")) && (var->getMachine()->getIdent() == "L2Cache")) { + // FIXME - dnuca mover is a special case + sstr << " m_" << var->cIdent() << "_ptr = NULL;" << endl; + sstr << " if (RubyConfig::isL2CacheDNUCAMoverChip(m_id)) {" << endl; + sstr << " m_" << var->cIdent() << "_ptr = new " << var->getType()->cIdent() << template_hack; + if (!var->getType()->existPair("non_obj") && (!var->getType()->isEnumeration())) { + if (var->existPair("constructor_hack")) { + string constructor_hack = var->lookupPair("constructor_hack"); + sstr << "(this, " << constructor_hack << ")"; + } else { + sstr << "(this)"; + } + } + sstr << ";\n"; + sstr << " }\n"; + } else if (var->getType()->existPair("mover") && ((var->getMachine()->getIdent() == "L1Cache") || (var->getMachine()->getIdent() == "Collector"))) { + sstr << " m_" << var->cIdent() << "_ptr = NULL;" << endl; + sstr << " \n"; + } else { + sstr << " m_" << var->cIdent(); + sstr << "_vec.setSize(RubyConfig::numberOf"; + sstr << var->getMachine()->getIdent() << "PerChip(m_id));" << endl; + sstr << " for (int i = 0; i < RubyConfig::numberOf" << var->getMachine()->getIdent() + << "PerChip(m_id); i++) {" << endl; + + + ostringstream tail; + tail << template_hack; + if (!var->getType()->existPair("non_obj") && (!var->getType()->isEnumeration())) { + if (var->existPair("constructor_hack")) { + string constructor_hack = var->lookupPair("constructor_hack"); + tail << "(this, " << constructor_hack << ")"; + } else { + tail << "(this)"; + } + } + tail << ";\n"; + + + if(var->existPair("child_selector")){ + string child_selector = var->lookupPair("child_selector"); + string child_types = var->lookupPair("child_types"); + string::iterator it = child_types.begin(); + + uint num_types = 0; + for(uint t=0;t<child_types.size();t++){ + if(child_types.at(t) == '<'){ + num_types++; + } + } + + string* types = new string[num_types]; + string* ids = new string[num_types]; + int type_idx = 0; + bool id_done = false; + for(uint t=0;t<child_types.size();t++){ + if(child_types[t] == '<'){ + id_done = false; + uint r; + for(r=t+1;child_types.at(r)!='>';r++){ + if(r == child_types.size()){ + cerr << "Parse error in child_types" << endl; + exit(EXIT_FAILURE); + } + if(child_types.at(r) == ' ') continue; //ignore whitespace + if(child_types.at(r) == ',') {id_done = true;continue;} + if(id_done == true) + types[type_idx].push_back(child_types.at(r)); + else + ids[type_idx].push_back(child_types.at(r)); + } + type_idx++; + t = r; + } + } + + for(uint t=0;t<num_types;t++){ + if(t==0) + sstr << " if(strcmp(" << child_selector << ", \"" << ids[t] << "\") == 0)" << endl; + else + sstr << " else if(strcmp(" << child_selector << ", \"" << ids[t] << "\") == 0)" << endl; + sstr << " m_" << var->cIdent() << "_vec[i] = new " << types[t] << tail.str() << endl; + } + } + else { + sstr << " m_" << var->cIdent() << "_vec[i] = new " << var->getType()->cIdent() << tail.str() << endl; + } + + sstr << " assert(m_" << var->cIdent() << "_vec[i] != NULL);" << endl; + if (var->existPair("ordered")) { + string ordered = var->lookupPair("ordered"); + sstr << " m_" << var->cIdent() << "_vec[i]->setOrdering(" << ordered << ");\n"; + } + if (var->existPair("rank")) { + string rank = var->lookupPair("rank"); + sstr << " m_" << var->cIdent() << "_vec[i]->setPriority(" << rank << ");\n"; + } + + // Set buffer size + if (var->getType()->isBuffer() && !var->existPair("infinite")) { + sstr << " if (FINITE_BUFFERING) {\n"; + sstr << " m_" << var->cIdent() << "_vec[i]->setSize(PROCESSOR_BUFFER_SIZE);\n"; + sstr << " }\n"; + } + + sstr << " }\n"; + } + } + + sstr << endl; + + } else { + // Network port object + string network = var->lookupPair("network"); + string ordered = var->lookupPair("ordered"); + string vnet = var->lookupPair("virtual_network"); + + if (var->getMachine() != NULL) { + sstr << " m_" << var->cIdent() << "_vec.setSize(RubyConfig::numberOf" + << var->getMachine()->getIdent() << "PerChip(m_id));" << endl; + sstr << " for (int i = 0; i < RubyConfig::numberOf" << var->getMachine()->getIdent() + << "PerChip(m_id); i++) {" << endl; + sstr << " m_" << var->cIdent() << "_vec[i] = m_net_ptr->get" + << network << "NetQueue(i+m_id*RubyConfig::numberOf" <<var->getMachine()->getIdent() + << "PerChip()+MachineType_base_number(string_to_MachineType(\"" + << var->getMachine()->getIdent() << "\")), " + << ordered << ", " << vnet << ");\n"; + sstr << " assert(m_" << var->cIdent() << "_vec[i] != NULL);" << endl; + } else { // old protocol + sstr << " m_" << var->cIdent() << "_vec.setSize(1);" << endl; + sstr << " for (int i = 0; i < 1; i++) {" << endl; + sstr << " m_" << var->cIdent() << "_vec[i] = m_net_ptr->get" + << network << "NetQueue(m_id, " + << ordered << ", " << vnet << ");\n"; + sstr << " assert(m_" << var->cIdent() << "_vec[i] != NULL);" << endl; + } + + // Set ordering + if (var->existPair("ordered")) { + // A buffer + string ordered = var->lookupPair("ordered"); + sstr << " m_" << var->cIdent() << "_vec[i]->setOrdering(" << ordered << ");\n"; + } + + // Set randomization + if (var->existPair("random")) { + // A buffer + string value = var->lookupPair("random"); + sstr << " m_" << var->cIdent() << "_vec[i]->setRandomization(" << value << ");\n"; + } + + // Set Priority + if (var->existPair("rank")) { + string rank = var->lookupPair("rank"); + sstr << " m_" << var->cIdent() << "_vec[i]->setPriority(" << rank << ");\n"; + } + + // Set buffer size + if (var->getType()->isBuffer()) { + sstr << " if (FINITE_BUFFERING) {\n"; + sstr << " m_" << var->cIdent() << "_vec[i]->setSize(PROTOCOL_BUFFER_SIZE);\n"; + sstr << " }\n"; + } + + sstr << " }\n"; + } + } + } + // Look at all 'Machines' + for(int i=0; i<size; i++) { + StateMachine* machine = dynamic_cast<StateMachine*>(m_sym_vec[i]); + if (machine != NULL) { + string ident = machine->getIdent() + "_Controller"; + sstr << " m_" << ident << "_vec.setSize(RubyConfig::numberOf" << machine->getIdent() + << "PerChip(m_id));" << endl; + sstr << " for (int i = 0; i < RubyConfig::numberOf" << machine->getIdent() + << "PerChip(m_id); i++) {" << endl; + sstr << " m_" << ident << "_vec[i] = new " << ident << "(this, i);\n"; + sstr << " assert(m_" << ident << "_vec[i] != NULL);" << endl; + sstr << " }\n"; + sstr << endl; + } + } + + sstr << "}" << endl; + sstr << endl; + sstr << "Chip::~Chip()\n"; + sstr << "{\n"; + +// // FIXME: sequencer shouldn' be manually handled +// sstr << " delete m_sequencer_ptr;" << endl; + + // Look at all 'Vars' + for(int i=0; i<size; i++) { + Var* var = dynamic_cast<Var*>(m_sym_vec[i]); + if (var != NULL) { + if (var->existPair("chip_object")) { + if (var->existPair("no_chip_object")) { + // Do nothing + } else { + string template_hack = ""; + if (var->existPair("template_hack")) { + template_hack = var->lookupPair("template_hack"); + } + if (// var->getType()->existPair("cache") || var->getType()->existPair("tbe") || +// var->getType()->existPair("newtbe") || var->getType()->existPair("timer") || +// var->getType()->existPair("dir") || var->getType()->existPair("persistent") || +// var->getType()->existPair("filter") || var->existPair("trigger_queue") + var->existPair("no_vector")) { + sstr << " delete m_" << var->cIdent() << "_ptr;\n"; + } else if ((var->getType()->existPair("mover")) && (var->getMachine()->getIdent() == "L2Cache")) { + sstr << " if (RubyConfig::isL2CacheDNUCAMoverChip(m_id)) {" << endl; + sstr << " delete m_" << var->cIdent() << "_ptr;\n"; + sstr << " }\n"; + } else if (var->getType()->existPair("mover") && ((var->getMachine()->getIdent() == "L1Cache") || (var->getMachine()->getIdent() == "Collector"))) { + sstr << " m_" << var->cIdent() << "_ptr = NULL;" << endl; + } else if (!var->existPair("network")) { + // Normal Object + sstr << " for (int i = 0; i < RubyConfig::numberOf" << var->getMachine()->getIdent() + << "PerChip(m_id); i++) {" << endl; + sstr << " delete m_" << var->cIdent() << "_vec[i];\n"; + sstr << " }\n"; + } + } + } + } + } + + // Look at all 'Machines' + for(int i=0; i<size; i++) { + StateMachine* machine = dynamic_cast<StateMachine*>(m_sym_vec[i]); + if (machine != NULL) { + string ident = machine->getIdent() + "_Controller"; + sstr << " for (int i = 0; i < RubyConfig::numberOf" << machine->getIdent() + << "PerChip(m_id); i++) {" << endl; + sstr << " delete m_" << ident << "_vec[i];\n"; + sstr << " }\n"; + } + } + sstr << "}\n"; + + sstr << "\n"; + sstr << "void Chip::clearStats()\n"; + sstr << "{\n"; + + + // Look at all 'Machines' + for(int i=0; i<size; i++) { + StateMachine* machine = dynamic_cast<StateMachine*>(m_sym_vec[i]); + if (machine != NULL) { + string ident = machine->getIdent() + "_Controller"; + sstr << " " << ident << "::clearStats();\n"; + } + } + + sstr << "}\n"; + + sstr << "\n"; + sstr << "void Chip::printStats(ostream& out)\n"; + sstr << "{\n"; + sstr << " out << endl;\n"; + sstr << " out << \"Chip Stats\" << endl;\n"; + sstr << " out << \"----------\" << endl << endl;\n"; + + // Look at all 'Machines' + for(int i=0; i<size; i++) { + StateMachine* machine = dynamic_cast<StateMachine*>(m_sym_vec[i]); + if (machine != NULL) { + string ident = machine->getIdent() + "_Controller"; + sstr << " " << ident << "::dumpStats(out);\n"; + } + } + + sstr << "}" << endl; + sstr << endl; + sstr << "void Chip::printConfig(ostream& out)\n"; + sstr << "{\n"; + sstr << " out << \"Chip Config\" << endl;\n"; + sstr << " out << \"-----------\" << endl;\n"; + sstr << " out << \"Total_Chips: \" << RubyConfig::numberOfChips() << endl;\n"; + + // Look at all 'Vars' + for(int i=0; i<size; i++) { + Var* var = dynamic_cast<Var*>(m_sym_vec[i]); + if (var != NULL) { + if (var->existPair("chip_object")) { + if (var->existPair("no_chip_object")) { + // Do nothing + } else { + string template_hack = ""; + if (var->existPair("template_hack")) { + template_hack = var->lookupPair("template_hack"); + } + + if (!var->existPair("network") && (!var->getType()->existPair("primitive"))) { + // Normal Object + if (!var->getType()->existPair("non_obj") && (!var->getType()->isEnumeration())) { + if (var->existPair("no_vector")) { + sstr << " m_" << var->cIdent() << "_ptr->printConfig(out);\n"; + } else { + sstr << " out << \"\\n" << var->cIdent() << " numberPerChip: \" << RubyConfig::numberOf" << var->getMachine()->getIdent() + << "PerChip() << endl;\n"; + sstr << " m_" << var->cIdent() << "_vec[0]->printConfig(out);\n"; +// sstr << " for (int i = 0; i < RubyConfig::numberOf" << var->getMachine()->getIdent() +// << "PerChip(m_id); i++) {" << endl; +// sstr << " m_" << var->cIdent() << "_vec[i]->printConfig(out);\n"; +// sstr << " }\n"; + } + } + } + } + } + } + } + + sstr << " out << endl;\n"; + sstr << "}" << endl; + + sstr << endl; + sstr << "void Chip::print(ostream& out) const\n"; + sstr << "{\n"; + sstr << " out << \"Ruby Chip\" << endl;\n"; + sstr << "}" << endl; + + sstr << "#ifdef CHECK_COHERENCE" << endl; + sstr << endl; + sstr << "bool Chip::isBlockShared(const Address& addr) const" << endl; + sstr << "{" << endl; + + // Look at all 'Machines' + for(int i=0; i<size; i++) { + StateMachine* machine = dynamic_cast<StateMachine*>(m_sym_vec[i]); + if (machine != NULL) { + string ident = machine->getIdent() + "_Controller"; + sstr << " for (int i = 0; i < RubyConfig::numberOf" << machine->getIdent() + << "PerChip(m_id); i++) {" << endl; + sstr << " if (m_" << ident << "_vec[i]->" << machine->getIdent() << "_isBlockShared(addr)) {\n"; + sstr << " return true; \n"; + sstr << " }\n"; + sstr << " }\n"; + } + } + sstr << " return false;" << endl; + sstr << "}" << endl; + sstr << endl; + + sstr << endl; + sstr << "bool Chip::isBlockExclusive(const Address& addr) const" << endl; + sstr << "{" << endl; + + // Look at all 'Machines' + for(int i=0; i<size; i++) { + StateMachine* machine = dynamic_cast<StateMachine*>(m_sym_vec[i]); + if (machine != NULL) { + string ident = machine->getIdent() + "_Controller"; + sstr << " for (int i = 0; i < RubyConfig::numberOf" << machine->getIdent() + << "PerChip(m_id); i++) {" << endl; + sstr << " if (m_" << ident << "_vec[i]->" << machine->getIdent() << "_isBlockExclusive(addr)) {\n"; + sstr << " return true; \n"; + sstr << " }\n"; + sstr << " }\n"; + } + } + + sstr << " return false;" << endl; + sstr << "}" << endl; + sstr << endl; + + sstr << "#endif /* CHECK_COHERENCE */ " << endl; + + + sstr << endl; + sstr << "void Chip::dumpCaches(ostream& out) const" << endl; + sstr << "{" << endl; + + // Look at all 'Vars' + for(int i=0; i<size; i++) { + Var* var = dynamic_cast<Var*>(m_sym_vec[i]); + if (var != NULL) { + if (var->getType()->existPair("cache")){ // caches are partitioned one per controller instaniation + sstr << " for (int i = 0; i < RubyConfig::numberOf" << var->getMachine()->getIdent() + << "PerChip(m_id); i++) {" << endl; + sstr << " m_" << var->cIdent() << "_vec[i]->print(out);\n"; + sstr << " }\n"; + } + } + } + sstr << "}" << endl; + sstr << endl; + + // Function to dump cache tag and data information + sstr << "void Chip::dumpCacheData(ostream& out) const" << endl; + sstr << "{" << endl; + + // Look at all 'Vars' + for(int i=0; i<size; i++) { + Var* var = dynamic_cast<Var*>(m_sym_vec[i]); + if (var != NULL) { + if (var->getType()->existPair("cache")){ // caches are partitioned one per controller instaniation + sstr << " for (int i = 0; i < RubyConfig::numberOf" << var->getMachine()->getIdent() + << "PerChip(m_id); i++) {" << endl; + sstr << " m_" << var->cIdent() << "_vec[i]->printData(out);\n"; + sstr << " }\n"; + } + } + } + sstr << "}" << endl; + sstr << endl; + + sstr << "void Chip::recordCacheContents(CacheRecorder& tr) const" << endl; + sstr << "{" << endl; + + // Look at all 'Vars' + for(int i=0; i<size; i++) { + Var* var = dynamic_cast<Var*>(m_sym_vec[i]); + if (var != NULL) { + if (var->getType()->existPair("cache")){ // caches are partitioned one per controller instaniation + sstr << " for (int i = 0; i < RubyConfig::numberOf" << var->getMachine()->getIdent() + << "PerChip(m_id); i++) {" << endl; + sstr << " m_" << var->cIdent() << "_vec[i]->recordCacheContents(tr);\n"; + sstr << " }\n"; + } + } + } + sstr << "}" << endl; + + conditionally_write_file(path + "/Chip.cc", sstr); + } +} + +Vector<StateMachine*> SymbolTable::getStateMachines() const +{ + Vector<StateMachine*> machine_vec; + int size = m_sym_vec.size(); + for(int i=0; i<size; i++) { + StateMachine* type = dynamic_cast<StateMachine*>(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 << "<HTML></HTML>"; + conditionally_write_file(path + "empty.html", out); + } + + // Write all the symbols + int size = m_sym_vec.size(); + for(int i=0; i<size; i++) { + m_sym_vec[i]->writeHTMLFiles(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<size; i++) { + ostringstream states, events, actions, transitions; + StateMachine* machine = dynamic_cast<StateMachine*>(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 new file mode 100644 index 000000000..5e032e65d --- /dev/null +++ b/src/mem/slicc/symbols/SymbolTable.hh @@ -0,0 +1,121 @@ + +/* + * 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.h + * + * 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<StateMachine*> 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 writeChipFiles(string path) const; + + // Private copy constructor and assignment operator + SymbolTable(const SymbolTable& obj); + SymbolTable& operator=(const SymbolTable& obj); + + // Data Members (m_ prefix) + Vector<Symbol*> m_sym_vec; + Vector<Map<string, Symbol*> > m_sym_map_vec; + Map<string, Map<string, Symbol*> > 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/Transition.cc b/src/mem/slicc/symbols/Transition.cc new file mode 100644 index 000000000..d6d348166 --- /dev/null +++ b/src/mem/slicc/symbols/Transition.cc @@ -0,0 +1,173 @@ + +/* + * 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<string>& actionList, + const Location& location, + const Map<string, string>& 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<State*>& states, + const Vector<Event*>& events, + const Vector<Action*>& 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; i<numActions; i++) { + str += m_actionPtrs[i]->getShorthand(); + } + 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<Event*>& vec, string ident) +{ + int size = vec.size(); + for(int i=0; i<size; i++) { + if (ident == vec[i]->getIdent()) { + return vec[i]; + } + } + error("Event not found: " + ident); + return NULL; +} + +State* Transition::findIndex(const Vector<State*>& vec, string ident) +{ + int size = vec.size(); + for(int i=0; i<size; i++) { + if (ident == vec[i]->getIdent()) { + return vec[i]; + } + } + error("State not found: " + ident); + return NULL; +} + +Action* Transition::findIndex(const Vector<Action*>& vec, string ident) +{ + int size = vec.size(); + for(int i=0; i<size; i++) { + if (ident == vec[i]->getIdent()) { + 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 new file mode 100644 index 000000000..7d39447b0 --- /dev/null +++ b/src/mem/slicc/symbols/Transition.hh @@ -0,0 +1,120 @@ + +/* + * 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.h + * + * 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<string>& actionList, + const Location& location, + const Map<string, string>& 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<State*>& states, + const Vector<Event*>& events, + const Vector<Action*>& actions); + + const string& getStateShorthand() const; + const string& getEventShorthand() const; + const string& getNextStateShorthand() const; + string getActionShorthands() const; + const Vector<Action*>& getActions() const { assert(m_actionPtrsValid); return m_actionPtrs; } + const Map<Var*, string>& 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<Event*>& vec, string ident); + State* findIndex(const Vector<State*>& vec, string ident); + Action* findIndex(const Vector<Action*>& 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<string> m_actionList; + Vector<Action*> m_actionPtrs; + Map<Var*, string> 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/Type.cc b/src/mem/slicc/symbols/Type.cc new file mode 100644 index 000000000..a1de381ec --- /dev/null +++ b/src/mem/slicc/symbols/Type.cc @@ -0,0 +1,746 @@ + +/* + * 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. + */ + +#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<string, string>& 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<string, string>& 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<Type*>& 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<Type*>& 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<string, string> 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) const +{ + 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; + } + 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; + } + + } + out << " }" << endl; + } // end of if(!isGlobal()) + + // 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; + } + } + + 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; + if (m_isMachineType) { + out << "#include \"mem/ruby/config/RubyConfig.hh\"" << endl << 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 << "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, NodeID 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; + out << endl; + + // Code for output operator + out << "ostream& operator<<(ostream& out, const " << type_name << "& obj)" << endl; + out << "{" << endl; + out << " out << " << type_name << "_to_string(obj);" << endl; + out << " out << flush;" << endl; + out << " return out;" << endl; + out << "}" << endl; + + // Code to convert state to a string + out << endl; + out << "string " << type_name << "_to_string(const " << type_name << "& obj)" << endl; + out << "{" << endl; + out << " switch(obj) {" << endl; + + // For each field + for( int i = 0; i<size; i++ ) { + out << " case " << type_name << "_" << m_enum_vec[i] << ":" << endl; + out << " return \"" << m_enum_vec[i] << "\";" << endl; + } + + // Trailer + out << " default:" << endl; + out << " ERROR_MSG(\"Invalid range for type " << type_name << "\");" << endl; + out << " return \"\";" << endl; + out << " }" << endl; + out << "}" << endl; + + // Code to convert from a string to the enumeration + out << endl; + out << type_name << " string_to_" << type_name << "(const string& str)" << endl; + out << "{" << endl; + out << " if (false) {" << endl; + + // For each field + for( int i = 0; i<size; i++ ) { + out << " } else if (str == \"" << m_enum_vec[i] << "\") {" << endl; + out << " return " << type_name << "_" << m_enum_vec[i] << ";" << endl; + } + + out << " } else {" << endl; + out << " WARN_EXPR(str);" << endl; + out << " ERROR_MSG(\"Invalid string conversion for type " << type_name << "\");" << endl; + out << " }" << endl; + out << "}" << endl; + + // Code to increment an enumeration type + out << endl; + out << type_name << "& operator++( " << type_name << "& e) {" << endl; + out << " assert(e < " << type_name << "_NUM);" << endl; + out << " return e = " << type_name << "(e+1);" << endl; + out << "}" << endl; + + // MachineType hack used to set the base level and number of components for each Machine + if (m_isMachineType) { + out << endl; + out << "/** \\brief returns the base vector index for each machine type to be used by NetDest " << endl; + out << " * " << endl; + out << " * \\return the base vector index for each machine type to be used by NetDest" << endl; + out << " * \\see mem/ruby/common/NetDest.hh" << endl; + out << " */" << endl; + out << "int " << type_name << "_base_level(const " << type_name << "& obj)" << endl; + out << "{" << endl; + out << " switch(obj) {" << endl; + + // For each field + Vector < string > MachineNames; + for( int i = 0; i<size; i++ ) { + out << " case " << type_name << "_" << m_enum_vec[i] << ":" << endl; + out << " return " << MachineNames.size() << ";" << endl; + MachineNames.insertAtBottom(m_enum_vec[i]); + } + + // total num + out << " case " << type_name << "_NUM:" << endl; + out << " return " << MachineNames.size() << ";" << endl; + + // Trailer + out << " default:" << endl; + out << " ERROR_MSG(\"Invalid range for type " << type_name << "\");" << endl; + out << " return -1;" << endl; + out << " }" << endl; + out << "}" << endl; + + out << endl; + out << "/** \\brief The return value indicates the number of components created" << endl; + out << " * before a particular machine's components" << endl; + out << " * " << endl; + out << " * \\return the base number of components for each machine" << endl; + out << " */" << endl; + out << "int " << type_name << "_base_number(const " << type_name << "& obj)" << endl; + out << "{" << endl; + out << " switch(obj) {" << endl; + + // For each field + MachineNames.clear(); + for( int i = 0; i<size; i++ ) { + out << " case " << type_name << "_" << m_enum_vec[i] << ":" << endl; + out << " return 0"; + for ( int m = 0; m<MachineNames.size(); m++) { + out << "+RubyConfig::numberOf" << MachineNames[m] << "()"; + } + out << ";" << endl; + MachineNames.insertAtBottom(m_enum_vec[i]); + } + + // total num + out << " case " << type_name << "_NUM:" << endl; + out << " return 0"; + for ( int m = 0; m<MachineNames.size(); m++) { + out << "+RubyConfig::numberOf" << MachineNames[m] << "()"; + } + out << ";" << endl; + + // Trailer + out << " default:" << endl; + out << " ERROR_MSG(\"Invalid range for type " << type_name << "\");" << endl; + out << " return -1;" << endl; + out << " }" << endl; + out << "}" << endl; + + + out << endl; + out << "/** \\brief returns the total number of components for each machine" << endl; + out << " * \\return the total number of components for each machine" << endl; + out << " */" << endl; + out << "int " << type_name << "_base_count(const " << type_name << "& obj)" << endl; + out << "{" << endl; + out << " switch(obj) {" << endl; + + // For each field + for( int i = 0; i<size; i++ ) { + out << " case " << type_name << "_" << m_enum_vec[i] << ":" << endl; + out << " return RubyConfig::numberOf" << m_enum_vec[i] << "();" << endl; + } + + // total num + out << " case " << type_name << "_NUM:" << endl; + // Trailer + out << " default:" << endl; + out << " ERROR_MSG(\"Invalid range for type " << type_name << "\");" << endl; + out << " return -1;" << endl; + out << " }" << endl; + out << "}" << endl; + + out << endl; + out << "/** \\brief returns the total number of components for each machine" << endl; + out << " * \\return the total number of components for each machine" << endl; + out << " */" << endl; + out << "int " << type_name << "_chip_count(const " << type_name << "& obj, NodeID chipID)" << endl; + out << "{" << endl; + out << " switch(obj) {" << endl; + + // For each field + for( int i = 0; i<size; i++ ) { + out << " case " << type_name << "_" << m_enum_vec[i] << ":" << endl; + out << " return RubyConfig::numberOf" << m_enum_vec[i] << "PerChip(chipID);" << endl; + } + + // total num + out << " case " << type_name << "_NUM:" << endl; + // Trailer + out << " default:" << endl; + out << " ERROR_MSG(\"Invalid range for type " << type_name << "\");" << endl; + out << " return -1;" << endl; + out << " }" << endl; + out << "}" << endl; + + + } + + // Write the file + conditionally_write_file(path + type_name + ".cc", out); +} diff --git a/src/mem/slicc/symbols/Type.hh b/src/mem/slicc/symbols/Type.hh new file mode 100644 index 000000000..4187d8ad5 --- /dev/null +++ b/src/mem/slicc/symbols/Type.hh @@ -0,0 +1,154 @@ + +/* + * 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.h + * + * Description: + * + * $Id$ + * + * */ + +#ifndef TYPE_H +#define TYPE_H + +#include "mem/slicc/slicc_global.hh" +#include "mem/gems_common/Map.hh" +#include "mem/slicc/symbols/Symbol.hh" + +class StateMachine; + +class Type : public Symbol { +public: + // Constructors + Type(string id, const Location& location, + const Map<string, string>& 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"); } + + // 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<string, string>& 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<Type*>& param_type_vec); + bool methodExist(string id) const { return m_method_return_type_map.exist(id); } + + string methodId(string name, const Vector<Type*>& param_type_vec); + Type* methodReturnType(string id) const { return m_method_return_type_map.lookup(id); } + const Vector<Type*>& 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<string, string> pairs); + bool enumExist(string id) const { return m_enum_map.exist(id); } + + // Write the C output files + void writeCFiles(string path) const; + + 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<string, Type*> m_data_member_map; + Vector<string> m_data_member_ident_vec; + Vector<Type*> m_data_member_type_vec; + Vector<Map<string, string> > m_data_member_pairs_vec; + Vector<string*> m_data_member_init_code_vec; + // Needs pairs here + + // Methods + Map<string, Type*> m_method_return_type_map; + Map<string, Vector<Type*> > m_method_param_type_map; + // Needs pairs here + + // Enum + Map<string, bool> m_enum_map; + Vector<string> 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/Var.cc b/src/mem/slicc/symbols/Var.cc new file mode 100644 index 000000000..a6e8dfd55 --- /dev/null +++ b/src/mem/slicc/symbols/Var.cc @@ -0,0 +1,57 @@ + +/* + * 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<string, string>& 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 new file mode 100644 index 000000000..7b1a2c77d --- /dev/null +++ b/src/mem/slicc/symbols/Var.hh @@ -0,0 +1,98 @@ + +/* + * 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.h + * + * 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<string, string>& 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) const {} + 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 |