diff options
Diffstat (limited to 'src/sim')
-rw-r--r-- | src/sim/SConscript | 54 | ||||
-rw-r--r-- | src/sim/async.cc | 38 | ||||
-rw-r--r-- | src/sim/async.hh | 4 | ||||
-rw-r--r-- | src/sim/builder.cc | 4 | ||||
-rw-r--r-- | src/sim/byteswap.hh | 19 | ||||
-rw-r--r-- | src/sim/core.cc | 140 | ||||
-rw-r--r-- | src/sim/core.hh | 85 | ||||
-rw-r--r-- | src/sim/eventq.cc | 7 | ||||
-rw-r--r-- | src/sim/eventq.hh | 22 | ||||
-rw-r--r-- | src/sim/faults.cc | 28 | ||||
-rw-r--r-- | src/sim/faults.hh | 12 | ||||
-rw-r--r-- | src/sim/main.cc | 368 | ||||
-rw-r--r-- | src/sim/param.cc | 109 | ||||
-rw-r--r-- | src/sim/param.hh | 47 | ||||
-rw-r--r-- | src/sim/process.cc | 53 | ||||
-rw-r--r-- | src/sim/process.hh | 25 | ||||
-rw-r--r-- | src/sim/pseudo_inst.cc | 12 | ||||
-rw-r--r-- | src/sim/pseudo_inst.hh | 2 | ||||
-rw-r--r-- | src/sim/root.cc | 99 | ||||
-rw-r--r-- | src/sim/serialize.cc | 33 | ||||
-rw-r--r-- | src/sim/sim_events.cc | 18 | ||||
-rw-r--r-- | src/sim/sim_events.hh | 19 | ||||
-rw-r--r-- | src/sim/sim_object.cc | 9 | ||||
-rw-r--r-- | src/sim/sim_object.hh | 1 | ||||
-rw-r--r-- | src/sim/simulate.cc | 121 | ||||
-rw-r--r-- | src/sim/simulate.hh | 35 | ||||
-rw-r--r-- | src/sim/stat_control.cc | 96 | ||||
-rw-r--r-- | src/sim/stat_control.hh | 19 | ||||
-rw-r--r-- | src/sim/syscall_emul.cc | 33 | ||||
-rw-r--r-- | src/sim/syscall_emul.hh | 28 | ||||
-rw-r--r-- | src/sim/system.cc | 39 |
31 files changed, 741 insertions, 838 deletions
diff --git a/src/sim/SConscript b/src/sim/SConscript new file mode 100644 index 000000000..46dc2c8dd --- /dev/null +++ b/src/sim/SConscript @@ -0,0 +1,54 @@ +# -*- mode:python -*- + +# Copyright (c) 2006 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. +# +# Authors: Nathan Binkert + +Import('*') + +Source('async.cc') +Source('builder.cc') +Source('core.cc') +Source('debug.cc') +Source('eventq.cc') +Source('faults.cc') +Source('main.cc') +Source('param.cc') +Source('root.cc') +Source('serialize.cc') +Source('sim_events.cc') +Source('sim_object.cc') +Source('simulate.cc') +Source('startup.cc') +Source('stat_control.cc') +Source('system.cc') + +if env['FULL_SYSTEM']: + Source('pseudo_inst.cc') +else: + Source('process.cc') + Source('syscall_emul.cc') diff --git a/src/sim/async.cc b/src/sim/async.cc new file mode 100644 index 000000000..1a8e499f7 --- /dev/null +++ b/src/sim/async.cc @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2000-2005 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. + * + * Authors: Nathan Binkert + */ + +volatile bool async_event = false; +volatile bool async_statdump = false; +volatile bool async_statreset = false; +volatile bool async_exit = false; +volatile bool async_io = false; +volatile bool async_alarm = false; +volatile bool async_exception = false; + diff --git a/src/sim/async.hh b/src/sim/async.hh index 50ae73040..932f975d2 100644 --- a/src/sim/async.hh +++ b/src/sim/async.hh @@ -43,10 +43,12 @@ /// @note See the PollQueue object (in pollevent.hh) for the use of async_io and async_alarm. //@{ extern volatile bool async_event; ///< Some asynchronous event has happened. -extern volatile bool async_dump; ///< Async request to dump stats. +extern volatile bool async_statdump; ///< Async request to dump stats. +extern volatile bool async_statreset; ///< Async request to reset stats. extern volatile bool async_exit; ///< Async request to exit simulator. extern volatile bool async_io; ///< Async I/O request (SIGIO). extern volatile bool async_alarm; ///< Async alarm event (SIGALRM). +extern volatile bool async_exception; ///< Python exception. //@} #endif // __ASYNC_HH__ diff --git a/src/sim/builder.cc b/src/sim/builder.cc index 9074cc899..532df36b1 100644 --- a/src/sim/builder.cc +++ b/src/sim/builder.cc @@ -35,12 +35,12 @@ #include "sim/builder.hh" #include "sim/host.hh" #include "sim/sim_object.hh" -#include "sim/root.hh" +#include "sim/core.hh" using namespace std; SimObjectBuilder::SimObjectBuilder(const std::string &_iniSection) - : ParamContext(_iniSection, NoAutoInit) + : ParamContext(_iniSection) { } diff --git a/src/sim/byteswap.hh b/src/sim/byteswap.hh index cbc0b5088..062fc4513 100644 --- a/src/sim/byteswap.hh +++ b/src/sim/byteswap.hh @@ -37,6 +37,7 @@ #ifndef __SIM_BYTE_SWAP_HH__ #define __SIM_BYTE_SWAP_HH__ +#include "base/bigint.hh" #include "base/misc.hh" #include "sim/host.hh" @@ -109,7 +110,7 @@ swap_byte16(uint16_t x) // This function lets the compiler figure out how to call the // swap_byte functions above for different data types. Since the -// sizeof() values are known at compiel time, it should inline to a +// sizeof() values are known at compile time, it should inline to a // direct call to the right swap_byteNN() function. template <typename T> static inline T swap_byte(T x) { @@ -125,6 +126,22 @@ static inline T swap_byte(T x) { panic("Can't byte-swap values larger than 64 bits"); } +template<> +static inline Twin64_t swap_byte<Twin64_t>(Twin64_t x) +{ + x.a = swap_byte(x.a); + x.b = swap_byte(x.b); + return x; +} + +template<> +static inline Twin32_t swap_byte<Twin32_t>(Twin32_t x) +{ + x.a = swap_byte(x.a); + x.b = swap_byte(x.b); + return x; +} + //The conversion functions with fixed endianness on both ends don't need to //be in a namespace template <typename T> static inline T betole(T value) {return swap_byte(value);} diff --git a/src/sim/core.cc b/src/sim/core.cc new file mode 100644 index 000000000..c961e9eb8 --- /dev/null +++ b/src/sim/core.cc @@ -0,0 +1,140 @@ +/* + * Copyright (c) 2006 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. + * + * Authors: Nathan Binkert + * Steve Reinhardt + */ + +#include <iostream> +#include <string> + +#include "base/callback.hh" +#include "base/output.hh" +#include "sim/core.hh" + +using namespace std; + +Tick curTick = 0; + +namespace Clock { +/// The simulated frequency of curTick. (In ticks per second) +Tick Frequency; + +namespace Float { +double s; +double ms; +double us; +double ns; +double ps; + +double Hz; +double kHz; +double MHz; +double GHZ; +/* namespace Float */ } + +namespace Int { +Tick s; +Tick ms; +Tick us; +Tick ns; +Tick ps; +/* namespace Float */ } + +/* namespace Clock */ } + +void +setClockFrequency(Tick ticksPerSecond) +{ + using namespace Clock; + Frequency = ticksPerSecond; + Float::s = static_cast<double>(Frequency); + Float::ms = Float::s / 1.0e3; + Float::us = Float::s / 1.0e6; + Float::ns = Float::s / 1.0e9; + Float::ps = Float::s / 1.0e12; + + Float::Hz = 1.0 / Float::s; + Float::kHz = 1.0 / Float::ms; + Float::MHz = 1.0 / Float::us; + Float::GHZ = 1.0 / Float::ns; + + Int::s = Frequency; + Int::ms = Int::s / 1000; + Int::us = Int::ms / 1000; + Int::ns = Int::us / 1000; + Int::ps = Int::ns / 1000; + +} + +void +setOutputDir(const string &dir) +{ + simout.setDirectory(dir); +} + +ostream *outputStream; +ostream *configStream; + +void +setOutputFile(const string &file) +{ + outputStream = simout.find(file); +} + +/** + * Queue of C++ callbacks to invoke on simulator exit. + */ +inline CallbackQueue & +exitCallbacks() +{ + static CallbackQueue theQueue; + return theQueue; +} + +/** + * Register an exit callback. + */ +void +registerExitCallback(Callback *callback) +{ + exitCallbacks().add(callback); +} + +/** + * Do C++ simulator exit processing. Exported to SWIG to be invoked + * when simulator terminates via Python's atexit mechanism. + */ +void +doExitCleanup() +{ + exitCallbacks().process(); + exitCallbacks().clear(); + + cout.flush(); +} + diff --git a/src/sim/core.hh b/src/sim/core.hh new file mode 100644 index 000000000..7360032c2 --- /dev/null +++ b/src/sim/core.hh @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2006 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. + * + * Authors: Nathan Binkert + * Steve Reinhardt + */ + +#ifndef __SIM_CORE_HH__ +#define __SIM_CORE_HH__ + +#include <string> + +#include "sim/host.hh" + +/// The universal simulation clock. +extern Tick curTick; +const Tick retryTime = 1000; + +namespace Clock { +/// The simulated frequency of curTick. +extern Tick Frequency; + +namespace Float { +extern double s; +extern double ms; +extern double us; +extern double ns; +extern double ps; + +extern double Hz; +extern double kHz; +extern double MHz; +extern double GHZ; +/* namespace Float */ } + +namespace Int { +extern Tick s; +extern Tick ms; +extern Tick us; +extern Tick ns; +extern Tick ps; +/* namespace Int */ } +/* namespace Clock */ } + +void setClockFrequency(Tick ticksPerSecond); + +/// Output stream for simulator messages (e.g., cprintf()). Also used +/// as default stream for tracing and DPRINTF() messages (unless +/// overridden with trace:file option). +extern std::ostream *outputStream; +void setOutputFile(const std::string &file); +void setOutputDir(const std::string &dir); + +/// Output stream for configuration dump. +extern std::ostream *configStream; + +struct Callback; +void registerExitCallback(Callback *callback); +void doExitCleanup(); + +#endif /* __SIM_CORE_HH__ */ diff --git a/src/sim/eventq.cc b/src/sim/eventq.cc index 6ae838897..65e115256 100644 --- a/src/sim/eventq.cc +++ b/src/sim/eventq.cc @@ -41,7 +41,7 @@ #include "sim/eventq.hh" #include "base/trace.hh" -#include "sim/root.hh" +#include "sim/core.hh" using namespace std; @@ -53,6 +53,10 @@ using namespace std; // EventQueue mainEventQueue("MainEventQueue"); +#ifndef NDEBUG +Counter Event::instanceCounter = 0; +#endif + void EventQueue::insert(Event *event) { @@ -218,7 +222,6 @@ EventQueue::dump() cprintf("============================================================\n"); } -extern "C" void dumpMainQueue() { diff --git a/src/sim/eventq.hh b/src/sim/eventq.hh index fa65b08af..a57e9077e 100644 --- a/src/sim/eventq.hh +++ b/src/sim/eventq.hh @@ -75,6 +75,18 @@ class Event : public Serializable, public FastAlloc friend class EventQueue; private: + +#ifndef NDEBUG + /// Global counter to generate unique IDs for Event instances + static Counter instanceCounter; + + /// This event's unique ID. We can also use pointer values for + /// this but they're not consistent across runs making debugging + /// more difficult. Thus we use a global counter value when + /// debugging. + Counter instanceId; +#endif // NDEBUG + /// queue to which this event belongs (though it may or may not be /// scheduled on this queue yet) EventQueue *queue; @@ -157,6 +169,9 @@ class Event : public Serializable, public FastAlloc /// everything else, but before exit. Stat_Event_Pri = 90, + /// Progress events come at the end. + Progress_Event_Pri = 95, + /// If we want to exit on this cycle, it's the very last thing /// we do. Sim_Exit_Pri = 100 @@ -173,12 +188,19 @@ class Event : public Serializable, public FastAlloc #endif annotated_value(0) { +#ifndef NDEBUG + instanceId = ++instanceCounter; +#endif } ~Event() {} virtual const std::string name() const { +#ifndef NDEBUG + return csprintf("Event_%d", instanceId); +#else return csprintf("Event_%x", (uintptr_t)this); +#endif } /// Determine if the current event is scheduled diff --git a/src/sim/faults.cc b/src/sim/faults.cc index cea35482a..b09bbc177 100644 --- a/src/sim/faults.cc +++ b/src/sim/faults.cc @@ -29,10 +29,13 @@ * Gabe Black */ +#include "arch/isa_traits.hh" #include "base/misc.hh" -#include "sim/faults.hh" #include "cpu/thread_context.hh" #include "cpu/base.hh" +#include "sim/faults.hh" +#include "sim/process.hh" +#include "mem/page_table.hh" #if !FULL_SYSTEM void FaultBase::invoke(ThreadContext * tc) @@ -53,3 +56,26 @@ void UnimpFault::invoke(ThreadContext * tc) { panic("Unimpfault: %s\n", panicStr.c_str()); } +#if !FULL_SYSTEM +void PageTableFault::invoke(ThreadContext *tc) +{ + Process *p = tc->getProcessPtr(); + + // We've accessed the next page of the stack, so extend the stack + // to cover it. + if(vaddr < p->stack_min && vaddr >= p->stack_min - TheISA::PageBytes) + { + p->stack_min -= TheISA::PageBytes; + if(p->stack_base - p->stack_min > 8*1024*1024) + fatal("Over max stack size for one thread\n"); + p->pTable->allocate(p->stack_min, TheISA::PageBytes); + warn("Increasing stack size by one page."); + } + // Otherwise, we have an unexpected page fault. Report that fact, + // and what address was accessed to cause the fault. + else + { + panic("Page table fault when accessing virtual address %#x\n", vaddr); + } +} +#endif diff --git a/src/sim/faults.hh b/src/sim/faults.hh index 00264d8fc..2f0b5af62 100644 --- a/src/sim/faults.hh +++ b/src/sim/faults.hh @@ -76,4 +76,16 @@ class UnimpFault : public FaultBase void invoke(ThreadContext * tc); }; +#if !FULL_SYSTEM +class PageTableFault : public FaultBase +{ + private: + Addr vaddr; + public: + FaultName name() {return "M5 page table fault";} + PageTableFault(Addr va) : vaddr(va) {} + void invoke(ThreadContext * tc); +}; +#endif + #endif // __FAULTS_HH__ diff --git a/src/sim/main.cc b/src/sim/main.cc index 04dbe1ef4..5bf4add4b 100644 --- a/src/sim/main.cc +++ b/src/sim/main.cc @@ -25,77 +25,39 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * Authors: Steve Raasch - * Nathan Binkert - * Steve Reinhardt + * Authors: Nathan Binkert */ -/// -/// @file sim/main.cc -/// -#include <Python.h> // must be before system headers... see Python docs - -#include <sys/types.h> -#include <sys/stat.h> -#include <errno.h> -#include <libgen.h> -#include <stdlib.h> +#include <Python.h> #include <signal.h> -#include <getopt.h> -#include <list> +#include <iostream> #include <string> -#include <vector> -#include "base/callback.hh" -#include "base/inifile.hh" +#include "base/cprintf.hh" #include "base/misc.hh" -#include "base/output.hh" -#include "base/pollevent.hh" -#include "base/statistics.hh" -#include "base/str.hh" -#include "base/time.hh" #include "config/pythonhome.hh" -#include "cpu/base.hh" -#include "cpu/smt.hh" -#include "mem/mem_object.hh" -#include "mem/port.hh" #include "python/swig/init.hh" #include "sim/async.hh" -#include "sim/builder.hh" #include "sim/host.hh" -#include "sim/serialize.hh" -#include "sim/sim_events.hh" -#include "sim/sim_exit.hh" -#include "sim/sim_object.hh" -#include "sim/system.hh" -#include "sim/stat_control.hh" -#include "sim/stats.hh" -#include "sim/root.hh" +#include "sim/core.hh" using namespace std; -// See async.h. -volatile bool async_event = false; -volatile bool async_dump = false; -volatile bool async_dumpreset = false; -volatile bool async_exit = false; -volatile bool async_io = false; -volatile bool async_alarm = false; - /// Stats signal handler. void dumpStatsHandler(int sigtype) { async_event = true; - async_dump = true; + async_statdump = true; } void dumprstStatsHandler(int sigtype) { async_event = true; - async_dumpreset = true; + async_statdump = true; + async_statreset = true; } /// Exit signal handler. @@ -110,12 +72,7 @@ exitNowHandler(int sigtype) void abortHandler(int sigtype) { - cerr << "Program aborted at cycle " << curTick << endl; - -#if TRACING_ON - // dump trace buffer, if there is one - Trace::theLog.dump(cerr); -#endif + ccprintf(cerr, "Program aborted at cycle %d\n", curTick); } int @@ -163,310 +120,3 @@ main(int argc, char **argv) // clean up Python intepreter. Py_Finalize(); } - - -void -setOutputDir(const string &dir) -{ - simout.setDirectory(dir); -} - - -IniFile inifile; - -SimObject * -createSimObject(const string &name) -{ - return SimObjectClass::createObject(inifile, name); -} - - -/** - * Pointer to the Python function that maps names to SimObjects. - */ -PyObject *resolveFunc = NULL; - -/** - * Convert a pointer to the Python object that SWIG wraps around a C++ - * SimObject pointer back to the actual C++ pointer. See main.i. - */ -extern "C" SimObject *convertSwigSimObjectPtr(PyObject *); - - -SimObject * -resolveSimObject(const string &name) -{ - PyObject *pyPtr = PyEval_CallFunction(resolveFunc, "(s)", name.c_str()); - if (pyPtr == NULL) { - PyErr_Print(); - panic("resolveSimObject: failure on call to Python for %s", name); - } - - SimObject *simObj = convertSwigSimObjectPtr(pyPtr); - if (simObj == NULL) - panic("resolveSimObject: failure on pointer conversion for %s", name); - - return simObj; -} - - -/** - * Load config.ini into C++ database. Exported to Python via SWIG; - * invoked from m5.instantiate(). - */ -void -loadIniFile(PyObject *_resolveFunc) -{ - resolveFunc = _resolveFunc; - configStream = simout.find("config.out"); - - // The configuration database is now complete; start processing it. - inifile.load(simout.resolve("config.ini")); - - // Initialize statistics database - Stats::InitSimStats(); -} - - -/** - * Look up a MemObject port. Helper function for connectPorts(). - */ -Port * -lookupPort(SimObject *so, const std::string &name, int i) -{ - MemObject *mo = dynamic_cast<MemObject *>(so); - if (mo == NULL) { - warn("error casting SimObject %s to MemObject", so->name()); - return NULL; - } - - Port *p = mo->getPort(name, i); - if (p == NULL) - warn("error looking up port %s on object %s", name, so->name()); - return p; -} - - -/** - * Connect the described MemObject ports. Called from Python via SWIG. - */ -int -connectPorts(SimObject *o1, const std::string &name1, int i1, - SimObject *o2, const std::string &name2, int i2) -{ - Port *p1 = lookupPort(o1, name1, i1); - Port *p2 = lookupPort(o2, name2, i2); - - if (p1 == NULL || p2 == NULL) { - warn("connectPorts: port lookup error"); - return 0; - } - - p1->setPeer(p2); - p2->setPeer(p1); - - return 1; -} - -/** - * Do final initialization steps after object construction but before - * start of simulation. - */ -void -finalInit() -{ - // Parse and check all non-config-hierarchy parameters. - ParamContext::parseAllContexts(inifile); - ParamContext::checkAllContexts(); - - // Echo all parameter settings to stats file as well. - ParamContext::showAllContexts(*configStream); - - // Do a second pass to finish initializing the sim objects - SimObject::initAll(); - - // Restore checkpointed state, if any. -#if 0 - configHierarchy.unserializeSimObjects(); -#endif - - SimObject::regAllStats(); - - // Check to make sure that the stats package is properly initialized - Stats::check(); - - // Reset to put the stats in a consistent state. - Stats::reset(); - - SimStartup(); -} - - -/** Simulate for num_cycles additional cycles. If num_cycles is -1 - * (the default), do not limit simulation; some other event must - * terminate the loop. Exported to Python via SWIG. - * @return The SimLoopExitEvent that caused the loop to exit. - */ -SimLoopExitEvent * -simulate(Tick num_cycles = MaxTick) -{ - warn("Entering event queue @ %d. Starting simulation...\n", curTick); - - if (num_cycles < 0) - fatal("simulate: num_cycles must be >= 0 (was %d)\n", num_cycles); - else if (curTick + num_cycles < 0) //Overflow - num_cycles = MaxTick; - else - num_cycles = curTick + num_cycles; - - Event *limit_event = schedExitSimLoop("simulate() limit reached", - num_cycles); - - while (1) { - // there should always be at least one event (the SimLoopExitEvent - // we just scheduled) in the queue - assert(!mainEventQueue.empty()); - assert(curTick <= mainEventQueue.nextTick() && - "event scheduled in the past"); - - // forward current cycle to the time of the first event on the - // queue - curTick = mainEventQueue.nextTick(); - Event *exit_event = mainEventQueue.serviceOne(); - if (exit_event != NULL) { - // hit some kind of exit event; return to Python - // event must be subclass of SimLoopExitEvent... - SimLoopExitEvent *se_event = dynamic_cast<SimLoopExitEvent *>(exit_event); - if (se_event == NULL) - panic("Bogus exit event class!"); - - // if we didn't hit limit_event, delete it - if (se_event != limit_event) { - assert(limit_event->scheduled()); - limit_event->deschedule(); - delete limit_event; - } - - return se_event; - } - - if (async_event) { - async_event = false; - if (async_dump) { - async_dump = false; - - using namespace Stats; - SetupEvent(Dump, curTick); - } - - if (async_dumpreset) { - async_dumpreset = false; - - using namespace Stats; - SetupEvent(Dump | Reset, curTick); - } - - if (async_exit) { - async_exit = false; - exitSimLoop("user interrupt received"); - } - - if (async_io || async_alarm) { - async_io = false; - async_alarm = false; - pollQueue.service(); - } - } - } - - // not reached... only exit is return on SimLoopExitEvent -} - -Event * -createCountedDrain() -{ - return new CountedDrainEvent(); -} - -void -cleanupCountedDrain(Event *counted_drain) -{ - CountedDrainEvent *event = - dynamic_cast<CountedDrainEvent *>(counted_drain); - if (event == NULL) { - fatal("Called cleanupCountedDrain() on an event that was not " - "a CountedDrainEvent."); - } - assert(event->getCount() == 0); - delete event; -} - -void -serializeAll(const std::string &cpt_dir) -{ - Serializable::serializeAll(cpt_dir); -} - -void -unserializeAll(const std::string &cpt_dir) -{ - Serializable::unserializeAll(cpt_dir); -} - -/** - * Queue of C++ callbacks to invoke on simulator exit. - */ -CallbackQueue& -exitCallbacks() -{ - static CallbackQueue theQueue; - return theQueue; -} - -/** - * Register an exit callback. - */ -void -registerExitCallback(Callback *callback) -{ - exitCallbacks().add(callback); -} - -BaseCPU * -convertToBaseCPUPtr(SimObject *obj) -{ - BaseCPU *ptr = dynamic_cast<BaseCPU *>(obj); - - if (ptr == NULL) - warn("Casting to BaseCPU pointer failed"); - return ptr; -} - -System * -convertToSystemPtr(SimObject *obj) -{ - System *ptr = dynamic_cast<System *>(obj); - - if (ptr == NULL) - warn("Casting to System pointer failed"); - return ptr; -} - - -/** - * Do C++ simulator exit processing. Exported to SWIG to be invoked - * when simulator terminates via Python's atexit mechanism. - */ -void -doExitCleanup() -{ - exitCallbacks().process(); - exitCallbacks().clear(); - - cout.flush(); - - ParamContext::cleanupAllContexts(); - - // print simulation stats - Stats::DumpNow(); -} diff --git a/src/sim/param.cc b/src/sim/param.cc index 5cc69b161..51d389f5a 100644 --- a/src/sim/param.cc +++ b/src/sim/param.cc @@ -583,30 +583,10 @@ SimObjectBaseParam::parse(const string &s, vector<SimObject *>&value) // //////////////////////////////////////////////////////////////////////// -list<ParamContext *> *ParamContext::ctxList = NULL; - -ParamContext::ParamContext(const string &_iniSection, InitPhase _initPhase) +ParamContext::ParamContext(const string &_iniSection) : iniFilePtr(NULL), // initialized on call to parseParams() - iniSection(_iniSection), paramList(NULL), - initPhase(_initPhase) -{ - // Put this context on global list for initialization - if (initPhase != NoAutoInit) { - if (ctxList == NULL) - ctxList = new list<ParamContext *>(); - - // 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); - } + iniSection(_iniSection), paramList(NULL) +{ } @@ -695,89 +675,6 @@ ParamContext::printErrorProlog(ostream &os) os << "Parameter error in section [" << iniSection << "]: " << endl; } -// -// static method: call parseParams() on all registered contexts -// -void -ParamContext::parseAllContexts(IniFile &iniFile) -{ - list<ParamContext *>::iterator iter; - - for (iter = ctxList->begin(); iter != ctxList->end(); ++iter) { - ParamContext *pc = *iter; - - pc->parseParams(iniFile); - } -} - - -// -// static method: call checkParams() on all registered contexts -// -void -ParamContext::checkAllContexts() -{ - list<ParamContext *>::iterator iter; - - for (iter = ctxList->begin(); iter != ctxList->end(); ++iter) { - ParamContext *pc = *iter; - - pc->checkParams(); - } -} - - -// -// static method: call showParams() on all registered contexts -// -void -ParamContext::showAllContexts(ostream &os) -{ - list<ParamContext *>::iterator iter; - - for (iter = ctxList->begin(); iter != ctxList->end(); ++iter) { - ParamContext *pc = *iter; - - os << "[" << pc->iniSection << "]" << endl; - pc->showParams(os); - os << endl; - } -} - - -// -// static method: call cleanup() on all registered contexts -// -void -ParamContext::cleanupAllContexts() -{ - list<ParamContext *>::iterator iter; - - for (iter = ctxList->begin(); iter != ctxList->end(); ++iter) { - ParamContext *pc = *iter; - - pc->cleanup(); - } -} - - -// -// static method: call describeParams() on all registered contexts -// -void -ParamContext::describeAllContexts(ostream &os) -{ - list<ParamContext *>::iterator iter; - - for (iter = ctxList->begin(); iter != ctxList->end(); ++iter) { - ParamContext *pc = *iter; - - os << "[" << pc->iniSection << "]\n"; - pc->describeParams(os); - os << endl; - } -} - void parseTime(const std::vector<int> &time, struct tm *tm) { diff --git a/src/sim/param.hh b/src/sim/param.hh index 8a4670e27..dff0fa72d 100644 --- a/src/sim/param.hh +++ b/src/sim/param.hh @@ -50,12 +50,6 @@ class SimObject; // class ParamContext : protected StartupCallback { - private: - - // static list of all ParamContext objects, built as a side effect - // of the ParamContext constructor - static std::list<ParamContext *> *ctxList; - protected: // .ini file (database) for parameter lookup... initialized on call @@ -78,31 +72,10 @@ class ParamContext : protected StartupCallback public: - /// 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); - + ParamContext(const std::string &_iniSection); virtual ~ParamContext() {} // add a parameter to the context... called from the parameter @@ -135,24 +108,6 @@ class ParamContext : protected StartupCallback // generate the name for this instance of this context (used as a // prefix to create unique names in resolveSimObject() virtual const std::string &getInstanceName() { return iniSection; } - - // Parse all parameters registered with all ParamContext objects. - static void parseAllContexts(IniFile &iniFile); - - // Check all parameters registered with all ParamContext objects. - // (calls checkParams() on each) - static void checkAllContexts(); - - // Print all parameter values on indicated ostream. - static void showAllContexts(std::ostream &os); - - // Clean up all registered ParamContext objects. (calls cleanup() - // on each) - static void cleanupAllContexts(); - - // print descriptions of all parameters registered with all - // ParamContext objects - static void describeAllContexts(std::ostream &os); }; diff --git a/src/sim/process.cc b/src/sim/process.cc index e5d868115..2b283c9d1 100644 --- a/src/sim/process.cc +++ b/src/sim/process.cc @@ -60,6 +60,8 @@ #include "arch/sparc/solaris/process.hh" #elif THE_ISA == MIPS_ISA #include "arch/mips/linux/process.hh" +#elif THE_ISA == X86_ISA +#include "arch/x86/linux/process.hh" #else #error "THE_ISA not set" #endif @@ -300,24 +302,6 @@ DEFINE_SIM_OBJECT_CLASS_NAME("Process", Process) //////////////////////////////////////////////////////////////////////// -void -copyStringArray(vector<string> &strings, Addr array_ptr, Addr data_ptr, - TranslatingPort* memPort) -{ - Addr data_ptr_swap; - for (int i = 0; i < strings.size(); ++i) { - data_ptr_swap = htog(data_ptr); - memPort->writeBlob(array_ptr, (uint8_t*)&data_ptr_swap, sizeof(Addr)); - memPort->writeString(data_ptr, strings[i].c_str()); - array_ptr += sizeof(Addr); - data_ptr += strings[i].size() + 1; - } - // add NULL terminator - data_ptr = 0; - - memPort->writeBlob(array_ptr, (uint8_t*)&data_ptr, sizeof(Addr)); -} - LiveProcess::LiveProcess(const string &nm, ObjectFile *_objFile, System *_system, int stdin_fd, int stdout_fd, int stderr_fd, @@ -475,14 +459,23 @@ LiveProcess::create(const std::string &nm, System *system, int stdin_fd, fatal("Unknown/unsupported operating system."); } #elif THE_ISA == SPARC_ISA - if (objFile->getArch() != ObjectFile::SPARC) + if (objFile->getArch() != ObjectFile::SPARC64 && objFile->getArch() != ObjectFile::SPARC32) fatal("Object file architecture does not match compiled ISA (SPARC)."); switch (objFile->getOpSys()) { case ObjectFile::Linux: - process = new SparcLinuxProcess(nm, objFile, system, - stdin_fd, stdout_fd, stderr_fd, - argv, envp, cwd, - _uid, _euid, _gid, _egid, _pid, _ppid); + if (objFile->getArch() == ObjectFile::SPARC64) { + process = new Sparc64LinuxProcess(nm, objFile, system, + stdin_fd, stdout_fd, stderr_fd, + argv, envp, cwd, + _uid, _euid, _gid, + _egid, _pid, _ppid); + } else { + process = new Sparc32LinuxProcess(nm, objFile, system, + stdin_fd, stdout_fd, stderr_fd, + argv, envp, cwd, + _uid, _euid, _gid, + _egid, _pid, _ppid); + } break; @@ -495,6 +488,20 @@ LiveProcess::create(const std::string &nm, System *system, int stdin_fd, default: fatal("Unknown/unsupported operating system."); } +#elif THE_ISA == X86_ISA + if (objFile->getArch() != ObjectFile::X86) + fatal("Object file architecture does not match compiled ISA (x86)."); + switch (objFile->getOpSys()) { + case ObjectFile::Linux: + process = new X86LinuxProcess(nm, objFile, system, + stdin_fd, stdout_fd, stderr_fd, + argv, envp, cwd, + _uid, _euid, _gid, + _egid, _pid, _ppid); + break; + default: + fatal("Unknown/unsupported operating system."); + } #elif THE_ISA == MIPS_ISA if (objFile->getArch() != ObjectFile::Mips) fatal("Object file architecture does not match compiled ISA (MIPS)."); diff --git a/src/sim/process.hh b/src/sim/process.hh index bf65c6e06..dd64fa607 100644 --- a/src/sim/process.hh +++ b/src/sim/process.hh @@ -41,9 +41,12 @@ #if !FULL_SYSTEM +#include <string> #include <vector> #include "base/statistics.hh" +#include "mem/translating_port.hh" +#include "sim/host.hh" #include "sim/sim_object.hh" class ThreadContext; @@ -57,9 +60,27 @@ namespace TheISA class RemoteGDB; } +//This needs to be templated for cases where 32 bit pointers are needed. +template<class AddrType> void -copyStringArray(std::vector<std::string> &strings, Addr array_ptr, - Addr data_ptr, TranslatingPort* memPort); +copyStringArray(std::vector<std::string> &strings, + AddrType array_ptr, AddrType data_ptr, + TranslatingPort* memPort) +{ + AddrType data_ptr_swap; + for (int i = 0; i < strings.size(); ++i) { + data_ptr_swap = htog(data_ptr); + memPort->writeBlob(array_ptr, (uint8_t*)&data_ptr_swap, + sizeof(AddrType)); + memPort->writeString(data_ptr, strings[i].c_str()); + array_ptr += sizeof(AddrType); + data_ptr += strings[i].size() + 1; + } + // add NULL terminator + data_ptr = 0; + + memPort->writeBlob(array_ptr, (uint8_t*)&data_ptr, sizeof(AddrType)); +} class Process : public SimObject { diff --git a/src/sim/pseudo_inst.cc b/src/sim/pseudo_inst.cc index 4a8c0eb66..56a779674 100644 --- a/src/sim/pseudo_inst.cc +++ b/src/sim/pseudo_inst.cc @@ -32,6 +32,7 @@ #include <fcntl.h> #include <unistd.h> +#include <fstream> #include <string> #include "arch/vtophys.hh" @@ -54,7 +55,7 @@ using namespace std; using namespace Stats; using namespace TheISA; -namespace AlphaPseudo +namespace PseudoInst { void arm(ThreadContext *tc) @@ -199,8 +200,7 @@ namespace AlphaPseudo Tick when = curTick + delay * Clock::Int::ns; Tick repeat = period * Clock::Int::ns; - using namespace Stats; - SetupEvent(Reset, when, repeat); + Stats::StatEvent(false, true, when, repeat); } void @@ -213,8 +213,7 @@ namespace AlphaPseudo Tick when = curTick + delay * Clock::Int::ns; Tick repeat = period * Clock::Int::ns; - using namespace Stats; - SetupEvent(Dump, when, repeat); + Stats::StatEvent(true, false, when, repeat); } void @@ -254,8 +253,7 @@ namespace AlphaPseudo Tick when = curTick + delay * Clock::Int::ns; Tick repeat = period * Clock::Int::ns; - using namespace Stats; - SetupEvent(Dump|Reset, when, repeat); + Stats::StatEvent(true, true, when, repeat); } void diff --git a/src/sim/pseudo_inst.hh b/src/sim/pseudo_inst.hh index bc71a7e64..93021abad 100644 --- a/src/sim/pseudo_inst.hh +++ b/src/sim/pseudo_inst.hh @@ -33,7 +33,7 @@ class ThreadContext; //We need the "Tick" and "Addr" data types from here #include "sim/host.hh" -namespace AlphaPseudo +namespace PseudoInst { /** * @todo these externs are only here for a hack in fullCPU::takeOver... diff --git a/src/sim/root.cc b/src/sim/root.cc index 565b57269..f4743af0a 100644 --- a/src/sim/root.cc +++ b/src/sim/root.cc @@ -36,91 +36,24 @@ #include <vector> #include "base/misc.hh" -#include "base/output.hh" #include "sim/builder.hh" -#include "sim/host.hh" -#include "sim/sim_events.hh" -#include "sim/sim_exit.hh" #include "sim/sim_object.hh" -#include "sim/root.hh" - -using namespace std; - -Tick curTick = 0; -ostream *outputStream; -ostream *configStream; - -/// The simulated frequency of curTick. (This is only here for a short time) -Tick ticksPerSecond; - -namespace Clock { -/// The simulated frequency of curTick. (In ticks per second) -Tick Frequency; - -namespace Float { -double s; -double ms; -double us; -double ns; -double ps; - -double Hz; -double kHz; -double MHz; -double GHZ; -/* namespace Float */ } - -namespace Int { -Tick s; -Tick ms; -Tick us; -Tick ns; -Tick ps; -/* namespace Float */ } - -/* namespace Clock */ } - // Dummy Object -class Root : public SimObject +struct Root : public SimObject { - private: - Tick max_tick; - Tick progress_interval; - - public: - Root(const std::string &name, Tick maxtick, Tick pi) - : SimObject(name), max_tick(maxtick), progress_interval(pi) - {} - - virtual void startup(); + Root(const std::string &name) : SimObject(name) {} }; -void -Root::startup() -{ - if (max_tick != 0) - schedExitSimLoop("reached maximum cycle count", curTick + max_tick); - - if (progress_interval != 0) - new ProgressEvent(&mainEventQueue, progress_interval); -} - BEGIN_DECLARE_SIM_OBJECT_PARAMS(Root) - Param<Tick> clock; - Param<Tick> max_tick; - Param<Tick> progress_interval; - Param<string> output_file; + Param<int> dummy; // needed below END_DECLARE_SIM_OBJECT_PARAMS(Root) BEGIN_INIT_SIM_OBJECT_PARAMS(Root) - INIT_PARAM(clock, "tick frequency"), - INIT_PARAM(max_tick, "maximum simulation time"), - INIT_PARAM(progress_interval, "print a progress message"), - INIT_PARAM(output_file, "file to dump simulator output to") + INIT_PARAM(dummy, "") // All SimObjects must have params END_INIT_SIM_OBJECT_PARAMS(Root) @@ -132,29 +65,7 @@ CREATE_SIM_OBJECT(Root) created = true; - outputStream = simout.find(output_file); - Root *root = new Root(getInstanceName(), max_tick, progress_interval); - - using namespace Clock; - Frequency = clock; - Float::s = static_cast<double>(Frequency); - Float::ms = Float::s / 1.0e3; - Float::us = Float::s / 1.0e6; - Float::ns = Float::s / 1.0e9; - Float::ps = Float::s / 1.0e12; - - Float::Hz = 1.0 / Float::s; - Float::kHz = 1.0 / Float::ms; - Float::MHz = 1.0 / Float::us; - Float::GHZ = 1.0 / Float::ns; - - Int::s = Frequency; - Int::ms = Int::s / 1000; - Int::us = Int::ms / 1000; - Int::ns = Int::us / 1000; - Int::ps = Int::ns / 1000; - - return root; + return new Root(getInstanceName()); } REGISTER_SIM_OBJECT("Root", Root) diff --git a/src/sim/serialize.cc b/src/sim/serialize.cc index 1ff16976d..d32bb1142 100644 --- a/src/sim/serialize.cc +++ b/src/sim/serialize.cc @@ -407,36 +407,3 @@ Checkpoint::sectionExists(const std::string §ion) { return db->sectionExists(section); } - -/** Hacked stat reset event */ - -class StatresetParamContext : public ParamContext -{ - public: - StatresetParamContext(const string §ion); - ~StatresetParamContext(); - void startup(); -}; - -StatresetParamContext statParams("statsreset"); - -Param<Tick> reset_cycle(&statParams, "reset_cycle", - "Cycle to reset stats on", 0); - -StatresetParamContext::StatresetParamContext(const string §ion) - : ParamContext(section) -{ } - -StatresetParamContext::~StatresetParamContext() -{ -} - -void -StatresetParamContext::startup() -{ - if (reset_cycle > 0) { - Stats::SetupEvent(Stats::Reset, curTick + reset_cycle, 0); - cprintf("Stats reset event scheduled for %lli\n", - curTick + reset_cycle); - } -} diff --git a/src/sim/sim_events.cc b/src/sim/sim_events.cc index 2ccc9dad2..a4457a11c 100644 --- a/src/sim/sim_events.cc +++ b/src/sim/sim_events.cc @@ -158,21 +158,3 @@ CheckSwapEvent::description() { return "check swap"; } - -// -// handle progress event: print message and reschedule -// -void -ProgressEvent::process() -{ - DPRINTFN("ProgressEvent\n"); - // reschedule for next interval - schedule(curTick + interval); -} - - -const char * -ProgressEvent::description() -{ - return "progress message"; -} diff --git a/src/sim/sim_events.hh b/src/sim/sim_events.hh index e1576b38c..94e2540b1 100644 --- a/src/sim/sim_events.hh +++ b/src/sim/sim_events.hh @@ -125,23 +125,4 @@ class CheckSwapEvent : public Event virtual const char *description(); }; -// -// Progress event: print out cycle every so often so we know we're -// making forward progress. -// -class ProgressEvent : public Event -{ - protected: - Tick interval; - - public: - ProgressEvent(EventQueue *q, Tick ival) - : Event(q), interval(ival) - { schedule(curTick + interval); } - - void process(); // process event - - virtual const char *description(); -}; - #endif // __SIM_SIM_EVENTS_HH__ diff --git a/src/sim/sim_object.cc b/src/sim/sim_object.cc index 8fc8fe58f..434fcffe6 100644 --- a/src/sim/sim_object.cc +++ b/src/sim/sim_object.cc @@ -56,10 +56,6 @@ using namespace std; // SimObject::SimObjectList SimObject::simObjectList; -namespace Stats { - extern ObjectMatch event_ignore; -} - // // SimObject constructor: used to maintain static simObjectList // @@ -70,7 +66,6 @@ SimObject::SimObject(Params *p) doDebugBreak = false; #endif - doRecordEvent = !Stats::event_ignore.match(name()); simObjectList.push_back(this); state = Running; } @@ -86,7 +81,6 @@ SimObject::SimObject(const string &_name) doDebugBreak = false; #endif - doRecordEvent = !Stats::event_ignore.match(name()); simObjectList.push_back(this); state = Running; } @@ -245,8 +239,7 @@ debugObjectBreak(const char *objs) void SimObject::recordEvent(const std::string &stat) { - if (doRecordEvent) - Stats::recordEvent(stat); + Stats::recordEvent(stat); } unsigned int diff --git a/src/sim/sim_object.hh b/src/sim/sim_object.hh index 93802e247..536e761e5 100644 --- a/src/sim/sim_object.hh +++ b/src/sim/sim_object.hh @@ -136,7 +136,6 @@ class SimObject : public Serializable, protected StartupCallback #endif public: - bool doRecordEvent; void recordEvent(const std::string &stat); }; diff --git a/src/sim/simulate.cc b/src/sim/simulate.cc new file mode 100644 index 000000000..55cbb50a9 --- /dev/null +++ b/src/sim/simulate.cc @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2006 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. + * + * Authors: Nathan Binkert + * Steve Reinhardt + */ + +#include "base/misc.hh" +#include "base/pollevent.hh" +#include "sim/stat_control.hh" +#include "sim/async.hh" +#include "sim/eventq.hh" +#include "sim/host.hh" +#include "sim/sim_events.hh" +#include "sim/sim_exit.hh" +#include "sim/simulate.hh" + +/** Simulate for num_cycles additional cycles. If num_cycles is -1 + * (the default), do not limit simulation; some other event must + * terminate the loop. Exported to Python via SWIG. + * @return The SimLoopExitEvent that caused the loop to exit. + */ +SimLoopExitEvent * +simulate(Tick num_cycles) +{ + warn("Entering event queue @ %d. Starting simulation...\n", curTick); + + if (num_cycles < 0) + fatal("simulate: num_cycles must be >= 0 (was %d)\n", num_cycles); + else if (curTick + num_cycles < 0) //Overflow + num_cycles = MaxTick; + else + num_cycles = curTick + num_cycles; + + Event *limit_event; + limit_event = schedExitSimLoop("simulate() limit reached", num_cycles); + + while (1) { + // there should always be at least one event (the SimLoopExitEvent + // we just scheduled) in the queue + assert(!mainEventQueue.empty()); + assert(curTick <= mainEventQueue.nextTick() && + "event scheduled in the past"); + + // forward current cycle to the time of the first event on the + // queue + curTick = mainEventQueue.nextTick(); + Event *exit_event = mainEventQueue.serviceOne(); + if (exit_event != NULL) { + // hit some kind of exit event; return to Python + // event must be subclass of SimLoopExitEvent... + SimLoopExitEvent *se_event; + se_event = dynamic_cast<SimLoopExitEvent *>(exit_event); + + if (se_event == NULL) + panic("Bogus exit event class!"); + + // if we didn't hit limit_event, delete it + if (se_event != limit_event) { + assert(limit_event->scheduled()); + limit_event->deschedule(); + delete limit_event; + } + + return se_event; + } + + if (async_event) { + async_event = false; + if (async_statdump || async_statreset) { + async_statdump = false; + async_statreset = false; + + Stats::StatEvent(async_statdump, async_statreset); + } + + if (async_exit) { + async_exit = false; + exitSimLoop("user interrupt received"); + } + + if (async_io || async_alarm) { + async_io = false; + async_alarm = false; + pollQueue.service(); + } + + if (async_exception) { + async_exception = false; + return NULL; + } + } + } + + // not reached... only exit is return on SimLoopExitEvent +} + diff --git a/src/sim/simulate.hh b/src/sim/simulate.hh new file mode 100644 index 000000000..139bddb82 --- /dev/null +++ b/src/sim/simulate.hh @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2006 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. + * + * Authors: Nathan Binkert + * Steve Reinhardt + */ + +#include "sim/host.hh" +#include "sim/sim_events.hh" + +SimLoopExitEvent *simulate(Tick num_cycles = MaxTick); diff --git a/src/sim/stat_control.cc b/src/sim/stat_control.cc index 3fad8beb5..228c83898 100644 --- a/src/sim/stat_control.cc +++ b/src/sim/stat_control.cc @@ -38,14 +38,9 @@ #include "base/callback.hh" #include "base/hostinfo.hh" #include "base/statistics.hh" -#include "base/str.hh" #include "base/time.hh" -#include "base/stats/output.hh" #include "cpu/base.hh" #include "sim/eventq.hh" -#include "sim/sim_object.hh" -#include "sim/stat_control.hh" -#include "sim/root.hh" using namespace std; @@ -63,11 +58,9 @@ namespace Stats { Time statTime(true); Tick startTick; -Tick lastDump(0); -class SimTicksReset : public Callback +struct SimTicksReset : public Callback { - public: void process() { statTime.set(); @@ -92,7 +85,7 @@ statElapsedTicks() SimTicksReset simTicksReset; void -InitSimStats() +initSimStats() { simInsts .functor(BaseCPU::numSimulatedInstructions) @@ -153,81 +146,40 @@ InitSimStats() registerResetCallback(&simTicksReset); } -class StatEvent : public Event +class _StatEvent : public Event { - protected: - int flags; + private: + bool dump; + bool reset; Tick repeat; public: - StatEvent(EventQueue *queue, int _flags, Tick _when, Tick _repeat); - virtual void process(); - virtual const char *description(); -}; - -StatEvent::StatEvent(EventQueue *queue, int _flags, Tick _when, Tick _repeat) - : Event(queue, Stat_Event_Pri), - flags(_flags), repeat(_repeat) -{ - setFlags(AutoDelete); - schedule(_when); -} - -const char * -StatEvent::description() -{ - return "Statistics dump and/or reset"; -} - -void -StatEvent::process() -{ - if (flags & Stats::Dump) - DumpNow(); - - if (flags & Stats::Reset) { - cprintf("Resetting stats at cycle %d!\n", curTick); - reset(); + _StatEvent(bool _dump, bool _reset, Tick _when, Tick _repeat) + : Event(&mainEventQueue, Stat_Event_Pri), dump(_dump), reset(_reset), + repeat(_repeat) + { + setFlags(AutoDelete); + schedule(_when); } - if (repeat) - schedule(curTick + repeat); -} + virtual void + process() + { + if (dump) + Stats::dump(); -list<Output *> OutputList; + if (reset) + Stats::reset(); -void -DumpNow() -{ - assert(lastDump <= curTick); - if (lastDump == curTick) - return; - lastDump = curTick; - - list<Output *>::iterator i = OutputList.begin(); - list<Output *>::iterator end = OutputList.end(); - for (; i != end; ++i) { - Output *output = *i; - if (!output->valid()) - continue; - - output->output(); + if (repeat) + new _StatEvent(dump, reset, curTick + repeat, repeat); } -} +}; void -SetupEvent(int flags, Tick when, Tick repeat, EventQueue *queue) +StatEvent(bool dump, bool reset, Tick when, Tick repeat) { - if (queue == NULL) - queue = &mainEventQueue; - - new StatEvent(queue, flags, when, repeat); + new _StatEvent(dump, reset, when, repeat); } /* namespace Stats */ } - -void debugDumpStats() -{ - Stats::DumpNow(); -} - diff --git a/src/sim/stat_control.hh b/src/sim/stat_control.hh index 67f7cc491..1efa2554e 100644 --- a/src/sim/stat_control.hh +++ b/src/sim/stat_control.hh @@ -31,25 +31,10 @@ #ifndef __SIM_STAT_CONTROL_HH__ #define __SIM_STAT_CONTROL_HH__ -#include <fstream> -#include <list> - -class EventQueue; - namespace Stats { -enum { - Reset = 0x1, - Dump = 0x2 -}; - -class Output; -extern std::list<Output *> OutputList; - -void DumpNow(); -void SetupEvent(int flags, Tick when, Tick repeat = 0, EventQueue *queue = NULL); - -void InitSimStats(); +void initSimStats(); +void StatEvent(bool dump, bool reset, Tick when = curTick, Tick repeat = 0); /* namespace Stats */ } diff --git a/src/sim/syscall_emul.cc b/src/sim/syscall_emul.cc index ab44c0a35..876f39e99 100644 --- a/src/sim/syscall_emul.cc +++ b/src/sim/syscall_emul.cc @@ -184,6 +184,39 @@ lseekFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) SyscallReturn +_llseekFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) +{ + int fd = p->sim_fd(tc->getSyscallArg(0)); + uint64_t offset_high = tc->getSyscallArg(1); + uint32_t offset_low = tc->getSyscallArg(2); + Addr result_ptr = tc->getSyscallArg(3); + int whence = tc->getSyscallArg(4); + + uint64_t offset = (offset_high << 32) | offset_low; + + uint64_t result = lseek(fd, offset, whence); + result = TheISA::htog(result); + + if (result == (off_t)-1) { + //The seek failed. + return -errno; + } else { + //The seek succeeded. + //Copy "result" to "result_ptr" + //XXX We'll assume that the size of loff_t is 64 bits on the + //target platform + BufferArg result_buf(result_ptr, sizeof(result)); + memcpy(result_buf.bufferPtr(), &result, sizeof(result)); + result_buf.copyOut(tc->getMemPort()); + return 0; + } + + + return (result == (off_t)-1) ? -errno : result; +} + + +SyscallReturn munmapFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) { // given that we don't really implement mmap, munmap is really easy diff --git a/src/sim/syscall_emul.hh b/src/sim/syscall_emul.hh index 27356c9f1..a3d95b8ec 100644 --- a/src/sim/syscall_emul.hh +++ b/src/sim/syscall_emul.hh @@ -211,6 +211,10 @@ SyscallReturn writeFunc(SyscallDesc *desc, int num, SyscallReturn lseekFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc); +/// Target _llseek() handler. +SyscallReturn _llseekFunc(SyscallDesc *desc, int num, + LiveProcess *p, ThreadContext *tc); + /// Target munmap() handler. SyscallReturn munmapFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc); @@ -349,6 +353,8 @@ template <typename target_stat, typename host_stat> static void convertStatBuf(target_stat &tgt, host_stat *host, bool fakeTTY = false) { + using namespace TheISA; + if (fakeTTY) tgt->st_dev = 0xA; else @@ -377,7 +383,9 @@ convertStatBuf(target_stat &tgt, host_stat *host, bool fakeTTY = false) tgt->st_mtimeX = htog(tgt->st_mtimeX); tgt->st_ctimeX = host->st_ctime; tgt->st_ctimeX = htog(tgt->st_ctimeX); - tgt->st_blksize = host->st_blksize; + // Force the block size to be 8k. This helps to ensure buffered io works + // consistently across different hosts. + tgt->st_blksize = 0x2000; tgt->st_blksize = htog(tgt->st_blksize); tgt->st_blocks = host->st_blocks; tgt->st_blocks = htog(tgt->st_blocks); @@ -389,6 +397,8 @@ template <typename target_stat, typename host_stat64> static void convertStat64Buf(target_stat &tgt, host_stat64 *host, bool fakeTTY = false) { + using namespace TheISA; + convertStatBuf<target_stat, host_stat64>(tgt, host, fakeTTY); #if defined(STAT_HAVE_NSEC) tgt->st_atime_nsec = host->st_atime_nsec; @@ -446,14 +456,14 @@ ioctlFunc(SyscallDesc *desc, int callnum, LiveProcess *process, } switch (req) { - case OS::TIOCISATTY: - case OS::TIOCGETP: - case OS::TIOCSETP: - case OS::TIOCSETN: - case OS::TIOCSETC: - case OS::TIOCGETC: - case OS::TIOCGETS: - case OS::TIOCGETA: + case OS::TIOCISATTY_: + case OS::TIOCGETP_: + case OS::TIOCSETP_: + case OS::TIOCSETN_: + case OS::TIOCSETC_: + case OS::TIOCGETC_: + case OS::TIOCGETS_: + case OS::TIOCGETA_: return -ENOTTY; default: diff --git a/src/sim/system.cc b/src/sim/system.cc index f6febe4b1..2d0eaaf5b 100644 --- a/src/sim/system.cc +++ b/src/sim/system.cc @@ -33,6 +33,7 @@ #include "arch/isa_traits.hh" #include "arch/remote_gdb.hh" +#include "arch/utility.hh" #include "base/loader/object_file.hh" #include "base/loader/symtab.hh" #include "base/trace.hh" @@ -142,6 +143,7 @@ System::~System() } int rgdb_wait = -1; +int rgdb_enable = true; void System::setMemoryMode(MemoryMode mode) @@ -152,7 +154,9 @@ System::setMemoryMode(MemoryMode mode) bool System::breakpoint() { - return remoteGDB[0]->breakpoint(); + if (remoteGDB.size()) + return remoteGDB[0]->breakpoint(); + return false; } int @@ -174,22 +178,24 @@ System::registerThreadContext(ThreadContext *tc, int id) threadContexts[id] = tc; numcpus++; - RemoteGDB *rgdb = new RemoteGDB(this, tc); - GDBListener *gdbl = new GDBListener(rgdb, 7000 + id); - gdbl->listen(); - /** - * Uncommenting this line waits for a remote debugger to connect - * to the simulator before continuing. - */ - if (rgdb_wait != -1 && rgdb_wait == id) - gdbl->accept(); + if (rgdb_enable) { + RemoteGDB *rgdb = new RemoteGDB(this, tc); + GDBListener *gdbl = new GDBListener(rgdb, 7000 + id); + gdbl->listen(); + /** + * Uncommenting this line waits for a remote debugger to + * connect to the simulator before continuing. + */ + if (rgdb_wait != -1 && rgdb_wait == id) + gdbl->accept(); + + if (remoteGDB.size() <= id) { + remoteGDB.resize(id + 1); + } - if (remoteGDB.size() <= id) { - remoteGDB.resize(id + 1); + remoteGDB[id] = rgdb; } - remoteGDB[id] = rgdb; - return id; } @@ -198,7 +204,7 @@ System::startup() { int i; for (i = 0; i < threadContexts.size(); i++) - threadContexts[i]->activate(0); + TheISA::startupCPU(threadContexts[i], i); } void @@ -210,7 +216,8 @@ System::replaceThreadContext(ThreadContext *tc, int id) } threadContexts[id] = tc; - remoteGDB[id]->replaceThreadContext(tc); + if (id < remoteGDB.size()) + remoteGDB[id]->replaceThreadContext(tc); } #if !FULL_SYSTEM |