main.cc revision 2665:a124942bacb8
1/*
2 * Copyright (c) 2000-2005 The Regents of The University of Michigan
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 * Authors: Steve Raasch
29 *          Nathan Binkert
30 *          Steve Reinhardt
31 */
32
33///
34/// @file sim/main.cc
35///
36#include <Python.h>	// must be before system headers... see Python docs
37
38#include <sys/types.h>
39#include <sys/stat.h>
40#include <errno.h>
41#include <libgen.h>
42#include <stdlib.h>
43#include <signal.h>
44
45#include <list>
46#include <string>
47#include <vector>
48
49#include "base/inifile.hh"
50#include "base/misc.hh"
51#include "base/output.hh"
52#include "base/pollevent.hh"
53#include "base/statistics.hh"
54#include "base/str.hh"
55#include "base/time.hh"
56#include "cpu/base.hh"
57#include "cpu/smt.hh"
58#include "sim/async.hh"
59#include "sim/builder.hh"
60#include "sim/configfile.hh"
61#include "sim/host.hh"
62#include "sim/sim_events.hh"
63#include "sim/sim_exit.hh"
64#include "sim/sim_object.hh"
65#include "sim/stat_control.hh"
66#include "sim/stats.hh"
67#include "sim/root.hh"
68
69using namespace std;
70
71// See async.h.
72volatile bool async_event = false;
73volatile bool async_dump = false;
74volatile bool async_dumpreset = false;
75volatile bool async_exit = false;
76volatile bool async_io = false;
77volatile bool async_alarm = false;
78
79/// Stats signal handler.
80void
81dumpStatsHandler(int sigtype)
82{
83    async_event = true;
84    async_dump = true;
85}
86
87void
88dumprstStatsHandler(int sigtype)
89{
90    async_event = true;
91    async_dumpreset = true;
92}
93
94/// Exit signal handler.
95void
96exitNowHandler(int sigtype)
97{
98    async_event = true;
99    async_exit = true;
100}
101
102/// Abort signal handler.
103void
104abortHandler(int sigtype)
105{
106    cerr << "Program aborted at cycle " << curTick << endl;
107
108#if TRACING_ON
109    // dump trace buffer, if there is one
110    Trace::theLog.dump(cerr);
111#endif
112}
113
114/// Simulator executable name
115char *myProgName = "";
116
117///
118/// Echo the command line for posterity in such a way that it can be
119/// used to rerun the same simulation (given the same .ini files).
120///
121void
122echoCommandLine(int argc, char **argv, ostream &out)
123{
124    out << "command line: " << argv[0];
125    for (int i = 1; i < argc; i++) {
126        string arg(argv[i]);
127
128        out << ' ';
129
130        // If the arg contains spaces, we need to quote it.
131        // The rest of this is overkill to make it look purty.
132
133        // print dashes first outside quotes
134        int non_dash_pos = arg.find_first_not_of("-");
135        out << arg.substr(0, non_dash_pos);	// print dashes
136        string body = arg.substr(non_dash_pos);	// the rest
137
138        // if it's an assignment, handle the lhs & rhs separately
139        int eq_pos = body.find("=");
140        if (eq_pos == string::npos) {
141            out << quote(body);
142        }
143        else {
144            string lhs(body.substr(0, eq_pos));
145            string rhs(body.substr(eq_pos + 1));
146
147            out << quote(lhs) << "=" << quote(rhs);
148        }
149    }
150    out << endl << endl;
151}
152
153int
154main(int argc, char **argv)
155{
156    // Save off program name
157    myProgName = argv[0];
158
159    signal(SIGFPE, SIG_IGN);		// may occur on misspeculated paths
160    signal(SIGTRAP, SIG_IGN);
161    signal(SIGUSR1, dumpStatsHandler);		// dump intermediate stats
162    signal(SIGUSR2, dumprstStatsHandler);	// dump and reset stats
163    signal(SIGINT, exitNowHandler);		// dump final stats and exit
164    signal(SIGABRT, abortHandler);
165
166    // Python embedded interpreter invocation
167    Py_SetProgramName(argv[0]);
168    const char *fileName = Py_GetProgramFullPath();
169    Py_Initialize();
170    PySys_SetArgv(argc, argv);
171
172    // loadSwigModules();
173
174    // Set Python module path to include current file to find embedded
175    // zip archive
176    if (PyRun_SimpleString("import sys") != 0)
177        panic("Python error importing 'sys' module\n");
178    string pathCmd = csprintf("sys.path[1:1] = ['%s']", fileName);
179    if (PyRun_SimpleString(pathCmd.c_str()) != 0)
180        panic("Python error setting sys.path\n");
181
182    // Pass compile timestamp string to Python
183    extern const char *compileDate;	// from date.cc
184    string setCompileDate = csprintf("compileDate = '%s'", compileDate);
185    if (PyRun_SimpleString(setCompileDate.c_str()) != 0)
186        panic("Python error setting compileDate\n");
187
188    // PyRun_InteractiveLoop(stdin, "stdin");
189    // m5/__init__.py currently contains main argv parsing loop etc.,
190    // and will write out config.ini file before returning.
191    if (PyImport_ImportModule("defines") == NULL)
192        panic("Python error importing 'defines.py'\n");
193    if (PyImport_ImportModule("m5") == NULL)
194        panic("Python error importing 'm5' module\n");
195    Py_Finalize();
196
197    configStream = simout.find("config.out");
198
199    // The configuration database is now complete; start processing it.
200    IniFile inifile;
201    inifile.load("config.ini");
202
203    // Initialize statistics database
204    Stats::InitSimStats();
205
206    // Now process the configuration hierarchy and create the SimObjects.
207    ConfigHierarchy configHierarchy(inifile);
208    configHierarchy.build();
209    configHierarchy.createSimObjects();
210
211    // Parse and check all non-config-hierarchy parameters.
212    ParamContext::parseAllContexts(inifile);
213    ParamContext::checkAllContexts();
214
215    // Echo command line and all parameter settings to stats file as well.
216    echoCommandLine(argc, argv, *outputStream);
217    ParamContext::showAllContexts(*configStream);
218
219    // Any objects that can't connect themselves until after construction should
220    // do so now
221    SimObject::connectAll();
222
223    // Do a second pass to finish initializing the sim objects
224    SimObject::initAll();
225
226    // Restore checkpointed state, if any.
227    configHierarchy.unserializeSimObjects();
228
229    // Done processing the configuration database.
230    // Check for unreferenced entries.
231    if (inifile.printUnreferenced())
232        panic("unreferenced sections/entries in the intermediate ini file");
233
234    SimObject::regAllStats();
235
236    // uncomment the following to get PC-based execution-time profile
237#ifdef DO_PROFILE
238    init_profile((char *)&_init, (char *)&_fini);
239#endif
240
241    // Check to make sure that the stats package is properly initialized
242    Stats::check();
243
244    // Reset to put the stats in a consistent state.
245    Stats::reset();
246
247    warn("Entering event queue.  Starting simulation...\n");
248    SimStartup();
249    while (!mainEventQueue.empty()) {
250        assert(curTick <= mainEventQueue.nextTick() &&
251               "event scheduled in the past");
252
253        // forward current cycle to the time of the first event on the
254        // queue
255        curTick = mainEventQueue.nextTick();
256        mainEventQueue.serviceOne();
257
258        if (async_event) {
259            async_event = false;
260            if (async_dump) {
261                async_dump = false;
262
263                using namespace Stats;
264                SetupEvent(Dump, curTick);
265            }
266
267            if (async_dumpreset) {
268                async_dumpreset = false;
269
270                using namespace Stats;
271                SetupEvent(Dump | Reset, curTick);
272            }
273
274            if (async_exit) {
275                async_exit = false;
276                new SimExitEvent("User requested STOP");
277            }
278
279            if (async_io || async_alarm) {
280                async_io = false;
281                async_alarm = false;
282                pollQueue.service();
283            }
284        }
285    }
286
287    // This should never happen... every conceivable way for the
288    // simulation to terminate (hit max cycles/insts, signal,
289    // simulated system halts/exits) generates an exit event, so we
290    // should never run out of events on the queue.
291    exitNow("no events on event loop!  All CPUs must be idle.", 1);
292
293    return 0;
294}
295