main.cc revision 395
112852Sgabeblack@google.com/* 212852Sgabeblack@google.com * Copyright (c) 2003 The Regents of The University of Michigan 312852Sgabeblack@google.com * All rights reserved. 412852Sgabeblack@google.com * 512852Sgabeblack@google.com * Redistribution and use in source and binary forms, with or without 612852Sgabeblack@google.com * modification, are permitted provided that the following conditions are 712852Sgabeblack@google.com * met: redistributions of source code must retain the above copyright 812852Sgabeblack@google.com * notice, this list of conditions and the following disclaimer; 912852Sgabeblack@google.com * redistributions in binary form must reproduce the above copyright 1012852Sgabeblack@google.com * notice, this list of conditions and the following disclaimer in the 1112852Sgabeblack@google.com * documentation and/or other materials provided with the distribution; 1212852Sgabeblack@google.com * neither the name of the copyright holders nor the names of its 1312852Sgabeblack@google.com * contributors may be used to endorse or promote products derived from 1412852Sgabeblack@google.com * this software without specific prior written permission. 1512852Sgabeblack@google.com * 1612852Sgabeblack@google.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1712852Sgabeblack@google.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1812852Sgabeblack@google.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 1912852Sgabeblack@google.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 2012852Sgabeblack@google.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2112852Sgabeblack@google.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 2212852Sgabeblack@google.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2312852Sgabeblack@google.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2412852Sgabeblack@google.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2512852Sgabeblack@google.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 2612852Sgabeblack@google.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2712852Sgabeblack@google.com */ 2812852Sgabeblack@google.com 2912852Sgabeblack@google.com/// 3012997Sgabeblack@google.com/// @file sim/main.cc 3112997Sgabeblack@google.com/// 3212997Sgabeblack@google.com#include <sys/types.h> 3312997Sgabeblack@google.com#include <sys/stat.h> 3412997Sgabeblack@google.com#include <stdlib.h> 3512852Sgabeblack@google.com#include <signal.h> 3612997Sgabeblack@google.com 3712997Sgabeblack@google.com#include <string> 3812997Sgabeblack@google.com#include <vector> 3912852Sgabeblack@google.com 4012852Sgabeblack@google.com#include "base/copyright.hh" 4112852Sgabeblack@google.com#include "base/inifile.hh" 4212852Sgabeblack@google.com#include "base/misc.hh" 4312852Sgabeblack@google.com#include "base/pollevent.hh" 4412997Sgabeblack@google.com#include "base/statistics.hh" 4512997Sgabeblack@google.com#include "cpu/base_cpu.hh" 4612997Sgabeblack@google.com#include "cpu/full_cpu/smt.hh" 4712997Sgabeblack@google.com#include "sim/async.hh" 4812997Sgabeblack@google.com#include "sim/builder.hh" 4912997Sgabeblack@google.com#include "sim/configfile.hh" 5012997Sgabeblack@google.com#include "sim/host.hh" 5112997Sgabeblack@google.com#include "sim/sim_events.hh" 5212997Sgabeblack@google.com#include "sim/sim_exit.hh" 5312997Sgabeblack@google.com#include "sim/sim_object.hh" 5412997Sgabeblack@google.com#include "sim/sim_stats.hh" 5512997Sgabeblack@google.com#include "sim/sim_time.hh" 5612997Sgabeblack@google.com 5712997Sgabeblack@google.comusing namespace std; 5812997Sgabeblack@google.com 5912997Sgabeblack@google.com// See async.h. 6012997Sgabeblack@google.comvolatile bool async_event = false; 6112997Sgabeblack@google.comvolatile bool async_dump = false; 6212997Sgabeblack@google.comvolatile bool async_dumpreset = false; 6312997Sgabeblack@google.comvolatile bool async_exit = false; 6412997Sgabeblack@google.comvolatile bool async_io = false; 6512997Sgabeblack@google.comvolatile bool async_alarm = false; 6612997Sgabeblack@google.com 6712997Sgabeblack@google.com/// Stats signal handler. 6812997Sgabeblack@google.comvoid 6912997Sgabeblack@google.comdumpStatsHandler(int sigtype) 7012997Sgabeblack@google.com{ 7112997Sgabeblack@google.com async_event = true; 7212997Sgabeblack@google.com async_dump = true; 7312997Sgabeblack@google.com} 7412997Sgabeblack@google.com 7512997Sgabeblack@google.comvoid 7612997Sgabeblack@google.comdumprstStatsHandler(int sigtype) 7712997Sgabeblack@google.com{ 7812997Sgabeblack@google.com async_event = true; 7912997Sgabeblack@google.com async_dumpreset = true; 8012997Sgabeblack@google.com} 8112997Sgabeblack@google.com 8212997Sgabeblack@google.com/// Exit signal handler. 8312997Sgabeblack@google.comvoid 8412997Sgabeblack@google.comexitNowHandler(int sigtype) 8512997Sgabeblack@google.com{ 8612997Sgabeblack@google.com async_event = true; 8712997Sgabeblack@google.com async_exit = true; 8812997Sgabeblack@google.com} 8912997Sgabeblack@google.com 9012997Sgabeblack@google.com/// Simulator executable name 9112997Sgabeblack@google.comconst char *myProgName = ""; 9212997Sgabeblack@google.com 9312997Sgabeblack@google.com/// Show brief help message. 9412997Sgabeblack@google.comstatic void 9512997Sgabeblack@google.comshowBriefHelp(ostream &out) 9612997Sgabeblack@google.com{ 9712997Sgabeblack@google.com out << "Usage: " << myProgName 9812997Sgabeblack@google.com << " [-hn] [-Dname[=def]] [-Uname] [-I[dir]] " 9912997Sgabeblack@google.com << "[--<section>:<param>=<value>] [<config file> ...]" << endl 10012997Sgabeblack@google.com << " -h: print long help (including parameter listing)" << endl 10112997Sgabeblack@google.com << " -n: don't load default.ini" << endl 10212997Sgabeblack@google.com << " -u: don't quit on unreferenced parameters" << endl 10312997Sgabeblack@google.com << " -D,-U,-I: passed to cpp for preprocessing .ini files" << endl; 10412997Sgabeblack@google.com} 10512852Sgabeblack@google.com 10612997Sgabeblack@google.com/// Show verbose help message. Includes parameter listing from 10712997Sgabeblack@google.com/// showBriefHelp(), plus an exhaustive list of ini-file parameters 10812852Sgabeblack@google.com/// and SimObjects (with their parameters). 10912997Sgabeblack@google.comstatic void 11012852Sgabeblack@google.comshowLongHelp(ostream &out) 11112852Sgabeblack@google.com{ 11212852Sgabeblack@google.com showBriefHelp(out); 11312997Sgabeblack@google.com 11412997Sgabeblack@google.com out << endl 11512997Sgabeblack@google.com << endl 11612852Sgabeblack@google.com << "-----------------" << endl 11712997Sgabeblack@google.com << "Global Parameters" << endl 11812997Sgabeblack@google.com << "-----------------" << endl 11912997Sgabeblack@google.com << endl; 12012997Sgabeblack@google.com 12112997Sgabeblack@google.com ParamContext::describeAllContexts(out); 12212997Sgabeblack@google.com 12312997Sgabeblack@google.com out << endl 12412997Sgabeblack@google.com << endl 12512997Sgabeblack@google.com << "-----------------" << endl 12612997Sgabeblack@google.com << "Simulator Objects" << endl 12712997Sgabeblack@google.com << "-----------------" << endl 12812997Sgabeblack@google.com << endl; 12912997Sgabeblack@google.com 13012997Sgabeblack@google.com SimObjectClass::describeAllClasses(out); 13112997Sgabeblack@google.com} 13212997Sgabeblack@google.com 13312997Sgabeblack@google.com/// Print welcome message. 13412997Sgabeblack@google.comstatic void 13512997Sgabeblack@google.comsayHello(ostream &out) 13612997Sgabeblack@google.com{ 13712997Sgabeblack@google.com extern const char *compileDate; // from date.cc 13812997Sgabeblack@google.com 13912997Sgabeblack@google.com ccprintf(out, "M5 Simulator System\n"); 14012997Sgabeblack@google.com // display copyright 14112997Sgabeblack@google.com ccprintf(out, "%s\n", briefCopyright); 14212997Sgabeblack@google.com ccprintf(out, "M5 compiled on %d\n", compileDate); 14312997Sgabeblack@google.com 14412997Sgabeblack@google.com char *host = getenv("HOSTNAME"); 14512997Sgabeblack@google.com if (!host) 14612997Sgabeblack@google.com host = getenv("HOST"); 14712997Sgabeblack@google.com 14812997Sgabeblack@google.com if (host) 14912997Sgabeblack@google.com ccprintf(out, "M5 executing on %s\n", host); 15012997Sgabeblack@google.com 15112997Sgabeblack@google.com ccprintf(out, "M5 simulation started %s\n", Time::start); 15212997Sgabeblack@google.com} 15312997Sgabeblack@google.com 15412997Sgabeblack@google.com/// 15512997Sgabeblack@google.com/// Echo the command line for posterity in such a way that it can be 15612997Sgabeblack@google.com/// used to rerun the same simulation (given the same .ini files). 15712997Sgabeblack@google.com/// 15812852Sgabeblack@google.comstatic void 15912852Sgabeblack@google.comechoCommandLine(int argc, char **argv, ostream &out) 16012902Sgabeblack@google.com{ 16112902Sgabeblack@google.com out << "command line: " << argv[0]; 16212902Sgabeblack@google.com for (int i = 1; i < argc; i++) { 16312902Sgabeblack@google.com string arg(argv[i]); 16412997Sgabeblack@google.com 16512902Sgabeblack@google.com out << ' '; 16612902Sgabeblack@google.com 16712902Sgabeblack@google.com // If the arg contains spaces, we need to quote it. 16812852Sgabeblack@google.com // The rest of this is overkill to make it look purty. 16912997Sgabeblack@google.com 17012852Sgabeblack@google.com // print dashes first outside quotes 17112997Sgabeblack@google.com int non_dash_pos = arg.find_first_not_of("-"); 17212997Sgabeblack@google.com out << arg.substr(0, non_dash_pos); // print dashes 17312997Sgabeblack@google.com string body = arg.substr(non_dash_pos); // the rest 17412997Sgabeblack@google.com 17512852Sgabeblack@google.com // if it's an assignment, handle the lhs & rhs separately 17612852Sgabeblack@google.com int eq_pos = body.find("="); 17712852Sgabeblack@google.com if (eq_pos == string::npos) { 17812997Sgabeblack@google.com out << quote(body); 17912852Sgabeblack@google.com } 18012997Sgabeblack@google.com else { 18112997Sgabeblack@google.com string lhs(body.substr(0, eq_pos)); 18212997Sgabeblack@google.com string rhs(body.substr(eq_pos + 1)); 18312997Sgabeblack@google.com 18412852Sgabeblack@google.com out << quote(lhs) << "=" << quote(rhs); 18512852Sgabeblack@google.com } 18612852Sgabeblack@google.com } 18712997Sgabeblack@google.com out << endl << endl; 18812997Sgabeblack@google.com} 18912852Sgabeblack@google.com 19012997Sgabeblack@google.com 19112997Sgabeblack@google.com/// 19212997Sgabeblack@google.com/// The simulator configuration database. This is the union of all 19312997Sgabeblack@google.com/// specified .ini files. This shouldn't need to be visible outside 19412997Sgabeblack@google.com/// this file, as it is passed as a parameter to all the param-parsing 19512852Sgabeblack@google.com/// routines. 19612852Sgabeblack@google.com/// 19712852Sgabeblack@google.comstatic IniFile simConfigDB; 19812997Sgabeblack@google.com 19912852Sgabeblack@google.com/// Check for a default.ini file and load it if necessary. 20012997Sgabeblack@google.comstatic void 20112997Sgabeblack@google.comhandleDefaultIni(bool &loadIt, vector<char *> &cppArgs) 20212997Sgabeblack@google.com{ 20312997Sgabeblack@google.com struct stat sb; 20412852Sgabeblack@google.com 20512852Sgabeblack@google.com if (loadIt) { 20612852Sgabeblack@google.com if (stat("default.ini", &sb) == 0) { 20712852Sgabeblack@google.com if (!simConfigDB.loadCPP("default.ini", cppArgs)) { 20812852Sgabeblack@google.com cout << "Error processing file default.ini" << endl; 20912997Sgabeblack@google.com exit(1); 21012997Sgabeblack@google.com } 21112997Sgabeblack@google.com } 21212997Sgabeblack@google.com 21312852Sgabeblack@google.com // set this whether it actually was found or not, so we don't 21412852Sgabeblack@google.com // bother to check again next time 21512852Sgabeblack@google.com loadIt = false; 21612997Sgabeblack@google.com } 21712997Sgabeblack@google.com} 21812852Sgabeblack@google.com 21912997Sgabeblack@google.com 22012997Sgabeblack@google.com/// M5 entry point. 22112997Sgabeblack@google.comint 22212997Sgabeblack@google.commain(int argc, char **argv) 22312997Sgabeblack@google.com{ 22412852Sgabeblack@google.com // Save off program name 22512852Sgabeblack@google.com myProgName = argv[0]; 22612852Sgabeblack@google.com 22712997Sgabeblack@google.com signal(SIGFPE, SIG_IGN); // may occur on misspeculated paths 22812852Sgabeblack@google.com signal(SIGTRAP, SIG_IGN); 22912997Sgabeblack@google.com signal(SIGUSR1, dumpStatsHandler); // dump intermediate stats 23012852Sgabeblack@google.com signal(SIGUSR2, dumprstStatsHandler); // dump and reset stats 23112852Sgabeblack@google.com signal(SIGINT, exitNowHandler); // dump final stats and exit 23212852Sgabeblack@google.com 23312852Sgabeblack@google.com sayHello(cerr); 23412852Sgabeblack@google.com 23512997Sgabeblack@google.com // Initialize statistics database 23612852Sgabeblack@google.com initBaseStats(); 23712852Sgabeblack@google.com 23812852Sgabeblack@google.com vector<char *> cppArgs; 23912997Sgabeblack@google.com 24012852Sgabeblack@google.com // Should we use default.ini if it exists? By default, yes. (Use 24112997Sgabeblack@google.com // -n to override.) 24212997Sgabeblack@google.com bool loadDefaultIni = true; 24312852Sgabeblack@google.com 24412852Sgabeblack@google.com // Should we quit if there are unreferenced parameters? By 24512852Sgabeblack@google.com // default, yes... it's a good way of catching typos in 24612997Sgabeblack@google.com // section/parameter names (which otherwise go by silently). Use 24712852Sgabeblack@google.com // -u to override. 24812997Sgabeblack@google.com bool quitOnUnreferenced = true; 24912997Sgabeblack@google.com 25012997Sgabeblack@google.com // Parse command-line options. The tricky part here is figuring 25112852Sgabeblack@google.com // out whether to look for & load default.ini, and if needed, 25212852Sgabeblack@google.com // doing so at the right time w.r.t. processing the other 25312852Sgabeblack@google.com // parameters. 25412852Sgabeblack@google.com // 25512852Sgabeblack@google.com // Since most of the complex options are handled through the 25612997Sgabeblack@google.com // config database, we don't mess with getopts, and just parse 25712852Sgabeblack@google.com // manually. 25812852Sgabeblack@google.com for (int i = 1; i < argc; ++i) { 25912852Sgabeblack@google.com char *arg_str = argv[i]; 26012852Sgabeblack@google.com 26112997Sgabeblack@google.com // if arg starts with '-', parse as option, 26212852Sgabeblack@google.com // else treat it as a configuration file name and load it 26312997Sgabeblack@google.com if (arg_str[0] == '-') { 26412997Sgabeblack@google.com 26512997Sgabeblack@google.com // switch on second char 26612852Sgabeblack@google.com switch (arg_str[1]) { 26712852Sgabeblack@google.com case 'h': 26812852Sgabeblack@google.com // -h: show help 26912852Sgabeblack@google.com showLongHelp(cerr); 27012852Sgabeblack@google.com exit(1); 27112997Sgabeblack@google.com 27212852Sgabeblack@google.com case 'n': 27312852Sgabeblack@google.com // -n: don't load default.ini 27412852Sgabeblack@google.com if (!loadDefaultIni) { 27512997Sgabeblack@google.com cerr << "Warning: -n option needs to precede any " 27612852Sgabeblack@google.com << "explicit configuration file name " << endl 27712997Sgabeblack@google.com << " or command-line configuration parameter." 27812997Sgabeblack@google.com << endl; 27912997Sgabeblack@google.com } 28012852Sgabeblack@google.com loadDefaultIni = false; 28112852Sgabeblack@google.com break; 28212852Sgabeblack@google.com 28312852Sgabeblack@google.com case 'u': 28412852Sgabeblack@google.com // -u: don't quit on unreferenced parameters 28512997Sgabeblack@google.com quitOnUnreferenced = false; 28612852Sgabeblack@google.com break; 28712852Sgabeblack@google.com 28812852Sgabeblack@google.com case 'D': 28912911Sgabeblack@google.com case 'U': 29012997Sgabeblack@google.com case 'I': 29112911Sgabeblack@google.com // cpp options: record & pass to cpp. Note that these 29212997Sgabeblack@google.com // cannot have spaces, i.e., '-Dname=val' is OK, but 29312997Sgabeblack@google.com // '-D name=val' is not. I don't consider this a 29412997Sgabeblack@google.com // problem, since even though gnu cpp accepts the 29512911Sgabeblack@google.com // latter, other cpp implementations do not (Tru64, 29612911Sgabeblack@google.com // for one). 29712911Sgabeblack@google.com cppArgs.push_back(arg_str); 29812911Sgabeblack@google.com break; 29912911Sgabeblack@google.com 30012997Sgabeblack@google.com case '-': 30112911Sgabeblack@google.com // command-line configuration parameter: 30212911Sgabeblack@google.com // '--<section>:<parameter>=<value>' 30312911Sgabeblack@google.com 30412852Sgabeblack@google.com // Load default.ini if necessary -- see comment in 30512997Sgabeblack@google.com // else clause below. 30612852Sgabeblack@google.com handleDefaultIni(loadDefaultIni, cppArgs); 30712997Sgabeblack@google.com 30812852Sgabeblack@google.com if (!simConfigDB.add(arg_str + 2)) { 30912852Sgabeblack@google.com // parse error 31012852Sgabeblack@google.com ccprintf(cerr, 31112997Sgabeblack@google.com "Could not parse configuration argument '%s'\n" 31212997Sgabeblack@google.com "Expecting --<section>:<parameter>=<value>\n", 31312852Sgabeblack@google.com arg_str); 31412997Sgabeblack@google.com exit(0); 31512997Sgabeblack@google.com } 31612997Sgabeblack@google.com break; 31712997Sgabeblack@google.com 31812997Sgabeblack@google.com default: 31912997Sgabeblack@google.com showBriefHelp(cerr); 32012997Sgabeblack@google.com ccprintf(cerr, "Fatal: invalid argument '%s'\n", arg_str); 32112997Sgabeblack@google.com exit(0); 32212997Sgabeblack@google.com } 32312997Sgabeblack@google.com } 32412997Sgabeblack@google.com else { 32512997Sgabeblack@google.com // no '-', treat as config file name 32612997Sgabeblack@google.com 32712997Sgabeblack@google.com // If we haven't loaded default.ini yet, and we want to, 32812997Sgabeblack@google.com // now is the time. Can't do it sooner because we need to 32912997Sgabeblack@google.com // look for '-n', can't do it later since we want 33012997Sgabeblack@google.com // default.ini loaded first (so that any other settings 33112997Sgabeblack@google.com // override it). 33212997Sgabeblack@google.com handleDefaultIni(loadDefaultIni, cppArgs); 33312997Sgabeblack@google.com 33412997Sgabeblack@google.com if (!simConfigDB.loadCPP(arg_str, cppArgs)) { 33512852Sgabeblack@google.com cprintf("Error processing file %s\n", arg_str); 33612852Sgabeblack@google.com exit(1); 33712852Sgabeblack@google.com } 33812852Sgabeblack@google.com } 33912852Sgabeblack@google.com } 34012997Sgabeblack@google.com 34112997Sgabeblack@google.com // Final check for default.ini, in case no config files or 34212852Sgabeblack@google.com // command-line config parameters were given. 34312852Sgabeblack@google.com handleDefaultIni(loadDefaultIni, cppArgs); 34412852Sgabeblack@google.com 34512852Sgabeblack@google.com // The configuration database is now complete; start processing it. 34612852Sgabeblack@google.com 34712997Sgabeblack@google.com // Parse and check all non-config-hierarchy parameters. 34812997Sgabeblack@google.com ParamContext::parseAllContexts(simConfigDB); 34912997Sgabeblack@google.com ParamContext::checkAllContexts(); 35012997Sgabeblack@google.com 35112852Sgabeblack@google.com // Print header info into stats file. Can't do this sooner since 35212852Sgabeblack@google.com // the stat file name is set via a .ini param... thus it just got 35312852Sgabeblack@google.com // opened above during ParamContext::checkAllContexts(). 35412852Sgabeblack@google.com 35512852Sgabeblack@google.com // Print hello message to stats file if it's actually a file. If 35612997Sgabeblack@google.com // it's not (i.e. it's cout or cerr) then we already did it above. 35712997Sgabeblack@google.com if (statStreamIsFile) 35812997Sgabeblack@google.com sayHello(*statStream); 35912997Sgabeblack@google.com 36012997Sgabeblack@google.com // Echo command line and all parameter settings to stats file as well. 36112997Sgabeblack@google.com echoCommandLine(argc, argv, *statStream); 36212852Sgabeblack@google.com ParamContext::showAllContexts(*statStream); 36312852Sgabeblack@google.com 36412852Sgabeblack@google.com // Now process the configuration hierarchy and create the SimObjects. 36512997Sgabeblack@google.com ConfigHierarchy configHierarchy(simConfigDB); 36612852Sgabeblack@google.com configHierarchy.build(); 36712997Sgabeblack@google.com configHierarchy.createSimObjects(); 36812997Sgabeblack@google.com 36912997Sgabeblack@google.com // Restore checkpointed state, if any. 37012997Sgabeblack@google.com configHierarchy.unserializeSimObjects(); 37112997Sgabeblack@google.com 37212997Sgabeblack@google.com // Done processing the configuration database. 37312997Sgabeblack@google.com // Check for unreferenced entries. 37412997Sgabeblack@google.com if (simConfigDB.printUnreferenced() && quitOnUnreferenced) { 37512997Sgabeblack@google.com cerr << "Fatal: unreferenced .ini sections/entries." << endl 37612997Sgabeblack@google.com << "If this is not an error, add 'unref_section_ok=y' or " 37712997Sgabeblack@google.com << "'unref_entries_ok=y' to the appropriate sections " 37812852Sgabeblack@google.com << "to suppress this message." << endl; 37912852Sgabeblack@google.com exit(1); 38012852Sgabeblack@google.com } 38112852Sgabeblack@google.com 38212852Sgabeblack@google.com SimObject::regAllStats(); 38312997Sgabeblack@google.com 38412997Sgabeblack@google.com // uncomment the following to get PC-based execution-time profile 38512997Sgabeblack@google.com#ifdef DO_PROFILE 38612997Sgabeblack@google.com init_profile((char *)&_init, (char *)&_fini); 38712852Sgabeblack@google.com#endif 38812852Sgabeblack@google.com 38912852Sgabeblack@google.com // Check to make sure that the stats package is properly initialized 39012852Sgabeblack@google.com Statistics::check(); 39112852Sgabeblack@google.com 39212997Sgabeblack@google.com // Reset to put the stats in a consistent state. 39312852Sgabeblack@google.com Statistics::reset(); 39412852Sgabeblack@google.com 39512852Sgabeblack@google.com // Nothing to simulate if we don't have at least one CPU somewhere. 39612852Sgabeblack@google.com if (BaseCPU::numSimulatedCPUs() == 0) { 39712852Sgabeblack@google.com cerr << "Fatal: no CPUs to simulate." << endl; 39812997Sgabeblack@google.com exit(1); 39912852Sgabeblack@google.com } 40012852Sgabeblack@google.com 40112921Sgabeblack@google.com while (!mainEventQueue.empty()) { 40212997Sgabeblack@google.com assert(curTick <= mainEventQueue.nextTick() && 40312921Sgabeblack@google.com "event scheduled in the past"); 40412997Sgabeblack@google.com 40512997Sgabeblack@google.com // forward current cycle to the time of the first event on the 40612997Sgabeblack@google.com // queue 40712997Sgabeblack@google.com curTick = mainEventQueue.nextTick(); 40812997Sgabeblack@google.com mainEventQueue.serviceOne(); 40912997Sgabeblack@google.com 41012997Sgabeblack@google.com if (async_event) { 41112997Sgabeblack@google.com async_event = false; 41212997Sgabeblack@google.com if (async_dump) { 41312997Sgabeblack@google.com async_dump = false; 41412997Sgabeblack@google.com 41512997Sgabeblack@google.com using namespace Statistics; 41612997Sgabeblack@google.com SetupEvent(Dump, curTick); 41712997Sgabeblack@google.com } 41812997Sgabeblack@google.com 41912997Sgabeblack@google.com if (async_dumpreset) { 42012997Sgabeblack@google.com async_dumpreset = false; 42112997Sgabeblack@google.com 42212997Sgabeblack@google.com using namespace Statistics; 42312997Sgabeblack@google.com SetupEvent(Dump | Reset, curTick); 42412997Sgabeblack@google.com } 42512997Sgabeblack@google.com 42612997Sgabeblack@google.com if (async_exit) { 42712997Sgabeblack@google.com async_exit = false; 42812997Sgabeblack@google.com new SimExitEvent("User requested STOP"); 42912997Sgabeblack@google.com } 43012997Sgabeblack@google.com 43112997Sgabeblack@google.com if (async_io || async_alarm) { 43212921Sgabeblack@google.com async_io = false; 43312921Sgabeblack@google.com async_alarm = false; 43412921Sgabeblack@google.com pollQueue.service(); 43512921Sgabeblack@google.com } 43612921Sgabeblack@google.com } 43712997Sgabeblack@google.com } 43812997Sgabeblack@google.com 43912997Sgabeblack@google.com // This should never happen... every conceivable way for the 44012997Sgabeblack@google.com // simulation to terminate (hit max cycles/insts, signal, 44112997Sgabeblack@google.com // simulated system halts/exits) generates an exit event, so we 44212997Sgabeblack@google.com // should never run out of events on the queue. 44312921Sgabeblack@google.com exitNow("no events on event loop! All CPUs must be idle.", 1); 44412921Sgabeblack@google.com 44512852Sgabeblack@google.com return 0; 446} 447