summaryrefslogtreecommitdiff
path: root/sim
diff options
context:
space:
mode:
Diffstat (limited to 'sim')
-rw-r--r--sim/builder.cc30
-rw-r--r--sim/builder.hh3
-rw-r--r--sim/debug.cc6
-rw-r--r--sim/debug.hh4
-rw-r--r--sim/main.cc82
-rw-r--r--sim/param.cc25
-rw-r--r--sim/param.hh32
-rw-r--r--sim/process.cc27
-rw-r--r--sim/process.hh2
-rw-r--r--sim/serialize.cc5
-rw-r--r--sim/sim_events.cc26
-rw-r--r--sim/sim_object.hh6
-rw-r--r--sim/startup.cc51
-rw-r--r--sim/startup.hh41
-rw-r--r--sim/system.cc348
-rw-r--r--sim/system.hh136
-rw-r--r--sim/universe.cc81
17 files changed, 506 insertions, 399 deletions
diff --git a/sim/builder.cc b/sim/builder.cc
index 53e5cf3d8..fa5c113a7 100644
--- a/sim/builder.cc
+++ b/sim/builder.cc
@@ -39,31 +39,11 @@
using namespace std;
-
-ostream &
-builderStream()
-{
- static ofstream file;
- static ostream *stream = NULL;
-
- if (!stream) {
- if (!outputDirectory.empty()) {
- string filename = outputDirectory + "builder.txt";
- file.open(filename.c_str());
- stream = &file;
- } else {
- stream = outputStream;
- }
- }
-
- return *stream;
-}
-
SimObjectBuilder::SimObjectBuilder(const string &_configClass,
const string &_instanceName,
ConfigNode *_configNode,
const string &_simObjClassName)
- : ParamContext(_configClass, true),
+ : ParamContext(_configClass, NoAutoInit),
instanceName(_instanceName),
configNode(_configNode),
simObjClassName(_simObjClassName)
@@ -187,10 +167,10 @@ SimObjectClass::createObject(IniFile &configDB,
// echo object parameters to stats file (for documenting the
// config used to generate the associated stats)
- builderStream() << "[" << object->name() << "]" << endl;
- builderStream() << "type=" << simObjClassName << endl;
- objectBuilder->showParams(builderStream());
- builderStream() << endl;
+ *configStream << "[" << object->name() << "]" << endl;
+ *configStream << "type=" << simObjClassName << endl;
+ objectBuilder->showParams(*configStream);
+ *configStream << endl;
// done with the SimObjectBuilder now
delete objectBuilder;
diff --git a/sim/builder.hh b/sim/builder.hh
index a85c88b76..36e40c2a9 100644
--- a/sim/builder.hh
+++ b/sim/builder.hh
@@ -38,9 +38,6 @@
class SimObject;
-std::ostream &
-builderStream();
-
//
// A SimObjectBuilder serves as an evaluation context for a set of
// parameters that describe a specific instance of a SimObject. This
diff --git a/sim/debug.cc b/sim/debug.cc
index 293edcbe2..3467d1669 100644
--- a/sim/debug.cc
+++ b/sim/debug.cc
@@ -40,13 +40,15 @@
using namespace std;
-#ifdef DEBUG
void
debug_break()
{
+#ifndef NDEBUG
kill(getpid(), SIGTRAP);
-}
+#else
+ cprintf("debug_break suppressed, compiled with NDEBUG\n");
#endif
+}
//
// Debug event: place a breakpoint on the process function and
diff --git a/sim/debug.hh b/sim/debug.hh
index 3ccf1dbd4..5ee77cf28 100644
--- a/sim/debug.hh
+++ b/sim/debug.hh
@@ -29,10 +29,6 @@
#ifndef __DEBUG_HH__
#define __DEBUG_HH__
-#ifdef DEBUG
void debug_break();
-#else
-inline void debug_break() { }
-#endif
#endif // __DEBUG_HH__
diff --git a/sim/main.cc b/sim/main.cc
index 2a0427303..e8ac58786 100644
--- a/sim/main.cc
+++ b/sim/main.cc
@@ -51,7 +51,6 @@
#include "sim/host.hh"
#include "sim/sim_events.hh"
#include "sim/sim_exit.hh"
-#include "sim/sim_init.hh"
#include "sim/sim_object.hh"
#include "sim/stat_control.hh"
#include "sim/stats.hh"
@@ -111,12 +110,15 @@ static void
showBriefHelp(ostream &out)
{
out << "Usage: " << myProgName
- << " [-hn] [-Dname[=def]] [-Uname] [-I[dir]] "
- << "[--<section>:<param>=<value>] [<config file> ...]" << endl
- << " -h: print long help (including parameter listing)" << endl
- << " -n: don't load default.ini" << endl
- << " -u: don't quit on unreferenced parameters" << endl
- << " -D,-U,-I: passed to cpp for preprocessing .ini files" << endl;
+ << " [-hnu] [-Dname[=def]] [-Uname] [-I[dir]] "
+ << "<config-spec> [<config-spec> ...]\n"
+ << "[] [<config file> ...]\n"
+ << " -h: print long help (including parameter listing)\n"
+ << " -u: don't quit on unreferenced parameters\n"
+ << " -D,-U,-I: passed to cpp for preprocessing .ini files\n"
+ << " <config-spec>: config file name (.ini or .py) or\n"
+ << " single param (--<section>:<param>=<value>)"
+ << endl;
}
/// Show verbose help message. Includes parameter listing from
@@ -212,27 +214,6 @@ echoCommandLine(int argc, char **argv, ostream &out)
///
static IniFile simConfigDB;
-/// Check for a default.ini file and load it if necessary.
-static void
-handleDefaultIni(bool &loadIt, vector<char *> &cppArgs)
-{
- struct stat sb;
-
- if (loadIt) {
- if (stat("default.ini", &sb) == 0) {
- if (!simConfigDB.loadCPP("default.ini", cppArgs)) {
- cout << "Error processing file default.ini" << endl;
- exit(1);
- }
- }
-
- // set this whether it actually was found or not, so we don't
- // bother to check again next time
- loadIt = false;
- }
-}
-
-
/// M5 entry point.
int
main(int argc, char **argv)
@@ -254,21 +235,13 @@ main(int argc, char **argv)
vector<char *> cppArgs;
- // Should we use default.ini if it exists? By default, yes. (Use
- // -n to override.)
- bool loadDefaultIni = true;
-
// Should we quit if there are unreferenced parameters? By
// default, yes... it's a good way of catching typos in
// section/parameter names (which otherwise go by silently). Use
// -u to override.
bool quitOnUnreferenced = true;
- // Parse command-line options. The tricky part here is figuring
- // out whether to look for & load default.ini, and if needed,
- // doing so at the right time w.r.t. processing the other
- // parameters.
- //
+ // Parse command-line options.
// Since most of the complex options are handled through the
// config database, we don't mess with getopts, and just parse
// manually.
@@ -286,17 +259,6 @@ main(int argc, char **argv)
showLongHelp(cerr);
exit(1);
- case 'n':
- // -n: don't load default.ini
- if (!loadDefaultIni) {
- cerr << "Warning: -n option needs to precede any "
- << "explicit configuration file name " << endl
- << " or command-line configuration parameter."
- << endl;
- }
- loadDefaultIni = false;
- break;
-
case 'u':
// -u: don't quit on unreferenced parameters
quitOnUnreferenced = false;
@@ -317,11 +279,6 @@ main(int argc, char **argv)
case '-':
// command-line configuration parameter:
// '--<section>:<parameter>=<value>'
-
- // Load default.ini if necessary -- see comment in
- // else clause below.
- handleDefaultIni(loadDefaultIni, cppArgs);
-
if (!simConfigDB.add(arg_str + 2)) {
// parse error
ccprintf(cerr,
@@ -350,13 +307,6 @@ main(int argc, char **argv)
(ext_loc != string::npos) ? filename.substr(ext_loc) : "";
if (ext == ".ini") {
- // If we haven't loaded default.ini yet, and we want to,
- // now is the time. Can't do it sooner because we need to
- // look for '-n', can't do it later since we want
- // default.ini loaded first (so that any other settings
- // override it).
- handleDefaultIni(loadDefaultIni, cppArgs);
-
if (!simConfigDB.loadCPP(filename, cppArgs)) {
cprintf("Error processing file %s\n", filename);
exit(1);
@@ -375,10 +325,6 @@ main(int argc, char **argv)
}
}
- // Final check for default.ini, in case no config files or
- // command-line config parameters were given.
- handleDefaultIni(loadDefaultIni, cppArgs);
-
// The configuration database is now complete; start processing it.
// Parse and check all non-config-hierarchy parameters.
@@ -396,13 +342,16 @@ main(int argc, char **argv)
// Echo command line and all parameter settings to stats file as well.
echoCommandLine(argc, argv, *outputStream);
- ParamContext::showAllContexts(builderStream());
+ ParamContext::showAllContexts(*configStream);
// Now process the configuration hierarchy and create the SimObjects.
ConfigHierarchy configHierarchy(simConfigDB);
configHierarchy.build();
configHierarchy.createSimObjects();
+ // Do a second pass to finish initializing the sim objects
+ SimObject::initAll();
+
// Restore checkpointed state, if any.
configHierarchy.unserializeSimObjects();
@@ -435,9 +384,8 @@ main(int argc, char **argv)
exit(1);
}
- SimInit();
warn("Entering event queue. Starting simulation...\n");
-
+ SimStartup();
while (!mainEventQueue.empty()) {
assert(curTick <= mainEventQueue.nextTick() &&
"event scheduled in the past");
diff --git a/sim/param.cc b/sim/param.cc
index 4f9d0a577..d20be8d33 100644
--- a/sim/param.cc
+++ b/sim/param.cc
@@ -211,6 +211,11 @@ template <class T>
void
VectorParam<T>::parse(const string &s)
{
+ if (s.empty()) {
+ wasSet = true;
+ return;
+ }
+
vector<string> tokens;
tokenize(tokens, s, ' ');
@@ -555,15 +560,27 @@ SimObjectBaseParam::parse(const string &s, vector<SimObject *>&value)
list<ParamContext *> *ParamContext::ctxList = NULL;
-ParamContext::ParamContext(const string &_iniSection, bool noAutoParse)
+ParamContext::ParamContext(const string &_iniSection, InitPhase _initPhase)
: iniFilePtr(NULL), // initialized on call to parseParams()
- iniSection(_iniSection), paramList(NULL)
+ iniSection(_iniSection), paramList(NULL),
+ initPhase(_initPhase)
{
- if (!noAutoParse) {
+ // Put this context on global list for initialization
+ if (initPhase != NoAutoInit) {
if (ctxList == NULL)
ctxList = new list<ParamContext *>();
- (*ctxList).push_back(this);
+ // keep list sorted by ascending initPhase values
+ list<ParamContext *>::iterator i = ctxList->begin();
+ list<ParamContext *>::iterator end = ctxList->end();
+ for (; i != end; ++i) {
+ if (initPhase <= (*i)->initPhase) {
+ // found where we want to insert
+ break;
+ }
+ }
+ // (fall through case: insert at end)
+ ctxList->insert(i, this);
}
}
diff --git a/sim/param.hh b/sim/param.hh
index fe13edc48..ac57afa31 100644
--- a/sim/param.hh
+++ b/sim/param.hh
@@ -34,6 +34,7 @@
#include <vector>
#include "sim/configfile.hh"
+#include "sim/startup.hh"
// forward decls
class BaseParam;
@@ -44,7 +45,7 @@ class SimObject;
// SimObjectBuilder (which derives from ParamContext), but abstracted
// here to support more global simulator control parameters as well.
//
-class ParamContext
+class ParamContext : protected StartupCallback
{
private:
@@ -74,11 +75,30 @@ class ParamContext
public:
- // Second arg, if set to true, says don't put on paramContextList
- // (i.e. don't automatically parse params). Used by derived
- // SimObjectBuilder class, where parsing is done in
- // SimObject::create()
- ParamContext(const std::string &_iniSection, bool noAutoParse = false);
+ /// Initialization phases for ParamContext objects.
+ enum InitPhase {
+ NoAutoInit = -1, ///< Don't initialize at all... params
+ /// will be parsed later (used by
+ /// SimObjectBuilder, which parses
+ /// params in SimObject::create().
+ OutputInitPhase = 0, ///< Output stream initialization
+ TraceInitPhase = 1, ///< Trace context initialization:
+ /// depends on output streams, but
+ /// needs to come before others so we
+ /// can use tracing in other
+ /// ParamContext init code
+ StatsInitPhase = 2, ///< Stats output initialization
+ DefaultInitPhase = 3 ///< Everything else
+ };
+
+ /// Records the initialization phase for this ParamContext.
+ InitPhase initPhase;
+
+ /// Constructor.
+ /// @param _iniSection Name of .ini section corresponding to this context.
+ /// @param _initPhase Initialization phase (see InitPhase).
+ ParamContext(const std::string &_iniSection,
+ InitPhase _initPhase = DefaultInitPhase);
virtual ~ParamContext() {}
diff --git a/sim/process.cc b/sim/process.cc
index 7f93c1d9e..bd1a2d8fd 100644
--- a/sim/process.cc
+++ b/sim/process.cc
@@ -34,6 +34,7 @@
#include "base/intmath.hh"
#include "base/loader/object_file.hh"
+#include "base/loader/symtab.hh"
#include "base/statistics.hh"
#include "cpu/exec_context.hh"
#include "cpu/full_cpu/smt.hh"
@@ -161,7 +162,7 @@ Process::registerExecContext(ExecContext *xc)
void
-Process::replaceExecContext(int xcIndex, ExecContext *xc)
+Process::replaceExecContext(ExecContext *xc, int xcIndex)
{
if (xcIndex >= execContexts.size()) {
panic("replaceExecContext: bad xcIndex, %d >= %d\n",
@@ -263,6 +264,18 @@ LiveProcess::LiveProcess(const string &name, ObjectFile *objFile,
// load object file into target memory
objFile->loadSections(memory);
+ // load up symbols, if any... these may be used for debugging or
+ // profiling.
+ if (!debugSymbolTable) {
+ debugSymbolTable = new SymbolTable();
+ if (!objFile->loadGlobalSymbols(debugSymbolTable) ||
+ !objFile->loadLocalSymbols(debugSymbolTable)) {
+ // didn't load any symbols
+ delete debugSymbolTable;
+ debugSymbolTable = NULL;
+ }
+ }
+
// Set up stack. On Alpha, stack goes below text section. This
// code should get moved to some architecture-specific spot.
stack_base = text_base - (409600+4096);
@@ -392,14 +405,10 @@ CREATE_SIM_OBJECT(LiveProcess)
// dummy for default env
vector<string> null_vec;
- // We do this with "temp" because of the bogus compiler warning
- // you get with g++ 2.95 -O if you just "return new LiveProcess(..."
- LiveProcess *temp = LiveProcess::create(getInstanceName(),
- stdin_fd, stdout_fd, stderr_fd,
- cmd,
- env.isValid() ? env : null_vec);
-
- return temp;
+ return LiveProcess::create(getInstanceName(),
+ stdin_fd, stdout_fd, stderr_fd,
+ cmd,
+ env.isValid() ? env : null_vec);
}
diff --git a/sim/process.hh b/sim/process.hh
index bd6adc55c..bb4829875 100644
--- a/sim/process.hh
+++ b/sim/process.hh
@@ -130,7 +130,7 @@ class Process : public SimObject
int registerExecContext(ExecContext *xc);
- void replaceExecContext(int xcIndex, ExecContext *xc);
+ void replaceExecContext(ExecContext *xc, int xcIndex);
// map simulator fd sim_fd to target fd tgt_fd
void dup_fd(int sim_fd, int tgt_fd);
diff --git a/sim/serialize.cc b/sim/serialize.cc
index 91548f653..2a5e3d398 100644
--- a/sim/serialize.cc
+++ b/sim/serialize.cc
@@ -335,10 +335,7 @@ SerializeParamContext::checkParams()
if (serialize_dir.isValid()) {
checkpointDirBase = serialize_dir;
} else {
- if (outputDirectory.empty())
- checkpointDirBase = "m5.%012d";
- else
- checkpointDirBase = outputDirectory + "cpt.%012d";
+ checkpointDirBase = outputDirectory + "cpt.%012d";
}
// guarantee that directory ends with a '/'
diff --git a/sim/sim_events.cc b/sim/sim_events.cc
index c454fdcf9..99c09f259 100644
--- a/sim/sim_events.cc
+++ b/sim/sim_events.cc
@@ -34,7 +34,7 @@
#include "sim/param.hh"
#include "sim/sim_events.hh"
#include "sim/sim_exit.hh"
-#include "sim/sim_init.hh"
+#include "sim/startup.hh"
#include "sim/stats.hh"
using namespace std;
@@ -210,12 +210,11 @@ ProgressEvent::description()
// Parameter space for execution address tracing options. Derive
// from ParamContext so we can override checkParams() function.
-class ProgressParamContext : public ParamContext
+struct ProgressParamContext : public ParamContext
{
- public:
ProgressParamContext(const string &_iniSection)
: ParamContext(_iniSection) {}
- void checkParams();
+ void startup();
};
ProgressParamContext progessMessageParams("progress");
@@ -223,24 +222,9 @@ ProgressParamContext progessMessageParams("progress");
Param<Tick> progress_interval(&progessMessageParams, "cycle",
"cycle interval for progress messages");
-namespace {
- struct SetupProgress : public Callback
- {
- Tick interval;
- SetupProgress(Tick tick) : interval(tick) {}
-
- virtual void process()
- {
- new ProgressEvent(&mainEventQueue, interval);
- delete this;
- }
- };
-}
-
-/* check execute options */
void
-ProgressParamContext::checkParams()
+ProgressParamContext::startup()
{
if (progress_interval.isValid())
- registerInitCallback(new SetupProgress(progress_interval));
+ new ProgressEvent(&mainEventQueue, progress_interval);
}
diff --git a/sim/sim_object.hh b/sim/sim_object.hh
index dfd70f8ec..f4b316ebb 100644
--- a/sim/sim_object.hh
+++ b/sim/sim_object.hh
@@ -39,13 +39,14 @@
#include <iostream>
#include "sim/serialize.hh"
+#include "sim/startup.hh"
/*
* Abstract superclass for simulation objects. Represents things that
* correspond to physical components and can be specified via the
* config file (CPUs, caches, etc.).
*/
-class SimObject : public Serializable
+class SimObject : public Serializable, protected StartupCallback
{
protected:
std::string objName;
@@ -65,7 +66,8 @@ class SimObject : public Serializable
virtual const std::string name() const { return objName; }
- // initialization pass of all objects. Gets invoked by SimInit()
+ // initialization pass of all objects.
+ // Gets invoked after construction, before unserialize.
virtual void init();
static void initAll();
diff --git a/sim/startup.cc b/sim/startup.cc
new file mode 100644
index 000000000..ebb4c0bc0
--- /dev/null
+++ b/sim/startup.cc
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2004 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <list>
+
+#include "base/misc.hh"
+#include "sim/startup.hh"
+#include "sim/debug.hh"
+
+typedef std::list<StartupCallback *> startupq_t;
+startupq_t &startupq() { static startupq_t queue; return queue; }
+StartupCallback::StartupCallback() { startupq().push_back(this); }
+StartupCallback::~StartupCallback() { startupq().remove(this); }
+void StartupCallback::startup() { }
+
+void
+SimStartup()
+{
+ startupq_t::iterator i = startupq().begin();
+ startupq_t::iterator end = startupq().end();
+
+ while (i != end) {
+ (*i)->startup();
+ ++i;
+ }
+}
diff --git a/sim/startup.hh b/sim/startup.hh
new file mode 100644
index 000000000..e6c03a500
--- /dev/null
+++ b/sim/startup.hh
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2004 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __SIM_STARTUP_HH__
+#define __SIM_STARTUP_HH__
+
+struct StartupCallback
+{
+ StartupCallback();
+ virtual ~StartupCallback();
+ virtual void startup();
+};
+
+void SimStartup();
+
+#endif // __SIM_STARTUP_HH__
diff --git a/sim/system.cc b/sim/system.cc
index b5a0e7a56..c6a65f9d9 100644
--- a/sim/system.cc
+++ b/sim/system.cc
@@ -26,7 +26,13 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+#include "base/loader/object_file.hh"
+#include "base/loader/symtab.hh"
+#include "base/remote_gdb.hh"
#include "cpu/exec_context.hh"
+#include "kern/kernel_stats.hh"
+#include "mem/functional_mem/memory_control.hh"
+#include "mem/functional_mem/physical_memory.hh"
#include "targetarch/vtophys.hh"
#include "sim/param.hh"
#include "sim/system.hh"
@@ -38,237 +44,229 @@ vector<System *> System::systemList;
int System::numSystemsRunning = 0;
-System::System(const std::string _name,
- const uint64_t _init_param,
- MemoryController *_memCtrl,
- PhysicalMemory *_physmem,
- const bool _bin,
- const std::vector<string> &binned_fns)
-
- : SimObject(_name),
- init_param(_init_param),
- memCtrl(_memCtrl),
- physmem(_physmem),
- bin(_bin),
- binned_fns(binned_fns)
+System::System(Params *p)
+ : SimObject(p->name), memctrl(p->memctrl), physmem(p->physmem),
+ init_param(p->init_param), params(p)
{
- // increment the number of running systems
- numSystemsRunning++;
-
// add self to global system list
systemList.push_back(this);
- if (bin == true) {
- Kernel = new Stats::MainBin("non TCPIP Kernel stats");
- Kernel->activate();
- User = new Stats::MainBin("User stats");
- int end = binned_fns.size();
- assert(!(end & 1));
+ kernelSymtab = new SymbolTable;
+ consoleSymtab = new SymbolTable;
+ palSymtab = new SymbolTable;
+ debugSymbolTable = new SymbolTable;
+
+ /**
+ * Load the kernel, pal, and console code into memory
+ */
+ // Load kernel code
+ kernel = createObjectFile(params->kernel_path);
+ if (kernel == NULL)
+ fatal("Could not load kernel file %s", params->kernel_path);
+
+ // Load Console Code
+ console = createObjectFile(params->console_path);
+ if (console == NULL)
+ fatal("Could not load console file %s", params->console_path);
+
+ // Load pal file
+ pal = createObjectFile(params->palcode);
+ if (pal == NULL)
+ fatal("Could not load PALcode file %s", params->palcode);
+
+
+ // Load program sections into memory
+ pal->loadSections(physmem, true);
+ console->loadSections(physmem, true);
+ kernel->loadSections(physmem, true);
+
+ // setup entry points
+ kernelStart = kernel->textBase();
+ kernelEnd = kernel->bssBase() + kernel->bssSize();
+ kernelEntry = kernel->entryPoint();
+
+ // load symbols
+ if (!kernel->loadGlobalSymbols(kernelSymtab))
+ panic("could not load kernel symbols\n");
+
+ if (!kernel->loadLocalSymbols(kernelSymtab))
+ panic("could not load kernel local symbols\n");
+
+ if (!console->loadGlobalSymbols(consoleSymtab))
+ panic("could not load console symbols\n");
+
+ if (!pal->loadGlobalSymbols(palSymtab))
+ panic("could not load pal symbols\n");
+
+ if (!pal->loadLocalSymbols(palSymtab))
+ panic("could not load pal symbols\n");
+
+ if (!kernel->loadGlobalSymbols(debugSymbolTable))
+ panic("could not load kernel symbols\n");
+
+ if (!kernel->loadLocalSymbols(debugSymbolTable))
+ panic("could not load kernel local symbols\n");
+
+ if (!console->loadGlobalSymbols(debugSymbolTable))
+ panic("could not load console symbols\n");
+
+ if (!pal->loadGlobalSymbols(debugSymbolTable))
+ panic("could not load pal symbols\n");
+
+ if (!pal->loadLocalSymbols(debugSymbolTable))
+ panic("could not load pal symbols\n");
+
- Stats::MainBin *Bin;
+ DPRINTF(Loader, "Kernel start = %#x\n", kernelStart);
+ DPRINTF(Loader, "Kernel end = %#x\n", kernelEnd);
+ DPRINTF(Loader, "Kernel entry = %#x\n", kernelEntry);
+ DPRINTF(Loader, "Kernel loaded...\n");
- fnEvents.resize(end>>1);
+ Addr addr = 0;
+#ifdef DEBUG
+ consolePanicEvent = new BreakPCEvent(&pcEventQueue, "console panic");
+ if (consoleSymtab->findAddress("panic", addr))
+ consolePanicEvent->schedule(addr);
+#endif
- for (int i = 0; i < end; i +=2) {
- Bin = new Stats::MainBin(binned_fns[i]);
- fnBins.insert(make_pair(binned_fns[i], Bin));
+ /**
+ * Copy the osflags (kernel arguments) into the consoles
+ * memory. (Presently Linux does not use the console service
+ * routine to get these command line arguments, but Tru64 and
+ * others do.)
+ */
+ if (consoleSymtab->findAddress("env_booted_osflags", addr)) {
+ Addr paddr = vtophys(physmem, addr);
+ char *osflags = (char *)physmem->dma_addr(paddr, sizeof(uint32_t));
- fnEvents[(i>>1)] = new FnEvent(&pcEventQueue, binned_fns[i], this);
+ if (osflags)
+ strcpy(osflags, params->boot_osflags.c_str());
+ }
- if (binned_fns[i+1] == "null")
- populateMap(binned_fns[i], "");
- else
- populateMap(binned_fns[i], binned_fns[i+1]);
- }
+ /**
+ * Set the hardware reset parameter block system type and revision
+ * information to Tsunami.
+ */
+ if (consoleSymtab->findAddress("xxm_rpb", addr)) {
+ Addr paddr = vtophys(physmem, addr);
+ char *hwrpb = (char *)physmem->dma_addr(paddr, sizeof(uint64_t));
- fnCalls
- .name(name() + ":fnCalls")
- .desc("all fn calls being tracked")
- ;
+ if (!hwrpb)
+ panic("could not translate hwrpb addr\n");
+ *(uint64_t*)(hwrpb+0x50) = htoa(params->system_type);
+ *(uint64_t*)(hwrpb+0x58) = htoa(params->system_rev);
} else
- Kernel = NULL;
-}
+ panic("could not find hwrpb\n");
+ // increment the number of running systms
+ numSystemsRunning++;
+
+ kernelBinning = new Kernel::Binning(this);
+}
System::~System()
{
- if (bin == true) {
- int end = fnEvents.size();
- for (int i = 0; i < end; ++i) {
- delete fnEvents[i];
- }
- fnEvents.clear();
- }
+ delete kernelSymtab;
+ delete consoleSymtab;
+ delete kernel;
+ delete console;
+ delete pal;
+
+ delete kernelBinning;
+
+#ifdef DEBUG
+ delete consolePanicEvent;
+#endif
}
+bool
+System::breakpoint()
+{
+ return remoteGDB[0]->trap(ALPHA_KENTRY_INT);
+}
int
System::registerExecContext(ExecContext *xc)
{
- int myIndex = execContexts.size();
+ int xcIndex = execContexts.size();
execContexts.push_back(xc);
- return myIndex;
-}
-
-void
-System::replaceExecContext(int xcIndex, ExecContext *xc)
-{
- if (xcIndex >= execContexts.size()) {
- panic("replaceExecContext: bad xcIndex, %d >= %d\n",
- xcIndex, execContexts.size());
+ RemoteGDB *rgdb = new RemoteGDB(this, xc);
+ GDBListener *gdbl = new GDBListener(rgdb, 7000 + xcIndex);
+ gdbl->listen();
+ /**
+ * Uncommenting this line waits for a remote debugger to connect
+ * to the simulator before continuing.
+ */
+ //gdbl->accept();
+
+ if (remoteGDB.size() <= xcIndex) {
+ remoteGDB.resize(xcIndex+1);
}
- execContexts[xcIndex] = xc;
-}
+ remoteGDB[xcIndex] = rgdb;
+ return xcIndex;
+}
void
-System::printSystems()
+System::startup()
{
- vector<System *>::iterator i = systemList.begin();
- vector<System *>::iterator end = systemList.end();
- for (; i != end; ++i) {
- System *sys = *i;
- cerr << "System " << sys->name() << ": " << hex << sys << endl;
+ if (!execContexts.empty()) {
+ // activate with zero delay so that we start ticking right
+ // away on cycle 0
+ execContexts[0]->activate(0);
}
}
-extern "C"
void
-printSystems()
+System::replaceExecContext(ExecContext *xc, int xcIndex)
{
- System::printSystems();
-}
+ if (xcIndex >= execContexts.size()) {
+ panic("replaceExecContext: bad xcIndex, %d >= %d\n",
+ xcIndex, execContexts.size());
+ }
-void
-System::populateMap(std::string callee, std::string caller)
-{
- multimap<const string, string>::const_iterator i;
- i = callerMap.insert(make_pair(callee, caller));
- assert(i != callerMap.end() && "should not fail populating callerMap");
+ execContexts[xcIndex] = xc;
+ remoteGDB[xcIndex]->replaceExecContext(xc);
}
-bool
-System::findCaller(std::string callee, std::string caller) const
+void
+System::regStats()
{
- typedef multimap<const std::string, std::string>::const_iterator iter;
- pair<iter, iter> range;
-
- range = callerMap.equal_range(callee);
- for (iter i = range.first; i != range.second; ++i) {
- if ((*i).second == caller)
- return true;
- }
- return false;
+ kernelBinning->regStats(name() + ".kern");
}
void
-System::dumpState(ExecContext *xc) const
+System::serialize(ostream &os)
{
- if (xc->swCtx) {
- stack<fnCall *> copy(xc->swCtx->callStack);
- if (copy.empty())
- return;
- DPRINTF(TCPIP, "xc->swCtx, size: %d:\n", copy.size());
- fnCall *top;
- DPRINTF(TCPIP, "|| call : %d\n",xc->swCtx->calls);
- for (top = copy.top(); !copy.empty(); copy.pop() ) {
- top = copy.top();
- DPRINTF(TCPIP, "|| %13s : %s \n", top->name, top->myBin->name());
- }
- }
+ kernelBinning->serialize(os);
}
-Stats::MainBin *
-System::getBin(const std::string &name)
-{
- std::map<const std::string, Stats::MainBin *>::const_iterator i;
- i = fnBins.find(name);
- if (i == fnBins.end())
- panic("trying to getBin %s that is not on system map!", name);
- return (*i).second;
-}
-SWContext *
-System::findContext(Addr pcb)
+void
+System::unserialize(Checkpoint *cp, const string &section)
{
- std::map<Addr, SWContext *>::const_iterator iter;
- iter = swCtxMap.find(pcb);
- if (iter != swCtxMap.end()) {
- SWContext *ctx = (*iter).second;
- assert(ctx != NULL && "should never have a null ctx in ctxMap");
- return ctx;
- } else
- return NULL;
+ kernelBinning->unserialize(cp, section);
}
void
-System::serialize(std::ostream &os)
+System::printSystems()
{
- if (bin == true) {
- map<const Addr, SWContext *>::const_iterator iter, end;
- iter = swCtxMap.begin();
- end = swCtxMap.end();
-
- int numCtxs = swCtxMap.size();
- SERIALIZE_SCALAR(numCtxs);
- SWContext *ctx;
- for (int i = 0; iter != end; ++i, ++iter) {
- paramOut(os, csprintf("Addr[%d]",i), (*iter).first);
- ctx = (*iter).second;
- paramOut(os, csprintf("calls[%d]",i), ctx->calls);
-
- stack<fnCall *> *stack = &(ctx->callStack);
- fnCall *top;
- int size = stack->size();
- paramOut(os, csprintf("stacksize[%d]",i), size);
- for (int j=0; j<size; ++j) {
- top = stack->top();
- paramOut(os, csprintf("ctx[%d].stackpos[%d]",i,j),
- top->name);
- delete top;
- stack->pop();
- }
- }
+ vector<System *>::iterator i = systemList.begin();
+ vector<System *>::iterator end = systemList.end();
+ for (; i != end; ++i) {
+ System *sys = *i;
+ cerr << "System " << sys->name() << ": " << hex << sys << endl;
}
}
+extern "C"
void
-System::unserialize(Checkpoint *cp, const std::string &section)
+printSystems()
{
- if (bin == true) {
- int numCtxs;
- UNSERIALIZE_SCALAR(numCtxs);
-
- SWContext *ctx;
- Addr addr;
- int size;
- for(int i = 0; i < numCtxs; ++i) {
- ctx = new SWContext;
- paramIn(cp, section, csprintf("Addr[%d]",i), addr);
- paramIn(cp, section, csprintf("calls[%d]",i), ctx->calls);
-
- paramIn(cp, section, csprintf("stacksize[%d]",i), size);
-
- vector<fnCall *> calls;
- fnCall *call;
- for (int j = 0; j < size; ++j) {
- call = new fnCall;
- paramIn(cp, section, csprintf("ctx[%d].stackpos[%d]",i,j),
- call->name);
- call->myBin = getBin(call->name);
- calls.push_back(call);
- }
-
- for (int j=size-1; j>=0; --j) {
- ctx->callStack.push(calls[j]);
- }
-
- addContext(addr, ctx);
- }
- }
+ System::printSystems();
}
DEFINE_SIM_OBJECT_CLASS_NAME("System", System)
diff --git a/sim/system.hh b/sim/system.hh
index da974cfdd..07881ff01 100644
--- a/sim/system.hh
+++ b/sim/system.hh
@@ -32,85 +32,123 @@
#include <string>
#include <vector>
-#include "base/loader/symtab.hh"
#include "base/statistics.hh"
#include "cpu/pc_event.hh"
#include "kern/system_events.hh"
#include "sim/sim_object.hh"
-#include "sim/sw_context.hh"
class MemoryController;
class PhysicalMemory;
class Platform;
class RemoteGDB;
class GDBListener;
-
+class SymbolTable;
+class ObjectFile;
class ExecContext;
+namespace Kernel { class Binning; }
class System : public SimObject
{
- // lisa's binning stuff
- private:
- std::map<const std::string, Stats::MainBin *> fnBins;
- std::map<const Addr, SWContext *> swCtxMap;
+ public:
+ MemoryController *memctrl;
+ PhysicalMemory *physmem;
+ Platform *platform;
+ PCEventQueue pcEventQueue;
+ uint64_t init_param;
- protected:
- std::vector<FnEvent *> fnEvents;
+ std::vector<ExecContext *> execContexts;
- public:
- Stats::Scalar<> fnCalls;
- Stats::MainBin *Kernel;
- Stats::MainBin *User;
+ /** kernel Symbol table */
+ SymbolTable *kernelSymtab;
- Stats::MainBin * getBin(const std::string &name);
- bool findCaller(std::string, std::string) const;
+ /** console symbol table */
+ SymbolTable *consoleSymtab;
- SWContext *findContext(Addr pcb);
- bool addContext(Addr pcb, SWContext *ctx) {
- return (swCtxMap.insert(make_pair(pcb, ctx))).second;
- }
- void remContext(Addr pcb) {
- swCtxMap.erase(pcb);
- return;
- }
- void dumpState(ExecContext *xc) const;
+ /** pal symbol table */
+ SymbolTable *palSymtab;
- virtual void serialize(std::ostream &os);
- virtual void unserialize(Checkpoint *cp, const std::string &section);
+ /** Object pointer for the kernel code */
+ ObjectFile *kernel;
+ /** Object pointer for the console code */
+ ObjectFile *console;
- private:
- std::multimap<const std::string, std::string> callerMap;
- void populateMap(std::string caller, std::string callee);
-//
+ /** Object pointer for the PAL code */
+ ObjectFile *pal;
- public:
- const uint64_t init_param;
- MemoryController *memCtrl;
- PhysicalMemory *physmem;
- Platform *platform;
- bool bin;
- std::vector<string> binned_fns;
+ /** Begining of kernel code */
+ Addr kernelStart;
- PCEventQueue pcEventQueue;
+ /** End of kernel code */
+ Addr kernelEnd;
- std::vector<ExecContext *> execContexts;
+ /** Entry point in the kernel to start at */
+ Addr kernelEntry;
- std::string readfile;
+ Kernel::Binning *kernelBinning;
- virtual int registerExecContext(ExecContext *xc);
- virtual void replaceExecContext(int xcIndex, ExecContext *xc);
+#ifdef DEBUG
+ /** Event to halt the simulator if the console calls panic() */
+ BreakPCEvent *consolePanicEvent;
+#endif
public:
- System(const std::string _name, const uint64_t _init_param,
- MemoryController *, PhysicalMemory *, const bool,
- const std::vector<string> &binned_fns);
+ std::vector<RemoteGDB *> remoteGDB;
+ std::vector<GDBListener *> gdbListen;
+ bool breakpoint();
+
+ public:
+ struct Params
+ {
+ std::string name;
+ MemoryController *memctrl;
+ PhysicalMemory *physmem;
+ uint64_t init_param;
+ bool bin;
+ std::vector<std::string> binned_fns;
+ bool bin_int;
+
+ std::string kernel_path;
+ std::string console_path;
+ std::string palcode;
+ std::string boot_osflags;
+
+ std::string readfile;
+ uint64_t system_type;
+ uint64_t system_rev;
+ };
+ Params *params;
+
+ System(Params *p);
~System();
- virtual Addr getKernelStart() const = 0;
- virtual Addr getKernelEnd() const = 0;
- virtual Addr getKernelEntry() const = 0;
- virtual bool breakpoint() = 0;
+ void startup();
+
+ public:
+ /**
+ * Returns the addess the kernel starts at.
+ * @return address the kernel starts at
+ */
+ Addr getKernelStart() const { return kernelStart; }
+
+ /**
+ * Returns the addess the kernel ends at.
+ * @return address the kernel ends at
+ */
+ Addr getKernelEnd() const { return kernelEnd; }
+
+ /**
+ * Returns the addess the entry point to the kernel code.
+ * @return entry point of the kernel code
+ */
+ Addr getKernelEntry() const { return kernelEntry; }
+
+ int registerExecContext(ExecContext *xc);
+ void replaceExecContext(ExecContext *xc, int xcIndex);
+
+ void regStats();
+ void serialize(std::ostream &os);
+ void unserialize(Checkpoint *cp, const std::string &section);
public:
////////////////////////////////////////////
diff --git a/sim/universe.cc b/sim/universe.cc
index 79e32098c..824b985fa 100644
--- a/sim/universe.cc
+++ b/sim/universe.cc
@@ -51,14 +51,13 @@ double __ticksPerPS;
string outputDirectory;
ostream *outputStream;
+ostream *configStream;
class UniverseParamContext : public ParamContext
{
- private:
- ofstream outputFile;
-
public:
- UniverseParamContext(const string &is) : ParamContext(is) {}
+ UniverseParamContext(const string &is)
+ : ParamContext(is, OutputInitPhase) {}
void checkParams();
};
@@ -68,9 +67,14 @@ Param<Tick> universe_freq(&universe, "frequency", "tick frequency",
200000000);
Param<string> universe_output_dir(&universe, "output_dir",
- "directory to output data to");
+ "directory to output data to",
+ ".");
Param<string> universe_output_file(&universe, "output_file",
- "file to dump simulator output to");
+ "file to dump simulator output to",
+ "cout");
+Param<string> universe_config_output_file(&universe, "config_output_file",
+ "file to dump simulator config to",
+ "m5config.out");
void
UniverseParamContext::checkParams()
@@ -97,26 +101,49 @@ UniverseParamContext::checkParams()
}
}
- string filename;
- if (universe_output_file.isValid()) {
- string f = universe_output_file;
- if (f != "stdout" && f != "cout" && f != "stderr" && f != "cerr")
- filename = outputDirectory + f;
- else
- filename = f;
- } else {
- if (outputDirectory.empty())
- filename = "stdout";
- else
- filename = outputDirectory + "output.txt";
- }
+ outputStream = makeOutputStream(universe_output_file);
+ configStream = universe_config_output_file.isValid()
+ ? makeOutputStream(universe_config_output_file)
+ : outputStream;
+}
- if (filename == "stdout" || filename == "cout")
- outputStream = &cout;
- else if (filename == "stderr" || filename == "cerr")
- outputStream = &cerr;
- else {
- outputFile.open(filename.c_str(), ios::trunc);
- outputStream = &outputFile;
- }
+
+std::ostream *
+makeOutputStream(std::string &name)
+{
+ if (name == "cerr" || name == "stderr")
+ return &std::cerr;
+
+ if (name == "cout" || name == "stdout")
+ return &std::cout;
+
+ string path = (name[0] != '/') ? outputDirectory + name : name;
+
+ // have to dynamically allocate a stream since we're going to
+ // return it... though the caller can't easily free it since it
+ // may be cerr or cout. need GC!
+ ofstream *s = new ofstream(path.c_str(), ios::trunc);
+
+ if (!s->is_open())
+ fatal("Cannot open file %s", path);
+
+ return s;
}
+
+
+void
+closeOutputStream(std::ostream *os)
+{
+ // can't close cerr or cout
+ if (os == &std::cerr || os == &std::cout)
+ return;
+
+ // can only close ofstreams, not generic ostreams, so try to
+ // downcast and close only if the downcast succeeds
+ std::ofstream *ofs = dynamic_cast<std::ofstream *>(os);
+ if (ofs)
+ ofs->close();
+}
+
+
+