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