/* * 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& 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; igetIdent() == action_ptr->getIdent()) { m_actions[i]->warning("Duplicate action definition: " + m_actions[i]->getIdent()); action_ptr->error("Duplicate action definition: " + action_ptr->getIdent()); } if (m_actions[i]->getShorthand() == action_ptr->getShorthand()) { m_actions[i]->warning("Duplicate action shorthand: " + m_actions[i]->getIdent()); m_actions[i]->warning(" shorthand = " + m_actions[i]->getShorthand()); action_ptr->warning("Duplicate action shorthand: " + action_ptr->getIdent()); action_ptr->error(" shorthand = " + action_ptr->getShorthand()); } } m_actions.insertAtBottom(action_ptr); } void StateMachine::addTransition(Transition* trans_ptr) { assert(m_table_built == false); trans_ptr->checkIdents(m_states, m_events, m_actions); m_transitions.insertAtBottom(trans_ptr); } void StateMachine::addFunc(Func* func_ptr) { // register func in the symbol table g_sym_table.registerSym(func_ptr->toString(), func_ptr); m_internal_func_vec.insertAtBottom(func_ptr); } void StateMachine::buildTable() { assert(m_table_built == false); int numStates = m_states.size(); int numEvents = m_events.size(); int numTransitions = m_transitions.size(); int stateIndex, eventIndex; for(stateIndex=0; stateIndex < numStates; stateIndex++) { m_table.insertAtBottom(Vector()); for(eventIndex=0; eventIndex < numEvents; eventIndex++) { m_table[stateIndex].insertAtBottom(NULL); } } for(int i=0; i actions = trans_ptr->getActions(); for(int actionIndex=0; actionIndex < actions.size(); actionIndex++) { actions[actionIndex]->markUsed(); } stateIndex = getStateIndex(trans_ptr->getStatePtr()); eventIndex = getEventIndex(trans_ptr->getEventPtr()); if (m_table[stateIndex][eventIndex] != NULL) { m_table[stateIndex][eventIndex]->warning("Duplicate transition: " + m_table[stateIndex][eventIndex]->toString()); trans_ptr->error("Duplicate transition: " + trans_ptr->toString()); } m_table[stateIndex][eventIndex] = trans_ptr; } // Look at all actions to make sure we used them all for(int actionIndex=0; actionIndex < m_actions.size(); actionIndex++) { Action* action_ptr = m_actions[actionIndex]; if (!action_ptr->wasUsed()) { string error_msg = "Unused action: " + action_ptr->getIdent(); if (action_ptr->existPair("desc")) { error_msg += ", " + action_ptr->getDescription(); } action_ptr->warning(error_msg); } } m_table_built = true; } const Transition* StateMachine::getTransPtr(int stateIndex, int eventIndex) const { return m_table[stateIndex][eventIndex]; } // *********************** // // ******* C Files ******* // // *********************** // void StateMachine::writeCFiles(string path) 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; iwriteCFiles(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; ifuncPrototype(proto); if (proto != "") { out << " " << proto; } } out << " // Actions" << endl; for(int i=0; i < numActions(); i++) { const Action& action = getAction(i); out << "/** \\brief " << action.getDescription() << "*/" << endl; out << " void " << action.getIdent() << "(const Address& addr);" << endl; } 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& action_vec = t.getActions(); int numActions = action_vec.size(); // Figure out if we stall bool stall = false; for (int i=0; igetIdent() == "z_stall") { stall = true; } } // Only possible if it is not a 'z' case if (!stall) { out << " s_profiler.possibleTransition(" << component << "_State_" << t.getStatePtr()->getIdent() << ", " << component << "_Event_" << t.getEventPtr()->getIdent() << ");" << endl; } } 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 > code_map; // This map will allow suppress generating duplicate code Vector code_vec; for(int i=0; igetIdent() + ", " + component + "_Event_" + t.getEventPtr()->getIdent(); string code; code += " {\n"; // Only set next_state if it changes if (t.getStatePtr() != t.getNextStatePtr()) { code += " next_state = " + component + "_State_" + t.getNextStatePtr()->getIdent() + ";\n"; } const Vector& action_vec = t.getActions(); int numActions = action_vec.size(); // Check for resources Vector code_sorter; const Map& res = t.getResources(); Vector res_keys = res.keys(); for (int i=0; igetType()->cIdent() == "DNUCAStopTable") { temp_code += res.lookup(res_keys[i]); } else { temp_code += " if (!" + (res_keys[i]->getCode()) + ".areNSlotsAvailable(" + res.lookup(res_keys[i]) + ")) {\n"; if(CHECK_INVALID_RESOURCE_STALLS) { // assert that the resource stall is for a resource of equal or greater priority temp_code += " assert(priority >= "+ (res_keys[i]->getCode()) + ".getPriority());\n"; } temp_code += " return TransitionResult_ResourceStall;\n"; temp_code += " }\n"; } code_sorter.insertAtBottom(temp_code); } // Emit the code sequences in a sorted order. This makes the // output deterministic (without this the output order can vary // since Map's keys() on a vector of pointers is not deterministic code_sorter.sortVector(); for (int i=0; igetIdent() == "z_stall") { stall = true; } } if (stall) { code += " return TransitionResult_ProtocolStall;\n"; } else { for (int i=0; igetIdent() + "(addr);\n"; } code += " return TransitionResult_Valid;\n"; } code += " }\n"; // Look to see if this transition code is unique. if (code_map.exist(code)) { code_map.lookup(code).insertAtBottom(case_string); } else { Vector vec; vec.insertAtBottom(case_string); code_map.add(code, vec); code_vec.insertAtBottom(code); } } // Walk through all of the unique code blocks and spit out the // corresponding case statement elements for (int i=0; igetTime());" << endl; out << " WARN_EXPR(addr);" << endl; out << " WARN_EXPR(event);" << endl; out << " WARN_EXPR(state);" << endl; out << " ERROR_MSG(\"Invalid transition\");" << endl; out << " }" << endl; out << " return TransitionResult_Valid;" << endl; out << "}" << endl; } void StateMachine::printProfilerH(ostream& out, string component) 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 += ""; 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 << "" << endl; out << "" << endl; out << "" << component << "" << endl; out << "" << endl; out << "" << endl; out << " " << endl; out << " " << endl; out << "" << endl; out << "" << endl; conditionally_write_file(path + component + ".html", out); } */ // Create table with no row hilighted { ostringstream out; printHTMLTransitions(out, numStates()+1); // -- Write file filename = component + "_table.html"; conditionally_write_file(path + filename, out); } // Generate transition tables for(int i=0; i" << endl; // -- Header out << "

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

