Added atomics implementation which would work for MI_example
[gem5.git] / src / mem / slicc / symbols / StateMachine.cc
1
2 /*
3 * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
4 * All rights reserved.
5 *
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.
16 *
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.
28 */
29
30 /*
31 * $Id$
32 *
33 * */
34
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"
46
47 #include <set>
48
49 StateMachine::StateMachine(string ident, const Location& location, const Map<string, string>& pairs, std::vector<std::string*>* latency_vector)
50 : Symbol(ident, location, pairs)
51 {
52 m_table_built = false;
53 m_latency_vector = *latency_vector;
54 }
55
56 StateMachine::~StateMachine()
57 {
58 // FIXME
59 // assert(0);
60 }
61
62 void StateMachine::addState(State* state_ptr)
63 {
64 assert(m_table_built == false);
65 m_state_map.add(state_ptr, m_states.size());
66 m_states.insertAtBottom(state_ptr);
67 }
68
69 void StateMachine::addEvent(Event* event_ptr)
70 {
71 assert(m_table_built == false);
72 m_event_map.add(event_ptr, m_events.size());
73 m_events.insertAtBottom(event_ptr);
74 }
75
76 void StateMachine::addAction(Action* action_ptr)
77 {
78 assert(m_table_built == false);
79
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());
86 }
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());
92 }
93 }
94
95 m_actions.insertAtBottom(action_ptr);
96 }
97
98 void StateMachine::addTransition(Transition* trans_ptr)
99 {
100 assert(m_table_built == false);
101 trans_ptr->checkIdents(m_states, m_events, m_actions);
102 m_transitions.insertAtBottom(trans_ptr);
103 }
104
105 void StateMachine::addFunc(Func* func_ptr)
106 {
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);
110 }
111
112 void StateMachine::buildTable()
113 {
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;
119
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);
124 }
125 }
126
127 for(int i=0; i<numTransitions; i++) {
128 Transition* trans_ptr = m_transitions[i];
129
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,
133 // etc.
134
135 Vector<Action*> actions = trans_ptr->getActions();
136 for(int actionIndex=0; actionIndex < actions.size(); actionIndex++) {
137 actions[actionIndex]->markUsed();
138 }
139
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());
145 }
146 m_table[stateIndex][eventIndex] = trans_ptr;
147 }
148
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();
156 }
157 action_ptr->warning(error_msg);
158 }
159 }
160
161 m_table_built = true;
162 }
163
164 const Transition* StateMachine::getTransPtr(int stateIndex, int eventIndex) const
165 {
166 return m_table[stateIndex][eventIndex];
167 }
168
169 // *********************** //
170 // ******* C Files ******* //
171 // *********************** //
172
173 void StateMachine::writeCFiles(string path)
174 {
175 string comp = getIdent();
176 string filename;
177
178 // Output the method declarations for the class declaration
179 {
180 ostringstream sstr;
181 printControllerH(sstr, comp);
182 conditionally_write_file(path + comp + "_Controller.hh", sstr);
183 }
184
185 // Output switch statement for transition table
186 {
187 ostringstream sstr;
188 printCSwitch(sstr, comp);
189 conditionally_write_file(path + comp + "_Transitions.cc", sstr);
190 }
191
192 // Output the actions for performing the actions
193 {
194 ostringstream sstr;
195 printControllerC(sstr, comp);
196 conditionally_write_file(path + comp + "_Controller.cc", sstr);
197 }
198
199 // Output the wakeup loop for the events
200 {
201 ostringstream sstr;
202 printCWakeup(sstr, comp);
203 conditionally_write_file(path + comp + "_Wakeup.cc", sstr);
204 }
205
206 // Profiling
207 {
208 ostringstream sstr;
209 printProfilerC(sstr, comp);
210 conditionally_write_file(path + comp + "_Profiler.cc", sstr);
211 }
212 {
213 ostringstream sstr;
214 printProfilerH(sstr, comp);
215 conditionally_write_file(path + comp + "_Profiler.hh", sstr);
216 }
217
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);
221 }
222
223 }
224
225 void StateMachine::printControllerH(ostream& out, string component)
226 {
227
228 m_message_buffer_names.clear();
229
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;
235 out << endl;
236 out << "#ifndef " << component << "_CONTROLLER_H" << endl;
237 out << "#define " << component << "_CONTROLLER_H" << endl;
238 out << 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;
245
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());
254 }
255 }
256
257 out << endl;
258
259 // for adding information to the protocol debug trace
260 out << "extern stringstream " << component << "_" << "transitionComment;" << endl;
261
262 out << "class " << component << "_Controller : public AbstractController {" << endl;
263
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;
268
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;
285
286 //added by SS
287 // found_to_mem = 0;
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;
291 }
292 out << " int m_number_of_TBEs;" << endl;
293
294 out << " TransitionResult doTransition(" << component << "_Event event, " << component
295 << "_State state, const Address& addr";
296 if(CHECK_INVALID_RESOURCE_STALLS) {
297 out << ", int priority";
298 }
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";
304 }
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;
316
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];
321 string proto;
322 func->funcPrototype(proto);
323 if (proto != "") {
324 out << " " << proto;
325 }
326 }
327
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;
333 }
334
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");
342 }
343 out << " " << var->getType()->cIdent() << template_hack << "* m_"
344 << var->cIdent() << "_ptr;" << endl;
345
346 string str = "m_"+ var->cIdent() + "_ptr";
347 if (var->getType()->cIdent() == "MessageBuffer")
348 m_message_buffer_names.push_back(str);
349
350 }
351
352
353 out << "};" << endl;
354 out << "#endif // " << component << "_CONTROLLER_H" << endl;
355 }
356
357 void StateMachine::printControllerC(ostream& out, string component)
358 {
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;
364 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;
372
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());
380 }
381
382 }
383
384 out << endl;
385
386 out << "int " << component << "_Controller::m_num_controllers = 0;" << endl;
387
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;
391
392 out << "/** \\brief static profiler defn */" << endl;
393 out << component << "_Profiler " << component << "_Controller::s_profiler;" << endl;
394 out << endl;
395
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;
401 out << "{ " << 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;
407 }
408 out << "}" << endl << endl;
409
410 out << "void " << component << "_Controller::init(Network * net_ptr, const vector<string> & argv)" << endl;
411 out << "{" << 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;
414
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;
421 //added by SS
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;
428
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();
434 str.erase(0,8);
435 //convert to lowercase
436 size_t i;
437 char* strc = (char*) malloc (str.length()+1);
438 strc[str.length()]=0;
439 for(i=0; i < str.length(); i++) {
440 strc[i] = str.at(i);
441 strc[i] = tolower(strc[i]);
442 }
443 str = strc;
444 delete strc;
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;
448 else
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;
451 out << " }" << endl;
452 }
453 out << " }" << endl;
454 }
455 out << " }" << endl;
456
457 out << " m_net_ptr = net_ptr;" << endl;
458 out << " m_machineID.type = MachineType_" << component << ";" << endl;
459 out << " m_machineID.num = m_version;" << endl;
460
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;
463
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;
468 out << " }" << endl;
469
470 out << endl;
471
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";
482 }
483 out << " }\n";
484
485 } else {
486 // Normal Object
487 string template_hack = "";
488 if (var->existPair("template_hack")) {
489 template_hack = var->lookupPair("template_hack");
490 }
491 //added by SS
492 string str = "";
493 int found = 0;
494 if (var->existPair("factory")) {
495 out << " m_" << var->cIdent() << "_ptr = " << var->lookupPair("factory");
496 } else {
497 if ( var->cIdent().find("mandatoryQueue") == string::npos) {
498
499 str = " m_" + var->cIdent() + "_ptr = new " + var->getType()->cIdent() + template_hack;
500 out << str;
501 if (str.find("TBETable")!=string::npos){
502 found = 1;
503 }
504
505 if (!var->getType()->existPair("non_obj") && (!var->getType()->isEnumeration())) {
506 str = "";
507 if (var->existPair("constructor_hack")) {
508 string constructor_hack = var->lookupPair("constructor_hack");
509 str = "(" + constructor_hack + ")";
510 } else {
511 str = "()";
512 }
513 if (found)
514 str = "(m_number_of_TBEs)";
515 out << str;
516 }
517 }
518 }
519
520 out << ";\n";
521 out << " assert(m_" << var->cIdent() << "_ptr != NULL);" << endl;
522
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;
529 }
530
531 // Set ordering
532 if (var->existPair("ordered") && !var->existPair("trigger_queue")) {
533 // A buffer
534 string ordered = var->lookupPair("ordered");
535 out << " m_" << var->cIdent() << "_ptr->setOrdering(" << ordered << ");\n";
536 }
537
538 // Set randomization
539 if (var->existPair("random")) {
540 // A buffer
541 string value = var->lookupPair("random");
542 out << " m_" << var->cIdent() << "_ptr->setRandomization(" << value << ");\n";
543 }
544
545 // Set Priority
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";
549 }
550 }
551 } else {
552 // Network port object
553 string network = var->lookupPair("network");
554 string ordered = var->lookupPair("ordered");
555 string vnet = var->lookupPair("virtual_network");
556
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;
563
564 // Set ordering
565 if (var->existPair("ordered")) {
566 // A buffer
567 string ordered = var->lookupPair("ordered");
568 out << " m_" << var->cIdent() << "_ptr->setOrdering(" << ordered << ");\n";
569 }
570
571 // Set randomization
572 if (var->existPair("random")) {
573 // A buffer
574 string value = var->lookupPair("random");
575 out << " m_" << var->cIdent() << "_ptr->setRandomization(" << value << ");\n";
576 }
577
578 // Set Priority
579 if (var->existPair("rank")) {
580 string rank = var->lookupPair("rank");
581 out << " m_" << var->cIdent() << "_ptr->setPriority(" << rank << ");\n";
582 }
583
584 // Set buffer size
585 if (var->getType()->isBuffer()) {
586 out << " if (m_buffer_size > 0) {\n";
587 out << " m_" << var->cIdent() << "_ptr->setSize(m_buffer_size);\n";
588 out << " }\n";
589 }
590
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;
595 out << endl;
596 }
597 }
598
599 // Set the queue consumers
600 out << endl;
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;
604 }
605
606 // Set the queue descriptions
607 out << endl;
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;
613 }
614
615 // Initialize the transition profiling
616 out << endl;
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();
621
622 // Figure out if we stall
623 bool stall = false;
624 for (int i=0; i<numActions; i++) {
625 if(action_vec[i]->getIdent() == "z_stall") {
626 stall = true;
627 }
628 }
629
630 // Only possible if it is not a 'z' case
631 if (!stall) {
632 out << " s_profiler.possibleTransition(" << component << "_State_"
633 << t.getStatePtr()->getIdent() << ", " << component << "_Event_"
634 << t.getEventPtr()->getIdent() << ");" << endl;
635 }
636 }
637
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;
642 }
643
644
645 out << "}" << endl;
646
647 out << endl;
648
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;
653 }
654
655 out << "int " << component << "_Controller::getNumControllers() {" << endl;
656 out << " return m_num_controllers;" << endl;
657 out << "}" << endl;
658
659 out << endl;
660
661 out << "MessageBuffer* " << component << "_Controller::getMandatoryQueue() const {" << endl;
662 if (has_mandatory_q)
663 out << " return m_" << component << "_mandatoryQueue_ptr;" << endl;
664 else
665 out << " return NULL;" << endl;
666 out << "}" << endl;
667
668 out << endl;
669
670 out << "const int & "<<component<<"_Controller::getVersion() const{" << endl;
671 out << " return m_version;" << endl;
672 out << "}";
673
674 out << endl;
675
676 out << "const string "<<component<<"_Controller::toString() const{" << endl;
677 out << " return \"" << component<< "_Controller\";" << endl;
678 out << "}";
679
680 out << endl;
681
682 out << "const string "<<component<<"_Controller::getName() const{" << endl;
683 out << " return m_name;" << endl;
684 out << "}";
685
686 out << endl;
687
688 out << "const MachineType "<<component<<"_Controller::getMachineType() const{" << endl;
689 out << " return MachineType_" << component<< ";" << endl;
690 out << "}";
691
692 out << endl;
693
694 out << "void " << component << "_Controller::print(ostream& out) const { out << \"[" << component
695 << "_Controller \" << m_version << \"]\"; }" << endl;
696
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;
702 out << " }" << endl;
703 out << "}" << endl;
704
705 out << endl;
706 out << "// Actions" << endl;
707 out << endl;
708
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;
715 out << "{" << endl;
716 out << " DEBUG_MSG(GENERATED_COMP, HighPrio,\"executing\");" << endl;
717 //added by SS
718 //instead of rubyconfig:: --> it should point to m_latency...
719 //so I should change the string output of this lookup
720
721 string c_code_string = action.lookupPair("c_code");
722
723 size_t found = c_code_string.find("RubyConfig::get");
724
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();
730 str.erase(0,8);
731 size_t fd = c_code_string.find(str, found);
732 if (fd!=string::npos && (fd == found+15)){
733 string rstr = "m_";
734 rstr += (*it)->c_str();
735 c_code_string.replace(found,15+str.size()+2,rstr);
736 break;
737 }
738 }
739 }
740
741 out << c_code_string;
742
743 out << "}" << endl;
744 }
745 out << endl;
746 }
747 }
748
749 void StateMachine::printCWakeup(ostream& out, string component)
750 {
751 out << "// Auto generated C++ code started by "<<__FILE__<<":"<<__LINE__<< endl;
752 out << "// " << getIdent() << ": " << getShorthand() << endl;
753 out << 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;
761 out << endl;
762 if (strncmp(component.c_str(), "L1Cache", 7) == 0) {
763 out << "NodeID servicing_atomic = -1;" << endl;
764 out << endl;
765 out << "Address locked_read_request = Address(-1);" << endl;
766 out << endl;
767 out << "NodeID servicing_locked_read = -1;" << endl;
768 out << endl;
769 }
770 else {
771 cout << component << endl << flush;
772 }
773 out << "void " << component << "_Controller::wakeup()" << endl;
774 out << "{" << endl;
775 // out << " DEBUG_EXPR(GENERATED_COMP, MedPrio,*this);" << endl;
776 // out << " DEBUG_EXPR(GENERATED_COMP, MedPrio,g_eventQueue_ptr->getTime());" << endl;
777 out << 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;
786 out << " }" << endl;
787
788 // InPorts
789 //
790 // Find the position of the mandatory queue in the vector so that we can print it out first
791 int j = -1;
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) {
797 assert (j == -1);
798 j = i;
799 }
800 else {
801 cout << port->toString() << endl << flush;
802 }
803 }
804
805 assert(j != -1);
806
807 // print out the mandatory queue here
808 const Var* port = m_in_ports[j];
809 assert(port->existPair("c_code_in_port"));
810 out << " // "
811 << component << "InPort " << port->toString()
812 << endl;
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 \
824 } \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 \
828 } \n \
829 else { \n \
830 postpone = true; \n \
831 g_eventQueue_ptr->scheduleEvent(this, 1); \n \
832 } \n \
833 } \n \
834 else { \n \
835 postpone = true; \n \
836 g_eventQueue_ptr->scheduleEvent(this, 1); \n \
837 } \n \
838 } \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 \
843 } \n \
844 if (!postpone) { \n \
845 ";
846
847
848
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");
855 out << output;
856 out << endl;
857 }
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
861 if (i != j) {
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;
865 }
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;
869 }
870 }
871 assert(port->existPair("c_code_in_port"));
872 out << " // "
873 << component << "InPort " << port->toString()
874 << endl;
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) {
878 out << "}" << endl;
879 }
880 else if (port->toString().find("responseNetwork_in") != string::npos) {
881 out << "}" << endl;
882 }
883 }
884 out << endl;
885 }
886 }
887
888 out << " break; // If we got this far, we have nothing left todo" << endl;
889 out << " }" << endl;
890 // out << " g_eventQueue_ptr->scheduleEvent(this, 1);" << endl;
891 // out << " DEBUG_NEWLINE(GENERATED_COMP, MedPrio);" << endl;
892 out << "}" << endl;
893 out << endl;
894 }
895
896 void StateMachine::printCSwitch(ostream& out, string component)
897 {
898 out << "// Auto generated C++ code started by "<<__FILE__<<":"<<__LINE__<< endl;
899 out << "// " << getIdent() << ": " << getShorthand() << endl;
900 out << 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;
907 out << endl;
908 out << "#define HASH_FUN(state, event) ((int(state)*" << component
909 << "_Event_NUM)+int(event))" << endl;
910 out << endl;
911 out << "#define GET_TRANSITION_COMMENT() (" << component << "_" << "transitionComment.str())" << endl;
912 out << "#define CLEAR_TRANSITION_COMMENT() (" << component << "_" << "transitionComment.str(\"\"))" << endl;
913 out << 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";
920 }
921 out << ")" << endl;
922
923 out << "{" << endl;
924 out << " " << component << "_State next_state = state;" << endl;
925 out << 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;
932 out << endl;
933 out << " TransitionResult result = doTransitionWorker(event, state, next_state, addr";
934 if(CHECK_INVALID_RESOURCE_STALLS) {
935 out << ", priority";
936 }
937 out << ");" << endl;
938 out << endl;
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
949 << " }" << endl;
950 out << " CLEAR_TRANSITION_COMMENT();" << endl;
951 out << " " << component << "_setState(addr, next_state);" << endl;
952 out << " " << 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
961 << " }" << 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
972 << " }" << endl
973 << " }" << endl;
974 out << " return result;" << endl;
975 out << "}" << endl;
976 out << 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;
984 }
985 out << ")" << endl;
986
987 out << "{" << endl;
988 out << "" << endl;
989
990 out << " switch(HASH_FUN(state, event)) {" << endl;
991
992 Map<string, Vector<string> > code_map; // This map will allow suppress generating duplicate code
993 Vector<string> code_vec;
994
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();
999
1000 string code;
1001
1002 code += " {\n";
1003 // Only set next_state if it changes
1004 if (t.getStatePtr() != t.getNextStatePtr()) {
1005 code += " next_state = " + component + "_State_" + t.getNextStatePtr()->getIdent() + ";\n";
1006 }
1007
1008 const Vector<Action*>& action_vec = t.getActions();
1009 int numActions = action_vec.size();
1010
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++) {
1016 string temp_code;
1017 if (res_keys[i]->getType()->cIdent() == "DNUCAStopTable") {
1018 temp_code += res.lookup(res_keys[i]);
1019 } else {
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";
1024 }
1025 temp_code += " return TransitionResult_ResourceStall;\n";
1026 temp_code += " }\n";
1027 }
1028 code_sorter.insertAtBottom(temp_code);
1029 }
1030
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];
1037 }
1038
1039 // Figure out if we stall
1040 bool stall = false;
1041 for (int i=0; i<numActions; i++) {
1042 if(action_vec[i]->getIdent() == "z_stall") {
1043 stall = true;
1044 }
1045 }
1046
1047 if (stall) {
1048 code += " return TransitionResult_ProtocolStall;\n";
1049 } else {
1050 for (int i=0; i<numActions; i++) {
1051 code += " " + action_vec[i]->getIdent() + "(addr);\n";
1052 }
1053 code += " return TransitionResult_Valid;\n";
1054 }
1055 code += " }\n";
1056
1057
1058 // Look to see if this transition code is unique.
1059 if (code_map.exist(code)) {
1060 code_map.lookup(code).insertAtBottom(case_string);
1061 } else {
1062 Vector<string> vec;
1063 vec.insertAtBottom(case_string);
1064 code_map.add(code, vec);
1065 code_vec.insertAtBottom(code);
1066 }
1067 }
1068
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];
1073
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;
1078 }
1079 out << code;
1080 }
1081
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;
1091 out << "}" << endl;
1092 }
1093
1094 void StateMachine::printProfilerH(ostream& out, string component)
1095 {
1096 out << "// Auto generated C++ code started by "<<__FILE__<<":"<<__LINE__<< endl;
1097 out << "// " << getIdent() << ": " << getShorthand() << endl;
1098 out << endl;
1099 out << "#ifndef " << component << "_PROFILER_H" << endl;
1100 out << "#define " << component << "_PROFILER_H" << endl;
1101 out << 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;
1105 out << 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;
1119 }
1120
1121 void StateMachine::printProfilerC(ostream& out, string component)
1122 {
1123 out << "// Auto generated C++ code started by "<<__FILE__<<":"<<__LINE__<< endl;
1124 out << "// " << getIdent() << ": " << getShorthand() << endl;
1125 out << endl;
1126 out << "#include \"mem/protocol/" << component << "_Profiler.hh\"" << endl;
1127 out << endl;
1128
1129 // Constructor
1130 out << component << "_Profiler::" << component << "_Profiler()" << endl;
1131 out << "{" << 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;
1141 out << "}" << endl;
1142
1143 // Clearstats
1144 out << "void " << component << "_Profiler::clearStats()" << endl;
1145 out << "{" << 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;
1154 out << "}" << endl;
1155
1156 // Count Transition
1157 out << "void " << component << "_Profiler::countTransition(" << component << "_State state, " << component << "_Event event)" << endl;
1158 out << "{" << endl;
1159 out << " assert(m_possible[state][event]);" << endl;
1160 out << " m_counters[state][event]++;" << endl;
1161 out << " m_event_counters[event]++;" << endl;
1162 out << "}" << endl;
1163
1164 // Possible Transition
1165 out << "void " << component << "_Profiler::possibleTransition(" << component << "_State state, " << component << "_Event event)" << endl;
1166 out << "{" << endl;
1167 out << " m_possible[state][event] = true;" << endl;
1168 out << "}" << endl;
1169
1170 // dumpStats
1171 out << "void " << component << "_Profiler::dumpStats(ostream& out) const" << endl;
1172 out << "{" << 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;
1194 out << "}" << endl;
1195 }
1196
1197
1198
1199 // ************************** //
1200 // ******* HTML Files ******* //
1201 // ************************** //
1202
1203 string frameRef(string click_href, string click_target, string over_href, string over_target_num, string text)
1204 {
1205 string temp;
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>";
1212 return temp;
1213 }
1214
1215 string frameRef(string href, string target, string target_num, string text)
1216 {
1217 return frameRef(href, target, href, target_num, text);
1218 }
1219
1220
1221 void StateMachine::writeHTMLFiles(string path)
1222 {
1223 string filename;
1224 string component = getIdent();
1225
1226 /*
1227 {
1228 ostringstream out;
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);
1239 }
1240 */
1241
1242 // Create table with no row hilighted
1243 {
1244 ostringstream out;
1245 printHTMLTransitions(out, numStates()+1);
1246
1247 // -- Write file
1248 filename = component + "_table.html";
1249 conditionally_write_file(path + filename, out);
1250 }
1251
1252 // Generate transition tables
1253 for(int i=0; i<numStates(); i++) {
1254 ostringstream out;
1255 printHTMLTransitions(out, i);
1256
1257 // -- Write file
1258 filename = component + "_table_" + getState(i).getIdent() + ".html";
1259 conditionally_write_file(path + filename, out);
1260 }
1261
1262 // Generate action descriptions
1263 for(int i=0; i<numActions(); i++) {
1264 ostringstream out;
1265 createHTMLSymbol(getAction(i), "Action", out);
1266
1267 // -- Write file
1268 filename = component + "_action_" + getAction(i).getIdent() + ".html";
1269 conditionally_write_file(path + filename, out);
1270 }
1271
1272 // Generate state descriptions
1273 for(int i=0; i<numStates(); i++) {
1274 ostringstream out;
1275 createHTMLSymbol(getState(i), "State", out);
1276
1277 // -- Write file
1278 filename = component + "_State_" + getState(i).getIdent() + ".html";
1279 conditionally_write_file(path + filename, out);
1280 }
1281
1282 // Generate event descriptions
1283 for(int i=0; i<numEvents(); i++) {
1284 ostringstream out;
1285 createHTMLSymbol(getEvent(i), "Event", out);
1286
1287 // -- Write file
1288 filename = component + "_Event_" + getEvent(i).getIdent() + ".html";
1289 conditionally_write_file(path + filename, out);
1290 }
1291 }
1292
1293 void StateMachine::printHTMLTransitions(ostream& out, int active_state)
1294 {
1295 // -- Prolog
1296 out << "<HTML><BODY link=\"blue\" vlink=\"blue\">" << endl;
1297
1298 // -- Header
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];
1303 if (i != 0) {
1304 out << " - ";
1305 }
1306 if (type == this) {
1307 out << type->getIdent() << endl;
1308 } else {
1309 out << "<A target=\"Table\"href=\"" + type->getIdent() + "_table.html\">" + type->getIdent() + "</A> " << endl;
1310 }
1311 }
1312 out << "</H1>" << endl;
1313
1314 // -- Table header
1315 out << "<TABLE border=1>" << endl;
1316
1317 // -- Column headers
1318 out << "<TR>" << endl;
1319
1320 // -- First column header
1321 out << " <TH> </TH>" << endl;
1322
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;
1327 }
1328
1329 out << "</TR>" << endl;
1330
1331 // -- Body of table
1332 for(int state = 0; state < numStates(); state++ ) {
1333 out << "<TR>" << endl;
1334
1335 // -- Each row
1336 if (state == active_state) {
1337 out << " <TH bgcolor=yellow>";
1338 } else {
1339 out << " <TH bgcolor=white>";
1340 }
1341
1342 string click_href = getIdent() + "_table_" + getState(state).getIdent() + ".html";
1343 string text = formatHTMLShorthand(getState(state).getShorthand());
1344
1345 out << frameRef(click_href, "Table", getIdent() + "_State_" + getState(state).getIdent() + ".html", "1", formatHTMLShorthand(getState(state).getShorthand()));
1346 out << "</TH>" << endl;
1347
1348 // -- One column for each event
1349 for(int event = 0; event < numEvents(); event++ ) {
1350 const Transition* trans_ptr = getTransPtr(state, event);
1351
1352 if( trans_ptr != NULL ) {
1353 bool stall_action = false;
1354 string nextState;
1355 string actions_str;
1356
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;
1364 }
1365 actions_str += " ";
1366 actions_str += frameRef(getIdent() + "_action_" + actions[action]->getIdent() + ".html", "Status", "1",
1367 formatHTMLShorthand(actions[action]->getShorthand()));
1368 actions_str += "\n";
1369 }
1370
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()));
1376 } else {
1377 nextState = "";
1378 }
1379
1380 // -- Print out "actions/next-state"
1381 if (stall_action) {
1382 if (state == active_state) {
1383 out << " <TD bgcolor=#C0C000>";
1384 } else {
1385 out << " <TD bgcolor=lightgrey>";
1386 }
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>";
1391 } else {
1392 out << " <TD bgcolor=white>";
1393 }
1394
1395 out << actions_str;
1396 if ((nextState.length() != 0) && (actions_str.length() != 0)) {
1397 out << "/";
1398 }
1399 out << nextState;
1400 out << "</TD>" << endl;
1401 } else {
1402 // This is the no transition case
1403 if (state == active_state) {
1404 out << " <TD bgcolor=#C0C000>&nbsp;</TD>" << endl;
1405 } else {
1406 out << " <TD bgcolor=lightgrey>&nbsp;</TD>" << endl;
1407 }
1408 }
1409 }
1410 // -- Each row
1411 if (state == active_state) {
1412 out << " <TH bgcolor=yellow>";
1413 } else {
1414 out << " <TH bgcolor=white>";
1415 }
1416
1417 click_href = getIdent() + "_table_" + getState(state).getIdent() + ".html";
1418 text = formatHTMLShorthand(getState(state).getShorthand());
1419
1420 out << frameRef(click_href, "Table", getIdent() + "_State_" + getState(state).getIdent() + ".html", "1", formatHTMLShorthand(getState(state).getShorthand()));
1421 out << "</TH>" << endl;
1422
1423 out << "</TR>" << endl;
1424 }
1425
1426 // -- Column footer
1427 out << "<TR>" << endl;
1428 out << " <TH> </TH>" << endl;
1429
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;
1434 }
1435 out << "</TR>" << endl;
1436
1437 // -- Epilog
1438 out << "</TABLE>" << endl;
1439 out << "</BODY></HTML>" << endl;
1440 }
1441
1442