main.cc revision 329
12SN/A/*
21762SN/A * Copyright (c) 2003 The Regents of The University of Michigan
32SN/A * All rights reserved.
42SN/A *
52SN/A * Redistribution and use in source and binary forms, with or without
62SN/A * modification, are permitted provided that the following conditions are
72SN/A * met: redistributions of source code must retain the above copyright
82SN/A * notice, this list of conditions and the following disclaimer;
92SN/A * redistributions in binary form must reproduce the above copyright
102SN/A * notice, this list of conditions and the following disclaimer in the
112SN/A * documentation and/or other materials provided with the distribution;
122SN/A * neither the name of the copyright holders nor the names of its
132SN/A * contributors may be used to endorse or promote products derived from
142SN/A * this software without specific prior written permission.
152SN/A *
162SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
172SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
182SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
192SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
202SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
212SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
222SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
232SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
242SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
252SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
262SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
272665Ssaidi@eecs.umich.edu */
282665Ssaidi@eecs.umich.edu
292665Ssaidi@eecs.umich.edu///
302665Ssaidi@eecs.umich.edu/// @file sim/main.cc
312SN/A///
322SN/A#include <sys/types.h>
332623SN/A#include <sys/stat.h>
342623SN/A#include <stdlib.h>
352SN/A#include <signal.h>
364182Sgblack@eecs.umich.edu
371354SN/A#include <string>
381858SN/A#include <vector>
391717SN/A
402683Sktlim@umich.edu#include "base/copyright.hh"
411354SN/A#include "base/inifile.hh"
421354SN/A#include "base/misc.hh"
432387SN/A#include "base/pollevent.hh"
442387SN/A#include "base/statistics.hh"
452387SN/A#include "cpu/base_cpu.hh"
4656SN/A#include "cpu/full_cpu/smt.hh"
472SN/A#include "sim/async.hh"
482SN/A#include "sim/builder.hh"
491858SN/A#include "sim/configfile.hh"
502SN/A#include "sim/host.hh"
513453Sgblack@eecs.umich.edu#include "sim/sim_events.hh"
523453Sgblack@eecs.umich.edu#include "sim/sim_exit.hh"
533453Sgblack@eecs.umich.edu#include "sim/sim_object.hh"
543453Sgblack@eecs.umich.edu#include "sim/sim_stats.hh"
553453Sgblack@eecs.umich.edu#include "sim/sim_time.hh"
562462SN/A
572SN/Ausing namespace std;
58715SN/A
59715SN/A// See async.h.
60715SN/Avolatile bool async_event = false;
61715SN/Avolatile bool async_dump = false;
622SN/Avolatile bool async_dumpreset = false;
632SN/Avolatile bool async_exit = false;
643960Sgblack@eecs.umich.eduvolatile bool async_io = false;
653960Sgblack@eecs.umich.eduvolatile bool async_alarm = false;
663960Sgblack@eecs.umich.edu
674182Sgblack@eecs.umich.edu/// Stats signal handler.
684182Sgblack@eecs.umich.eduvoid
694182Sgblack@eecs.umich.edudumpStatsHandler(int sigtype)
704182Sgblack@eecs.umich.edu{
712680Sktlim@umich.edu    async_event = true;
72237SN/A    async_dump = true;
732SN/A}
742SN/A
752SN/Avoid
762SN/AdumprstStatsHandler(int sigtype)
772SN/A{
782420SN/A    async_event = true;
792623SN/A    async_dumpreset = true;
802SN/A}
812107SN/A
822159SN/A/// Exit signal handler.
832455SN/Avoid
842455SN/AexitNowHandler(int sigtype)
852386SN/A{
862623SN/A    async_event = true;
872SN/A    async_exit = true;
881371SN/A}
892SN/A
902SN/A/// Simulator executable name
912SN/Aconst char *myProgName = "";
922SN/A
932SN/A/// Show brief help message.
942SN/Astatic void
952SN/AshowBriefHelp(ostream &out)
962SN/A{
972SN/A    out << "Usage: " << myProgName
982SN/A         << " [-hn] [-Dname[=def]] [-Uname] [-I[dir]] "
992SN/A         << "[--<section>:<param>=<value>] [<config file> ...]" << endl
1001400SN/A         << "   -h: print long help (including parameter listing)" << endl
1011400SN/A         << "   -n: don't load default.ini" << endl
1021400SN/A         << "   -u: don't quit on unreferenced parameters" << endl
1031858SN/A         << "   -D,-U,-I: passed to cpp for preprocessing .ini files" << endl;
1043453Sgblack@eecs.umich.edu}
1053453Sgblack@eecs.umich.edu
1062SN/A/// Show verbose help message.  Includes parameter listing from
1071400SN/A/// showBriefHelp(), plus an exhaustive list of ini-file parameters
1082SN/A/// and SimObjects (with their parameters).
1091400SN/Astatic void
1102623SN/AshowLongHelp(ostream &out)
1112623SN/A{
1122SN/A    showBriefHelp(out);
1131400SN/A
1142683Sktlim@umich.edu    out << endl
1152683Sktlim@umich.edu        << endl
1162190SN/A        << "-----------------" << endl
1172683Sktlim@umich.edu        << "Global Parameters" << endl
1182683Sktlim@umich.edu        << "-----------------" << endl
1192683Sktlim@umich.edu        << endl;
1202680Sktlim@umich.edu
1212SN/A    ParamContext::describeAllContexts(out);
1221858SN/A
1232SN/A    out << endl
1242SN/A        << endl
1252SN/A        << "-----------------" << endl
1262SN/A        << "Simulator Objects" << endl
1272SN/A        << "-----------------" << endl
1282SN/A        << endl;
1294181Sgblack@eecs.umich.edu
1304181Sgblack@eecs.umich.edu    SimObjectClass::describeAllClasses(out);
1314182Sgblack@eecs.umich.edu}
1324182Sgblack@eecs.umich.edu
1332SN/A/// Print welcome message.
1342566SN/Astatic void
1354040Ssaidi@eecs.umich.edusayHello(ostream &out)
1362566SN/A{
1372107SN/A    extern const char *compileDate;	// from date.cc
1383276Sgblack@eecs.umich.edu
1391469SN/A    ccprintf(out, "M5 Simulator System\n");
1404377Sgblack@eecs.umich.edu    // display copyright
1414377Sgblack@eecs.umich.edu    ccprintf(out, "%s\n", briefCopyright);
1424377Sgblack@eecs.umich.edu    ccprintf(out, "M5 compiled on %d\n", compileDate);
1434377Sgblack@eecs.umich.edu
1444377Sgblack@eecs.umich.edu    char *host = getenv("HOSTNAME");
1454377Sgblack@eecs.umich.edu    if (!host)
1462623SN/A        host = getenv("HOST");
1472662Sstever@eecs.umich.edu
1482623SN/A    if (host)
1492623SN/A        ccprintf(out, "M5 executing on %s\n", host);
1502623SN/A
151180SN/A    ccprintf(out, "M5 simulation started %s\n", Time::start);
152393SN/A}
153393SN/A
1542SN/A///
1552SN/A/// Echo the command line for posterity in such a way that it can be
156334SN/A/// used to rerun the same simulation (given the same .ini files).
157334SN/A///
1582SN/Astatic void
1592SN/AechoCommandLine(int argc, char **argv, ostream &out)
1602SN/A{
161334SN/A    out << "command line: " << argv[0];
162729SN/A    for (int i = 1; i < argc; i++) {
163707SN/A        string arg(argv[i]);
164707SN/A
165707SN/A        out << ' ';
166707SN/A
167707SN/A        // If the arg contains spaces, we need to quote it.
1682SN/A        // The rest of this is overkill to make it look purty.
1694564Sgblack@eecs.umich.edu
1704564Sgblack@eecs.umich.edu        // print dashes first outside quotes
1714564Sgblack@eecs.umich.edu        int non_dash_pos = arg.find_first_not_of("-");
1722SN/A        out << arg.substr(0, non_dash_pos);	// print dashes
173729SN/A        string body = arg.substr(non_dash_pos);	// the rest
1742SN/A
175124SN/A        // if it's an assignment, handle the lhs & rhs separately
176124SN/A        int eq_pos = body.find("=");
177334SN/A        if (eq_pos == string::npos) {
178124SN/A            out << quote(body);
1792SN/A        }
180729SN/A        else {
181729SN/A            string lhs(body.substr(0, eq_pos));
1822SN/A            string rhs(body.substr(eq_pos + 1));
1832390SN/A
184729SN/A            out << quote(lhs) << "=" << quote(rhs);
1852SN/A        }
1862SN/A    }
1872390SN/A    out << endl << endl;
1882390SN/A}
1892390SN/A
1902390SN/A
1912390SN/A///
192729SN/A/// The simulator configuration database.  This is the union of all
1932SN/A/// specified .ini files.  This shouldn't need to be visible outside
1942SN/A/// this file, as it is passed as a parameter to all the param-parsing
1952390SN/A/// routines.
1962390SN/A///
1972390SN/Astatic IniFile simConfigDB;
1982390SN/A
199217SN/A/// Check for a default.ini file and load it if necessary.
200237SN/Astatic void
2012SN/AhandleDefaultIni(bool &loadIt, vector<char *> &cppArgs)
2021371SN/A{
2031371SN/A    struct stat sb;
2042623SN/A
2053918Ssaidi@eecs.umich.edu    if (loadIt) {
2063918Ssaidi@eecs.umich.edu        if (stat("default.ini", &sb) == 0) {
2071371SN/A            if (!simConfigDB.loadCPP("default.ini", cppArgs)) {
208581SN/A                cout << "Error processing file default.ini" << endl;
2092SN/A                exit(1);
2102SN/A            }
2112SN/A        }
2122SN/A
213753SN/A        // set this whether it actually was found or not, so we don't
2142SN/A        // bother to check again next time
2152SN/A        loadIt = false;
2162SN/A    }
217594SN/A}
2184661Sksewell@umich.edu
219595SN/A
220594SN/A/// M5 entry point.
221595SN/Aint
222705SN/Amain(int argc, char **argv)
223726SN/A{
224726SN/A    // Save off program name
225726SN/A    myProgName = argv[0];
226726SN/A
227726SN/A    signal(SIGFPE, SIG_IGN);		// may occur on misspeculated paths
228726SN/A    signal(SIGPIPE, SIG_IGN);
229726SN/A    signal(SIGTRAP, SIG_IGN);
230726SN/A    signal(SIGUSR1, dumpStatsHandler);		// dump intermediate stats
231726SN/A    signal(SIGUSR2, dumprstStatsHandler);	// dump and reset stats
232726SN/A    signal(SIGINT, exitNowHandler);		// dump final stats and exit
233705SN/A
2343735Sstever@eecs.umich.edu    sayHello(cerr);
235726SN/A
2362683Sktlim@umich.edu    // Initialize statistics database
237726SN/A    initBaseStats();
238705SN/A
2393735Sstever@eecs.umich.edu    vector<char *> cppArgs;
240726SN/A
241726SN/A    // Should we use default.ini if it exists?  By default, yes.  (Use
2422683Sktlim@umich.edu    // -n to override.)
243726SN/A    bool loadDefaultIni = true;
244705SN/A
2453735Sstever@eecs.umich.edu    // Should we quit if there are unreferenced parameters?  By
246726SN/A    // default, yes... it's a good way of catching typos in
247726SN/A    // section/parameter names (which otherwise go by silently).  Use
2482683Sktlim@umich.edu    // -u to override.
249726SN/A    bool quitOnUnreferenced = true;
250705SN/A
2513735Sstever@eecs.umich.edu    // Parse command-line options.  The tricky part here is figuring
2523735Sstever@eecs.umich.edu    // out whether to look for & load default.ini, and if needed,
253726SN/A    // doing so at the right time w.r.t. processing the other
254726SN/A    // parameters.
2552683Sktlim@umich.edu    //
2562455SN/A    // Since most of the complex options are handled through the
2572455SN/A    // config database, we don't mess with getopts, and just parse
2583735Sstever@eecs.umich.edu    // manually.
2592455SN/A    for (int i = 1; i < argc; ++i) {
2602455SN/A        char *arg_str = argv[i];
2612683Sktlim@umich.edu
262726SN/A        // if arg starts with '-', parse as option,
263705SN/A        // else treat it as a configuration file name and load it
2643735Sstever@eecs.umich.edu        if (arg_str[0] == '-') {
265726SN/A
2662683Sktlim@umich.edu            // switch on second char
267726SN/A            switch (arg_str[1]) {
268705SN/A              case 'h':
2693735Sstever@eecs.umich.edu                // -h: show help
2703735Sstever@eecs.umich.edu                showLongHelp(cerr);
271726SN/A                exit(1);
272726SN/A
2732683Sktlim@umich.edu              case 'n':
274726SN/A                // -n: don't load default.ini
275705SN/A                if (!loadDefaultIni) {
2763735Sstever@eecs.umich.edu                    cerr << "Warning: -n option needs to precede any "
277726SN/A                         << "explicit configuration file name " << endl
278726SN/A                         << "         or command-line configuration parameter."
2792683Sktlim@umich.edu                         << endl;
280726SN/A                }
281726SN/A                loadDefaultIni = false;
2823735Sstever@eecs.umich.edu                break;
2833735Sstever@eecs.umich.edu
284726SN/A              case 'u':
285726SN/A                // -u: don't quit on unreferenced parameters
2862683Sktlim@umich.edu                quitOnUnreferenced = false;
2872455SN/A                break;
2882455SN/A
2893735Sstever@eecs.umich.edu              case 'D':
2903735Sstever@eecs.umich.edu              case 'U':
2912455SN/A              case 'I':
2922455SN/A                // cpp options: record & pass to cpp.  Note that these
2932683Sktlim@umich.edu                // cannot have spaces, i.e., '-Dname=val' is OK, but
294726SN/A                // '-D name=val' is not.  I don't consider this a
295705SN/A                // problem, since even though gnu cpp accepts the
2962683Sktlim@umich.edu                // latter, other cpp implementations do not (Tru64,
2972683Sktlim@umich.edu                // for one).
2982683Sktlim@umich.edu                cppArgs.push_back(arg_str);
2992447SN/A                break;
3002683Sktlim@umich.edu
3012683Sktlim@umich.edu              case '-':
3022683Sktlim@umich.edu                // command-line configuration parameter:
303705SN/A                // '--<section>:<parameter>=<value>'
3044172Ssaidi@eecs.umich.edu
3054172Ssaidi@eecs.umich.edu                // Load default.ini if necessary -- see comment in
3064172Ssaidi@eecs.umich.edu                // else clause below.
3074172Ssaidi@eecs.umich.edu                handleDefaultIni(loadDefaultIni, cppArgs);
3084172Ssaidi@eecs.umich.edu
3092159SN/A                if (!simConfigDB.add(arg_str + 2)) {
3102159SN/A                    // parse error
3112683Sktlim@umich.edu                    ccprintf(cerr,
3122159SN/A                             "Could not parse configuration argument '%s'\n"
313705SN/A                             "Expecting --<section>:<parameter>=<value>\n",
3144172Ssaidi@eecs.umich.edu                             arg_str);
3152159SN/A                    exit(0);
3164172Ssaidi@eecs.umich.edu                }
3172159SN/A                break;
3182159SN/A
3193468Sgblack@eecs.umich.edu              default:
3202159SN/A                showBriefHelp(cerr);
3212683Sktlim@umich.edu                ccprintf(cerr, "Fatal: invalid argument '%s'\n", arg_str);
3222159SN/A                exit(0);
3232159SN/A            }
3244185Ssaidi@eecs.umich.edu        }
3252159SN/A        else {
3264172Ssaidi@eecs.umich.edu            // no '-', treat as config file name
3274172Ssaidi@eecs.umich.edu
3282159SN/A            // If we haven't loaded default.ini yet, and we want to,
329705SN/A            // now is the time.  Can't do it sooner because we need to
3304185Ssaidi@eecs.umich.edu            // look for '-n', can't do it later since we want
3313792Sgblack@eecs.umich.edu            // default.ini loaded first (so that any other settings
3323792Sgblack@eecs.umich.edu            // override it).
3333792Sgblack@eecs.umich.edu            handleDefaultIni(loadDefaultIni, cppArgs);
3343792Sgblack@eecs.umich.edu
3353792Sgblack@eecs.umich.edu            if (!simConfigDB.loadCPP(arg_str, cppArgs)) {
3364185Ssaidi@eecs.umich.edu                cprintf("Error processing file %s\n", arg_str);
3373792Sgblack@eecs.umich.edu                exit(1);
3383792Sgblack@eecs.umich.edu            }
3394172Ssaidi@eecs.umich.edu        }
3403792Sgblack@eecs.umich.edu    }
3413792Sgblack@eecs.umich.edu
3424185Ssaidi@eecs.umich.edu    // Final check for default.ini, in case no config files or
3433792Sgblack@eecs.umich.edu    // command-line config parameters were given.
3443792Sgblack@eecs.umich.edu    handleDefaultIni(loadDefaultIni, cppArgs);
3453792Sgblack@eecs.umich.edu
3464172Ssaidi@eecs.umich.edu    // The configuration database is now complete; start processing it.
3473792Sgblack@eecs.umich.edu
3483792Sgblack@eecs.umich.edu    // Parse and check all non-config-hierarchy parameters.
3494027Sstever@eecs.umich.edu    ParamContext::parseAllContexts(simConfigDB);
3504027Sstever@eecs.umich.edu    ParamContext::checkAllContexts();
3514027Sstever@eecs.umich.edu
3524027Sstever@eecs.umich.edu    // Print header info into stats file.  Can't do this sooner since
3534027Sstever@eecs.umich.edu    // the stat file name is set via a .ini param... thus it just got
3544027Sstever@eecs.umich.edu    // opened above during ParamContext::checkAllContexts().
3554027Sstever@eecs.umich.edu
3564027Sstever@eecs.umich.edu    // Print hello message to stats file if it's actually a file.  If
3574661Sksewell@umich.edu    // it's not (i.e. it's cout or cerr) then we already did it above.
3584661Sksewell@umich.edu    if (statStreamIsFile)
3594661Sksewell@umich.edu        sayHello(*statStream);
3604661Sksewell@umich.edu
3614661Sksewell@umich.edu    // Echo command line and all parameter settings to stats file as well.
3624661Sksewell@umich.edu    echoCommandLine(argc, argv, *statStream);
3634661Sksewell@umich.edu    ParamContext::showAllContexts(*statStream);
3644661Sksewell@umich.edu
3654661Sksewell@umich.edu    // Now process the configuration hierarchy and create the SimObjects.
3664661Sksewell@umich.edu    ConfigHierarchy configHierarchy(simConfigDB);
3674661Sksewell@umich.edu    configHierarchy.build();
3684661Sksewell@umich.edu    configHierarchy.createSimObjects();
3691858SN/A
3702683Sktlim@umich.edu    // Restore checkpointed state, if any.
3712680Sktlim@umich.edu    configHierarchy.unserializeSimObjects();
3722683Sktlim@umich.edu
373705SN/A    // Done processing the configuration database.
3742683Sktlim@umich.edu    // Check for unreferenced entries.
375705SN/A    if (simConfigDB.printUnreferenced() && quitOnUnreferenced) {
376705SN/A        cerr << "Fatal: unreferenced .ini sections/entries." << endl
3772683Sktlim@umich.edu             << "If this is not an error, add 'unref_section_ok=y' or "
3782680Sktlim@umich.edu             << "'unref_entries_ok=y' to the appropriate sections "
3792SN/A             << "to suppress this message." << endl;
3802SN/A        exit(1);
3812623SN/A    }
382
383    SimObject::regAllStats();
384
385    // uncomment the following to get PC-based execution-time profile
386#ifdef DO_PROFILE
387    init_profile((char *)&_init, (char *)&_fini);
388#endif
389
390    // Check to make sure that the stats package is properly initialized
391    Statistics::check();
392
393    // Nothing to simulate if we don't have at least one CPU somewhere.
394    if (BaseCPU::numSimulatedCPUs() == 0) {
395        cerr << "Fatal: no CPUs to simulate." << endl;
396        exit(1);
397    }
398
399    while (!mainEventQueue.empty()) {
400        assert(curTick <= mainEventQueue.nextTick() &&
401               "event scheduled in the past");
402
403        // forward current cycle to the time of the first event on the
404        // queue
405        curTick = mainEventQueue.nextTick();
406        mainEventQueue.serviceOne();
407
408        if (async_event) {
409            async_event = false;
410            if (async_dump) {
411                async_dump = false;
412
413                using namespace Statistics;
414                SetupEvent(Dump, curTick);
415            }
416
417            if (async_dumpreset) {
418                async_dumpreset = false;
419
420                using namespace Statistics;
421                SetupEvent(Dump | Reset, curTick);
422            }
423
424            if (async_exit) {
425                async_exit = false;
426                new SimExitEvent("User requested STOP");
427            }
428
429            if (async_io || async_alarm) {
430                async_io = false;
431                async_alarm = false;
432                pollQueue.service();
433            }
434        }
435    }
436
437    // This should never happen... every conceivable way for the
438    // simulation to terminate (hit max cycles/insts, signal,
439    // simulated system halts/exits) generates an exit event, so we
440    // should never run out of events on the queue.
441    exitNow("improperly exited event loop!", 1);
442
443    return 0;
444}
445