diff options
Diffstat (limited to 'sim')
-rw-r--r-- | sim/builder.cc | 30 | ||||
-rw-r--r-- | sim/builder.hh | 3 | ||||
-rw-r--r-- | sim/debug.cc | 6 | ||||
-rw-r--r-- | sim/debug.hh | 4 | ||||
-rw-r--r-- | sim/main.cc | 82 | ||||
-rw-r--r-- | sim/param.cc | 25 | ||||
-rw-r--r-- | sim/param.hh | 32 | ||||
-rw-r--r-- | sim/process.cc | 27 | ||||
-rw-r--r-- | sim/process.hh | 2 | ||||
-rw-r--r-- | sim/serialize.cc | 5 | ||||
-rw-r--r-- | sim/sim_events.cc | 26 | ||||
-rw-r--r-- | sim/sim_object.hh | 6 | ||||
-rw-r--r-- | sim/startup.cc | 51 | ||||
-rw-r--r-- | sim/startup.hh | 41 | ||||
-rw-r--r-- | sim/system.cc | 348 | ||||
-rw-r--r-- | sim/system.hh | 136 | ||||
-rw-r--r-- | sim/universe.cc | 81 |
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 §ion) { - 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 §ion) +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 §ion); + /** 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 §ion); 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(); +} + + + |