1/* 2 * Copyright (c) 2000-2005 The Regents of The University of Michigan 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer; 9 * redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution; 12 * neither the name of the copyright holders nor the names of its 13 * contributors may be used to endorse or promote products derived from 14 * this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * 28 * Authors: Steve Raasch 29 * Nathan Binkert 30 * Steve Reinhardt 31 */ 32 33/// 34/// @file sim/main.cc 35/// 36#include <Python.h> // must be before system headers... see Python docs 37 38#include <sys/types.h> 39#include <sys/stat.h> 40#include <errno.h> 41#include <libgen.h> 42#include <stdlib.h> 43#include <signal.h> 44#include <getopt.h> 45 46#include <list> 47#include <string> 48#include <vector> 49 50#include "base/callback.hh" 51#include "base/inifile.hh" 52#include "base/misc.hh" 53#include "base/output.hh" 54#include "base/pollevent.hh" 55#include "base/statistics.hh" 56#include "base/str.hh" 57#include "base/time.hh" 58#include "cpu/base.hh" 59#include "cpu/smt.hh" 60#include "mem/mem_object.hh" 61#include "mem/port.hh" 62#include "sim/async.hh" 63#include "sim/builder.hh" 64#include "sim/host.hh" 65#include "sim/serialize.hh" 66#include "sim/sim_events.hh" 67#include "sim/sim_exit.hh" 68#include "sim/sim_object.hh" 69#include "sim/stat_control.hh" 70#include "sim/stats.hh" 71#include "sim/root.hh" 72 73using namespace std; 74 75// See async.h. 76volatile bool async_event = false; 77volatile bool async_dump = false; 78volatile bool async_dumpreset = false; 79volatile bool async_exit = false; 80volatile bool async_io = false; 81volatile bool async_alarm = false; 82 83/// Stats signal handler. 84void 85dumpStatsHandler(int sigtype) 86{ 87 async_event = true; 88 async_dump = true; 89} 90 91void 92dumprstStatsHandler(int sigtype) 93{ 94 async_event = true; 95 async_dumpreset = true; 96} 97 98/// Exit signal handler. 99void 100exitNowHandler(int sigtype) 101{ 102 async_event = true; 103 async_exit = true; 104} 105 106/// Abort signal handler. 107void 108abortHandler(int sigtype) 109{ 110 cerr << "Program aborted at cycle " << curTick << endl; 111 112#if TRACING_ON 113 // dump trace buffer, if there is one 114 Trace::theLog.dump(cerr); 115#endif 116} 117
| 1/* 2 * Copyright (c) 2000-2005 The Regents of The University of Michigan 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer; 9 * redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution; 12 * neither the name of the copyright holders nor the names of its 13 * contributors may be used to endorse or promote products derived from 14 * this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * 28 * Authors: Steve Raasch 29 * Nathan Binkert 30 * Steve Reinhardt 31 */ 32 33/// 34/// @file sim/main.cc 35/// 36#include <Python.h> // must be before system headers... see Python docs 37 38#include <sys/types.h> 39#include <sys/stat.h> 40#include <errno.h> 41#include <libgen.h> 42#include <stdlib.h> 43#include <signal.h> 44#include <getopt.h> 45 46#include <list> 47#include <string> 48#include <vector> 49 50#include "base/callback.hh" 51#include "base/inifile.hh" 52#include "base/misc.hh" 53#include "base/output.hh" 54#include "base/pollevent.hh" 55#include "base/statistics.hh" 56#include "base/str.hh" 57#include "base/time.hh" 58#include "cpu/base.hh" 59#include "cpu/smt.hh" 60#include "mem/mem_object.hh" 61#include "mem/port.hh" 62#include "sim/async.hh" 63#include "sim/builder.hh" 64#include "sim/host.hh" 65#include "sim/serialize.hh" 66#include "sim/sim_events.hh" 67#include "sim/sim_exit.hh" 68#include "sim/sim_object.hh" 69#include "sim/stat_control.hh" 70#include "sim/stats.hh" 71#include "sim/root.hh" 72 73using namespace std; 74 75// See async.h. 76volatile bool async_event = false; 77volatile bool async_dump = false; 78volatile bool async_dumpreset = false; 79volatile bool async_exit = false; 80volatile bool async_io = false; 81volatile bool async_alarm = false; 82 83/// Stats signal handler. 84void 85dumpStatsHandler(int sigtype) 86{ 87 async_event = true; 88 async_dump = true; 89} 90 91void 92dumprstStatsHandler(int sigtype) 93{ 94 async_event = true; 95 async_dumpreset = true; 96} 97 98/// Exit signal handler. 99void 100exitNowHandler(int sigtype) 101{ 102 async_event = true; 103 async_exit = true; 104} 105 106/// Abort signal handler. 107void 108abortHandler(int sigtype) 109{ 110 cerr << "Program aborted at cycle " << curTick << endl; 111 112#if TRACING_ON 113 // dump trace buffer, if there is one 114 Trace::theLog.dump(cerr); 115#endif 116} 117
|
118/// Simulator executable name 119char *myProgName = ""; 120 121/// Show brief help message. 122void 123showBriefHelp(ostream &out) 124{ 125 char *prog = basename(myProgName); 126 127 ccprintf(out, "Usage:\n"); 128 ccprintf(out, 129"%s [-p <path>] [-i ] [-h] <config file>\n" 130"\n" 131" -p, --path <path> prepends <path> to PYTHONPATH instead of using\n" 132" built-in zip archive. Useful when developing/debugging\n" 133" changes to built-in Python libraries, as the new Python\n" 134" can be tested without building a new m5 binary.\n\n" 135" -i, --interactive forces entry into interactive mode after the supplied\n" 136" script is executed (just like the -i option to the\n" 137" Python interpreter).\n\n" 138" -h Prints this help\n\n" 139" <configfile> config file name which ends in .py. (Normally you can\n" 140" run <configfile> --help to get help on that config files\n" 141" parameters.\n\n", 142 prog); 143 144} 145 146const char *briefCopyright = 147"Copyright (c) 2001-2006\n" 148"The Regents of The University of Michigan\n" 149"All Rights Reserved\n"; 150 151/// Print welcome message. 152void 153sayHello(ostream &out) 154{ 155 extern const char *compileDate; // from date.cc 156 157 ccprintf(out, "M5 Simulator System\n"); 158 // display copyright 159 ccprintf(out, "%s\n", briefCopyright); 160 ccprintf(out, "M5 compiled %d\n", compileDate); 161 ccprintf(out, "M5 started %s\n", Time::start); 162 163 char *host = getenv("HOSTNAME"); 164 if (!host) 165 host = getenv("HOST"); 166 167 if (host) 168 ccprintf(out, "M5 executing on %s\n", host); 169} 170 171
| |
172extern "C" { void init_cc_main(); } 173 174int 175main(int argc, char **argv) 176{
| 118extern "C" { void init_cc_main(); } 119 120int 121main(int argc, char **argv) 122{
|
177 // Saze off program name 178 myProgName = argv[0]; 179 180 sayHello(cerr); 181
| |
182 signal(SIGFPE, SIG_IGN); // may occur on misspeculated paths 183 signal(SIGTRAP, SIG_IGN); 184 signal(SIGUSR1, dumpStatsHandler); // dump intermediate stats 185 signal(SIGUSR2, dumprstStatsHandler); // dump and reset stats 186 signal(SIGINT, exitNowHandler); // dump final stats and exit 187 signal(SIGABRT, abortHandler); 188 189 Py_SetProgramName(argv[0]); 190 191 // default path to m5 python code is the currently executing
| 123 signal(SIGFPE, SIG_IGN); // may occur on misspeculated paths 124 signal(SIGTRAP, SIG_IGN); 125 signal(SIGUSR1, dumpStatsHandler); // dump intermediate stats 126 signal(SIGUSR2, dumprstStatsHandler); // dump and reset stats 127 signal(SIGINT, exitNowHandler); // dump final stats and exit 128 signal(SIGABRT, abortHandler); 129 130 Py_SetProgramName(argv[0]); 131 132 // default path to m5 python code is the currently executing
|
192 // file... Python ZipImporter will find embedded zip archive 193 char *pythonpath = argv[0];
| 133 // file... Python ZipImporter will find embedded zip archive. 134 // The M5_ARCHIVE environment variable can be used to override this. 135 char *m5_archive = getenv("M5_ARCHIVE"); 136 string pythonpath = m5_archive ? m5_archive : argv[0];
|
194
| 137
|
195 bool interactive = false; 196 bool show_help = false; 197 bool getopt_done = false; 198 int opt_index = 0; 199 200 static struct option long_options[] = { 201 {"python", 1, 0, 'p'}, 202 {"interactive", 0, 0, 'i'}, 203 {"help", 0, 0, 'h'}, 204 {0,0,0,0} 205 }; 206 207 do { 208 switch (getopt_long(argc, argv, "+p:ih", long_options, &opt_index)) { 209 // -p <path> prepends <path> to PYTHONPATH instead of 210 // using built-in zip archive. Useful when 211 // developing/debugging changes to built-in Python 212 // libraries, as the new Python can be tested without 213 // building a new m5 binary. 214 case 'p': 215 pythonpath = optarg; 216 break; 217 218 // -i forces entry into interactive mode after the 219 // supplied script is executed (just like the -i option to 220 // the Python interpreter). 221 case 'i': 222 interactive = true; 223 break; 224 225 case 'h': 226 show_help = true; 227 break; 228 case -1: 229 getopt_done = true; 230 break; 231 232 default: 233 fatal("Unrecognized option %c\n", optopt); 234 } 235 } while (!getopt_done); 236 237 if (show_help) { 238 showBriefHelp(cerr); 239 exit(1); 240 } 241 242 // Fix up argc & argv to hide arguments we just processed. 243 // getopt() sets optind to the index of the first non-processed 244 // argv element. 245 argc -= optind; 246 argv += optind; 247 248 // Set up PYTHONPATH to make sure the m5 module is found 249 string newpath(pythonpath); 250
| |
251 char *oldpath = getenv("PYTHONPATH"); 252 if (oldpath != NULL) {
| 138 char *oldpath = getenv("PYTHONPATH"); 139 if (oldpath != NULL) {
|
253 newpath += ":"; 254 newpath += oldpath;
| 140 pythonpath += ":"; 141 pythonpath += oldpath;
|
255 } 256
| 142 } 143
|
257 if (setenv("PYTHONPATH", newpath.c_str(), true) == -1)
| 144 if (setenv("PYTHONPATH", pythonpath.c_str(), true) == -1)
|
258 fatal("setenv: %s\n", strerror(errno)); 259 260 // initialize embedded Python interpreter 261 Py_Initialize(); 262 PySys_SetArgv(argc, argv); 263 264 // initialize SWIG 'cc_main' module 265 init_cc_main(); 266
| 145 fatal("setenv: %s\n", strerror(errno)); 146 147 // initialize embedded Python interpreter 148 Py_Initialize(); 149 PySys_SetArgv(argc, argv); 150 151 // initialize SWIG 'cc_main' module 152 init_cc_main(); 153
|
267 if (argc > 0) { 268 // extra arg(s): first is script file, remaining ones are args 269 // to script file 270 char *filename = argv[0]; 271 FILE *fp = fopen(filename, "r"); 272 if (!fp) { 273 fatal("cannot open file '%s'\n", filename); 274 }
| 154 PyRun_SimpleString("import m5"); 155 PyRun_SimpleString("m5.main()");
|
275
| 156
|
276 PyRun_AnyFile(fp, filename); 277 } else { 278 // no script file argument... force interactive prompt 279 interactive = true; 280 } 281 282 if (interactive) { 283 // The following code to import readline was copied from Python 284 // 2.4.3's Modules/main.c. 285 // Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006 286 // Python Software Foundation; All Rights Reserved 287 // We should only enable this if we're actually using an 288 // interactive prompt. 289 PyObject *v; 290 v = PyImport_ImportModule("readline"); 291 if (v == NULL) 292 PyErr_Clear(); 293 else 294 Py_DECREF(v); 295 296 PyRun_InteractiveLoop(stdin, "stdin"); 297 } 298
| |
299 // clean up Python intepreter. 300 Py_Finalize(); 301} 302 303 304void 305setOutputDir(const string &dir) 306{ 307 simout.setDirectory(dir); 308} 309 310 311IniFile inifile; 312 313SimObject * 314createSimObject(const string &name) 315{ 316 return SimObjectClass::createObject(inifile, name); 317} 318 319 320/** 321 * Pointer to the Python function that maps names to SimObjects. 322 */ 323PyObject *resolveFunc = NULL; 324 325/** 326 * Convert a pointer to the Python object that SWIG wraps around a C++ 327 * SimObject pointer back to the actual C++ pointer. See main.i. 328 */ 329extern "C" SimObject *convertSwigSimObjectPtr(PyObject *); 330 331 332SimObject * 333resolveSimObject(const string &name) 334{ 335 PyObject *pyPtr = PyEval_CallFunction(resolveFunc, "(s)", name.c_str()); 336 if (pyPtr == NULL) { 337 PyErr_Print(); 338 panic("resolveSimObject: failure on call to Python for %s", name); 339 } 340 341 SimObject *simObj = convertSwigSimObjectPtr(pyPtr); 342 if (simObj == NULL) 343 panic("resolveSimObject: failure on pointer conversion for %s", name); 344 345 return simObj; 346} 347 348 349/** 350 * Load config.ini into C++ database. Exported to Python via SWIG; 351 * invoked from m5.instantiate(). 352 */ 353void 354loadIniFile(PyObject *_resolveFunc) 355{ 356 resolveFunc = _resolveFunc; 357 configStream = simout.find("config.out"); 358 359 // The configuration database is now complete; start processing it. 360 inifile.load("config.ini"); 361 362 // Initialize statistics database 363 Stats::InitSimStats(); 364} 365 366 367/** 368 * Look up a MemObject port. Helper function for connectPorts(). 369 */ 370Port * 371lookupPort(SimObject *so, const std::string &name, int i) 372{ 373 MemObject *mo = dynamic_cast<MemObject *>(so); 374 if (mo == NULL) { 375 warn("error casting SimObject %s to MemObject", so->name()); 376 return NULL; 377 } 378 379 Port *p = mo->getPort(name, i); 380 if (p == NULL) 381 warn("error looking up port %s on object %s", name, so->name()); 382 return p; 383} 384 385 386/** 387 * Connect the described MemObject ports. Called from Python via SWIG. 388 */ 389int 390connectPorts(SimObject *o1, const std::string &name1, int i1, 391 SimObject *o2, const std::string &name2, int i2) 392{ 393 Port *p1 = lookupPort(o1, name1, i1); 394 Port *p2 = lookupPort(o2, name2, i2); 395 396 if (p1 == NULL || p2 == NULL) { 397 warn("connectPorts: port lookup error"); 398 return 0; 399 } 400 401 p1->setPeer(p2); 402 p2->setPeer(p1); 403 404 return 1; 405} 406 407/** 408 * Do final initialization steps after object construction but before 409 * start of simulation. 410 */ 411void 412finalInit() 413{ 414 // Parse and check all non-config-hierarchy parameters. 415 ParamContext::parseAllContexts(inifile); 416 ParamContext::checkAllContexts(); 417 418 // Echo all parameter settings to stats file as well. 419 ParamContext::showAllContexts(*configStream); 420 421 // Do a second pass to finish initializing the sim objects 422 SimObject::initAll(); 423 424 // Restore checkpointed state, if any. 425#if 0 426 configHierarchy.unserializeSimObjects(); 427#endif 428 429 SimObject::regAllStats(); 430 431 // Check to make sure that the stats package is properly initialized 432 Stats::check(); 433 434 // Reset to put the stats in a consistent state. 435 Stats::reset(); 436 437 SimStartup(); 438} 439 440 441/** Simulate for num_cycles additional cycles. If num_cycles is -1 442 * (the default), do not limit simulation; some other event must 443 * terminate the loop. Exported to Python via SWIG. 444 * @return The SimLoopExitEvent that caused the loop to exit. 445 */ 446SimLoopExitEvent * 447simulate(Tick num_cycles = -1) 448{ 449 warn("Entering event queue @ %d. Starting simulation...\n", curTick); 450 451 // Fix up num_cycles. Special default value -1 means simulate 452 // "forever"... schedule event at MaxTick just to be safe. 453 // Otherwise it's a delta for additional cycles to simulate past 454 // curTick, and thus must be non-negative. 455 if (num_cycles == -1) 456 num_cycles = MaxTick; 457 else if (num_cycles < 0) 458 fatal("simulate: num_cycles must be >= 0 (was %d)\n", num_cycles); 459 else 460 num_cycles = curTick + num_cycles; 461 462 Event *limit_event = new SimLoopExitEvent(num_cycles, 463 "simulate() limit reached"); 464 465 while (1) { 466 // there should always be at least one event (the SimLoopExitEvent 467 // we just scheduled) in the queue 468 assert(!mainEventQueue.empty()); 469 assert(curTick <= mainEventQueue.nextTick() && 470 "event scheduled in the past"); 471 472 // forward current cycle to the time of the first event on the 473 // queue 474 curTick = mainEventQueue.nextTick(); 475 Event *exit_event = mainEventQueue.serviceOne(); 476 if (exit_event != NULL) { 477 // hit some kind of exit event; return to Python 478 // event must be subclass of SimLoopExitEvent... 479 SimLoopExitEvent *se_event = dynamic_cast<SimLoopExitEvent *>(exit_event); 480 if (se_event == NULL) 481 panic("Bogus exit event class!"); 482 483 // if we didn't hit limit_event, delete it 484 if (se_event != limit_event) { 485 assert(limit_event->scheduled()); 486 limit_event->deschedule(); 487 delete limit_event; 488 } 489 490 return se_event; 491 } 492 493 if (async_event) { 494 async_event = false; 495 if (async_dump) { 496 async_dump = false; 497 498 using namespace Stats; 499 SetupEvent(Dump, curTick); 500 } 501 502 if (async_dumpreset) { 503 async_dumpreset = false; 504 505 using namespace Stats; 506 SetupEvent(Dump | Reset, curTick); 507 } 508 509 if (async_exit) { 510 async_exit = false; 511 exitSimLoop("user interrupt received"); 512 } 513 514 if (async_io || async_alarm) { 515 async_io = false; 516 async_alarm = false; 517 pollQueue.service(); 518 } 519 } 520 } 521 522 // not reached... only exit is return on SimLoopExitEvent 523} 524 525Event * 526createCountedDrain() 527{ 528 return new CountedDrainEvent(); 529} 530 531void 532cleanupCountedDrain(Event *counted_drain) 533{ 534 CountedDrainEvent *event = 535 dynamic_cast<CountedDrainEvent *>(counted_drain); 536 if (event == NULL) { 537 fatal("Called cleanupCountedDrain() on an event that was not " 538 "a CountedDrainEvent."); 539 } 540 assert(event->getCount() == 0); 541 delete event; 542} 543 544void 545serializeAll(const std::string &cpt_dir) 546{ 547 Serializable::serializeAll(cpt_dir); 548} 549 550void 551unserializeAll(const std::string &cpt_dir) 552{ 553 Serializable::unserializeAll(cpt_dir); 554} 555 556/** 557 * Queue of C++ callbacks to invoke on simulator exit. 558 */ 559CallbackQueue exitCallbacks; 560 561/** 562 * Register an exit callback. 563 */ 564void 565registerExitCallback(Callback *callback) 566{ 567 exitCallbacks.add(callback); 568} 569 570BaseCPU * 571convertToBaseCPUPtr(SimObject *obj) 572{ 573 BaseCPU *ptr = dynamic_cast<BaseCPU *>(obj); 574 575 if (ptr == NULL) 576 warn("Casting to BaseCPU pointer failed"); 577 return ptr; 578} 579 580/** 581 * Do C++ simulator exit processing. Exported to SWIG to be invoked 582 * when simulator terminates via Python's atexit mechanism. 583 */ 584void 585doExitCleanup() 586{ 587 exitCallbacks.process(); 588 exitCallbacks.clear(); 589 590 cout.flush(); 591 592 ParamContext::cleanupAllContexts(); 593 594 // print simulation stats 595 Stats::DumpNow(); 596}
| 157 // clean up Python intepreter. 158 Py_Finalize(); 159} 160 161 162void 163setOutputDir(const string &dir) 164{ 165 simout.setDirectory(dir); 166} 167 168 169IniFile inifile; 170 171SimObject * 172createSimObject(const string &name) 173{ 174 return SimObjectClass::createObject(inifile, name); 175} 176 177 178/** 179 * Pointer to the Python function that maps names to SimObjects. 180 */ 181PyObject *resolveFunc = NULL; 182 183/** 184 * Convert a pointer to the Python object that SWIG wraps around a C++ 185 * SimObject pointer back to the actual C++ pointer. See main.i. 186 */ 187extern "C" SimObject *convertSwigSimObjectPtr(PyObject *); 188 189 190SimObject * 191resolveSimObject(const string &name) 192{ 193 PyObject *pyPtr = PyEval_CallFunction(resolveFunc, "(s)", name.c_str()); 194 if (pyPtr == NULL) { 195 PyErr_Print(); 196 panic("resolveSimObject: failure on call to Python for %s", name); 197 } 198 199 SimObject *simObj = convertSwigSimObjectPtr(pyPtr); 200 if (simObj == NULL) 201 panic("resolveSimObject: failure on pointer conversion for %s", name); 202 203 return simObj; 204} 205 206 207/** 208 * Load config.ini into C++ database. Exported to Python via SWIG; 209 * invoked from m5.instantiate(). 210 */ 211void 212loadIniFile(PyObject *_resolveFunc) 213{ 214 resolveFunc = _resolveFunc; 215 configStream = simout.find("config.out"); 216 217 // The configuration database is now complete; start processing it. 218 inifile.load("config.ini"); 219 220 // Initialize statistics database 221 Stats::InitSimStats(); 222} 223 224 225/** 226 * Look up a MemObject port. Helper function for connectPorts(). 227 */ 228Port * 229lookupPort(SimObject *so, const std::string &name, int i) 230{ 231 MemObject *mo = dynamic_cast<MemObject *>(so); 232 if (mo == NULL) { 233 warn("error casting SimObject %s to MemObject", so->name()); 234 return NULL; 235 } 236 237 Port *p = mo->getPort(name, i); 238 if (p == NULL) 239 warn("error looking up port %s on object %s", name, so->name()); 240 return p; 241} 242 243 244/** 245 * Connect the described MemObject ports. Called from Python via SWIG. 246 */ 247int 248connectPorts(SimObject *o1, const std::string &name1, int i1, 249 SimObject *o2, const std::string &name2, int i2) 250{ 251 Port *p1 = lookupPort(o1, name1, i1); 252 Port *p2 = lookupPort(o2, name2, i2); 253 254 if (p1 == NULL || p2 == NULL) { 255 warn("connectPorts: port lookup error"); 256 return 0; 257 } 258 259 p1->setPeer(p2); 260 p2->setPeer(p1); 261 262 return 1; 263} 264 265/** 266 * Do final initialization steps after object construction but before 267 * start of simulation. 268 */ 269void 270finalInit() 271{ 272 // Parse and check all non-config-hierarchy parameters. 273 ParamContext::parseAllContexts(inifile); 274 ParamContext::checkAllContexts(); 275 276 // Echo all parameter settings to stats file as well. 277 ParamContext::showAllContexts(*configStream); 278 279 // Do a second pass to finish initializing the sim objects 280 SimObject::initAll(); 281 282 // Restore checkpointed state, if any. 283#if 0 284 configHierarchy.unserializeSimObjects(); 285#endif 286 287 SimObject::regAllStats(); 288 289 // Check to make sure that the stats package is properly initialized 290 Stats::check(); 291 292 // Reset to put the stats in a consistent state. 293 Stats::reset(); 294 295 SimStartup(); 296} 297 298 299/** Simulate for num_cycles additional cycles. If num_cycles is -1 300 * (the default), do not limit simulation; some other event must 301 * terminate the loop. Exported to Python via SWIG. 302 * @return The SimLoopExitEvent that caused the loop to exit. 303 */ 304SimLoopExitEvent * 305simulate(Tick num_cycles = -1) 306{ 307 warn("Entering event queue @ %d. Starting simulation...\n", curTick); 308 309 // Fix up num_cycles. Special default value -1 means simulate 310 // "forever"... schedule event at MaxTick just to be safe. 311 // Otherwise it's a delta for additional cycles to simulate past 312 // curTick, and thus must be non-negative. 313 if (num_cycles == -1) 314 num_cycles = MaxTick; 315 else if (num_cycles < 0) 316 fatal("simulate: num_cycles must be >= 0 (was %d)\n", num_cycles); 317 else 318 num_cycles = curTick + num_cycles; 319 320 Event *limit_event = new SimLoopExitEvent(num_cycles, 321 "simulate() limit reached"); 322 323 while (1) { 324 // there should always be at least one event (the SimLoopExitEvent 325 // we just scheduled) in the queue 326 assert(!mainEventQueue.empty()); 327 assert(curTick <= mainEventQueue.nextTick() && 328 "event scheduled in the past"); 329 330 // forward current cycle to the time of the first event on the 331 // queue 332 curTick = mainEventQueue.nextTick(); 333 Event *exit_event = mainEventQueue.serviceOne(); 334 if (exit_event != NULL) { 335 // hit some kind of exit event; return to Python 336 // event must be subclass of SimLoopExitEvent... 337 SimLoopExitEvent *se_event = dynamic_cast<SimLoopExitEvent *>(exit_event); 338 if (se_event == NULL) 339 panic("Bogus exit event class!"); 340 341 // if we didn't hit limit_event, delete it 342 if (se_event != limit_event) { 343 assert(limit_event->scheduled()); 344 limit_event->deschedule(); 345 delete limit_event; 346 } 347 348 return se_event; 349 } 350 351 if (async_event) { 352 async_event = false; 353 if (async_dump) { 354 async_dump = false; 355 356 using namespace Stats; 357 SetupEvent(Dump, curTick); 358 } 359 360 if (async_dumpreset) { 361 async_dumpreset = false; 362 363 using namespace Stats; 364 SetupEvent(Dump | Reset, curTick); 365 } 366 367 if (async_exit) { 368 async_exit = false; 369 exitSimLoop("user interrupt received"); 370 } 371 372 if (async_io || async_alarm) { 373 async_io = false; 374 async_alarm = false; 375 pollQueue.service(); 376 } 377 } 378 } 379 380 // not reached... only exit is return on SimLoopExitEvent 381} 382 383Event * 384createCountedDrain() 385{ 386 return new CountedDrainEvent(); 387} 388 389void 390cleanupCountedDrain(Event *counted_drain) 391{ 392 CountedDrainEvent *event = 393 dynamic_cast<CountedDrainEvent *>(counted_drain); 394 if (event == NULL) { 395 fatal("Called cleanupCountedDrain() on an event that was not " 396 "a CountedDrainEvent."); 397 } 398 assert(event->getCount() == 0); 399 delete event; 400} 401 402void 403serializeAll(const std::string &cpt_dir) 404{ 405 Serializable::serializeAll(cpt_dir); 406} 407 408void 409unserializeAll(const std::string &cpt_dir) 410{ 411 Serializable::unserializeAll(cpt_dir); 412} 413 414/** 415 * Queue of C++ callbacks to invoke on simulator exit. 416 */ 417CallbackQueue exitCallbacks; 418 419/** 420 * Register an exit callback. 421 */ 422void 423registerExitCallback(Callback *callback) 424{ 425 exitCallbacks.add(callback); 426} 427 428BaseCPU * 429convertToBaseCPUPtr(SimObject *obj) 430{ 431 BaseCPU *ptr = dynamic_cast<BaseCPU *>(obj); 432 433 if (ptr == NULL) 434 warn("Casting to BaseCPU pointer failed"); 435 return ptr; 436} 437 438/** 439 * Do C++ simulator exit processing. Exported to SWIG to be invoked 440 * when simulator terminates via Python's atexit mechanism. 441 */ 442void 443doExitCleanup() 444{ 445 exitCallbacks.process(); 446 exitCallbacks.clear(); 447 448 cout.flush(); 449 450 ParamContext::cleanupAllContexts(); 451 452 // print simulation stats 453 Stats::DumpNow(); 454}
|