" << endl; // -- Table header out << "" << endl; // -- Column headers out << "" << endl; // -- First column header out << " " << endl; for(int event = 0; event < numEvents(); event++ ) { out << " " << endl; } out << "" << endl; // -- Body of table for(int state = 0; state < numStates(); state++ ) { out << "" << endl; // -- Each row if (state == active_state) { out << " " << endl; // -- One column for each event for(int event = 0; event < numEvents(); event++ ) { const Transition* trans_ptr = getTransPtr(state, event); if( trans_ptr != NULL ) { bool stall_action = false; string nextState; string actions_str; // -- Get the actions // actions = trans_ptr->getActionShorthands(); const Vector actions = trans_ptr->getActions(); for (int action=0; action < actions.size(); action++) { if ((actions[action]->getIdent() == "z_stall") || (actions[action]->getIdent() == "zz_recycleMandatoryQueue")) { stall_action = true; } actions_str += " "; actions_str += frameRef(getIdent() + "_action_" + actions[action]->getIdent() + ".html", "Status", "1", formatHTMLShorthand(actions[action]->getShorthand())); actions_str += "\n"; } // -- Get the next state if (trans_ptr->getNextStatePtr()->getIdent() != getState(state).getIdent()) { string click_href = getIdent() + "_table_" + trans_ptr->getNextStatePtr()->getIdent() + ".html"; nextState = frameRef(click_href, "Table", getIdent() + "_State_" + trans_ptr->getNextStatePtr()->getIdent() + ".html", "1", formatHTMLShorthand(trans_ptr->getNextStateShorthand())); } else { nextState = ""; } // -- Print out "actions/next-state" if (stall_action) { if (state == active_state) { out << " " << endl; } else { // This is the no transition case if (state == active_state) { out << " " << endl; } else { out << " " << endl; } } } // -- Each row if (state == active_state) { out << " " << endl; out << "" << endl; } // -- Column footer out << "" << endl; out << " " << endl; for(int i = 0; i < numEvents(); i++ ) { out << " " << endl; } out << "" << endl; // -- Epilog out << "
"; out << frameRef(getIdent() + "_Event_" + getEvent(event).getIdent() + ".html", "Status", "1", formatHTMLShorthand(getEvent(event).getShorthand())); out << "
"; } else { out << " "; } string click_href = getIdent() + "_table_" + getState(state).getIdent() + ".html"; string text = formatHTMLShorthand(getState(state).getShorthand()); out << frameRef(click_href, "Table", getIdent() + "_State_" + getState(state).getIdent() + ".html", "1", formatHTMLShorthand(getState(state).getShorthand())); out << ""; } else { out << " "; } } else if (active_state < numStates() && (trans_ptr->getNextStatePtr()->getIdent() == getState(active_state).getIdent())) { out << " "; } else if (state == active_state) { out << " "; } else { out << " "; } out << actions_str; if ((nextState.length() != 0) && (actions_str.length() != 0)) { out << "/"; } out << nextState; out << "  "; } else { out << " "; } click_href = getIdent() + "_table_" + getState(state).getIdent() + ".html"; text = formatHTMLShorthand(getState(state).getShorthand()); out << frameRef(click_href, "Table", getIdent() + "_State_" + getState(state).getIdent() + ".html", "1", formatHTMLShorthand(getState(state).getShorthand())); out << "
"; out << frameRef(getIdent() + "_Event_" + getEvent(i).getIdent() + ".html", "Status", "1", formatHTMLShorthand(getEvent(i).getShorthand())); out << "
" << endl; out << "" << endl; }