3 * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
8 * met: redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer;
10 * redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution;
13 * neither the name of the copyright holders nor the names of its
14 * contributors may be used to endorse or promote products derived from
15 * this software without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 #include "mem/slicc/symbols/StateMachine.hh"
36 #include "mem/slicc/generator/fileio.hh"
37 #include "mem/slicc/generator/html_gen.hh"
38 #include "mem/slicc/symbols/Action.hh"
39 #include "mem/slicc/symbols/Event.hh"
40 #include "mem/slicc/symbols/State.hh"
41 #include "mem/slicc/symbols/Transition.hh"
42 #include "mem/slicc/symbols/Var.hh"
43 #include "mem/slicc/symbols/SymbolTable.hh"
44 #include "mem/gems_common/util.hh"
45 #include "mem/gems_common/Vector.hh"
49 StateMachine::StateMachine(string ident
, const Location
& location
, const Map
<string
, string
>& pairs
, std::vector
<std::string
*>* latency_vector
)
50 : Symbol(ident
, location
, pairs
)
52 m_table_built
= false;
53 m_latency_vector
= *latency_vector
;
56 StateMachine::~StateMachine()
62 void StateMachine::addState(State
* state_ptr
)
64 assert(m_table_built
== false);
65 m_state_map
.add(state_ptr
, m_states
.size());
66 m_states
.insertAtBottom(state_ptr
);
69 void StateMachine::addEvent(Event
* event_ptr
)
71 assert(m_table_built
== false);
72 m_event_map
.add(event_ptr
, m_events
.size());
73 m_events
.insertAtBottom(event_ptr
);
76 void StateMachine::addAction(Action
* action_ptr
)
78 assert(m_table_built
== false);
80 // Check for duplicate action
81 int size
= m_actions
.size();
82 for(int i
=0; i
<size
; i
++) {
83 if (m_actions
[i
]->getIdent() == action_ptr
->getIdent()) {
84 m_actions
[i
]->warning("Duplicate action definition: " + m_actions
[i
]->getIdent());
85 action_ptr
->error("Duplicate action definition: " + action_ptr
->getIdent());
87 if (m_actions
[i
]->getShorthand() == action_ptr
->getShorthand()) {
88 m_actions
[i
]->warning("Duplicate action shorthand: " + m_actions
[i
]->getIdent());
89 m_actions
[i
]->warning(" shorthand = " + m_actions
[i
]->getShorthand());
90 action_ptr
->warning("Duplicate action shorthand: " + action_ptr
->getIdent());
91 action_ptr
->error(" shorthand = " + action_ptr
->getShorthand());
95 m_actions
.insertAtBottom(action_ptr
);
98 void StateMachine::addTransition(Transition
* trans_ptr
)
100 assert(m_table_built
== false);
101 trans_ptr
->checkIdents(m_states
, m_events
, m_actions
);
102 m_transitions
.insertAtBottom(trans_ptr
);
105 void StateMachine::addFunc(Func
* func_ptr
)
107 // register func in the symbol table
108 g_sym_table
.registerSym(func_ptr
->toString(), func_ptr
);
109 m_internal_func_vec
.insertAtBottom(func_ptr
);
112 void StateMachine::buildTable()
114 assert(m_table_built
== false);
115 int numStates
= m_states
.size();
116 int numEvents
= m_events
.size();
117 int numTransitions
= m_transitions
.size();
118 int stateIndex
, eventIndex
;
120 for(stateIndex
=0; stateIndex
< numStates
; stateIndex
++) {
121 m_table
.insertAtBottom(Vector
<Transition
*>());
122 for(eventIndex
=0; eventIndex
< numEvents
; eventIndex
++) {
123 m_table
[stateIndex
].insertAtBottom(NULL
);
127 for(int i
=0; i
<numTransitions
; i
++) {
128 Transition
* trans_ptr
= m_transitions
[i
];
130 // Track which actions we touch so we know if we use them all --
131 // really this should be done for all symbols as part of the
132 // symbol table, then only trigger it for Actions, States, Events,
135 Vector
<Action
*> actions
= trans_ptr
->getActions();
136 for(int actionIndex
=0; actionIndex
< actions
.size(); actionIndex
++) {
137 actions
[actionIndex
]->markUsed();
140 stateIndex
= getStateIndex(trans_ptr
->getStatePtr());
141 eventIndex
= getEventIndex(trans_ptr
->getEventPtr());
142 if (m_table
[stateIndex
][eventIndex
] != NULL
) {
143 m_table
[stateIndex
][eventIndex
]->warning("Duplicate transition: " + m_table
[stateIndex
][eventIndex
]->toString());
144 trans_ptr
->error("Duplicate transition: " + trans_ptr
->toString());
146 m_table
[stateIndex
][eventIndex
] = trans_ptr
;
149 // Look at all actions to make sure we used them all
150 for(int actionIndex
=0; actionIndex
< m_actions
.size(); actionIndex
++) {
151 Action
* action_ptr
= m_actions
[actionIndex
];
152 if (!action_ptr
->wasUsed()) {
153 string error_msg
= "Unused action: " + action_ptr
->getIdent();
154 if (action_ptr
->existPair("desc")) {
155 error_msg
+= ", " + action_ptr
->getDescription();
157 action_ptr
->warning(error_msg
);
161 m_table_built
= true;
164 const Transition
* StateMachine::getTransPtr(int stateIndex
, int eventIndex
) const
166 return m_table
[stateIndex
][eventIndex
];
169 // *********************** //
170 // ******* C Files ******* //
171 // *********************** //
173 void StateMachine::writeCFiles(string path
)
175 string comp
= getIdent();
178 // Output the method declarations for the class declaration
181 printControllerH(sstr
, comp
);
182 conditionally_write_file(path
+ comp
+ "_Controller.hh", sstr
);
185 // Output switch statement for transition table
188 printCSwitch(sstr
, comp
);
189 conditionally_write_file(path
+ comp
+ "_Transitions.cc", sstr
);
192 // Output the actions for performing the actions
195 printControllerC(sstr
, comp
);
196 conditionally_write_file(path
+ comp
+ "_Controller.cc", sstr
);
199 // Output the wakeup loop for the events
202 printCWakeup(sstr
, comp
);
203 conditionally_write_file(path
+ comp
+ "_Wakeup.cc", sstr
);
209 printProfilerC(sstr
, comp
);
210 conditionally_write_file(path
+ comp
+ "_Profiler.cc", sstr
);
214 printProfilerH(sstr
, comp
);
215 conditionally_write_file(path
+ comp
+ "_Profiler.hh", sstr
);
218 // Write internal func files
219 for(int i
=0; i
<m_internal_func_vec
.size(); i
++) {
220 m_internal_func_vec
[i
]->writeCFiles(path
);
225 void StateMachine::printControllerH(ostream
& out
, string component
)
228 m_message_buffer_names
.clear();
230 out
<< "/** \\file " << getIdent() << ".hh" << endl
;
231 out
<< " * " << endl
;
232 out
<< " * Auto generated C++ code started by "<<__FILE__
<<":"<<__LINE__
<< endl
;
233 out
<< " * Created by slicc definition of Module \"" << getShorthand() << "\"" << endl
;
234 out
<< " */" << endl
;
236 out
<< "#ifndef " << component
<< "_CONTROLLER_H" << endl
;
237 out
<< "#define " << component
<< "_CONTROLLER_H" << endl
;
239 out
<< "#include \"mem/ruby/common/Global.hh\"" << endl
;
240 out
<< "#include \"mem/ruby/common/Consumer.hh\"" << endl
;
241 out
<< "#include \"mem/ruby/slicc_interface/AbstractController.hh\"" << endl
;
242 out
<< "#include \"mem/protocol/TransitionResult.hh\"" << endl
;
243 out
<< "#include \"mem/protocol/Types.hh\"" << endl
;
244 out
<< "#include \"mem/protocol/" << component
<< "_Profiler.hh\"" << endl
;
246 // include object classes
247 std::set
<string
> seen_types
;
248 for(int i
=0; i
<numObjects(); i
++) {
249 Var
* var
= m_objs
[i
];
250 if (seen_types
.count(var
->getType()->cIdent()) == 0) {
251 out
<< "#include \"mem/protocol/" << var
->getType()->cIdent() << ".hh\"" << endl
;
252 // out << "class " << var->getType()->cIdent() << ";" << endl;
253 seen_types
.insert(var
->getType()->cIdent());
259 // for adding information to the protocol debug trace
260 out
<< "extern stringstream " << component
<< "_" << "transitionComment;" << endl
;
262 out
<< "class " << component
<< "_Controller : public AbstractController {" << endl
;
264 /* the coherence checker needs to call isBlockExclusive() and isBlockShared()
265 making the Chip a friend class is an easy way to do this for now */
266 out
<< "#ifdef CHECK_COHERENCE" << endl
;
267 out
<< "#endif /* CHECK_COHERENCE */" << endl
;
269 out
<< "public:" << endl
;
270 // out << " " << component << "_Controller(int version, Network* net_ptr);" << endl;
271 out
<< " " << component
<< "_Controller(const string & name);" << endl
;
272 out
<< " static int getNumControllers();" << endl
;
273 out
<< " void init(Network* net_ptr, const vector<string> & argv);" << endl
;
274 out
<< " MessageBuffer* getMandatoryQueue() const;" << endl
;
275 out
<< " const int & getVersion() const;" << endl
;
276 out
<< " const string toString() const;" << endl
;
277 out
<< " const string getName() const;" << endl
;
278 out
<< " const MachineType getMachineType() const;" << endl
;
279 out
<< " void print(ostream& out) const;" << endl
;
280 out
<< " void printConfig(ostream& out) const;" << endl
;
281 out
<< " void wakeup();" << endl
;
282 out
<< " void printStats(ostream& out) const { s_profiler.dumpStats(out); }" << endl
;
283 out
<< " void clearStats() { s_profiler.clearStats(); }" << endl
;
284 out
<< "private:" << endl
;
288 std::vector
<std::string
*>::const_iterator it
;
289 for(it
=m_latency_vector
.begin();it
!=m_latency_vector
.end();it
++){
290 out
<< " int m_" << (*it
)->c_str() << ";" << endl
;
292 out
<< " int m_number_of_TBEs;" << endl
;
294 out
<< " TransitionResult doTransition(" << component
<< "_Event event, " << component
295 << "_State state, const Address& addr";
296 if(CHECK_INVALID_RESOURCE_STALLS
) {
297 out
<< ", int priority";
299 out
<< "); // in " << component
<< "_Transitions.cc" << endl
;
300 out
<< " TransitionResult doTransitionWorker(" << component
<< "_Event event, " << component
301 << "_State state, " << component
<< "_State& next_state, const Address& addr";
302 if(CHECK_INVALID_RESOURCE_STALLS
) {
303 out
<< ", int priority";
305 out
<< "); // in " << component
<< "_Transitions.cc" << endl
;
306 out
<< " string m_name;" << endl
;
307 out
<< " int m_transitions_per_cycle;" << endl
;
308 out
<< " int m_buffer_size;" << endl
;
309 out
<< " int m_recycle_latency;" << endl
;
310 out
<< " map< string, string > m_cfg;" << endl
;
311 out
<< " NodeID m_version;" << endl
;
312 out
<< " Network* m_net_ptr;" << endl
;
313 out
<< " MachineID m_machineID;" << endl
;
314 out
<< " static " << component
<< "_Profiler s_profiler;" << endl
;
315 out
<< " static int m_num_controllers;" << endl
;
317 // internal function protypes
318 out
<< " // Internal functions" << endl
;
319 for(int i
=0; i
<m_internal_func_vec
.size(); i
++) {
320 Func
* func
= m_internal_func_vec
[i
];
322 func
->funcPrototype(proto
);
328 out
<< " // Actions" << endl
;
329 for(int i
=0; i
< numActions(); i
++) {
330 const Action
& action
= getAction(i
);
331 out
<< "/** \\brief " << action
.getDescription() << "*/" << endl
;
332 out
<< " void " << action
.getIdent() << "(const Address& addr);" << endl
;
335 // the controller internal variables
336 out
<< " // Object" << endl
;
337 for(int i
=0; i
< numObjects(); i
++) {
338 const Var
* var
= m_objs
[i
];
339 string template_hack
= "";
340 if (var
->existPair("template_hack")) {
341 template_hack
= var
->lookupPair("template_hack");
343 out
<< " " << var
->getType()->cIdent() << template_hack
<< "* m_"
344 << var
->cIdent() << "_ptr;" << endl
;
346 string str
= "m_"+ var
->cIdent() + "_ptr";
347 if (var
->getType()->cIdent() == "MessageBuffer")
348 m_message_buffer_names
.push_back(str
);
354 out
<< "#endif // " << component
<< "_CONTROLLER_H" << endl
;
357 void StateMachine::printControllerC(ostream
& out
, string component
)
359 out
<< "/** \\file " << getIdent() << ".cc" << endl
;
360 out
<< " * " << endl
;
361 out
<< " * Auto generated C++ code started by "<<__FILE__
<<":"<<__LINE__
<< endl
;
362 out
<< " * Created by slicc definition of Module \"" << getShorthand() << "\"" << endl
;
363 out
<< " */" << endl
;
365 out
<< "#include \"mem/ruby/common/Global.hh\"" << endl
;
366 out
<< "#include \"mem/ruby/slicc_interface/RubySlicc_includes.hh\"" << endl
;
367 out
<< "#include \"mem/protocol/" << component
<< "_Controller.hh\"" << endl
;
368 out
<< "#include \"mem/protocol/" << component
<< "_State.hh\"" << endl
;
369 out
<< "#include \"mem/protocol/" << component
<< "_Event.hh\"" << endl
;
370 out
<< "#include \"mem/protocol/Types.hh\"" << endl
;
371 out
<< "#include \"mem/ruby/system/System.hh\"" << endl
;
373 // include object classes
374 std::set
<string
> seen_types
;
375 for(int i
=0; i
<numObjects(); i
++) {
376 Var
* var
= m_objs
[i
];
377 if (seen_types
.count(var
->getType()->cIdent()) == 0) {
378 out
<< "#include \"mem/protocol/" << var
->getType()->cIdent() << ".hh\"" << endl
;
379 seen_types
.insert(var
->getType()->cIdent());
386 out
<< "int " << component
<< "_Controller::m_num_controllers = 0;" << endl
;
388 // for adding information to the protocol debug trace
389 out
<< "stringstream " << component
<< "_" << "transitionComment;" << endl
;
390 out
<< "#define APPEND_TRANSITION_COMMENT(str) (" << component
<< "_" << "transitionComment << str)" << endl
;
392 out
<< "/** \\brief static profiler defn */" << endl
;
393 out
<< component
<< "_Profiler " << component
<< "_Controller::s_profiler;" << endl
;
396 out
<< "/** \\brief constructor */" << endl
;
397 out
<< component
<< "_Controller::" << component
398 // << "_Controller(int version, Network* net_ptr)" << endl;
399 << "_Controller(const string & name)" << endl
;
400 out
<< " : m_name(name)" << endl
;
402 out
<< " m_num_controllers++; " << endl
;
403 for(int i
=0; i
< numObjects(); i
++) {
404 const Var
* var
= m_objs
[i
];
405 if ( var
->cIdent().find("mandatoryQueue") != string::npos
)
406 out
<< " m_" << var
->cIdent() << "_ptr = new " << var
->getType()->cIdent() << "();" << endl
;
408 out
<< "}" << endl
<< endl
;
410 out
<< "void " << component
<< "_Controller::init(Network * net_ptr, const vector<string> & argv)" << endl
;
412 out
<< " for (size_t i=0; i < argv.size(); i+=2) {" << endl
;
413 // out << " printf (\"ARG: %s = %s \\n \", argv[i].c_str(), argv[i+1].c_str());"<< endl;
415 out
<< " if (argv[i] == \"version\") " << endl
;
416 out
<< " m_version = atoi(argv[i+1].c_str());" << endl
;
417 out
<< " else if (argv[i] == \"transitions_per_cycle\") " << endl
;
418 out
<< " m_transitions_per_cycle = atoi(argv[i+1].c_str());" << endl
;
419 out
<< " else if (argv[i] == \"buffer_size\") " << endl
;
420 out
<< " m_buffer_size = atoi(argv[i+1].c_str());" << endl
;
422 out
<< " else if (argv[i] == \"recycle_latency\") " << endl
;
423 out
<< " m_recycle_latency = atoi(argv[i+1].c_str());" << endl
;
424 //added by SS --> for latency
425 //for loop on latency_vector to check with argv[i] and assign the value to the related m_latency ...
426 out
<< " else if (argv[i] == \"number_of_TBEs\") " << endl
;
427 out
<< " m_number_of_TBEs = atoi(argv[i+1].c_str());" << endl
;
429 if (m_latency_vector
.size()) {
430 out
<< " else { " << endl
;
431 std::vector
<std::string
*>::const_iterator it
;
432 for(it
=m_latency_vector
.begin();it
!=m_latency_vector
.end();it
++) {
433 string str
= (*it
)->c_str();
435 //convert to lowercase
437 char* strc
= (char*) malloc (str
.length()+1);
438 strc
[str
.length()]=0;
439 for(i
=0; i
< str
.length(); i
++) {
441 strc
[i
] = tolower(strc
[i
]);
445 out
<< " if (argv[i] == \"" << str
<< "\"){" << endl
;
446 if (str
== "to_mem_ctrl_latency")
447 out
<< " m_" << (*it
)->c_str() << "=" << "atoi(argv[i+1].c_str())+(random() % 5);" << endl
;
449 out
<< " m_" << (*it
)->c_str() << "=" << "atoi(argv[i+1].c_str());" << endl
;
450 // out << " printf (\"SET m_" << it->c_str() << "= %i \\n \", m_" << it->c_str() << ");" << endl;
457 out
<< " m_net_ptr = net_ptr;" << endl
;
458 out
<< " m_machineID.type = MachineType_" << component
<< ";" << endl
;
459 out
<< " m_machineID.num = m_version;" << endl
;
461 // out << " printf (\"I set m_LATENCY_ISSUE_LATENCY to %i \\n \", m_LATENCY_ISSUE_LATENCY);" << endl;
462 // out << " printf (\"I set m_LATENCY_CACHE_RESPONSE_LATENCY to %i \\n \", m_LATENCY_CACHE_RESPONSE_LATENCY);" << endl;
464 // make configuration array
465 out
<< " for (size_t i=0; i < argv.size(); i+=2) {" << endl
;
466 out
<< " if (argv[i] != \"version\") " << endl
;
467 out
<< " m_cfg[argv[i]] = argv[i+1];" << endl
;
472 // initialize objects
473 out
<< " // Objects" << endl
;
474 for(int i
=0; i
< numObjects(); i
++) {
475 const Var
* var
= m_objs
[i
];
476 if (!var
->existPair("network")) {
477 // Not a network port object
478 if (var
->getType()->existPair("primitive")) {
479 out
<< " m_" << var
->cIdent() << "_ptr = new " << var
->getType()->cIdent() << ";\n";
480 if (var
->existPair("default")) {
481 out
<< " (*m_" << var
->cIdent() << "_ptr) = " << var
->lookupPair("default") << ";\n";
487 string template_hack
= "";
488 if (var
->existPair("template_hack")) {
489 template_hack
= var
->lookupPair("template_hack");
494 if (var
->existPair("factory")) {
495 out
<< " m_" << var
->cIdent() << "_ptr = " << var
->lookupPair("factory");
497 if ( var
->cIdent().find("mandatoryQueue") == string::npos
) {
499 str
= " m_" + var
->cIdent() + "_ptr = new " + var
->getType()->cIdent() + template_hack
;
501 if (str
.find("TBETable")!=string::npos
){
505 if (!var
->getType()->existPair("non_obj") && (!var
->getType()->isEnumeration())) {
507 if (var
->existPair("constructor_hack")) {
508 string constructor_hack
= var
->lookupPair("constructor_hack");
509 str
= "(" + constructor_hack
+ ")";
514 str
= "(m_number_of_TBEs)";
521 out
<< " assert(m_" << var
->cIdent() << "_ptr != NULL);" << endl
;
523 if (var
->existPair("default")) {
524 out
<< " (*m_" << var
->cIdent() << "_ptr) = " << var
->lookupPair("default")
525 << "; // Object default" << endl
;
526 } else if (var
->getType()->hasDefault()) {
527 out
<< " (*m_" << var
->cIdent() << "_ptr) = " << var
->getType()->getDefault()
528 << "; // Type " << var
->getType()->getIdent() << " default" << endl
;
532 if (var
->existPair("ordered") && !var
->existPair("trigger_queue")) {
534 string ordered
= var
->lookupPair("ordered");
535 out
<< " m_" << var
->cIdent() << "_ptr->setOrdering(" << ordered
<< ");\n";
539 if (var
->existPair("random")) {
541 string value
= var
->lookupPair("random");
542 out
<< " m_" << var
->cIdent() << "_ptr->setRandomization(" << value
<< ");\n";
546 if (var
->getType()->isBuffer() && var
->existPair("rank") && !var
->existPair("trigger_queue")) {
547 string rank
= var
->lookupPair("rank");
548 out
<< " m_" << var
->cIdent() << "_ptr->setPriority(" << rank
<< ");\n";
552 // Network port object
553 string network
= var
->lookupPair("network");
554 string ordered
= var
->lookupPair("ordered");
555 string vnet
= var
->lookupPair("virtual_network");
557 assert (var
->getMachine() != NULL
);
558 out
<< " m_" << var
->cIdent() << "_ptr = m_net_ptr->get"
559 << network
<< "NetQueue(m_version+MachineType_base_number(string_to_MachineType(\""
560 << var
->getMachine()->getIdent() << "\")), "
561 << ordered
<< ", " << vnet
<< ");\n";
562 out
<< " assert(m_" << var
->cIdent() << "_ptr != NULL);" << endl
;
565 if (var
->existPair("ordered")) {
567 string ordered
= var
->lookupPair("ordered");
568 out
<< " m_" << var
->cIdent() << "_ptr->setOrdering(" << ordered
<< ");\n";
572 if (var
->existPair("random")) {
574 string value
= var
->lookupPair("random");
575 out
<< " m_" << var
->cIdent() << "_ptr->setRandomization(" << value
<< ");\n";
579 if (var
->existPair("rank")) {
580 string rank
= var
->lookupPair("rank");
581 out
<< " m_" << var
->cIdent() << "_ptr->setPriority(" << rank
<< ");\n";
585 if (var
->getType()->isBuffer()) {
586 out
<< " if (m_buffer_size > 0) {\n";
587 out
<< " m_" << var
->cIdent() << "_ptr->setSize(m_buffer_size);\n";
591 // set description (may be overriden later by port def)
592 out
<< " m_" << var
->cIdent()
593 << "_ptr->setDescription(\"[Version \" + int_to_string(m_version) + \", "
594 << component
<< ", name=" << var
->cIdent() << "]\");" << endl
;
599 // Set the queue consumers
601 for(int i
=0; i
< m_in_ports
.size(); i
++) {
602 const Var
* port
= m_in_ports
[i
];
603 out
<< " " << port
->getCode() << ".setConsumer(this);" << endl
;
606 // Set the queue descriptions
608 for(int i
=0; i
< m_in_ports
.size(); i
++) {
609 const Var
* port
= m_in_ports
[i
];
610 out
<< " " << port
->getCode()
611 << ".setDescription(\"[Version \" + int_to_string(m_version) + \", "
612 << component
<< ", " << port
->toString() << "]\");" << endl
;
615 // Initialize the transition profiling
617 for(int i
=0; i
<numTransitions(); i
++) {
618 const Transition
& t
= getTransition(i
);
619 const Vector
<Action
*>& action_vec
= t
.getActions();
620 int numActions
= action_vec
.size();
622 // Figure out if we stall
624 for (int i
=0; i
<numActions
; i
++) {
625 if(action_vec
[i
]->getIdent() == "z_stall") {
630 // Only possible if it is not a 'z' case
632 out
<< " s_profiler.possibleTransition(" << component
<< "_State_"
633 << t
.getStatePtr()->getIdent() << ", " << component
<< "_Event_"
634 << t
.getEventPtr()->getIdent() << ");" << endl
;
638 //added by SS to initialize recycle_latency of message buffers
639 std::vector
<std::string
>::const_iterator it
;
640 for ( it
=m_message_buffer_names
.begin() ; it
!= m_message_buffer_names
.end(); it
++ ){
641 out
<< " "<< (*it
).c_str() << "->setRecycleLatency(m_recycle_latency);" << endl
;
649 bool has_mandatory_q
= false;
650 for(int i
=0; i
< m_in_ports
.size(); i
++) {
651 if (m_in_ports
[i
]->getCode().find("mandatoryQueue_ptr")!= string::npos
)
652 has_mandatory_q
= true;
655 out
<< "int " << component
<< "_Controller::getNumControllers() {" << endl
;
656 out
<< " return m_num_controllers;" << endl
;
661 out
<< "MessageBuffer* " << component
<< "_Controller::getMandatoryQueue() const {" << endl
;
663 out
<< " return m_" << component
<< "_mandatoryQueue_ptr;" << endl
;
665 out
<< " return NULL;" << endl
;
670 out
<< "const int & "<<component
<<"_Controller::getVersion() const{" << endl
;
671 out
<< " return m_version;" << endl
;
676 out
<< "const string "<<component
<<"_Controller::toString() const{" << endl
;
677 out
<< " return \"" << component
<< "_Controller\";" << endl
;
682 out
<< "const string "<<component
<<"_Controller::getName() const{" << endl
;
683 out
<< " return m_name;" << endl
;
688 out
<< "const MachineType "<<component
<<"_Controller::getMachineType() const{" << endl
;
689 out
<< " return MachineType_" << component
<< ";" << endl
;
694 out
<< "void " << component
<< "_Controller::print(ostream& out) const { out << \"[" << component
695 << "_Controller \" << m_version << \"]\"; }" << endl
;
697 out
<< "void " << component
<< "_Controller::printConfig(ostream& out) const {" << endl
;
698 out
<< " out << \"" << component
<< "_Controller config: \" << m_name << endl;" << endl
;
699 out
<< " out << \" version: \" << m_version << endl;" << endl
;
700 out
<< " for(map< string, string >::const_iterator it = m_cfg.begin(); it != m_cfg.end(); it++) {" << endl
;
701 out
<< " out << \" \" << (*it).first << \": \" << (*it).second << endl;" << endl
;
706 out
<< "// Actions" << endl
;
709 for(int i
=0; i
< numActions(); i
++) {
710 const Action
& action
= getAction(i
);
711 if (action
.existPair("c_code")) {
712 out
<< "/** \\brief " << action
.getDescription() << "*/" << endl
;
713 out
<< "void " << component
<< "_Controller::"
714 << action
.getIdent() << "(const Address& addr)" << endl
;
716 out
<< " DEBUG_MSG(GENERATED_COMP, HighPrio,\"executing\");" << endl
;
718 //instead of rubyconfig:: --> it should point to m_latency...
719 //so I should change the string output of this lookup
721 string c_code_string
= action
.lookupPair("c_code");
723 size_t found
= c_code_string
.find("RubyConfig::get");
725 if (found
!=string::npos
){ //found --> replace it with local access
726 //if it is related to latency --> replace it
727 std::vector
<std::string
*>::const_iterator it
;
728 for(it
=m_latency_vector
.begin();it
!=m_latency_vector
.end();it
++){
729 string str
= (*it
)->c_str();
731 size_t fd
= c_code_string
.find(str
, found
);
732 if (fd
!=string::npos
&& (fd
== found
+15)){
734 rstr
+= (*it
)->c_str();
735 c_code_string
.replace(found
,15+str
.size()+2,rstr
);
741 out
<< c_code_string
;
749 void StateMachine::printCWakeup(ostream
& out
, string component
)
751 out
<< "// Auto generated C++ code started by "<<__FILE__
<<":"<<__LINE__
<< endl
;
752 out
<< "// " << getIdent() << ": " << getShorthand() << endl
;
754 out
<< "#include \"mem/ruby/common/Global.hh\"" << endl
;
755 out
<< "#include \"mem/ruby/slicc_interface/RubySlicc_includes.hh\"" << endl
;
756 out
<< "#include \"mem/protocol/" << component
<< "_Controller.hh\"" << endl
;
757 out
<< "#include \"mem/protocol/" << component
<< "_State.hh\"" << endl
;
758 out
<< "#include \"mem/protocol/" << component
<< "_Event.hh\"" << endl
;
759 out
<< "#include \"mem/protocol/Types.hh\"" << endl
;
760 out
<< "#include \"mem/ruby/system/System.hh\"" << endl
;
762 if (strncmp(component
.c_str(), "L1Cache", 7) == 0) {
763 out
<< "NodeID servicing_atomic = -1;" << endl
;
765 out
<< "Address locked_read_request = Address(-1);" << endl
;
767 out
<< "NodeID servicing_locked_read = -1;" << endl
;
771 cout
<< component
<< endl
<< flush
;
773 out
<< "void " << component
<< "_Controller::wakeup()" << endl
;
775 // out << " DEBUG_EXPR(GENERATED_COMP, MedPrio,*this);" << endl;
776 // out << " DEBUG_EXPR(GENERATED_COMP, MedPrio,g_eventQueue_ptr->getTime());" << endl;
778 out
<< "int counter = 0;" << endl
;
779 out
<< " while (true) {" << endl
;
780 out
<< " // Some cases will put us into an infinite loop without this limit" << endl
;
781 out
<< " assert(counter <= m_transitions_per_cycle);" << endl
;
782 out
<< " if (counter == m_transitions_per_cycle) {" << endl
;
783 out
<< " g_system_ptr->getProfiler()->controllerBusy(m_machineID); // Count how often we're fully utilized" << endl
;
784 out
<< " g_eventQueue_ptr->scheduleEvent(this, 1); // Wakeup in another cycle and try again" << endl
;
785 out
<< " break;" << endl
;
790 // Find the position of the mandatory queue in the vector so that we can print it out first
792 if (strncmp(component
.c_str(), "L1Cache", 7) == 0) {
793 for(int i
=0; i
< m_in_ports
.size(); i
++) {
794 const Var
* port
= m_in_ports
[i
];
795 assert(port
->existPair("c_code_in_port"));
796 if (port
->toString().find("mandatoryQueue_in") != string::npos
) {
801 cout
<< port
->toString() << endl
<< flush
;
807 // print out the mandatory queue here
808 const Var
* port
= m_in_ports
[j
];
809 assert(port
->existPair("c_code_in_port"));
811 << component
<< "InPort " << port
->toString()
813 string output
= port
->lookupPair("c_code_in_port");
814 string::size_type pos
= output
.find("TransitionResult result = doTransition((L1Cache_mandatory_request_type_to_event(((*in_msg_ptr)).m_Type)), L1Cache_getState(addr), addr);");
815 assert(pos
!= string::npos
);
816 string atomics_string
= "\n \
817 bool postpone = false; \n \
818 if ((((*in_msg_ptr)).m_Type) == CacheRequestType_ATOMIC) { \n \
819 if (servicing_atomic == -1) { \n \
820 if (locked_read_request == Address(-1) && (servicing_locked_read == -1)) { \n \
821 assert(addr != Address(-1)); \n \
822 locked_read_request = addr; \n \
823 servicing_locked_read = m_version; \n \
825 else if ((addr == locked_read_request) && (servicing_locked_read == m_version)) { \n \
826 assert (servicing_atomic == -1); \n \
827 servicing_atomic = m_version; \n \
830 postpone = true; \n \
831 g_eventQueue_ptr->scheduleEvent(this, 1); \n \
835 postpone = true; \n \
836 g_eventQueue_ptr->scheduleEvent(this, 1); \n \
839 if (servicing_atomic == m_version) { \n \
840 servicing_atomic = -1; \n \
841 locked_read_request = Address(-1); \n \
842 servicing_locked_read = -1; \n \
844 if (!postpone) { \n \
849 output
.insert(pos
, atomics_string
);
850 string::size_type next_pos
= output
.find("// Cannot do anything with this transition, go check next doable transition (mostly likely of next port)", pos
);
851 assert(next_pos
!= string::npos
);
852 string complete
= "\n}";
853 output
.insert(next_pos
, complete
);
854 //out << port->lookupPair("c_code_in_port");
858 for(int i
=0; i
< m_in_ports
.size(); i
++) {
859 const Var
* port
= m_in_ports
[i
];
860 // don't print out mandatory queue twice
862 if (strncmp(component
.c_str(), "L1Cache", 7) == 0) {
863 if (port
->toString().find("forwardRequestNetwork_in") != string::npos
) {
864 out
<< "if (servicing_atomic != m_version && servicing_locked_read != m_version) {" << endl
;
866 else if (port
->toString().find("responseNetwork_in") != string::npos
) {
867 out
<< "// NOTE: this will only work if the WB_ACK always comes before issuing a request for which this line was replaced" << endl
;
868 out
<< "if (servicing_atomic == -1 || servicing_atomic == m_version) {" << endl
;
871 assert(port
->existPair("c_code_in_port"));
873 << component
<< "InPort " << port
->toString()
875 out
<< port
->lookupPair("c_code_in_port");
876 if (strncmp(component
.c_str(), "L1Cache", 7) == 0) {
877 if (port
->toString().find("forwardRequestNetwork_in") != string::npos
) {
880 else if (port
->toString().find("responseNetwork_in") != string::npos
) {
888 out
<< " break; // If we got this far, we have nothing left todo" << endl
;
890 // out << " g_eventQueue_ptr->scheduleEvent(this, 1);" << endl;
891 // out << " DEBUG_NEWLINE(GENERATED_COMP, MedPrio);" << endl;
896 void StateMachine::printCSwitch(ostream
& out
, string component
)
898 out
<< "// Auto generated C++ code started by "<<__FILE__
<<":"<<__LINE__
<< endl
;
899 out
<< "// " << getIdent() << ": " << getShorthand() << endl
;
901 out
<< "#include \"mem/ruby/common/Global.hh\"" << endl
;
902 out
<< "#include \"mem/protocol/" << component
<< "_Controller.hh\"" << endl
;
903 out
<< "#include \"mem/protocol/" << component
<< "_State.hh\"" << endl
;
904 out
<< "#include \"mem/protocol/" << component
<< "_Event.hh\"" << endl
;
905 out
<< "#include \"mem/protocol/Types.hh\"" << endl
;
906 out
<< "#include \"mem/ruby/system/System.hh\"" << endl
;
908 out
<< "#define HASH_FUN(state, event) ((int(state)*" << component
909 << "_Event_NUM)+int(event))" << endl
;
911 out
<< "#define GET_TRANSITION_COMMENT() (" << component
<< "_" << "transitionComment.str())" << endl
;
912 out
<< "#define CLEAR_TRANSITION_COMMENT() (" << component
<< "_" << "transitionComment.str(\"\"))" << endl
;
914 out
<< "TransitionResult " << component
<< "_Controller::doTransition("
915 << component
<< "_Event event, "
916 << component
<< "_State state, "
917 << "const Address& addr" << endl
;
918 if(CHECK_INVALID_RESOURCE_STALLS
) {
919 out
<< ", int priority";
924 out
<< " " << component
<< "_State next_state = state;" << endl
;
926 out
<< " DEBUG_NEWLINE(GENERATED_COMP, MedPrio);" << endl
;
927 out
<< " DEBUG_MSG(GENERATED_COMP, MedPrio,*this);" << endl
;
928 out
<< " DEBUG_EXPR(GENERATED_COMP, MedPrio,g_eventQueue_ptr->getTime());" << endl
;
929 out
<< " DEBUG_EXPR(GENERATED_COMP, MedPrio,state);" << endl
;
930 out
<< " DEBUG_EXPR(GENERATED_COMP, MedPrio,event);" << endl
;
931 out
<< " DEBUG_EXPR(GENERATED_COMP, MedPrio,addr);" << endl
;
933 out
<< " TransitionResult result = doTransitionWorker(event, state, next_state, addr";
934 if(CHECK_INVALID_RESOURCE_STALLS
) {
939 out
<< " if (result == TransitionResult_Valid) {" << endl
;
940 out
<< " DEBUG_EXPR(GENERATED_COMP, MedPrio, next_state);" << endl
;
941 out
<< " DEBUG_NEWLINE(GENERATED_COMP, MedPrio);" << endl
;
942 out
<< " s_profiler.countTransition(state, event);" << endl
;
943 out
<< " if (Debug::getProtocolTrace()) {" << endl
944 << " g_system_ptr->getProfiler()->profileTransition(\"" << component
945 << "\", m_version, addr, " << endl
946 << " " << component
<< "_State_to_string(state), " << endl
947 << " " << component
<< "_Event_to_string(event), " << endl
948 << " " << component
<< "_State_to_string(next_state), GET_TRANSITION_COMMENT());" << endl
950 out
<< " CLEAR_TRANSITION_COMMENT();" << endl
;
951 out
<< " " << component
<< "_setState(addr, next_state);" << endl
;
953 out
<< " } else if (result == TransitionResult_ResourceStall) {" << endl
;
954 out
<< " if (Debug::getProtocolTrace()) {" << endl
955 << " g_system_ptr->getProfiler()->profileTransition(\"" << component
956 << "\", m_version, addr, " << endl
957 << " " << component
<< "_State_to_string(state), " << endl
958 << " " << component
<< "_Event_to_string(event), " << endl
959 << " " << component
<< "_State_to_string(next_state), " << endl
960 << " \"Resource Stall\");" << endl
962 out
<< " } else if (result == TransitionResult_ProtocolStall) {" << endl
;
963 out
<< " DEBUG_MSG(GENERATED_COMP,HighPrio,\"stalling\");" << endl
964 << " DEBUG_NEWLINE(GENERATED_COMP, MedPrio);" << endl
;
965 out
<< " if (Debug::getProtocolTrace()) {" << endl
966 << " g_system_ptr->getProfiler()->profileTransition(\"" << component
967 << "\", m_version, addr, " << endl
968 << " " << component
<< "_State_to_string(state), " << endl
969 << " " << component
<< "_Event_to_string(event), " << endl
970 << " " << component
<< "_State_to_string(next_state), " << endl
971 << " \"Protocol Stall\");" << endl
974 out
<< " return result;" << endl
;
977 out
<< "TransitionResult " << component
<< "_Controller::doTransitionWorker("
978 << component
<< "_Event event, "
979 << component
<< "_State state, "
980 << component
<< "_State& next_state, "
981 << "const Address& addr" << endl
;
982 if(CHECK_INVALID_RESOURCE_STALLS
) {
983 out
<< ", int priority" << endl
;
990 out
<< " switch(HASH_FUN(state, event)) {" << endl
;
992 Map
<string
, Vector
<string
> > code_map
; // This map will allow suppress generating duplicate code
993 Vector
<string
> code_vec
;
995 for(int i
=0; i
<numTransitions(); i
++) {
996 const Transition
& t
= getTransition(i
);
997 string case_string
= component
+ "_State_" + t
.getStatePtr()->getIdent()
998 + ", " + component
+ "_Event_" + t
.getEventPtr()->getIdent();
1003 // Only set next_state if it changes
1004 if (t
.getStatePtr() != t
.getNextStatePtr()) {
1005 code
+= " next_state = " + component
+ "_State_" + t
.getNextStatePtr()->getIdent() + ";\n";
1008 const Vector
<Action
*>& action_vec
= t
.getActions();
1009 int numActions
= action_vec
.size();
1011 // Check for resources
1012 Vector
<string
> code_sorter
;
1013 const Map
<Var
*, string
>& res
= t
.getResources();
1014 Vector
<Var
*> res_keys
= res
.keys();
1015 for (int i
=0; i
<res_keys
.size(); i
++) {
1017 if (res_keys
[i
]->getType()->cIdent() == "DNUCAStopTable") {
1018 temp_code
+= res
.lookup(res_keys
[i
]);
1020 temp_code
+= " if (!" + (res_keys
[i
]->getCode()) + ".areNSlotsAvailable(" + res
.lookup(res_keys
[i
]) + ")) {\n";
1021 if(CHECK_INVALID_RESOURCE_STALLS
) {
1022 // assert that the resource stall is for a resource of equal or greater priority
1023 temp_code
+= " assert(priority >= "+ (res_keys
[i
]->getCode()) + ".getPriority());\n";
1025 temp_code
+= " return TransitionResult_ResourceStall;\n";
1026 temp_code
+= " }\n";
1028 code_sorter
.insertAtBottom(temp_code
);
1031 // Emit the code sequences in a sorted order. This makes the
1032 // output deterministic (without this the output order can vary
1033 // since Map's keys() on a vector of pointers is not deterministic
1034 code_sorter
.sortVector();
1035 for (int i
=0; i
<code_sorter
.size(); i
++) {
1036 code
+= code_sorter
[i
];
1039 // Figure out if we stall
1041 for (int i
=0; i
<numActions
; i
++) {
1042 if(action_vec
[i
]->getIdent() == "z_stall") {
1048 code
+= " return TransitionResult_ProtocolStall;\n";
1050 for (int i
=0; i
<numActions
; i
++) {
1051 code
+= " " + action_vec
[i
]->getIdent() + "(addr);\n";
1053 code
+= " return TransitionResult_Valid;\n";
1058 // Look to see if this transition code is unique.
1059 if (code_map
.exist(code
)) {
1060 code_map
.lookup(code
).insertAtBottom(case_string
);
1063 vec
.insertAtBottom(case_string
);
1064 code_map
.add(code
, vec
);
1065 code_vec
.insertAtBottom(code
);
1069 // Walk through all of the unique code blocks and spit out the
1070 // corresponding case statement elements
1071 for (int i
=0; i
<code_vec
.size(); i
++) {
1072 string code
= code_vec
[i
];
1074 // Iterative over all the multiple transitions that share the same code
1075 for (int case_num
=0; case_num
<code_map
.lookup(code
).size(); case_num
++) {
1076 string case_string
= code_map
.lookup(code
)[case_num
];
1077 out
<< " case HASH_FUN(" << case_string
<< "):" << endl
;
1082 out
<< " default:" << endl
;
1083 out
<< " WARN_EXPR(m_version);" << endl
;
1084 out
<< " WARN_EXPR(g_eventQueue_ptr->getTime());" << endl
;
1085 out
<< " WARN_EXPR(addr);" << endl
;
1086 out
<< " WARN_EXPR(event);" << endl
;
1087 out
<< " WARN_EXPR(state);" << endl
;
1088 out
<< " ERROR_MSG(\"Invalid transition\");" << endl
;
1089 out
<< " }" << endl
;
1090 out
<< " return TransitionResult_Valid;" << endl
;
1094 void StateMachine::printProfilerH(ostream
& out
, string component
)
1096 out
<< "// Auto generated C++ code started by "<<__FILE__
<<":"<<__LINE__
<< endl
;
1097 out
<< "// " << getIdent() << ": " << getShorthand() << endl
;
1099 out
<< "#ifndef " << component
<< "_PROFILER_H" << endl
;
1100 out
<< "#define " << component
<< "_PROFILER_H" << endl
;
1102 out
<< "#include \"mem/ruby/common/Global.hh\"" << endl
;
1103 out
<< "#include \"mem/protocol/" << component
<< "_State.hh\"" << endl
;
1104 out
<< "#include \"mem/protocol/" << component
<< "_Event.hh\"" << endl
;
1106 out
<< "class " << component
<< "_Profiler {" << endl
;
1107 out
<< "public:" << endl
;
1108 out
<< " " << component
<< "_Profiler();" << endl
;
1109 out
<< " void countTransition(" << component
<< "_State state, " << component
<< "_Event event);" << endl
;
1110 out
<< " void possibleTransition(" << component
<< "_State state, " << component
<< "_Event event);" << endl
;
1111 out
<< " void dumpStats(ostream& out) const;" << endl
;
1112 out
<< " void clearStats();" << endl
;
1113 out
<< "private:" << endl
;
1114 out
<< " int m_counters[" << component
<< "_State_NUM][" << component
<< "_Event_NUM];" << endl
;
1115 out
<< " int m_event_counters[" << component
<< "_Event_NUM];" << endl
;
1116 out
<< " bool m_possible[" << component
<< "_State_NUM][" << component
<< "_Event_NUM];" << endl
;
1117 out
<< "};" << endl
;
1118 out
<< "#endif // " << component
<< "_PROFILER_H" << endl
;
1121 void StateMachine::printProfilerC(ostream
& out
, string component
)
1123 out
<< "// Auto generated C++ code started by "<<__FILE__
<<":"<<__LINE__
<< endl
;
1124 out
<< "// " << getIdent() << ": " << getShorthand() << endl
;
1126 out
<< "#include \"mem/protocol/" << component
<< "_Profiler.hh\"" << endl
;
1130 out
<< component
<< "_Profiler::" << component
<< "_Profiler()" << endl
;
1132 out
<< " for (int state = 0; state < " << component
<< "_State_NUM; state++) {" << endl
;
1133 out
<< " for (int event = 0; event < " << component
<< "_Event_NUM; event++) {" << endl
;
1134 out
<< " m_possible[state][event] = false;" << endl
;
1135 out
<< " m_counters[state][event] = 0;" << endl
;
1136 out
<< " }" << endl
;
1137 out
<< " }" << endl
;
1138 out
<< " for (int event = 0; event < " << component
<< "_Event_NUM; event++) {" << endl
;
1139 out
<< " m_event_counters[event] = 0;" << endl
;
1140 out
<< " }" << endl
;
1144 out
<< "void " << component
<< "_Profiler::clearStats()" << endl
;
1146 out
<< " for (int state = 0; state < " << component
<< "_State_NUM; state++) {" << endl
;
1147 out
<< " for (int event = 0; event < " << component
<< "_Event_NUM; event++) {" << endl
;
1148 out
<< " m_counters[state][event] = 0;" << endl
;
1149 out
<< " }" << endl
;
1150 out
<< " }" << endl
;
1151 out
<< " for (int event = 0; event < " << component
<< "_Event_NUM; event++) {" << endl
;
1152 out
<< " m_event_counters[event] = 0;" << endl
;
1153 out
<< " }" << endl
;
1157 out
<< "void " << component
<< "_Profiler::countTransition(" << component
<< "_State state, " << component
<< "_Event event)" << endl
;
1159 out
<< " assert(m_possible[state][event]);" << endl
;
1160 out
<< " m_counters[state][event]++;" << endl
;
1161 out
<< " m_event_counters[event]++;" << endl
;
1164 // Possible Transition
1165 out
<< "void " << component
<< "_Profiler::possibleTransition(" << component
<< "_State state, " << component
<< "_Event event)" << endl
;
1167 out
<< " m_possible[state][event] = true;" << endl
;
1171 out
<< "void " << component
<< "_Profiler::dumpStats(ostream& out) const" << endl
;
1173 out
<< " out << \" --- " << component
<< " ---\" << endl;" << endl
;
1174 out
<< " out << \" - Event Counts -\" << endl;" << endl
;
1175 out
<< " for (int event = 0; event < " << component
<< "_Event_NUM; event++) {" << endl
;
1176 out
<< " int count = m_event_counters[event];" << endl
;
1177 out
<< " out << (" << component
<< "_Event) event << \" \" << count << endl;" << endl
;
1178 out
<< " }" << endl
;
1179 out
<< " out << endl;" << endl
;
1180 out
<< " out << \" - Transitions -\" << endl;" << endl
;
1181 out
<< " for (int state = 0; state < " << component
<< "_State_NUM; state++) {" << endl
;
1182 out
<< " for (int event = 0; event < " << component
<< "_Event_NUM; event++) {" << endl
;
1183 out
<< " if (m_possible[state][event]) {" << endl
;
1184 out
<< " int count = m_counters[state][event];" << endl
;
1185 out
<< " out << (" << component
<< "_State) state << \" \" << (" << component
<< "_Event) event << \" \" << count;" << endl
;
1186 out
<< " if (count == 0) {" << endl
;
1187 out
<< " out << \" <-- \";" << endl
;
1188 out
<< " }" << endl
;
1189 out
<< " out << endl;" << endl
;
1190 out
<< " }" << endl
;
1191 out
<< " }" << endl
;
1192 out
<< " out << endl;" << endl
;
1193 out
<< " }" << endl
;
1199 // ************************** //
1200 // ******* HTML Files ******* //
1201 // ************************** //
1203 string
frameRef(string click_href
, string click_target
, string over_href
, string over_target_num
, string text
)
1206 temp
+= "<A href=\"" + click_href
+ "\" ";
1207 temp
+= "target=\"" + click_target
+ "\" ";
1208 string javascript
= "if (parent.frames[" + over_target_num
+ "].location != parent.location + '" + over_href
+ "') { parent.frames[" + over_target_num
+ "].location='" + over_href
+ "' }";
1209 // string javascript = "parent." + target + ".location='" + href + "'";
1210 temp
+= "onMouseOver=\"" + javascript
+ "\" ";
1211 temp
+= ">" + text
+ "</A>";
1215 string
frameRef(string href
, string target
, string target_num
, string text
)
1217 return frameRef(href
, target
, href
, target_num
, text
);
1221 void StateMachine::writeHTMLFiles(string path
)
1224 string component
= getIdent();
1229 out << "<html>" << endl;
1230 out << "<head>" << endl;
1231 out << "<title>" << component << "</title>" << endl;
1232 out << "</head>" << endl;
1233 out << "<frameset rows=\"30,30,*\" frameborder=\"1\">" << endl;
1234 out << " <frame name=\"Status\" src=\"empty.html\" marginheight=\"1\">" << endl;
1235 out << " <frame name=\"Table\" src=\"" << component << "_table.html\" marginheight=\"1\">" << endl;
1236 out << "</frameset>" << endl;
1237 out << "</html>" << endl;
1238 conditionally_write_file(path + component + ".html", out);
1242 // Create table with no row hilighted
1245 printHTMLTransitions(out
, numStates()+1);
1248 filename
= component
+ "_table.html";
1249 conditionally_write_file(path
+ filename
, out
);
1252 // Generate transition tables
1253 for(int i
=0; i
<numStates(); i
++) {
1255 printHTMLTransitions(out
, i
);
1258 filename
= component
+ "_table_" + getState(i
).getIdent() + ".html";
1259 conditionally_write_file(path
+ filename
, out
);
1262 // Generate action descriptions
1263 for(int i
=0; i
<numActions(); i
++) {
1265 createHTMLSymbol(getAction(i
), "Action", out
);
1268 filename
= component
+ "_action_" + getAction(i
).getIdent() + ".html";
1269 conditionally_write_file(path
+ filename
, out
);
1272 // Generate state descriptions
1273 for(int i
=0; i
<numStates(); i
++) {
1275 createHTMLSymbol(getState(i
), "State", out
);
1278 filename
= component
+ "_State_" + getState(i
).getIdent() + ".html";
1279 conditionally_write_file(path
+ filename
, out
);
1282 // Generate event descriptions
1283 for(int i
=0; i
<numEvents(); i
++) {
1285 createHTMLSymbol(getEvent(i
), "Event", out
);
1288 filename
= component
+ "_Event_" + getEvent(i
).getIdent() + ".html";
1289 conditionally_write_file(path
+ filename
, out
);
1293 void StateMachine::printHTMLTransitions(ostream
& out
, int active_state
)
1296 out
<< "<HTML><BODY link=\"blue\" vlink=\"blue\">" << endl
;
1299 out
<< "<H1 align=\"center\">" << formatHTMLShorthand(getShorthand()) << ": " << endl
;
1300 Vector
<StateMachine
*> machine_vec
= g_sym_table
.getStateMachines();
1301 for (int i
=0; i
<machine_vec
.size(); i
++) {
1302 StateMachine
* type
= machine_vec
[i
];
1307 out
<< type
->getIdent() << endl
;
1309 out
<< "<A target=\"Table\"href=\"" + type
->getIdent() + "_table.html\">" + type
->getIdent() + "</A> " << endl
;
1312 out
<< "</H1>" << endl
;
1315 out
<< "<TABLE border=1>" << endl
;
1317 // -- Column headers
1318 out
<< "<TR>" << endl
;
1320 // -- First column header
1321 out
<< " <TH> </TH>" << endl
;
1323 for(int event
= 0; event
< numEvents(); event
++ ) {
1324 out
<< " <TH bgcolor=white>";
1325 out
<< frameRef(getIdent() + "_Event_" + getEvent(event
).getIdent() + ".html", "Status", "1", formatHTMLShorthand(getEvent(event
).getShorthand()));
1326 out
<< "</TH>" << endl
;
1329 out
<< "</TR>" << endl
;
1332 for(int state
= 0; state
< numStates(); state
++ ) {
1333 out
<< "<TR>" << endl
;
1336 if (state
== active_state
) {
1337 out
<< " <TH bgcolor=yellow>";
1339 out
<< " <TH bgcolor=white>";
1342 string click_href
= getIdent() + "_table_" + getState(state
).getIdent() + ".html";
1343 string text
= formatHTMLShorthand(getState(state
).getShorthand());
1345 out
<< frameRef(click_href
, "Table", getIdent() + "_State_" + getState(state
).getIdent() + ".html", "1", formatHTMLShorthand(getState(state
).getShorthand()));
1346 out
<< "</TH>" << endl
;
1348 // -- One column for each event
1349 for(int event
= 0; event
< numEvents(); event
++ ) {
1350 const Transition
* trans_ptr
= getTransPtr(state
, event
);
1352 if( trans_ptr
!= NULL
) {
1353 bool stall_action
= false;
1357 // -- Get the actions
1358 // actions = trans_ptr->getActionShorthands();
1359 const Vector
<Action
*> actions
= trans_ptr
->getActions();
1360 for (int action
=0; action
< actions
.size(); action
++) {
1361 if ((actions
[action
]->getIdent() == "z_stall") ||
1362 (actions
[action
]->getIdent() == "zz_recycleMandatoryQueue")) {
1363 stall_action
= true;
1366 actions_str
+= frameRef(getIdent() + "_action_" + actions
[action
]->getIdent() + ".html", "Status", "1",
1367 formatHTMLShorthand(actions
[action
]->getShorthand()));
1368 actions_str
+= "\n";
1371 // -- Get the next state
1372 if (trans_ptr
->getNextStatePtr()->getIdent() != getState(state
).getIdent()) {
1373 string click_href
= getIdent() + "_table_" + trans_ptr
->getNextStatePtr()->getIdent() + ".html";
1374 nextState
= frameRef(click_href
, "Table", getIdent() + "_State_" + trans_ptr
->getNextStatePtr()->getIdent() + ".html", "1",
1375 formatHTMLShorthand(trans_ptr
->getNextStateShorthand()));
1380 // -- Print out "actions/next-state"
1382 if (state
== active_state
) {
1383 out
<< " <TD bgcolor=#C0C000>";
1385 out
<< " <TD bgcolor=lightgrey>";
1387 } else if (active_state
< numStates() && (trans_ptr
->getNextStatePtr()->getIdent() == getState(active_state
).getIdent())) {
1388 out
<< " <TD bgcolor=aqua>";
1389 } else if (state
== active_state
) {
1390 out
<< " <TD bgcolor=yellow>";
1392 out
<< " <TD bgcolor=white>";
1396 if ((nextState
.length() != 0) && (actions_str
.length() != 0)) {
1400 out
<< "</TD>" << endl
;
1402 // This is the no transition case
1403 if (state
== active_state
) {
1404 out
<< " <TD bgcolor=#C0C000> </TD>" << endl
;
1406 out
<< " <TD bgcolor=lightgrey> </TD>" << endl
;
1411 if (state
== active_state
) {
1412 out
<< " <TH bgcolor=yellow>";
1414 out
<< " <TH bgcolor=white>";
1417 click_href
= getIdent() + "_table_" + getState(state
).getIdent() + ".html";
1418 text
= formatHTMLShorthand(getState(state
).getShorthand());
1420 out
<< frameRef(click_href
, "Table", getIdent() + "_State_" + getState(state
).getIdent() + ".html", "1", formatHTMLShorthand(getState(state
).getShorthand()));
1421 out
<< "</TH>" << endl
;
1423 out
<< "</TR>" << endl
;
1427 out
<< "<TR>" << endl
;
1428 out
<< " <TH> </TH>" << endl
;
1430 for(int i
= 0; i
< numEvents(); i
++ ) {
1431 out
<< " <TH bgcolor=white>";
1432 out
<< frameRef(getIdent() + "_Event_" + getEvent(i
).getIdent() + ".html", "Status", "1", formatHTMLShorthand(getEvent(i
).getShorthand()));
1433 out
<< "</TH>" << endl
;
1435 out
<< "</TR>" << endl
;
1438 out
<< "</TABLE>" << endl
;
1439 out
<< "</BODY></HTML>" << endl
;