main.cc revision 1388
1955SN/A/*
2955SN/A * Copyright (c) 2000-2004 The Regents of The University of Michigan
313576Sciro.santilli@arm.com * All rights reserved.
413576Sciro.santilli@arm.com *
513576Sciro.santilli@arm.com * Redistribution and use in source and binary forms, with or without
613576Sciro.santilli@arm.com * modification, are permitted provided that the following conditions are
713576Sciro.santilli@arm.com * met: redistributions of source code must retain the above copyright
813576Sciro.santilli@arm.com * notice, this list of conditions and the following disclaimer;
913576Sciro.santilli@arm.com * redistributions in binary form must reproduce the above copyright
1013576Sciro.santilli@arm.com * notice, this list of conditions and the following disclaimer in the
1113576Sciro.santilli@arm.com * documentation and/or other materials provided with the distribution;
1213576Sciro.santilli@arm.com * neither the name of the copyright holders nor the names of its
1313576Sciro.santilli@arm.com * contributors may be used to endorse or promote products derived from
141762SN/A * this software without specific prior written permission.
15955SN/A *
16955SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17955SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18955SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19955SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20955SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21955SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22955SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23955SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24955SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25955SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26955SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27955SN/A */
28955SN/A
29955SN/A///
30955SN/A/// @file sim/main.cc
31955SN/A///
32955SN/A#include <sys/types.h>
33955SN/A#include <sys/stat.h>
34955SN/A#include <stdlib.h>
35955SN/A#include <signal.h>
36955SN/A
37955SN/A#include <list>
38955SN/A#include <string>
392665Ssaidi@eecs.umich.edu#include <vector>
404762Snate@binkert.org
41955SN/A#include "base/copyright.hh"
4212563Sgabeblack@google.com#include "base/embedfile.hh"
4312563Sgabeblack@google.com#include "base/inifile.hh"
445522Snate@binkert.org#include "base/misc.hh"
456143Snate@binkert.org#include "base/output.hh"
4612371Sgabeblack@google.com#include "base/pollevent.hh"
474762Snate@binkert.org#include "base/statistics.hh"
485522Snate@binkert.org#include "base/str.hh"
49955SN/A#include "base/time.hh"
505522Snate@binkert.org#include "cpu/base_cpu.hh"
5111974Sgabeblack@google.com#include "cpu/full_cpu/smt.hh"
52955SN/A#include "sim/async.hh"
535522Snate@binkert.org#include "sim/builder.hh"
544202Sbinkertn@umich.edu#include "sim/configfile.hh"
555742Snate@binkert.org#include "sim/host.hh"
56955SN/A#include "sim/sim_events.hh"
574381Sbinkertn@umich.edu#include "sim/sim_exit.hh"
584381Sbinkertn@umich.edu#include "sim/sim_object.hh"
5912246Sgabeblack@google.com#include "sim/stat_control.hh"
6012246Sgabeblack@google.com#include "sim/stats.hh"
618334Snate@binkert.org#include "sim/universe.hh"
62955SN/A#include "sim/pyconfig/pyconfig.hh"
63955SN/A
644202Sbinkertn@umich.eduusing namespace std;
65955SN/A
664382Sbinkertn@umich.edu// See async.h.
674382Sbinkertn@umich.eduvolatile bool async_event = false;
684382Sbinkertn@umich.eduvolatile bool async_dump = false;
696654Snate@binkert.orgvolatile bool async_dumpreset = false;
705517Snate@binkert.orgvolatile bool async_exit = false;
718614Sgblack@eecs.umich.eduvolatile bool async_io = false;
727674Snate@binkert.orgvolatile bool async_alarm = false;
736143Snate@binkert.org
746143Snate@binkert.org/// Stats signal handler.
756143Snate@binkert.orgvoid
7612302Sgabeblack@google.comdumpStatsHandler(int sigtype)
7712302Sgabeblack@google.com{
7812302Sgabeblack@google.com    async_event = true;
7912371Sgabeblack@google.com    async_dump = true;
8012371Sgabeblack@google.com}
8112371Sgabeblack@google.com
8212371Sgabeblack@google.comvoid
8312371Sgabeblack@google.comdumprstStatsHandler(int sigtype)
8412371Sgabeblack@google.com{
8512371Sgabeblack@google.com    async_event = true;
8612371Sgabeblack@google.com    async_dumpreset = true;
8712371Sgabeblack@google.com}
8812371Sgabeblack@google.com
8912371Sgabeblack@google.com/// Exit signal handler.
9012371Sgabeblack@google.comvoid
9112371Sgabeblack@google.comexitNowHandler(int sigtype)
9212371Sgabeblack@google.com{
9312371Sgabeblack@google.com    async_event = true;
9412371Sgabeblack@google.com    async_exit = true;
9512371Sgabeblack@google.com}
9612371Sgabeblack@google.com
9712371Sgabeblack@google.com/// Abort signal handler.
9812371Sgabeblack@google.comvoid
9912371Sgabeblack@google.comabortHandler(int sigtype)
10012371Sgabeblack@google.com{
10112371Sgabeblack@google.com    cerr << "Program aborted at cycle " << curTick << endl;
10212371Sgabeblack@google.com
10312371Sgabeblack@google.com#if TRACING_ON
10412371Sgabeblack@google.com    // dump trace buffer, if there is one
10512371Sgabeblack@google.com    Trace::theLog.dump(cerr);
10612371Sgabeblack@google.com#endif
10712371Sgabeblack@google.com}
10812371Sgabeblack@google.com
10912371Sgabeblack@google.com/// Simulator executable name
11012371Sgabeblack@google.comconst char *myProgName = "";
11112371Sgabeblack@google.com
11212371Sgabeblack@google.com/// Show brief help message.
11312371Sgabeblack@google.comvoid
11412371Sgabeblack@google.comshowBriefHelp(ostream &out)
11512371Sgabeblack@google.com{
11612371Sgabeblack@google.com    char *prog = basename(myProgName);
11712371Sgabeblack@google.com
11812371Sgabeblack@google.com    ccprintf(out, "Usage:\n");
11912371Sgabeblack@google.com    ccprintf(out,
12012371Sgabeblack@google.com"%s [-d <dir>] [-E <var>[=<val>]] [-I <dir>] [-P <python>]\n"
12112371Sgabeblack@google.com"        [--<var>=<val>] <config file>\n"
12212371Sgabeblack@google.com"\n"
12312371Sgabeblack@google.com"   -d            set the output directory to <dir>\n"
12412371Sgabeblack@google.com"   -E            set the environment variable <var> to <val> (or 'True')\n"
12512371Sgabeblack@google.com"   -I            add the directory <dir> to python's path\n"
12612302Sgabeblack@google.com"   -P            execute <python> directly in the configuration\n"
12712371Sgabeblack@google.com"   --var=val     set the python variable <var> to '<val>'\n"
12812302Sgabeblack@google.com"   <configfile>  config file name (.py or .mpy)\n",
12912371Sgabeblack@google.com             prog);
13012302Sgabeblack@google.com
13112302Sgabeblack@google.com    ccprintf(out, "%s -X\n    -X            extract embedded files\n", prog);
13212371Sgabeblack@google.com    ccprintf(out, "%s -h\n    -h            print long help\n", prog);
13312371Sgabeblack@google.com}
13412371Sgabeblack@google.com
13512371Sgabeblack@google.com/// Show verbose help message.  Includes parameter listing from
13612302Sgabeblack@google.com/// showBriefHelp(), plus an exhaustive list of ini-file parameters
13712371Sgabeblack@google.com/// and SimObjects (with their parameters).
13812371Sgabeblack@google.comvoid
13912371Sgabeblack@google.comshowLongHelp(ostream &out)
14012371Sgabeblack@google.com{
14111983Sgabeblack@google.com    showBriefHelp(out);
1426143Snate@binkert.org
1438233Snate@binkert.org    out << endl
14412302Sgabeblack@google.com        << endl
1456143Snate@binkert.org        << "-----------------" << endl
1466143Snate@binkert.org        << "Global Parameters" << endl
14712302Sgabeblack@google.com        << "-----------------" << endl
1484762Snate@binkert.org        << endl;
1496143Snate@binkert.org
1508233Snate@binkert.org    ParamContext::describeAllContexts(out);
1518233Snate@binkert.org
15212302Sgabeblack@google.com    out << endl
15312302Sgabeblack@google.com        << endl
1546143Snate@binkert.org        << "-----------------" << endl
15512362Sgabeblack@google.com        << "Simulator Objects" << endl
15612362Sgabeblack@google.com        << "-----------------" << endl
15712362Sgabeblack@google.com        << endl;
15812362Sgabeblack@google.com
15912302Sgabeblack@google.com    SimObjectClass::describeAllClasses(out);
16012302Sgabeblack@google.com}
16112302Sgabeblack@google.com
16212302Sgabeblack@google.com/// Print welcome message.
16312302Sgabeblack@google.comvoid
16412363Sgabeblack@google.comsayHello(ostream &out)
16512363Sgabeblack@google.com{
16612363Sgabeblack@google.com    extern const char *compileDate;	// from date.cc
16712363Sgabeblack@google.com
16812302Sgabeblack@google.com    ccprintf(out, "M5 Simulator System\n");
16912363Sgabeblack@google.com    // display copyright
17012363Sgabeblack@google.com    ccprintf(out, "%s\n", briefCopyright);
17112363Sgabeblack@google.com    ccprintf(out, "M5 compiled on %d\n", compileDate);
17212363Sgabeblack@google.com
17312363Sgabeblack@google.com    char *host = getenv("HOSTNAME");
1748233Snate@binkert.org    if (!host)
1756143Snate@binkert.org        host = getenv("HOST");
1766143Snate@binkert.org
1776143Snate@binkert.org    if (host)
1786143Snate@binkert.org        ccprintf(out, "M5 executing on %s\n", host);
1796143Snate@binkert.org
1806143Snate@binkert.org    ccprintf(out, "M5 simulation started %s\n", Time::start);
1816143Snate@binkert.org}
1826143Snate@binkert.org
1836143Snate@binkert.org///
1847065Snate@binkert.org/// Echo the command line for posterity in such a way that it can be
1856143Snate@binkert.org/// used to rerun the same simulation (given the same .ini files).
18612362Sgabeblack@google.com///
18712362Sgabeblack@google.comvoid
18812362Sgabeblack@google.comechoCommandLine(int argc, char **argv, ostream &out)
18912362Sgabeblack@google.com{
19012362Sgabeblack@google.com    out << "command line: " << argv[0];
19112362Sgabeblack@google.com    for (int i = 1; i < argc; i++) {
19212362Sgabeblack@google.com        string arg(argv[i]);
19312362Sgabeblack@google.com
19412362Sgabeblack@google.com        out << ' ';
19512362Sgabeblack@google.com
19612362Sgabeblack@google.com        // If the arg contains spaces, we need to quote it.
19712362Sgabeblack@google.com        // The rest of this is overkill to make it look purty.
1988233Snate@binkert.org
1998233Snate@binkert.org        // print dashes first outside quotes
2008233Snate@binkert.org        int non_dash_pos = arg.find_first_not_of("-");
2018233Snate@binkert.org        out << arg.substr(0, non_dash_pos);	// print dashes
2028233Snate@binkert.org        string body = arg.substr(non_dash_pos);	// the rest
2038233Snate@binkert.org
2048233Snate@binkert.org        // if it's an assignment, handle the lhs & rhs separately
2058233Snate@binkert.org        int eq_pos = body.find("=");
2068233Snate@binkert.org        if (eq_pos == string::npos) {
2078233Snate@binkert.org            out << quote(body);
2088233Snate@binkert.org        }
2098233Snate@binkert.org        else {
2108233Snate@binkert.org            string lhs(body.substr(0, eq_pos));
2118233Snate@binkert.org            string rhs(body.substr(eq_pos + 1));
2128233Snate@binkert.org
2138233Snate@binkert.org            out << quote(lhs) << "=" << quote(rhs);
2148233Snate@binkert.org        }
2158233Snate@binkert.org    }
2168233Snate@binkert.org    out << endl << endl;
2178233Snate@binkert.org}
2188233Snate@binkert.org
2196143Snate@binkert.orgchar *
2206143Snate@binkert.orggetOptionString(int &index, int argc, char **argv)
2216143Snate@binkert.org{
2226143Snate@binkert.org    char *option = argv[index] + 2;
2236143Snate@binkert.org    if (*option != '\0')
2246143Snate@binkert.org        return option;
2259982Satgutier@umich.edu
22613576Sciro.santilli@arm.com    // We didn't find an argument, it must be in the next variable.
22713576Sciro.santilli@arm.com    if (++index >= argc)
22813576Sciro.santilli@arm.com        panic("option string for option '%s' not found", argv[index - 1]);
22913576Sciro.santilli@arm.com
23013576Sciro.santilli@arm.com    return argv[index];
23113576Sciro.santilli@arm.com}
23213576Sciro.santilli@arm.com
23313576Sciro.santilli@arm.comint
23413576Sciro.santilli@arm.commain(int argc, char **argv)
23513576Sciro.santilli@arm.com{
23613576Sciro.santilli@arm.com    // Save off program name
23713576Sciro.santilli@arm.com    myProgName = argv[0];
23813576Sciro.santilli@arm.com
23913576Sciro.santilli@arm.com    signal(SIGFPE, SIG_IGN);		// may occur on misspeculated paths
24013576Sciro.santilli@arm.com    signal(SIGTRAP, SIG_IGN);
24113576Sciro.santilli@arm.com    signal(SIGUSR1, dumpStatsHandler);		// dump intermediate stats
24213576Sciro.santilli@arm.com    signal(SIGUSR2, dumprstStatsHandler);	// dump and reset stats
24313576Sciro.santilli@arm.com    signal(SIGINT, exitNowHandler);		// dump final stats and exit
24413576Sciro.santilli@arm.com    signal(SIGABRT, abortHandler);
24513576Sciro.santilli@arm.com
24613576Sciro.santilli@arm.com    sayHello(cerr);
24713576Sciro.santilli@arm.com
24813576Sciro.santilli@arm.com    bool configfile_found = false;
24913576Sciro.santilli@arm.com    PythonConfig pyconfig;
25013576Sciro.santilli@arm.com    string outdir;
25113576Sciro.santilli@arm.com
25213576Sciro.santilli@arm.com    // Parse command-line options.
25313576Sciro.santilli@arm.com    // Since most of the complex options are handled through the
25413576Sciro.santilli@arm.com    // config database, we don't mess with getopts, and just parse
25513576Sciro.santilli@arm.com    // manually.
25613576Sciro.santilli@arm.com    for (int i = 1; i < argc; ++i) {
25713576Sciro.santilli@arm.com        char *arg_str = argv[i];
25813630Sciro.santilli@arm.com
25913630Sciro.santilli@arm.com        // if arg starts with '--', parse as a special python option
26013576Sciro.santilli@arm.com        // of the format --<python var>=<string value>, if the arg
26113576Sciro.santilli@arm.com        // starts with '-', it should be a simulator option with a
26213576Sciro.santilli@arm.com        // format similar to getopt.  In any other case, treat the
26313576Sciro.santilli@arm.com        // option as a configuration file name and load it.
26413576Sciro.santilli@arm.com        if (arg_str[0] == '-' && arg_str[1] == '-') {
26513576Sciro.santilli@arm.com            string str = &arg_str[2];
26613576Sciro.santilli@arm.com            string var, val;
26713576Sciro.santilli@arm.com
26813576Sciro.santilli@arm.com            if (!split_first(str, var, val, '='))
26913576Sciro.santilli@arm.com                panic("Could not parse configuration argument '%s'\n"
27013576Sciro.santilli@arm.com                      "Expecting --<variable>=<value>\n", arg_str);
27113576Sciro.santilli@arm.com
27213576Sciro.santilli@arm.com            pyconfig.setVariable(var, val);
27313576Sciro.santilli@arm.com        } else if (arg_str[0] == '-') {
27413576Sciro.santilli@arm.com            char *option;
27513576Sciro.santilli@arm.com            string var, val;
27613576Sciro.santilli@arm.com
27713576Sciro.santilli@arm.com            // switch on second char
27813576Sciro.santilli@arm.com            switch (arg_str[1]) {
27913576Sciro.santilli@arm.com              case 'd':
28013576Sciro.santilli@arm.com                outdir = getOptionString(i, argc, argv);
28113576Sciro.santilli@arm.com                break;
28213576Sciro.santilli@arm.com
28313576Sciro.santilli@arm.com              case 'h':
28413576Sciro.santilli@arm.com                showLongHelp(cerr);
28513576Sciro.santilli@arm.com                exit(1);
28613576Sciro.santilli@arm.com
28713576Sciro.santilli@arm.com              case 'E':
28813576Sciro.santilli@arm.com                option = getOptionString(i, argc, argv);
28913576Sciro.santilli@arm.com                if (!split_first(option, var, val, '='))
29013576Sciro.santilli@arm.com                    val = "True";
29113576Sciro.santilli@arm.com
29213576Sciro.santilli@arm.com                if (setenv(var.c_str(), val.c_str(), true) == -1)
29313576Sciro.santilli@arm.com                    panic("setenv: %s\n", strerror(errno));
29413576Sciro.santilli@arm.com                break;
29513576Sciro.santilli@arm.com
29613576Sciro.santilli@arm.com              case 'I':
29713577Sciro.santilli@arm.com                option = getOptionString(i, argc, argv);
29813577Sciro.santilli@arm.com                pyconfig.addPath(option);
29913577Sciro.santilli@arm.com                break;
3006143Snate@binkert.org
30112302Sgabeblack@google.com              case 'P':
30212302Sgabeblack@google.com                option = getOptionString(i, argc, argv);
30312302Sgabeblack@google.com                pyconfig.writeLine(option);
30412302Sgabeblack@google.com                break;
30512302Sgabeblack@google.com
30612302Sgabeblack@google.com              case 'X': {
30712302Sgabeblack@google.com                  list<EmbedFile> lst;
30812302Sgabeblack@google.com                  EmbedMap::all(lst);
30911983Sgabeblack@google.com                  list<EmbedFile>::iterator i = lst.begin();
31011983Sgabeblack@google.com                  list<EmbedFile>::iterator end = lst.end();
31111983Sgabeblack@google.com
31212302Sgabeblack@google.com                  while (i != end) {
31312302Sgabeblack@google.com                      cprintf("Embedded File: %s\n", i->name);
31412302Sgabeblack@google.com                      cout.write(i->data, i->length);
31512302Sgabeblack@google.com                      ++i;
31612302Sgabeblack@google.com                  }
31712302Sgabeblack@google.com
31811983Sgabeblack@google.com                  return 0;
3196143Snate@binkert.org              }
32012305Sgabeblack@google.com
32112302Sgabeblack@google.com              default:
32212302Sgabeblack@google.com                showBriefHelp(cerr);
32312302Sgabeblack@google.com                panic("invalid argument '%s'\n", arg_str);
3246143Snate@binkert.org            }
3256143Snate@binkert.org        } else {
3266143Snate@binkert.org            string file(arg_str);
3275522Snate@binkert.org            string base, ext;
3286143Snate@binkert.org
3296143Snate@binkert.org            if (!split_last(file, base, ext, '.') ||
3306143Snate@binkert.org                ext != "py" && ext != "mpy")
3319982Satgutier@umich.edu                panic("Config file '%s' must end in '.py' or '.mpy'\n", file);
33212302Sgabeblack@google.com
33312302Sgabeblack@google.com            pyconfig.load(file);
33412302Sgabeblack@google.com            configfile_found = true;
3356143Snate@binkert.org        }
3366143Snate@binkert.org    }
3376143Snate@binkert.org
3386143Snate@binkert.org    if (outdir.empty()) {
3395522Snate@binkert.org        char *env = getenv("OUTPUT_DIR");
3405522Snate@binkert.org        outdir = env ? env : ".";
3415522Snate@binkert.org    }
3425522Snate@binkert.org
3435604Snate@binkert.org    simout.setDirectory(outdir);
3445604Snate@binkert.org
3456143Snate@binkert.org    char *env = getenv("CONFIG_OUTPUT");
3466143Snate@binkert.org    if (!env)
3474762Snate@binkert.org        env = "config.out";
3484762Snate@binkert.org    configStream = simout.find(env);
3496143Snate@binkert.org
3506727Ssteve.reinhardt@amd.com    if (!configfile_found)
3516727Ssteve.reinhardt@amd.com        panic("no configuration file specified!");
3526727Ssteve.reinhardt@amd.com
3534762Snate@binkert.org    // The configuration database is now complete; start processing it.
3546143Snate@binkert.org    IniFile inifile;
3556143Snate@binkert.org    if (!pyconfig.output(inifile))
3566143Snate@binkert.org        panic("Error processing python code");
3576143Snate@binkert.org
3586727Ssteve.reinhardt@amd.com    // Initialize statistics database
3596143Snate@binkert.org    Stats::InitSimStats();
3607674Snate@binkert.org
3617674Snate@binkert.org    // Now process the configuration hierarchy and create the SimObjects.
3625604Snate@binkert.org    ConfigHierarchy configHierarchy(inifile);
3636143Snate@binkert.org    configHierarchy.build();
3646143Snate@binkert.org    configHierarchy.createSimObjects();
3656143Snate@binkert.org
3664762Snate@binkert.org    // Parse and check all non-config-hierarchy parameters.
3676143Snate@binkert.org    ParamContext::parseAllContexts(inifile);
3684762Snate@binkert.org    ParamContext::checkAllContexts();
3694762Snate@binkert.org
3704762Snate@binkert.org    // Print hello message to stats file if it's actually a file.  If
3716143Snate@binkert.org    // it's not (i.e. it's cout or cerr) then we already did it above.
3726143Snate@binkert.org    if (simout.isFile(*outputStream))
3734762Snate@binkert.org        sayHello(*outputStream);
37412302Sgabeblack@google.com
37512302Sgabeblack@google.com    // Echo command line and all parameter settings to stats file as well.
3768233Snate@binkert.org    echoCommandLine(argc, argv, *outputStream);
37712302Sgabeblack@google.com    ParamContext::showAllContexts(*configStream);
3786143Snate@binkert.org
3796143Snate@binkert.org    // Do a second pass to finish initializing the sim objects
3804762Snate@binkert.org    SimObject::initAll();
3816143Snate@binkert.org
3824762Snate@binkert.org    // Restore checkpointed state, if any.
3839396Sandreas.hansson@arm.com    configHierarchy.unserializeSimObjects();
3849396Sandreas.hansson@arm.com
3859396Sandreas.hansson@arm.com    // Done processing the configuration database.
38612302Sgabeblack@google.com    // Check for unreferenced entries.
38712302Sgabeblack@google.com    if (inifile.printUnreferenced())
38812302Sgabeblack@google.com        panic("unreferenced sections/entries in the intermediate ini file");
3899396Sandreas.hansson@arm.com
3909396Sandreas.hansson@arm.com    SimObject::regAllStats();
3919396Sandreas.hansson@arm.com
3929396Sandreas.hansson@arm.com    // uncomment the following to get PC-based execution-time profile
3939396Sandreas.hansson@arm.com#ifdef DO_PROFILE
3949396Sandreas.hansson@arm.com    init_profile((char *)&_init, (char *)&_fini);
3959396Sandreas.hansson@arm.com#endif
3969930Sandreas.hansson@arm.com
3979930Sandreas.hansson@arm.com    // Check to make sure that the stats package is properly initialized
3989396Sandreas.hansson@arm.com    Stats::check();
3996143Snate@binkert.org
40012797Sgabeblack@google.com    // Reset to put the stats in a consistent state.
40112797Sgabeblack@google.com    Stats::reset();
40212797Sgabeblack@google.com
4038235Snate@binkert.org    // Nothing to simulate if we don't have at least one CPU somewhere.
40412797Sgabeblack@google.com    if (BaseCPU::numSimulatedCPUs() == 0) {
40512797Sgabeblack@google.com        cerr << "Fatal: no CPUs to simulate." << endl;
40612797Sgabeblack@google.com        exit(1);
40712797Sgabeblack@google.com    }
40812797Sgabeblack@google.com
40912797Sgabeblack@google.com    warn("Entering event queue.  Starting simulation...\n");
41012797Sgabeblack@google.com    SimStartup();
41112797Sgabeblack@google.com    while (!mainEventQueue.empty()) {
41212797Sgabeblack@google.com        assert(curTick <= mainEventQueue.nextTick() &&
41312797Sgabeblack@google.com               "event scheduled in the past");
41412797Sgabeblack@google.com
41512797Sgabeblack@google.com        // forward current cycle to the time of the first event on the
41612797Sgabeblack@google.com        // queue
41712797Sgabeblack@google.com        curTick = mainEventQueue.nextTick();
41812797Sgabeblack@google.com        mainEventQueue.serviceOne();
41912757Sgabeblack@google.com
42012757Sgabeblack@google.com        if (async_event) {
42112797Sgabeblack@google.com            async_event = false;
42212797Sgabeblack@google.com            if (async_dump) {
42312797Sgabeblack@google.com                async_dump = false;
42412757Sgabeblack@google.com
42512757Sgabeblack@google.com                using namespace Stats;
42612757Sgabeblack@google.com                SetupEvent(Dump, curTick);
42712757Sgabeblack@google.com            }
4288235Snate@binkert.org
42912302Sgabeblack@google.com            if (async_dumpreset) {
4308235Snate@binkert.org                async_dumpreset = false;
4318235Snate@binkert.org
43212757Sgabeblack@google.com                using namespace Stats;
4338235Snate@binkert.org                SetupEvent(Dump | Reset, curTick);
4348235Snate@binkert.org            }
4358235Snate@binkert.org
43612757Sgabeblack@google.com            if (async_exit) {
43712313Sgabeblack@google.com                async_exit = false;
43812797Sgabeblack@google.com                new SimExitEvent("User requested STOP");
43912797Sgabeblack@google.com            }
44012797Sgabeblack@google.com
44112797Sgabeblack@google.com            if (async_io || async_alarm) {
44212797Sgabeblack@google.com                async_io = false;
44312797Sgabeblack@google.com                async_alarm = false;
44412797Sgabeblack@google.com                pollQueue.service();
44512797Sgabeblack@google.com            }
44612797Sgabeblack@google.com        }
44712797Sgabeblack@google.com    }
44812797Sgabeblack@google.com
44912797Sgabeblack@google.com    // This should never happen... every conceivable way for the
45012797Sgabeblack@google.com    // simulation to terminate (hit max cycles/insts, signal,
45112797Sgabeblack@google.com    // simulated system halts/exits) generates an exit event, so we
45213706Sgabeblack@google.com    // should never run out of events on the queue.
45313706Sgabeblack@google.com    exitNow("no events on event loop!  All CPUs must be idle.", 1);
45413706Sgabeblack@google.com
45513706Sgabeblack@google.com    return 0;
45612797Sgabeblack@google.com}
45712797Sgabeblack@google.com