diff options
-rw-r--r-- | arch/alpha/isa_desc | 6 | ||||
-rw-r--r-- | base/cprintf.cc | 26 | ||||
-rw-r--r-- | base/cprintf.hh | 1 | ||||
-rw-r--r-- | base/loader/elf_object.cc | 6 | ||||
-rw-r--r-- | base/misc.cc | 40 | ||||
-rw-r--r-- | base/statistics.cc | 57 | ||||
-rw-r--r-- | base/trace.cc | 7 | ||||
-rw-r--r-- | cpu/simple_cpu/simple_cpu.cc | 6 | ||||
-rw-r--r-- | dev/alpha_console.cc | 2 | ||||
-rw-r--r-- | dev/console.cc | 59 | ||||
-rw-r--r-- | dev/console.hh | 8 | ||||
-rw-r--r-- | dev/etherdump.cc | 18 | ||||
-rw-r--r-- | kern/tru64/tru64_system.cc | 6 | ||||
-rw-r--r-- | sim/builder.cc | 45 | ||||
-rw-r--r-- | sim/builder.hh | 19 | ||||
-rw-r--r-- | sim/main.cc | 10 | ||||
-rw-r--r-- | sim/serialize.cc | 18 | ||||
-rw-r--r-- | sim/universe.cc | 55 | ||||
-rw-r--r-- | test/stattest.cc | 6 |
19 files changed, 293 insertions, 102 deletions
diff --git a/arch/alpha/isa_desc b/arch/alpha/isa_desc index f0a4699f4..3533da09f 100644 --- a/arch/alpha/isa_desc +++ b/arch/alpha/isa_desc @@ -538,7 +538,7 @@ declare {{ trappingMode((enum TrappingMode)FP_TRAPMODE) { if (trappingMode != Imprecise) { - warn("Warning: precise FP traps unimplemented\n"); + warn("precise FP traps unimplemented\n"); } } @@ -1609,7 +1609,7 @@ declare {{ Trace::InstRecord *traceData) { if (!warned) { - warn("Warning: instruction '%s' unimplemented\n", mnemonic); + warn("instruction '%s' unimplemented\n", mnemonic); warned = true; } @@ -1620,7 +1620,7 @@ declare {{ Trace::InstRecord *traceData) { if (!xc->spec_mode && !warned) { - warn("Warning: instruction '%s' unimplemented\n", mnemonic); + warn("instruction '%s' unimplemented\n", mnemonic); warned = true; } diff --git a/base/cprintf.cc b/base/cprintf.cc index 5796a712b..5cbf0c057 100644 --- a/base/cprintf.cc +++ b/base/cprintf.cc @@ -37,9 +37,20 @@ using namespace std; namespace cp { +ArgList::~ArgList() +{ + while (!objects.empty()) { + delete objects.front(); + objects.pop_front(); + } +} + void ArgList::dump(const string &format) { + list_t::iterator iter = objects.begin(); + list_t::iterator end = objects.end(); + const char *p = format.c_str(); stream->fill(' '); @@ -198,22 +209,19 @@ ArgList::dump(const string &format) } } - if (!objects.empty()) + if (iter != end) { - Base *data = objects.front(); - objects.pop_front(); - ios::fmtflags saved_flags = stream->flags(); char old_fill = stream->fill(); int old_precision = stream->precision(); - data->process(*stream, fmt); + (*iter)->process(*stream, fmt); stream->flags(saved_flags); stream->fill(old_fill); stream->precision(old_precision); - delete data; + ++iter; } else { *stream << "<missing arg for format>"; } @@ -241,11 +249,9 @@ ArgList::dump(const string &format) } } - while (!objects.empty()) { + while (iter != end) { *stream << "<extra arg>"; - Base *data = objects.front(); - objects.pop_front(); - delete data; + ++iter; } } diff --git a/base/cprintf.hh b/base/cprintf.hh index ac34cd252..ca5c08b16 100644 --- a/base/cprintf.hh +++ b/base/cprintf.hh @@ -89,6 +89,7 @@ class ArgList public: ArgList() : stream(&std::cout) {} + ~ArgList(); template<class T> void append(const T &data) { diff --git a/base/loader/elf_object.cc b/base/loader/elf_object.cc index 929d455a5..9889b9d4c 100644 --- a/base/loader/elf_object.cc +++ b/base/loader/elf_object.cc @@ -30,7 +30,11 @@ // Because of the -Wundef flag we have to do this #define __LIBELF_INTERNAL__ 0 -#define __LIBELF64_LINUX 1 +// counterintuitive, but the flag below causes libelf to define +// 64-bit elf types that apparently didn't exist in some older +// versions of Linux. They seem to be there in 2.4.x, so don't +// set this now (it causes things to break on 64-bit platforms). +#define __LIBELF64_LINUX 0 #define __LIBELF_NEED_LINK_H 0 #include <libelf/libelf.h> diff --git a/base/misc.cc b/base/misc.cc index 8190caddd..5caf96d40 100644 --- a/base/misc.cc +++ b/base/misc.cc @@ -42,7 +42,17 @@ void __panic(const string &format, cp::ArgList &args, const char *func, const char *file, int line) { - string fmt = "panic: " + format + " @ cycle %d\n[%s:%s, line %d]\n"; + string fmt = "panic: " + format; + switch (fmt[fmt.size() - 1]) { + case '\n': + case '\r': + break; + default: + fmt += "\n"; + } + + fmt += " @ cycle %d\n[%s:%s, line %d]\n"; + args.append(curTick); args.append(func); args.append(file); @@ -63,8 +73,18 @@ void __fatal(const string &format, cp::ArgList &args, const char *func, const char *file, int line) { - string fmt = "fatal: " + format + " @ cycle %d\n[%s:%s, line %d]\n" - "Memory Usage: %ld KBytes\n"; + string fmt = "fatal: " + format; + + switch (fmt[fmt.size() - 1]) { + case '\n': + case '\r': + break; + default: + fmt += "\n"; + } + + fmt += " @ cycle %d\n[%s:%s, line %d]\n"; + fmt += "Memory Usage: %ld KBytes\n"; args.append(curTick); args.append(func); @@ -83,16 +103,26 @@ __warn(const string &format, cp::ArgList &args, const char *func, const char *file, int line) { string fmt = "warn: " + format; + + switch (fmt[fmt.size() - 1]) { + case '\n': + case '\r': + break; + default: + fmt += "\n"; + } + #ifdef VERBOSE_WARN fmt += " @ cycle %d\n[%s:%s, line %d]\n"; args.append(curTick); args.append(func); args.append(file); args.append(line); -#else - fmt += "\n"; #endif + args.dump(cerr, fmt); + if (outputStream != &cerr && outputStream != &cout) + args.dump(*outputStream, fmt); delete &args; } diff --git a/base/statistics.cc b/base/statistics.cc index 5c9a2bc65..49294ad27 100644 --- a/base/statistics.cc +++ b/base/statistics.cc @@ -116,7 +116,7 @@ Data::~Data() { if (stream) { delete py; - ccprintf(*stream, "if __name__ == '__main__':\n"); + ccprintf(*stream, "\n\nif __name__ == '__main__':\n"); ccprintf(*stream, " program_display()\n"); stream->close(); delete stream; @@ -209,30 +209,41 @@ Data::python_dump(const string &name, const string &subname) ++i; } } - py->next(); } void Data::python(const string &name, const string &subname, const string &bin) { - py->start("collections.append"); - py->start("Collection"); + py->name("collections.append"); + py->newline(); + py->name("Collection"); + py->newline(); py->qarg(name); + py->newline(); py->qarg(subname); + py->newline(); py->qarg(bin); + py->newline(); py->qarg(hostname()); + py->newline(); py->qarg(Time::start.date()); - py->startList(); + py->newline(); + py->list(); list_t::iterator i = allStats.begin(); list_t::iterator end = allStats.end(); while (i != end) { StatData *stat = *i; + py->newline(); stat->python(*py); ++i; } - py->endList(); - py->end(); - py->end(); + py->newline(); + py->listEnd(); + py->newline(); + py->nameEnd(); + py->newline(); + py->nameEnd(); + py->newline(); } StatData * @@ -996,7 +1007,7 @@ VectorDistDataBase::display(ostream &stream, DisplayMode mode) const void ScalarDataBase::python(Python &py) const { - py.start("Scalar"); + py.name("Scalar"); py.qarg(name); py.qqqarg(desc); py.kwarg("binned", binned()); @@ -1005,7 +1016,7 @@ ScalarDataBase::python(Python &py) const if (prereq) py.qkwarg("prereq", prereq->name); py.kwarg("value", val()); - py.end(); + py.nameEnd(); } void @@ -1013,7 +1024,7 @@ VectorDataBase::python(Python &py) const { const_cast<VectorDataBase *>(this)->update(); - py.start("Vector"); + py.name("Vector"); py.qarg(name); py.qqqarg(desc); py.kwarg("binned", binned()); @@ -1026,7 +1037,7 @@ VectorDataBase::python(Python &py) const py.qkwarg("subnames", subnames); if (!subdescs.empty()) py.qkwarg("subdescs", subdescs); - py.end(); + py.nameEnd(); } void @@ -1039,7 +1050,7 @@ DistDataData::python(Python &py, const string &name) const else s += "FullDist"; - py.start(s); + py.name(s); py.arg(sum); py.arg(squares); py.arg(samples); @@ -1054,7 +1065,7 @@ DistDataData::python(Python &py, const string &name) const py.arg(bucket_size); py.arg(size); } - py.end(); + py.nameEnd(); } void @@ -1062,7 +1073,7 @@ FormulaDataBase::python(Python &py) const { const_cast<FormulaDataBase *>(this)->update(); - py.start("Formula"); + py.name("Formula"); py.qarg(name); py.qqqarg(desc); py.kwarg("binned", binned()); @@ -1075,7 +1086,7 @@ FormulaDataBase::python(Python &py) const py.qkwarg("subnames", subnames); if (!subdescs.empty()) py.qkwarg("subdescs", subdescs); - py.end(); + py.nameEnd(); } void @@ -1083,7 +1094,7 @@ DistDataBase::python(Python &py) const { const_cast<DistDataBase *>(this)->update(); - py.start("Dist"); + py.name("Dist"); py.qarg(name); py.qqqarg(desc); py.kwarg("binned", binned()); @@ -1092,7 +1103,7 @@ DistDataBase::python(Python &py) const if (prereq) py.qkwarg("prereq", prereq->name); data.python(py, "dist"); - py.end(); + py.nameEnd(); } void @@ -1100,7 +1111,7 @@ VectorDistDataBase::python(Python &py) const { const_cast<VectorDistDataBase *>(this)->update(); - py.start("VectorDist"); + py.name("VectorDist"); py.qarg(name); py.qqqarg(desc); py.kwarg("binned", binned()); @@ -1121,8 +1132,8 @@ VectorDistDataBase::python(Python &py) const i->python(py, ""); ++i; } - py.endTuple(); - py.end(); + py.tupleEnd(); + py.nameEnd(); } void @@ -1130,7 +1141,7 @@ Vector2dDataBase::python(Python &py) const { const_cast<Vector2dDataBase *>(this)->update(); - py.start("Vector2d"); + py.name("Vector2d"); py.qarg(name); py.qqqarg(desc); py.kwarg("binned", binned()); @@ -1149,7 +1160,7 @@ Vector2dDataBase::python(Python &py) const py.kwarg("x", x); py.kwarg("y", y); - py.end(); + py.nameEnd(); } void diff --git a/base/trace.cc b/base/trace.cc index 99e97e7ea..156110376 100644 --- a/base/trace.cc +++ b/base/trace.cc @@ -49,7 +49,7 @@ FlagVec flags(NumFlags, false); // directly; use DebugOut() (see below) to access this stream for // output. // -ostream *dprintf_stream = NULL; +ostream *dprintf_stream = &cerr; int dprintf_ignore_size; vector<string> dprintf_ignore; @@ -267,10 +267,7 @@ RawDataRecord::dump(ostream &os) std::ostream & DebugOut() { - if (Trace::dprintf_stream) - return *Trace::dprintf_stream; - else - return cerr; + return *Trace::dprintf_stream; } ///////////////////////////////////////////// diff --git a/cpu/simple_cpu/simple_cpu.cc b/cpu/simple_cpu/simple_cpu.cc index adbd17a35..0d5fc4077 100644 --- a/cpu/simple_cpu/simple_cpu.cc +++ b/cpu/simple_cpu/simple_cpu.cc @@ -349,7 +349,7 @@ SimpleCPU::read(Addr addr, T& data, unsigned flags) // Ugly hack to get an event scheduled *only* if the access is // a miss. We really should add first-class support for this // at some point. - if (result != MA_HIT && dcacheInterface->doEvents) { + if (result != MA_HIT && dcacheInterface->doEvents()) { memReq->completionEvent = &cacheCompletionEvent; lastDcacheStall = curTick; unscheduleTickEvent(); @@ -432,7 +432,7 @@ SimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res) // Ugly hack to get an event scheduled *only* if the access is // a miss. We really should add first-class support for this // at some point. - if (result != MA_HIT && dcacheInterface->doEvents) { + if (result != MA_HIT && dcacheInterface->doEvents()) { memReq->completionEvent = &cacheCompletionEvent; lastDcacheStall = curTick; unscheduleTickEvent(); @@ -635,7 +635,7 @@ SimpleCPU::tick() // Ugly hack to get an event scheduled *only* if the access is // a miss. We really should add first-class support for this // at some point. - if (result != MA_HIT && icacheInterface->doEvents) { + if (result != MA_HIT && icacheInterface->doEvents()) { memReq->completionEvent = &cacheCompletionEvent; lastIcacheStall = curTick; unscheduleTickEvent(); diff --git a/dev/alpha_console.cc b/dev/alpha_console.cc index 359995693..89e121ed3 100644 --- a/dev/alpha_console.cc +++ b/dev/alpha_console.cc @@ -82,7 +82,7 @@ AlphaConsole::read(MemReqPtr req, uint8_t *data) Addr daddr = req->paddr & addr_mask; switch (daddr) { case offsetof(AlphaAccess, inputChar): - val = console->in(); + val = console->console_in(); break; default: diff --git a/dev/console.cc b/dev/console.cc index 08b169bc4..fb74c388a 100644 --- a/dev/console.cc +++ b/dev/console.cc @@ -228,27 +228,44 @@ SimConsole::configTerm() #define RECEIVE_NONE (ULL(2) << 62) #define RECEIVE_ERROR (ULL(3) << 62) -uint64_t -SimConsole::in() +bool +SimConsole::in(uint8_t &c) { - char c = 0; - uint64_t val = 0; - if (rxbuf.empty()) { + bool empty, ret; + + empty = rxbuf.empty(); + ret = !empty; + if (!empty) { + rxbuf.read((char *)&c, 1); + empty = rxbuf.empty(); + } + + if (empty) clearInt(ReceiveInterrupt); - val |= RECEIVE_NONE; - return 0x8; - } else { - uint64_t val; - rxbuf.read(&c, 1); - val |= RECEIVE_SUCCESS | c; + + DPRINTF(ConsoleVerbose, "in: \'%c\' %#02x more: %d, return: %d\n", + isprint(c) ? c : ' ', c, !empty, ret); + + return ret; +} + +uint64_t +SimConsole::console_in() +{ + uint8_t c; + uint64_t value; + + if (in(c)) { + value = RECEIVE_SUCCESS | c; if (!rxbuf.empty()) - val |= MORE_PENDING; + value |= MORE_PENDING; + } else { + value = RECEIVE_NONE; } - DPRINTF(ConsoleVerbose, "in: \'%c\' %#02x retval: %#x\n", - isprint(c) ? c : ' ', c, val); + DPRINTF(ConsoleVerbose, "console_in: return: %#x\n", value); - return val; + return value; } void @@ -383,8 +400,16 @@ END_INIT_SIM_OBJECT_PARAMS(SimConsole) CREATE_SIM_OBJECT(SimConsole) { string filename = output; - if (!filename.empty() && append_name) - filename += "." + getInstanceName(); + if (filename.empty()) { + if (!outputDirectory.empty()) + filename = outputDirectory + getInstanceName(); + } else { + if (append_name) + filename += "." + getInstanceName(); + if (!outputDirectory.empty()) + filename = outputDirectory + filename; + } + SimConsole *console = new SimConsole(getInstanceName(), filename, number); ((ConsoleListener *)listener)->add(console); ((SimConsole *)console)->initInt(intr_control); diff --git a/dev/console.hh b/dev/console.hh index 9913fe379..d2bba4612 100644 --- a/dev/console.hh +++ b/dev/console.hh @@ -109,7 +109,10 @@ class SimConsole : public SimObject // OS interface // Get a character from the console. - // the return value corresponds to the console GETC return value: + bool in(uint8_t &value); + + // get a character from the console in the console specific format + // corresponds to GETC: // retval<63:61> // 000: success: character received // 001: success: character received, more pending @@ -118,8 +121,9 @@ class SimConsole : public SimObject // 111: failure: character received with error, more pending // retval<31:0> // character read from console + // // Interrupts are cleared when the buffer is empty. - uint64_t in(); + uint64_t console_in(); // Send a character to the console void out(char c, bool raise_int = true); diff --git a/dev/etherdump.cc b/dev/etherdump.cc index 60dc1559d..89f1ce382 100644 --- a/dev/etherdump.cc +++ b/dev/etherdump.cc @@ -126,13 +126,27 @@ END_DECLARE_SIM_OBJECT_PARAMS(EtherDump) BEGIN_INIT_SIM_OBJECT_PARAMS(EtherDump) - INIT_PARAM_DFLT(file, "file to dump packets to", "") + INIT_PARAM(file, "file to dump packets to") END_INIT_SIM_OBJECT_PARAMS(EtherDump) CREATE_SIM_OBJECT(EtherDump) { - return new EtherDump(getInstanceName(), file); + string filename; + if (file.isValid()) { + filename = file; + + if (filename[0] != '/' && !outputDirectory.empty()) + filename = outputDirectory + filename; + } else { + if (outputDirectory.empty()) { + filename = "etherdump"; + } else { + filename = outputDirectory + "etherdump"; + } + } + + return new EtherDump(getInstanceName(), filename); } REGISTER_SIM_OBJECT("EtherDump", EtherDump) diff --git a/kern/tru64/tru64_system.cc b/kern/tru64/tru64_system.cc index 99d99afd4..07c655385 100644 --- a/kern/tru64/tru64_system.cc +++ b/kern/tru64/tru64_system.cc @@ -192,8 +192,10 @@ Tru64System::Tru64System(const string _name, const uint64_t _init_param, //INSTRUMENTATION CODEGEN END #endif //FS_MEASURE +#ifdef DEBUG kernelPanicEvent = new BreakPCEvent(&pcEventQueue, "kernel panic"); consolePanicEvent = new BreakPCEvent(&pcEventQueue, "console panic"); +#endif badaddrEvent = new BadAddrEvent(&pcEventQueue, "badaddr"); skipPowerStateEvent = new SkipFuncEvent(&pcEventQueue, "tl_v48_capture_power_state"); @@ -262,6 +264,7 @@ Tru64System::Tru64System(const string _name, const uint64_t _init_param, strcpy(osflags, boot_osflags.c_str()); } +#ifdef DEBUG if (kernelSymtab->findAddress("panic", addr)) kernelPanicEvent->schedule(addr); else @@ -269,6 +272,7 @@ Tru64System::Tru64System(const string _name, const uint64_t _init_param, if (consoleSymtab->findAddress("panic", addr)) consolePanicEvent->schedule(addr); +#endif if (kernelSymtab->findAddress("badaddr", addr)) badaddrEvent->schedule(addr); @@ -511,8 +515,10 @@ Tru64System::~Tru64System() delete kernelSymtab; delete consoleSymtab; +#ifdef DEBUG delete kernelPanicEvent; delete consolePanicEvent; +#endif delete badaddrEvent; delete skipPowerStateEvent; delete skipScavengeBootEvent; diff --git a/sim/builder.cc b/sim/builder.cc index fa435d322..e2345556e 100644 --- a/sim/builder.cc +++ b/sim/builder.cc @@ -34,10 +34,45 @@ #include "sim/configfile.hh" #include "sim/host.hh" #include "sim/sim_object.hh" -#include "sim/sim_stats.hh" +#include "sim/universe.hh" 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), + instanceName(_instanceName), + configNode(_configNode), + simObjClassName(_simObjClassName) +{ +} + +SimObjectBuilder::~SimObjectBuilder() +{ +} + /////////////////////////////////////////// // // SimObjectBuilder member definitions @@ -151,10 +186,10 @@ SimObjectClass::createObject(IniFile &configDB, // echo object parameters to stats file (for documenting the // config used to generate the associated stats) - *statStream << "[" << object->name() << "]" << endl; - *statStream << "type=" << simObjClassName << endl; - objectBuilder->showParams(*statStream); - *statStream << endl; + builderStream() << "[" << object->name() << "]" << endl; + builderStream() << "type=" << simObjClassName << endl; + objectBuilder->showParams(builderStream()); + builderStream() << endl; // done with the SimObjectBuilder now delete objectBuilder; diff --git a/sim/builder.hh b/sim/builder.hh index 0364276bf..e13a85272 100644 --- a/sim/builder.hh +++ b/sim/builder.hh @@ -29,15 +29,18 @@ #ifndef __BUILDER_HH__ #define __BUILDER_HH__ -#include <map> +#include <iosfwd> #include <list> +#include <map> #include <vector> -#include <iostream> #include "sim/param.hh" 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 @@ -69,15 +72,9 @@ class SimObjectBuilder : public ParamContext SimObjectBuilder(const std::string &_configClass, const std::string &_instanceName, ConfigNode *_configNode, - const std::string &_simObjClassName) - : ParamContext(_configClass, true), - instanceName(_instanceName), - configNode(_configNode), - simObjClassName(_simObjClassName) - { - } - - virtual ~SimObjectBuilder() {} + const std::string &_simObjClassName); + + virtual ~SimObjectBuilder(); // call parse() on all params in this context to convert string // representations to parameter values diff --git a/sim/main.cc b/sim/main.cc index d0cf23039..48d64d4cd 100644 --- a/sim/main.cc +++ b/sim/main.cc @@ -54,6 +54,7 @@ #include "sim/sim_init.hh" #include "sim/sim_object.hh" #include "sim/sim_stats.hh" +#include "sim/universe.hh" using namespace std; @@ -355,12 +356,12 @@ main(int argc, char **argv) // Print hello message to stats file if it's actually a file. If // it's not (i.e. it's cout or cerr) then we already did it above. - if (statStreamIsFile) - sayHello(*statStream); + if (outputStream != &cout && outputStream != &cerr) + sayHello(*outputStream); // Echo command line and all parameter settings to stats file as well. - echoCommandLine(argc, argv, *statStream); - ParamContext::showAllContexts(*statStream); + echoCommandLine(argc, argv, *outputStream); + ParamContext::showAllContexts(builderStream()); // Now process the configuration hierarchy and create the SimObjects. ConfigHierarchy configHierarchy(simConfigDB); @@ -400,6 +401,7 @@ main(int argc, char **argv) } SimInit(); + warn("Entering event queue. Starting simulation...\n"); while (!mainEventQueue.empty()) { assert(curTick <= mainEventQueue.nextTick() && diff --git a/sim/serialize.cc b/sim/serialize.cc index 33956c6e7..281e7cfc8 100644 --- a/sim/serialize.cc +++ b/sim/serialize.cc @@ -305,10 +305,9 @@ class SerializeParamContext : public ParamContext SerializeParamContext serialParams("serialize"); -Param<string> serialize_dir(&serialParams, - "dir", +Param<string> serialize_dir(&serialParams, "dir", "dir to stick checkpoint in " - "(sprintf format with cycle #)", "m5.%012d"); + "(sprintf format with cycle #)"); Param<Counter> serialize_cycle(&serialParams, "cycle", @@ -333,11 +332,18 @@ SerializeParamContext::~SerializeParamContext() void SerializeParamContext::checkParams() { - checkpointDirBase = serialize_dir; + if (serialize_dir.isValid()) { + checkpointDirBase = serialize_dir; + } else { + if (outputDirectory.empty()) + checkpointDirBase = "m5.%012d"; + else + checkpointDirBase = outputDirectory + "cpt.%012d"; + } + // guarantee that directory ends with a '/' - if (checkpointDirBase[checkpointDirBase.size() - 1] != '/') { + if (checkpointDirBase[checkpointDirBase.size() - 1] != '/') checkpointDirBase += "/"; - } if (serialize_cycle > 0) Checkpoint::setup(serialize_cycle, serialize_period); diff --git a/sim/universe.cc b/sim/universe.cc index b75b1f78a..feede514e 100644 --- a/sim/universe.cc +++ b/sim/universe.cc @@ -26,10 +26,16 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include <sys/types.h> +#include <sys/stat.h> + +#include <cstring> +#include <fstream> #include <list> #include <string> #include <vector> +#include "base/misc.hh" #include "sim/universe.hh" #include "sim/host.hh" #include "sim/param.hh" @@ -42,8 +48,14 @@ double __ticksPerMS; double __ticksPerUS; double __ticksPerNS; +string outputDirectory; +ostream *outputStream; + class UniverseParamContext : public ParamContext { + private: + ofstream outputFile; + public: UniverseParamContext(const string &is) : ParamContext(is) {} void checkParams(); @@ -54,6 +66,11 @@ UniverseParamContext universe("Universe"); Param<Tick> universe_freq(&universe, "frequency", "tick frequency", 200000000); +Param<string> universe_output_dir(&universe, "output_dir", + "directory to output data to"); +Param<string> universe_output_file(&universe, "output_file", + "file to dump simulator output to"); + void UniverseParamContext::checkParams() { @@ -62,4 +79,42 @@ UniverseParamContext::checkParams() __ticksPerMS = freq / 1.0e3; __ticksPerUS = freq / 1.0e6; __ticksPerNS = freq / 1.0e9; + + if (universe_output_dir.isValid()) { + outputDirectory = universe_output_dir; + + // guarantee that directory ends with a '/' + if (outputDirectory[outputDirectory.size() - 1] != '/') + outputDirectory += "/"; + + if (mkdir(outputDirectory.c_str(), 0777) < 0) { + if (errno != EEXIST) { + panic("%s\ncould not make output directory: %s\n", + strerror(errno), outputDirectory); + } + } + } + + 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"; + } + + 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; + } } diff --git a/test/stattest.cc b/test/stattest.cc index d4ae5d1fd..8dd8eeb8e 100644 --- a/test/stattest.cc +++ b/test/stattest.cc @@ -510,10 +510,8 @@ main(int argc, char *argv[]) s12.sample(100); // dump(cout, mode_simplescalar); - ofstream file("/tmp/stats.py"); - dump(file, "stattest", mode_python); - file.close(); - + python_start("/tmp/stats.py"); + python_dump("stattest", "all"); return 0; } |