main.cc (2665:a124942bacb8) | main.cc (2667:fe64b8353b1c) |
---|---|
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; --- 27 unchanged lines hidden (view full) --- 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> | 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; --- 27 unchanged lines hidden (view full) --- 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 <unistd.h> |
|
44 45#include <list> 46#include <string> 47#include <vector> 48 | 45 46#include <list> 47#include <string> 48#include <vector> 49 |
50#include "base/callback.hh" |
|
49#include "base/inifile.hh" 50#include "base/misc.hh" 51#include "base/output.hh" 52#include "base/pollevent.hh" 53#include "base/statistics.hh" 54#include "base/str.hh" 55#include "base/time.hh" 56#include "cpu/base.hh" --- 49 unchanged lines hidden (view full) --- 106 cerr << "Program aborted at cycle " << curTick << endl; 107 108#if TRACING_ON 109 // dump trace buffer, if there is one 110 Trace::theLog.dump(cerr); 111#endif 112} 113 | 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" --- 49 unchanged lines hidden (view full) --- 108 cerr << "Program aborted at cycle " << curTick << endl; 109 110#if TRACING_ON 111 // dump trace buffer, if there is one 112 Trace::theLog.dump(cerr); 113#endif 114} 115 |
114/// Simulator executable name 115char *myProgName = ""; | |
116 | 116 |
117/// 118/// Echo the command line for posterity in such a way that it can be 119/// used to rerun the same simulation (given the same .ini files). 120/// | 117const char *briefCopyright = 118"Copyright (c) 2001-2006\n" 119"The Regents of The University of Michigan\n" 120"All Rights Reserved\n"; 121 122/// Print welcome message. |
121void | 123void |
122echoCommandLine(int argc, char **argv, ostream &out) | 124sayHello(ostream &out) |
123{ | 125{ |
124 out << "command line: " << argv[0]; 125 for (int i = 1; i < argc; i++) { 126 string arg(argv[i]); | 126 extern const char *compileDate; // from date.cc |
127 | 127 |
128 out << ' '; | 128 ccprintf(out, "M5 Simulator System\n"); 129 // display copyright 130 ccprintf(out, "%s\n", briefCopyright); 131 ccprintf(out, "M5 compiled %d\n", compileDate); 132 ccprintf(out, "M5 started %s\n", Time::start); |
129 | 133 |
130 // If the arg contains spaces, we need to quote it. 131 // The rest of this is overkill to make it look purty. | 134 char *host = getenv("HOSTNAME"); 135 if (!host) 136 host = getenv("HOST"); |
132 | 137 |
133 // print dashes first outside quotes 134 int non_dash_pos = arg.find_first_not_of("-"); 135 out << arg.substr(0, non_dash_pos); // print dashes 136 string body = arg.substr(non_dash_pos); // the rest | 138 if (host) 139 ccprintf(out, "M5 executing on %s\n", host); 140} |
137 | 141 |
138 // if it's an assignment, handle the lhs & rhs separately 139 int eq_pos = body.find("="); 140 if (eq_pos == string::npos) { 141 out << quote(body); 142 } 143 else { 144 string lhs(body.substr(0, eq_pos)); 145 string rhs(body.substr(eq_pos + 1)); | |
146 | 142 |
147 out << quote(lhs) << "=" << quote(rhs); 148 } 149 } 150 out << endl << endl; 151} | 143extern "C" { void init_main(); } |
152 153int 154main(int argc, char **argv) 155{ | 144 145int 146main(int argc, char **argv) 147{ |
156 // Save off program name 157 myProgName = argv[0]; | 148 sayHello(cerr); |
158 159 signal(SIGFPE, SIG_IGN); // may occur on misspeculated paths 160 signal(SIGTRAP, SIG_IGN); 161 signal(SIGUSR1, dumpStatsHandler); // dump intermediate stats 162 signal(SIGUSR2, dumprstStatsHandler); // dump and reset stats 163 signal(SIGINT, exitNowHandler); // dump final stats and exit 164 signal(SIGABRT, abortHandler); 165 | 149 150 signal(SIGFPE, SIG_IGN); // may occur on misspeculated paths 151 signal(SIGTRAP, SIG_IGN); 152 signal(SIGUSR1, dumpStatsHandler); // dump intermediate stats 153 signal(SIGUSR2, dumprstStatsHandler); // dump and reset stats 154 signal(SIGINT, exitNowHandler); // dump final stats and exit 155 signal(SIGABRT, abortHandler); 156 |
166 // Python embedded interpreter invocation | |
167 Py_SetProgramName(argv[0]); | 157 Py_SetProgramName(argv[0]); |
168 const char *fileName = Py_GetProgramFullPath(); | 158 159 // default path to m5 python code is the currently executing 160 // file... Python ZipImporter will find embedded zip archive 161 char *pythonpath = argv[0]; 162 163 bool interactive = false; 164 bool getopt_done = false; 165 do { 166 switch (getopt(argc, argv, "+p:i")) { 167 // -p <path> prepends <path> to PYTHONPATH instead of 168 // using built-in zip archive. Useful when 169 // developing/debugging changes to built-in Python 170 // libraries, as the new Python can be tested without 171 // building a new m5 binary. 172 case 'p': 173 pythonpath = optarg; 174 break; 175 176 // -i forces entry into interactive mode after the 177 // supplied script is executed (just like the -i option to 178 // the Python interpreter). 179 case 'i': 180 interactive = true; 181 break; 182 183 case -1: 184 getopt_done = true; 185 break; 186 187 default: 188 fatal("Unrecognized option %c\n", optopt); 189 } 190 } while (!getopt_done); 191 192 // Fix up argc & argv to hide arguments we just processed. 193 // getopt() sets optind to the index of the first non-processed 194 // argv element. 195 argc -= optind; 196 argv += optind; 197 198 // Set up PYTHONPATH to make sure the m5 module is found 199 string newpath(pythonpath); 200 201 char *oldpath = getenv("PYTHONPATH"); 202 if (oldpath != NULL) { 203 newpath += ":"; 204 newpath += oldpath; 205 } 206 207 if (setenv("PYTHONPATH", newpath.c_str(), true) == -1) 208 fatal("setenv: %s\n", strerror(errno)); 209 210 // initialize embedded Python interpreter |
169 Py_Initialize(); 170 PySys_SetArgv(argc, argv); 171 | 211 Py_Initialize(); 212 PySys_SetArgv(argc, argv); 213 |
172 // loadSwigModules(); | 214 // initialize SWIG 'main' module 215 init_main(); |
173 | 216 |
174 // Set Python module path to include current file to find embedded 175 // zip archive 176 if (PyRun_SimpleString("import sys") != 0) 177 panic("Python error importing 'sys' module\n"); 178 string pathCmd = csprintf("sys.path[1:1] = ['%s']", fileName); 179 if (PyRun_SimpleString(pathCmd.c_str()) != 0) 180 panic("Python error setting sys.path\n"); | 217 if (argc > 0) { 218 // extra arg(s): first is script file, remaining ones are args 219 // to script file 220 char *filename = argv[0]; 221 FILE *fp = fopen(filename, "r"); 222 if (!fp) { 223 fatal("cannot open file '%s'\n", filename); 224 } |
181 | 225 |
182 // Pass compile timestamp string to Python 183 extern const char *compileDate; // from date.cc 184 string setCompileDate = csprintf("compileDate = '%s'", compileDate); 185 if (PyRun_SimpleString(setCompileDate.c_str()) != 0) 186 panic("Python error setting compileDate\n"); | 226 PyRun_AnyFile(fp, filename); 227 } else { 228 // no script file argument... force interactive prompt 229 interactive = true; 230 } |
187 | 231 |
188 // PyRun_InteractiveLoop(stdin, "stdin"); 189 // m5/__init__.py currently contains main argv parsing loop etc., 190 // and will write out config.ini file before returning. 191 if (PyImport_ImportModule("defines") == NULL) 192 panic("Python error importing 'defines.py'\n"); 193 if (PyImport_ImportModule("m5") == NULL) 194 panic("Python error importing 'm5' module\n"); | 232 if (interactive) { 233 // The following code to import readline was copied from Python 234 // 2.4.3's Modules/main.c. 235 // Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006 236 // Python Software Foundation; All Rights Reserved 237 // We should only enable this if we're actually using an 238 // interactive prompt. 239 PyObject *v; 240 v = PyImport_ImportModule("readline"); 241 if (v == NULL) 242 PyErr_Clear(); 243 else 244 Py_DECREF(v); 245 246 PyRun_InteractiveLoop(stdin, "stdin"); 247 } 248 249 // clean up Python intepreter. |
195 Py_Finalize(); | 250 Py_Finalize(); |
251} |
|
196 | 252 |
253 254/// Initialize C++ configuration. Exported to Python via SWIG; invoked 255/// from m5.instantiate(). 256void 257initialize() 258{ |
|
197 configStream = simout.find("config.out"); 198 199 // The configuration database is now complete; start processing it. 200 IniFile inifile; 201 inifile.load("config.ini"); 202 203 // Initialize statistics database 204 Stats::InitSimStats(); 205 206 // Now process the configuration hierarchy and create the SimObjects. 207 ConfigHierarchy configHierarchy(inifile); 208 configHierarchy.build(); 209 configHierarchy.createSimObjects(); 210 211 // Parse and check all non-config-hierarchy parameters. 212 ParamContext::parseAllContexts(inifile); 213 ParamContext::checkAllContexts(); 214 | 259 configStream = simout.find("config.out"); 260 261 // The configuration database is now complete; start processing it. 262 IniFile inifile; 263 inifile.load("config.ini"); 264 265 // Initialize statistics database 266 Stats::InitSimStats(); 267 268 // Now process the configuration hierarchy and create the SimObjects. 269 ConfigHierarchy configHierarchy(inifile); 270 configHierarchy.build(); 271 configHierarchy.createSimObjects(); 272 273 // Parse and check all non-config-hierarchy parameters. 274 ParamContext::parseAllContexts(inifile); 275 ParamContext::checkAllContexts(); 276 |
215 // Echo command line and all parameter settings to stats file as well. 216 echoCommandLine(argc, argv, *outputStream); | 277 // Echo all parameter settings to stats file as well. |
217 ParamContext::showAllContexts(*configStream); 218 219 // Any objects that can't connect themselves until after construction should 220 // do so now 221 SimObject::connectAll(); 222 223 // Do a second pass to finish initializing the sim objects 224 SimObject::initAll(); --- 14 unchanged lines hidden (view full) --- 239#endif 240 241 // Check to make sure that the stats package is properly initialized 242 Stats::check(); 243 244 // Reset to put the stats in a consistent state. 245 Stats::reset(); 246 | 278 ParamContext::showAllContexts(*configStream); 279 280 // Any objects that can't connect themselves until after construction should 281 // do so now 282 SimObject::connectAll(); 283 284 // Do a second pass to finish initializing the sim objects 285 SimObject::initAll(); --- 14 unchanged lines hidden (view full) --- 300#endif 301 302 // Check to make sure that the stats package is properly initialized 303 Stats::check(); 304 305 // Reset to put the stats in a consistent state. 306 Stats::reset(); 307 |
247 warn("Entering event queue. Starting simulation...\n"); | |
248 SimStartup(); | 308 SimStartup(); |
249 while (!mainEventQueue.empty()) { | 309} 310 311 312/** Simulate for num_cycles additional cycles. If num_cycles is -1 313 * (the default), do not limit simulation; some other event must 314 * terminate the loop. Exported to Python via SWIG. 315 * @return The SimLoopExitEvent that caused the loop to exit. 316 */ 317SimLoopExitEvent * 318simulate(Tick num_cycles = -1) 319{ 320 warn("Entering event queue @ %d. Starting simulation...\n", curTick); 321 322 // Fix up num_cycles. Special default value -1 means simulate 323 // "forever"... schedule event at MaxTick just to be safe. 324 // Otherwise it's a delta for additional cycles to simulate past 325 // curTick, and thus must be non-negative. 326 if (num_cycles == -1) 327 num_cycles = MaxTick; 328 else if (num_cycles < 0) 329 fatal("simulate: num_cycles must be >= 0 (was %d)\n", num_cycles); 330 else 331 num_cycles = curTick + num_cycles; 332 333 Event *limit_event = new SimLoopExitEvent(num_cycles, 334 "simulate() limit reached"); 335 336 while (1) { 337 // there should always be at least one event (the SimLoopExitEvent 338 // we just scheduled) in the queue 339 assert(!mainEventQueue.empty()); |
250 assert(curTick <= mainEventQueue.nextTick() && 251 "event scheduled in the past"); 252 253 // forward current cycle to the time of the first event on the 254 // queue 255 curTick = mainEventQueue.nextTick(); | 340 assert(curTick <= mainEventQueue.nextTick() && 341 "event scheduled in the past"); 342 343 // forward current cycle to the time of the first event on the 344 // queue 345 curTick = mainEventQueue.nextTick(); |
256 mainEventQueue.serviceOne(); | 346 Event *exit_event = mainEventQueue.serviceOne(); 347 if (exit_event != NULL) { 348 // hit some kind of exit event; return to Python 349 // event must be subclass of SimLoopExitEvent... 350 SimLoopExitEvent *se_event = dynamic_cast<SimLoopExitEvent *>(exit_event); 351 if (se_event == NULL) 352 panic("Bogus exit event class!"); |
257 | 353 |
354 // if we didn't hit limit_event, delete it 355 if (se_event != limit_event) { 356 assert(limit_event->scheduled()); 357 limit_event->deschedule(); 358 delete limit_event; 359 } 360 361 return se_event; 362 } 363 |
|
258 if (async_event) { 259 async_event = false; 260 if (async_dump) { 261 async_dump = false; 262 263 using namespace Stats; 264 SetupEvent(Dump, curTick); 265 } 266 267 if (async_dumpreset) { 268 async_dumpreset = false; 269 270 using namespace Stats; 271 SetupEvent(Dump | Reset, curTick); 272 } 273 274 if (async_exit) { 275 async_exit = false; | 364 if (async_event) { 365 async_event = false; 366 if (async_dump) { 367 async_dump = false; 368 369 using namespace Stats; 370 SetupEvent(Dump, curTick); 371 } 372 373 if (async_dumpreset) { 374 async_dumpreset = false; 375 376 using namespace Stats; 377 SetupEvent(Dump | Reset, curTick); 378 } 379 380 if (async_exit) { 381 async_exit = false; |
276 new SimExitEvent("User requested STOP"); | 382 exitSimLoop("user interrupt received"); |
277 } 278 279 if (async_io || async_alarm) { 280 async_io = false; 281 async_alarm = false; 282 pollQueue.service(); 283 } 284 } 285 } 286 | 383 } 384 385 if (async_io || async_alarm) { 386 async_io = false; 387 async_alarm = false; 388 pollQueue.service(); 389 } 390 } 391 } 392 |
287 // This should never happen... every conceivable way for the 288 // simulation to terminate (hit max cycles/insts, signal, 289 // simulated system halts/exits) generates an exit event, so we 290 // should never run out of events on the queue. 291 exitNow("no events on event loop! All CPUs must be idle.", 1); | 393 // not reached... only exit is return on SimLoopExitEvent 394} |
292 | 395 |
293 return 0; | 396/** 397 * Queue of C++ callbacks to invoke on simulator exit. 398 */ 399CallbackQueue exitCallbacks; 400 401/** 402 * Register an exit callback. 403 */ 404void 405registerExitCallback(Callback *callback) 406{ 407 exitCallbacks.add(callback); |
294} | 408} |
409 410/** 411 * Do C++ simulator exit processing. Exported to SWIG to be invoked 412 * when simulator terminates via Python's atexit mechanism. 413 */ 414void 415doExitCleanup() 416{ 417 exitCallbacks.process(); 418 exitCallbacks.clear(); 419 420 cout.flush(); 421 422 ParamContext::cleanupAllContexts(); 423 424 // print simulation stats 425 Stats::DumpNow(); 426} |
|