main.cc revision 3868
14202Sbinkertn@umich.edu/* 24202Sbinkertn@umich.edu * Copyright (c) 2000-2005 The Regents of The University of Michigan 34202Sbinkertn@umich.edu * All rights reserved. 44202Sbinkertn@umich.edu * 54202Sbinkertn@umich.edu * Redistribution and use in source and binary forms, with or without 64202Sbinkertn@umich.edu * modification, are permitted provided that the following conditions are 74202Sbinkertn@umich.edu * met: redistributions of source code must retain the above copyright 84202Sbinkertn@umich.edu * notice, this list of conditions and the following disclaimer; 94202Sbinkertn@umich.edu * redistributions in binary form must reproduce the above copyright 104202Sbinkertn@umich.edu * notice, this list of conditions and the following disclaimer in the 114202Sbinkertn@umich.edu * documentation and/or other materials provided with the distribution; 124202Sbinkertn@umich.edu * neither the name of the copyright holders nor the names of its 134202Sbinkertn@umich.edu * contributors may be used to endorse or promote products derived from 144202Sbinkertn@umich.edu * this software without specific prior written permission. 154202Sbinkertn@umich.edu * 164202Sbinkertn@umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 174202Sbinkertn@umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 184202Sbinkertn@umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 194202Sbinkertn@umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 204202Sbinkertn@umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 214202Sbinkertn@umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 224202Sbinkertn@umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 234202Sbinkertn@umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 244202Sbinkertn@umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 254202Sbinkertn@umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 264202Sbinkertn@umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 274202Sbinkertn@umich.edu * 284202Sbinkertn@umich.edu * Authors: Steve Raasch 294202Sbinkertn@umich.edu * Nathan Binkert 304202Sbinkertn@umich.edu * Steve Reinhardt 314202Sbinkertn@umich.edu */ 324202Sbinkertn@umich.edu 339157Sandreas.hansson@arm.com/// 3410259SAndrew.Bardsley@arm.com/// @file sim/main.cc 354486Sbinkertn@umich.edu/// 369793Sakash.bagdia@arm.com#include <Python.h> // must be before system headers... see Python docs 379827Sakash.bagdia@arm.com 389850Sandreas.hansson@arm.com#include <sys/types.h> 3910249Sstephan.diestelhorst@arm.com#include <sys/stat.h> 4010268SGeoffrey.Blake@arm.com#include <errno.h> 414486Sbinkertn@umich.edu#include <libgen.h> 428774Sgblack@eecs.umich.edu#include <stdlib.h> 434202Sbinkertn@umich.edu#include <signal.h> 4411235Sandreas.sandberg@arm.com#include <getopt.h> 454202Sbinkertn@umich.edu 4611077SCurtis.Dunham@arm.com#include <list> 4710458Sandreas.hansson@arm.com#include <string> 4810458Sandreas.hansson@arm.com#include <vector> 4910458Sandreas.hansson@arm.com 504202Sbinkertn@umich.edu#include "base/callback.hh" 5110453SAndrew.Bardsley@arm.com#include "base/inifile.hh" 524202Sbinkertn@umich.edu#include "base/misc.hh" 539983Sstever@gmail.com#include "base/output.hh" 5410453SAndrew.Bardsley@arm.com#include "base/pollevent.hh" 5510453SAndrew.Bardsley@arm.com#include "base/statistics.hh" 568233Snate@binkert.org#include "base/str.hh" 574202Sbinkertn@umich.edu#include "base/time.hh" 584202Sbinkertn@umich.edu#include "config/pythonhome.hh" 599342SAndreas.Sandberg@arm.com#include "cpu/base.hh" 604202Sbinkertn@umich.edu#include "cpu/smt.hh" 614202Sbinkertn@umich.edu#include "mem/mem_object.hh" 6210268SGeoffrey.Blake@arm.com#include "mem/port.hh" 6310259SAndrew.Bardsley@arm.com#include "python/swig/init.hh" 644202Sbinkertn@umich.edu#include "sim/async.hh" 654202Sbinkertn@umich.edu#include "sim/builder.hh" 6610453SAndrew.Bardsley@arm.com#include "sim/host.hh" 679793Sakash.bagdia@arm.com#include "sim/serialize.hh" 689827Sakash.bagdia@arm.com#include "sim/sim_events.hh" 6911420Sdavid.guillen@arm.com#include "sim/sim_exit.hh" 709850Sandreas.hansson@arm.com#include "sim/sim_object.hh" 7110249Sstephan.diestelhorst@arm.com#include "sim/system.hh" 7211524Sdavid.guillen@arm.com#include "sim/stat_control.hh" 7311527Sdavid.guillen@arm.com#include "sim/stats.hh" 747768SAli.Saidi@ARM.com#include "sim/root.hh" 759850Sandreas.hansson@arm.com 769850Sandreas.hansson@arm.comusing namespace std; 778766Sgblack@eecs.umich.edu 7811854Sbrandon.potter@amd.com// See async.h. 797768SAli.Saidi@ARM.comvolatile bool async_event = false; 808766Sgblack@eecs.umich.eduvolatile bool async_dump = false; 8110930Sbrandon.potter@amd.comvolatile bool async_dumpreset = false; 827768SAli.Saidi@ARM.comvolatile bool async_exit = false; 839850Sandreas.hansson@arm.comvolatile bool async_io = false; 8411794Sbrandon.potter@amd.comvolatile bool async_alarm = false; 854486Sbinkertn@umich.edu 8611800Sbrandon.potter@amd.com/// Stats signal handler. 8711800Sbrandon.potter@amd.comvoid 8811800Sbrandon.potter@amd.comdumpStatsHandler(int sigtype) 898335Snate@binkert.org{ 908335Snate@binkert.org async_event = true; 9110458Sandreas.hansson@arm.com async_dump = true; 929152Satgutier@umich.edu} 938335Snate@binkert.org 948335Snate@binkert.orgvoid 958335Snate@binkert.orgdumprstStatsHandler(int sigtype) 968335Snate@binkert.org{ 978335Snate@binkert.org async_event = true; 988335Snate@binkert.org async_dumpreset = true; 998335Snate@binkert.org} 1009733Sandreas@sandberg.pp.se 1018335Snate@binkert.org/// Exit signal handler. 10211380Salexandru.dutu@amd.comvoid 1038335Snate@binkert.orgexitNowHandler(int sigtype) 1048335Snate@binkert.org{ 1058335Snate@binkert.org async_event = true; 1068335Snate@binkert.org async_exit = true; 1078335Snate@binkert.org} 1088335Snate@binkert.org 1099793Sakash.bagdia@arm.com/// Abort signal handler. 1109827Sakash.bagdia@arm.comvoid 11110249Sstephan.diestelhorst@arm.comabortHandler(int sigtype) 11211380Salexandru.dutu@amd.com{ 11311380Salexandru.dutu@amd.com cerr << "Program aborted at cycle " << curTick << endl; 114 115#if TRACING_ON 116 // dump trace buffer, if there is one 117 Trace::theLog.dump(cerr); 118#endif 119} 120 121int 122main(int argc, char **argv) 123{ 124 signal(SIGFPE, SIG_IGN); // may occur on misspeculated paths 125 signal(SIGTRAP, SIG_IGN); 126 signal(SIGUSR1, dumpStatsHandler); // dump intermediate stats 127 signal(SIGUSR2, dumprstStatsHandler); // dump and reset stats 128 signal(SIGINT, exitNowHandler); // dump final stats and exit 129 signal(SIGABRT, abortHandler); 130 131 Py_SetProgramName(argv[0]); 132 133 // default path to m5 python code is the currently executing 134 // file... Python ZipImporter will find embedded zip archive. 135 // The M5_ARCHIVE environment variable can be used to override this. 136 char *m5_archive = getenv("M5_ARCHIVE"); 137 string pythonpath = m5_archive ? m5_archive : argv[0]; 138 139 char *oldpath = getenv("PYTHONPATH"); 140 if (oldpath != NULL) { 141 pythonpath += ":"; 142 pythonpath += oldpath; 143 } 144 145 if (setenv("PYTHONPATH", pythonpath.c_str(), true) == -1) 146 fatal("setenv: %s\n", strerror(errno)); 147 148 char *python_home = getenv("PYTHONHOME"); 149 if (!python_home) 150 python_home = PYTHONHOME; 151 Py_SetPythonHome(python_home); 152 153 // initialize embedded Python interpreter 154 Py_Initialize(); 155 PySys_SetArgv(argc, argv); 156 157 // initialize SWIG modules 158 init_swig(); 159 160 PyRun_SimpleString("import m5.main"); 161 PyRun_SimpleString("m5.main.main()"); 162 163 // clean up Python intepreter. 164 Py_Finalize(); 165} 166 167 168void 169setOutputDir(const string &dir) 170{ 171 simout.setDirectory(dir); 172} 173 174 175IniFile inifile; 176 177SimObject * 178createSimObject(const string &name) 179{ 180 return SimObjectClass::createObject(inifile, name); 181} 182 183 184/** 185 * Pointer to the Python function that maps names to SimObjects. 186 */ 187PyObject *resolveFunc = NULL; 188 189/** 190 * Convert a pointer to the Python object that SWIG wraps around a C++ 191 * SimObject pointer back to the actual C++ pointer. See main.i. 192 */ 193extern "C" SimObject *convertSwigSimObjectPtr(PyObject *); 194 195 196SimObject * 197resolveSimObject(const string &name) 198{ 199 PyObject *pyPtr = PyEval_CallFunction(resolveFunc, "(s)", name.c_str()); 200 if (pyPtr == NULL) { 201 PyErr_Print(); 202 panic("resolveSimObject: failure on call to Python for %s", name); 203 } 204 205 SimObject *simObj = convertSwigSimObjectPtr(pyPtr); 206 if (simObj == NULL) 207 panic("resolveSimObject: failure on pointer conversion for %s", name); 208 209 return simObj; 210} 211 212 213/** 214 * Load config.ini into C++ database. Exported to Python via SWIG; 215 * invoked from m5.instantiate(). 216 */ 217void 218loadIniFile(PyObject *_resolveFunc) 219{ 220 resolveFunc = _resolveFunc; 221 configStream = simout.find("config.out"); 222 223 // The configuration database is now complete; start processing it. 224 inifile.load(simout.resolve("config.ini")); 225 226 // Initialize statistics database 227 Stats::InitSimStats(); 228} 229 230 231/** 232 * Look up a MemObject port. Helper function for connectPorts(). 233 */ 234Port * 235lookupPort(SimObject *so, const std::string &name, int i) 236{ 237 MemObject *mo = dynamic_cast<MemObject *>(so); 238 if (mo == NULL) { 239 warn("error casting SimObject %s to MemObject", so->name()); 240 return NULL; 241 } 242 243 Port *p = mo->getPort(name, i); 244 if (p == NULL) 245 warn("error looking up port %s on object %s", name, so->name()); 246 return p; 247} 248 249 250/** 251 * Connect the described MemObject ports. Called from Python via SWIG. 252 */ 253int 254connectPorts(SimObject *o1, const std::string &name1, int i1, 255 SimObject *o2, const std::string &name2, int i2) 256{ 257 Port *p1 = lookupPort(o1, name1, i1); 258 Port *p2 = lookupPort(o2, name2, i2); 259 260 if (p1 == NULL || p2 == NULL) { 261 warn("connectPorts: port lookup error"); 262 return 0; 263 } 264 265 p1->setPeer(p2); 266 p2->setPeer(p1); 267 268 return 1; 269} 270 271/** 272 * Do final initialization steps after object construction but before 273 * start of simulation. 274 */ 275void 276finalInit() 277{ 278 // Parse and check all non-config-hierarchy parameters. 279 ParamContext::parseAllContexts(inifile); 280 ParamContext::checkAllContexts(); 281 282 // Echo all parameter settings to stats file as well. 283 ParamContext::showAllContexts(*configStream); 284 285 // Do a second pass to finish initializing the sim objects 286 SimObject::initAll(); 287 288 // Restore checkpointed state, if any. 289#if 0 290 configHierarchy.unserializeSimObjects(); 291#endif 292 293 SimObject::regAllStats(); 294 295 // Check to make sure that the stats package is properly initialized 296 Stats::check(); 297 298 // Reset to put the stats in a consistent state. 299 Stats::reset(); 300 301 SimStartup(); 302} 303 304 305/** Simulate for num_cycles additional cycles. If num_cycles is -1 306 * (the default), do not limit simulation; some other event must 307 * terminate the loop. Exported to Python via SWIG. 308 * @return The SimLoopExitEvent that caused the loop to exit. 309 */ 310SimLoopExitEvent * 311simulate(Tick num_cycles = MaxTick) 312{ 313 warn("Entering event queue @ %d. Starting simulation...\n", curTick); 314 315 if (num_cycles < 0) 316 fatal("simulate: num_cycles must be >= 0 (was %d)\n", num_cycles); 317 else if (curTick + num_cycles < 0) //Overflow 318 num_cycles = MaxTick; 319 else 320 num_cycles = curTick + num_cycles; 321 322 Event *limit_event = schedExitSimLoop("simulate() limit reached", 323 num_cycles); 324 325 while (1) { 326 // there should always be at least one event (the SimLoopExitEvent 327 // we just scheduled) in the queue 328 assert(!mainEventQueue.empty()); 329 assert(curTick <= mainEventQueue.nextTick() && 330 "event scheduled in the past"); 331 332 // forward current cycle to the time of the first event on the 333 // queue 334 curTick = mainEventQueue.nextTick(); 335 Event *exit_event = mainEventQueue.serviceOne(); 336 if (exit_event != NULL) { 337 // hit some kind of exit event; return to Python 338 // event must be subclass of SimLoopExitEvent... 339 SimLoopExitEvent *se_event = dynamic_cast<SimLoopExitEvent *>(exit_event); 340 if (se_event == NULL) 341 panic("Bogus exit event class!"); 342 343 // if we didn't hit limit_event, delete it 344 if (se_event != limit_event) { 345 assert(limit_event->scheduled()); 346 limit_event->deschedule(); 347 delete limit_event; 348 } 349 350 return se_event; 351 } 352 353 if (async_event) { 354 async_event = false; 355 if (async_dump) { 356 async_dump = false; 357 358 using namespace Stats; 359 SetupEvent(Dump, curTick); 360 } 361 362 if (async_dumpreset) { 363 async_dumpreset = false; 364 365 using namespace Stats; 366 SetupEvent(Dump | Reset, curTick); 367 } 368 369 if (async_exit) { 370 async_exit = false; 371 exitSimLoop("user interrupt received"); 372 } 373 374 if (async_io || async_alarm) { 375 async_io = false; 376 async_alarm = false; 377 pollQueue.service(); 378 } 379 } 380 } 381 382 // not reached... only exit is return on SimLoopExitEvent 383} 384 385Event * 386createCountedDrain() 387{ 388 return new CountedDrainEvent(); 389} 390 391void 392cleanupCountedDrain(Event *counted_drain) 393{ 394 CountedDrainEvent *event = 395 dynamic_cast<CountedDrainEvent *>(counted_drain); 396 if (event == NULL) { 397 fatal("Called cleanupCountedDrain() on an event that was not " 398 "a CountedDrainEvent."); 399 } 400 assert(event->getCount() == 0); 401 delete event; 402} 403 404void 405serializeAll(const std::string &cpt_dir) 406{ 407 Serializable::serializeAll(cpt_dir); 408} 409 410void 411unserializeAll(const std::string &cpt_dir) 412{ 413 Serializable::unserializeAll(cpt_dir); 414} 415 416/** 417 * Queue of C++ callbacks to invoke on simulator exit. 418 */ 419CallbackQueue& 420exitCallbacks() 421{ 422 static CallbackQueue theQueue; 423 return theQueue; 424} 425 426/** 427 * Register an exit callback. 428 */ 429void 430registerExitCallback(Callback *callback) 431{ 432 exitCallbacks().add(callback); 433} 434 435BaseCPU * 436convertToBaseCPUPtr(SimObject *obj) 437{ 438 BaseCPU *ptr = dynamic_cast<BaseCPU *>(obj); 439 440 if (ptr == NULL) 441 warn("Casting to BaseCPU pointer failed"); 442 return ptr; 443} 444 445System * 446convertToSystemPtr(SimObject *obj) 447{ 448 System *ptr = dynamic_cast<System *>(obj); 449 450 if (ptr == NULL) 451 warn("Casting to System pointer failed"); 452 return ptr; 453} 454 455 456/** 457 * Do C++ simulator exit processing. Exported to SWIG to be invoked 458 * when simulator terminates via Python's atexit mechanism. 459 */ 460void 461doExitCleanup() 462{ 463 exitCallbacks().process(); 464 exitCallbacks().clear(); 465 466 cout.flush(); 467 468 ParamContext::cleanupAllContexts(); 469 470 // print simulation stats 471 Stats::DumpNow(); 472} 473