summaryrefslogtreecommitdiff
path: root/src/sim
diff options
context:
space:
mode:
authorGabe Black <gblack@eecs.umich.edu>2009-04-06 10:19:36 -0700
committerGabe Black <gblack@eecs.umich.edu>2009-04-06 10:19:36 -0700
commitd080581db1f9ee4e1e6d07d2b01c13c67908a391 (patch)
treecc484b289fa5a30c4631f9faa1d8b456bffeebfc /src/sim
parent7a7c4c5fca83a8d47c7e71c9c080a882ebe204a9 (diff)
parent639cb0a42d953ee32bc7e96b0cdfa96cd40e9fc1 (diff)
downloadgem5-d080581db1f9ee4e1e6d07d2b01c13c67908a391.tar.xz
Merge ARM into the head. ARM will compile but may not actually work.
Diffstat (limited to 'src/sim')
-rw-r--r--src/sim/BaseTLB.py33
-rw-r--r--src/sim/InstTracer.py2
-rw-r--r--src/sim/Process.py3
-rw-r--r--src/sim/SConscript6
-rw-r--r--src/sim/System.py2
-rw-r--r--src/sim/async.hh12
-rw-r--r--src/sim/byteswap.hh56
-rw-r--r--src/sim/core.cc8
-rw-r--r--src/sim/core.hh5
-rw-r--r--src/sim/debug.cc65
-rw-r--r--src/sim/debug.hh14
-rw-r--r--src/sim/eventq.cc273
-rw-r--r--src/sim/eventq.hh510
-rw-r--r--src/sim/faults.hh2
-rw-r--r--src/sim/host.hh8
-rw-r--r--src/sim/init.cc209
-rw-r--r--src/sim/init.hh54
-rw-r--r--src/sim/insttracer.hh17
-rw-r--r--src/sim/main.cc124
-rw-r--r--src/sim/microcode_rom.hh52
-rw-r--r--src/sim/process.cc143
-rw-r--r--src/sim/process.hh52
-rw-r--r--src/sim/pseudo_inst.cc408
-rw-r--r--src/sim/pseudo_inst.hh58
-rw-r--r--src/sim/serialize.cc54
-rw-r--r--src/sim/serialize.hh47
-rw-r--r--src/sim/sim_events.cc54
-rw-r--r--src/sim/sim_events.hh44
-rw-r--r--src/sim/sim_exit.hh8
-rw-r--r--src/sim/sim_object.cc10
-rw-r--r--src/sim/sim_object.hh13
-rw-r--r--src/sim/sim_object_params.hh58
-rw-r--r--src/sim/simulate.cc11
-rw-r--r--src/sim/stat_control.cc46
-rw-r--r--src/sim/stats.hh1
-rw-r--r--src/sim/syscall_emul.cc193
-rw-r--r--src/sim/syscall_emul.hh207
-rw-r--r--src/sim/system.cc72
-rw-r--r--src/sim/system.hh23
-rw-r--r--src/sim/tlb.cc10
-rw-r--r--src/sim/tlb.hh19
-rw-r--r--src/sim/vptr.hh3
42 files changed, 1941 insertions, 1048 deletions
diff --git a/src/sim/BaseTLB.py b/src/sim/BaseTLB.py
new file mode 100644
index 000000000..9aca4a97c
--- /dev/null
+++ b/src/sim/BaseTLB.py
@@ -0,0 +1,33 @@
+# Copyright (c) 2008 The Hewlett-Packard Development Company
+# 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: Gabe Black
+
+from m5.SimObject import SimObject
+
+class BaseTLB(SimObject):
+ type = 'BaseTLB'
+ abstract = True
diff --git a/src/sim/InstTracer.py b/src/sim/InstTracer.py
index f7500f1e8..9ba91a019 100644
--- a/src/sim/InstTracer.py
+++ b/src/sim/InstTracer.py
@@ -31,5 +31,5 @@ from m5.params import *
class InstTracer(SimObject):
type = 'InstTracer'
- cxx_namespace = 'Trace'
+ cxx_class = 'Trace::InstTracer'
abstract = True
diff --git a/src/sim/Process.py b/src/sim/Process.py
index 37a27bf3b..81108dd70 100644
--- a/src/sim/Process.py
+++ b/src/sim/Process.py
@@ -34,7 +34,8 @@ class Process(SimObject):
type = 'Process'
abstract = True
input = Param.String('cin', "filename for stdin")
- output = Param.String('cout', 'filename for stdout/stderr')
+ output = Param.String('cout', 'filename for stdout')
+ errout = Param.String('cerr', 'filename for stderr')
system = Param.System(Parent.any, "system process will run on")
max_stack_size = Param.MemorySize('64MB', 'maximum size of the stack')
diff --git a/src/sim/SConscript b/src/sim/SConscript
index 0b39ab8e8..750007947 100644
--- a/src/sim/SConscript
+++ b/src/sim/SConscript
@@ -30,6 +30,7 @@
Import('*')
+SimObject('BaseTLB.py')
SimObject('Root.py')
SimObject('System.py')
SimObject('InstTracer.py')
@@ -39,7 +40,9 @@ Source('core.cc')
Source('debug.cc')
Source('eventq.cc')
Source('faults.cc')
-Source('main.cc')
+Source('init.cc')
+BinSource('main.cc')
+Source('pseudo_inst.cc')
Source('root.cc')
Source('serialize.cc')
Source('sim_events.cc')
@@ -51,7 +54,6 @@ Source('system.cc')
if env['FULL_SYSTEM']:
Source('arguments.cc')
- Source('pseudo_inst.cc')
else:
Source('tlb.cc')
SimObject('Process.py')
diff --git a/src/sim/System.py b/src/sim/System.py
index 5712a5c03..3b0bc1e46 100644
--- a/src/sim/System.py
+++ b/src/sim/System.py
@@ -38,7 +38,7 @@ class System(SimObject):
type = 'System'
swig_objdecls = [ '%include "python/swig/system.i"' ]
- physmem = Param.PhysicalMemory(Parent.any, "phsyical memory")
+ physmem = Param.PhysicalMemory(Parent.any, "physical memory")
mem_mode = Param.MemoryMode('atomic', "The mode the memory system is in")
if build_env['FULL_SYSTEM']:
abstract = True
diff --git a/src/sim/async.hh b/src/sim/async.hh
index 932f975d2..6dd5b8a0d 100644
--- a/src/sim/async.hh
+++ b/src/sim/async.hh
@@ -42,12 +42,12 @@
/// then checked in the main event loop. Defined in main.cc.
/// @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_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_event; ///< Some asynchronous event has happened.
+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.
//@}
diff --git a/src/sim/byteswap.hh b/src/sim/byteswap.hh
index 062fc4513..2519e552b 100644
--- a/src/sim/byteswap.hh
+++ b/src/sim/byteswap.hh
@@ -62,7 +62,7 @@ enum ByteOrder {BigEndianByteOrder, LittleEndianByteOrder};
//These functions actually perform the swapping for parameters
//of various bit lengths
-static inline uint64_t
+inline uint64_t
swap_byte64(uint64_t x)
{
#if defined(linux)
@@ -81,7 +81,7 @@ swap_byte64(uint64_t x)
#endif
}
-static inline uint32_t
+inline uint32_t
swap_byte32(uint32_t x)
{
#if defined(linux)
@@ -95,7 +95,7 @@ swap_byte32(uint32_t x)
#endif
}
-static inline uint16_t
+inline uint16_t
swap_byte16(uint16_t x)
{
#if defined(linux)
@@ -113,7 +113,7 @@ swap_byte16(uint16_t x)
// 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) {
+inline T swap_byte(T x) {
if (sizeof(T) == 8)
return swap_byte64((uint64_t)x);
else if (sizeof(T) == 4)
@@ -127,7 +127,7 @@ static inline T swap_byte(T x) {
}
template<>
-static inline Twin64_t swap_byte<Twin64_t>(Twin64_t x)
+inline Twin64_t swap_byte<Twin64_t>(Twin64_t x)
{
x.a = swap_byte(x.a);
x.b = swap_byte(x.b);
@@ -135,7 +135,7 @@ static inline Twin64_t swap_byte<Twin64_t>(Twin64_t x)
}
template<>
-static inline Twin32_t swap_byte<Twin32_t>(Twin32_t x)
+inline Twin32_t swap_byte<Twin32_t>(Twin32_t x)
{
x.a = swap_byte(x.a);
x.b = swap_byte(x.b);
@@ -144,23 +144,23 @@ static inline Twin32_t swap_byte<Twin32_t>(Twin32_t 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);}
-template <typename T> static inline T letobe(T value) {return swap_byte(value);}
+template <typename T> inline T betole(T value) {return swap_byte(value);}
+template <typename T> inline T letobe(T value) {return swap_byte(value);}
//For conversions not involving the guest system, we can define the functions
//conditionally based on the BYTE_ORDER macro and outside of the namespaces
#if defined(_BIG_ENDIAN) || !defined(_LITTLE_ENDIAN) && BYTE_ORDER == BIG_ENDIAN
const ByteOrder HostByteOrder = BigEndianByteOrder;
-template <typename T> static inline T htole(T value) {return swap_byte(value);}
-template <typename T> static inline T letoh(T value) {return swap_byte(value);}
-template <typename T> static inline T htobe(T value) {return value;}
-template <typename T> static inline T betoh(T value) {return value;}
+template <typename T> inline T htole(T value) {return swap_byte(value);}
+template <typename T> inline T letoh(T value) {return swap_byte(value);}
+template <typename T> inline T htobe(T value) {return value;}
+template <typename T> inline T betoh(T value) {return value;}
#elif defined(_LITTLE_ENDIAN) || BYTE_ORDER == LITTLE_ENDIAN
const ByteOrder HostByteOrder = LittleEndianByteOrder;
-template <typename T> static inline T htole(T value) {return value;}
-template <typename T> static inline T letoh(T value) {return value;}
-template <typename T> static inline T htobe(T value) {return swap_byte(value);}
-template <typename T> static inline T betoh(T value) {return swap_byte(value);}
+template <typename T> inline T htole(T value) {return value;}
+template <typename T> inline T letoh(T value) {return value;}
+template <typename T> inline T htobe(T value) {return swap_byte(value);}
+template <typename T> inline T betoh(T value) {return swap_byte(value);}
#else
#error Invalid Endianess
#endif
@@ -169,33 +169,33 @@ namespace BigEndianGuest
{
const bool ByteOrderDiffers = (HostByteOrder != BigEndianByteOrder);
template <typename T>
- static inline T gtole(T value) {return betole(value);}
+ inline T gtole(T value) {return betole(value);}
template <typename T>
- static inline T letog(T value) {return letobe(value);}
+ inline T letog(T value) {return letobe(value);}
template <typename T>
- static inline T gtobe(T value) {return value;}
+ inline T gtobe(T value) {return value;}
template <typename T>
- static inline T betog(T value) {return value;}
+ inline T betog(T value) {return value;}
template <typename T>
- static inline T htog(T value) {return htobe(value);}
+ inline T htog(T value) {return htobe(value);}
template <typename T>
- static inline T gtoh(T value) {return betoh(value);}
+ inline T gtoh(T value) {return betoh(value);}
}
namespace LittleEndianGuest
{
const bool ByteOrderDiffers = (HostByteOrder != LittleEndianByteOrder);
template <typename T>
- static inline T gtole(T value) {return value;}
+ inline T gtole(T value) {return value;}
template <typename T>
- static inline T letog(T value) {return value;}
+ inline T letog(T value) {return value;}
template <typename T>
- static inline T gtobe(T value) {return letobe(value);}
+ inline T gtobe(T value) {return letobe(value);}
template <typename T>
- static inline T betog(T value) {return betole(value);}
+ inline T betog(T value) {return betole(value);}
template <typename T>
- static inline T htog(T value) {return htole(value);}
+ inline T htog(T value) {return htole(value);}
template <typename T>
- static inline T gtoh(T value) {return letoh(value);}
+ inline T gtoh(T value) {return letoh(value);}
}
#endif // __SIM_BYTE_SWAP_HH__
diff --git a/src/sim/core.cc b/src/sim/core.cc
index 75f1f384c..8342b6740 100644
--- a/src/sim/core.cc
+++ b/src/sim/core.cc
@@ -97,14 +97,6 @@ setOutputDir(const string &dir)
simout.setDirectory(dir);
}
-ostream *outputStream;
-
-void
-setOutputFile(const string &file)
-{
- outputStream = simout.find(file);
-}
-
/**
* Queue of C++ callbacks to invoke on simulator exit.
*/
diff --git a/src/sim/core.hh b/src/sim/core.hh
index fb7f921f4..50cb2ef59 100644
--- a/src/sim/core.hh
+++ b/src/sim/core.hh
@@ -68,11 +68,6 @@ extern Tick ps;
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);
struct Callback;
diff --git a/src/sim/debug.cc b/src/sim/debug.cc
index b4f4cd9dc..f8a3215d0 100644
--- a/src/sim/debug.cc
+++ b/src/sim/debug.cc
@@ -29,51 +29,36 @@
* Steve Reinhardt
*/
-#include <sys/types.h>
-#include <signal.h>
-#include <unistd.h>
+#include <Python.h>
#include <string>
#include <vector>
+#include "base/debug.hh"
#include "sim/debug.hh"
#include "sim/eventq.hh"
#include "sim/sim_events.hh"
using namespace std;
-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
// schedule the event to break at a particular cycle
//
-class DebugBreakEvent : public Event
+struct DebugBreakEvent : public Event
{
- public:
-
- DebugBreakEvent(EventQueue *q, Tick _when);
-
- void process(); // process event
+ DebugBreakEvent();
+ void process(); // process event
virtual const char *description() const;
};
//
// constructor: schedule at specified time
//
-DebugBreakEvent::DebugBreakEvent(EventQueue *q, Tick _when)
- : Event(q, Debug_Break_Pri)
+DebugBreakEvent::DebugBreakEvent()
+ : Event(Debug_Break_Pri)
{
setFlags(AutoDelete);
- schedule(_when);
}
//
@@ -99,12 +84,46 @@ DebugBreakEvent::description() const
void
schedBreakCycle(Tick when)
{
- new DebugBreakEvent(&mainEventQueue, when);
+ mainEventQueue.schedule(new DebugBreakEvent, when);
+ warn("need to stop all queues");
}
void
eventqDump()
{
mainEventQueue.dump();
+ warn("need to dump all queues");
+}
+
+void
+py_interact()
+{
+ PyObject *globals;
+ PyObject *locals;
+
+ globals = PyEval_GetGlobals();
+ Py_INCREF(globals);
+ locals = PyDict_New();
+ PyRun_String("import code", Py_file_input, globals, locals);
+ PyRun_String("code.interact(local=globals())", Py_file_input,
+ globals, locals);
+ Py_DECREF(globals);
+ Py_DECREF(locals);
+}
+
+int remote_gdb_base_port = 7000;
+
+int
+getRemoteGDBPort()
+{
+ return remote_gdb_base_port;
+}
+
+// Set remote GDB base port. 0 means disable remote GDB.
+// Callable from python.
+void
+setRemoteGDBPort(int port)
+{
+ remote_gdb_base_port = port;
}
diff --git a/src/sim/debug.hh b/src/sim/debug.hh
index 79792234b..7dafb8394 100644
--- a/src/sim/debug.hh
+++ b/src/sim/debug.hh
@@ -28,9 +28,15 @@
* Authors: Nathan Binkert
*/
-#ifndef __DEBUG_HH__
-#define __DEBUG_HH__
+#ifndef __SIM_DEBUG_HH__
+#define __SIM_DEBUG_HH__
-void debug_break();
+#include "sim/host.hh"
-#endif // __DEBUG_HH__
+void schedBreakCycle(Tick when);
+
+int getRemoteGDBPort();
+// Remote gdb base port. 0 disables remote gdb.
+void setRemoteGDBPort(int port);
+
+#endif // __SIM_DEBUG_HH__
diff --git a/src/sim/eventq.cc b/src/sim/eventq.cc
index 2c679be1e..d1f84fcb2 100644
--- a/src/sim/eventq.cc
+++ b/src/sim/eventq.cc
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2000-2005 The Regents of The University of Michigan
+ * Copyright (c) 2008 The Hewlett-Packard Development Company
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -30,18 +31,17 @@
* Steve Raasch
*/
-#include <assert.h>
-
+#include <cassert>
#include <iostream>
#include <string>
#include <vector>
-#include "cpu/smt.hh"
+#include "base/hashmap.hh"
#include "base/misc.hh"
-
-#include "sim/eventq.hh"
#include "base/trace.hh"
+#include "cpu/smt.hh"
#include "sim/core.hh"
+#include "sim/eventq.hh"
using namespace std;
@@ -51,100 +51,183 @@ using namespace std;
// Events on this queue are processed at the *beginning* of each
// cycle, before the pipeline simulation is performed.
//
-EventQueue mainEventQueue("MainEventQueue");
+EventQueue mainEventQueue("Main Event Queue");
#ifndef NDEBUG
Counter Event::instanceCounter = 0;
#endif
+Event::~Event()
+{
+ assert(!scheduled());
+}
+
+const std::string
+Event::name() const
+{
+#ifndef NDEBUG
+ return csprintf("Event_%d", instance);
+#else
+ return csprintf("Event_%x", (uintptr_t)this);
+#endif
+}
+
+
+Event *
+Event::insertBefore(Event *event, Event *curr)
+{
+ // Either way, event will be the top element in the 'in bin' list
+ // which is the pointer we need in order to look into the list, so
+ // we need to insert that into the bin list.
+ if (!curr || *event < *curr) {
+ // Insert the event before the current list since it is in the future.
+ event->nextBin = curr;
+ event->nextInBin = NULL;
+ } else {
+ // Since we're on the correct list, we need to point to the next list
+ event->nextBin = curr->nextBin; // curr->nextBin can now become stale
+
+ // Insert event at the top of the stack
+ event->nextInBin = curr;
+ }
+
+ return event;
+}
+
void
EventQueue::insert(Event *event)
{
- if (head == NULL || event->when() < head->when() ||
- (event->when() == head->when() &&
- event->priority() <= head->priority())) {
- event->next = head;
- head = event;
- } else {
- Event *prev = head;
- Event *curr = head->next;
+ // Deal with the head case
+ if (!head || *event <= *head) {
+ head = Event::insertBefore(event, head);
+ return;
+ }
- while (curr) {
- if (event->when() <= curr->when() &&
- (event->when() < curr->when() ||
- event->priority() <= curr->priority()))
- break;
+ // Figure out either which 'in bin' list we are on, or where a new list
+ // needs to be inserted
+ Event *prev = head;
+ Event *curr = head->nextBin;
+ while (curr && *curr < *event) {
+ prev = curr;
+ curr = curr->nextBin;
+ }
- prev = curr;
- curr = curr->next;
- }
+ // Note: this operation may render all nextBin pointers on the
+ // prev 'in bin' list stale (except for the top one)
+ prev->nextBin = Event::insertBefore(event, curr);
+}
+
+Event *
+Event::removeItem(Event *event, Event *top)
+{
+ Event *curr = top;
+ Event *next = top->nextInBin;
+
+ // if we removed the top item, we need to handle things specially
+ // and just remove the top item, fixing up the next bin pointer of
+ // the new top item
+ if (event == top) {
+ if (!next)
+ return top->nextBin;
+ next->nextBin = top->nextBin;
+ return next;
+ }
+
+ // Since we already checked the current element, we're going to
+ // keep checking event against the next element.
+ while (event != next) {
+ if (!next)
+ panic("event not found!");
- event->next = curr;
- prev->next = event;
+ curr = next;
+ next = next->nextInBin;
}
+
+ // remove next from the 'in bin' list since it's what we're looking for
+ curr->nextInBin = next->nextInBin;
+ return top;
}
void
EventQueue::remove(Event *event)
{
if (head == NULL)
- return;
+ panic("event not found!");
- if (head == event){
- head = event->next;
+ // deal with an event on the head's 'in bin' list (event has the same
+ // time as the head)
+ if (*head == *event) {
+ head = Event::removeItem(event, head);
return;
}
+ // Find the 'in bin' list that this event belongs on
Event *prev = head;
- Event *curr = head->next;
- while (curr && curr != event) {
+ Event *curr = head->nextBin;
+ while (curr && *curr < *event) {
prev = curr;
- curr = curr->next;
+ curr = curr->nextBin;
}
- if (curr == event)
- prev->next = curr->next;
+ if (!curr || *curr != *event)
+ panic("event not found!");
+
+ // curr points to the top item of the the correct 'in bin' list, when
+ // we remove an item, it returns the new top item (which may be
+ // unchanged)
+ prev->nextBin = Event::removeItem(event, curr);
}
Event *
EventQueue::serviceOne()
{
Event *event = head;
- event->clearFlags(Event::Scheduled);
- head = event->next;
+ Event *next = head->nextInBin;
+ event->flags.clear(Event::Scheduled);
+
+ if (next) {
+ // update the next bin pointer since it could be stale
+ next->nextBin = head->nextBin;
+
+ // pop the stack
+ head = next;
+ } else {
+ // this was the only element on the 'in bin' list, so get rid of
+ // the 'in bin' list and point to the next bin list
+ head = head->nextBin;
+ }
// handle action
if (!event->squashed()) {
event->process();
if (event->isExitEvent()) {
- assert(!event->getFlags(Event::AutoDelete)); // would be silly
+ assert(!event->flags.isSet(Event::AutoDelete)); // would be silly
return event;
}
} else {
- event->clearFlags(Event::Squashed);
+ event->flags.clear(Event::Squashed);
}
- if (event->getFlags(Event::AutoDelete) && !event->scheduled())
+ if (event->flags.isSet(Event::AutoDelete) && !event->scheduled())
delete event;
return NULL;
}
-
void
Event::serialize(std::ostream &os)
{
SERIALIZE_SCALAR(_when);
SERIALIZE_SCALAR(_priority);
- SERIALIZE_ENUM(_flags);
+ short _flags = flags;
+ SERIALIZE_SCALAR(_flags);
}
-
void
Event::unserialize(Checkpoint *cp, const string &section)
{
if (scheduled())
- deschedule();
+ mainEventQueue.deschedule(this);
UNSERIALIZE_SCALAR(_when);
UNSERIALIZE_SCALAR(_priority);
@@ -152,13 +235,16 @@ Event::unserialize(Checkpoint *cp, const string &section)
// need to see if original event was in a scheduled, unsquashed
// state, but don't want to restore those flags in the current
// object itself (since they aren't immediately true)
- UNSERIALIZE_ENUM(_flags);
- bool wasScheduled = (_flags & Scheduled) && !(_flags & Squashed);
- _flags &= ~(Squashed | Scheduled);
+ short _flags;
+ UNSERIALIZE_SCALAR(_flags);
+ flags = _flags;
+
+ bool wasScheduled = flags.isSet(Scheduled) && !flags.isSet(Squashed);
+ flags.clear(Squashed | Scheduled);
if (wasScheduled) {
DPRINTF(Config, "rescheduling at %d\n", _when);
- schedule(_when);
+ mainEventQueue.schedule(this, _when);
}
}
@@ -168,18 +254,25 @@ EventQueue::serialize(ostream &os)
std::list<Event *> eventPtrs;
int numEvents = 0;
- Event *event = head;
- while (event) {
- if (event->getFlags(Event::AutoSerialize)) {
- eventPtrs.push_back(event);
- paramOut(os, csprintf("event%d", numEvents++), event->name());
+ Event *nextBin = head;
+ while (nextBin) {
+ Event *nextInBin = nextBin;
+
+ while (nextInBin) {
+ if (nextInBin->flags.isSet(Event::AutoSerialize)) {
+ eventPtrs.push_back(nextInBin);
+ paramOut(os, csprintf("event%d", numEvents++),
+ nextInBin->name());
+ }
+ nextInBin = nextInBin->nextInBin;
}
- event = event->next;
+
+ nextBin = nextBin->nextBin;
}
SERIALIZE_SCALAR(numEvents);
- for (std::list<Event *>::iterator it=eventPtrs.begin();
+ for (std::list<Event *>::iterator it = eventPtrs.begin();
it != eventPtrs.end(); ++it) {
(*it)->nameOut(os);
(*it)->serialize(os);
@@ -203,7 +296,7 @@ EventQueue::unserialize(Checkpoint *cp, const std::string &section)
}
void
-EventQueue::dump()
+EventQueue::dump() const
{
cprintf("============================================================\n");
cprintf("EventQueue Dump (cycle %d)\n", curTick);
@@ -212,16 +305,63 @@ EventQueue::dump()
if (empty())
cprintf("<No Events>\n");
else {
- Event *event = head;
- while (event) {
- event->dump();
- event = event->next;
+ Event *nextBin = head;
+ while (nextBin) {
+ Event *nextInBin = nextBin;
+ while (nextInBin) {
+ nextInBin->dump();
+ nextInBin = nextInBin->nextInBin;
+ }
+
+ nextBin = nextBin->nextBin;
}
}
cprintf("============================================================\n");
}
+bool
+EventQueue::debugVerify() const
+{
+ m5::hash_map<long, bool> map;
+
+ Tick time = 0;
+ short priority = 0;
+
+ Event *nextBin = head;
+ while (nextBin) {
+ Event *nextInBin = nextBin;
+ while (nextInBin) {
+ if (nextInBin->when() < time) {
+ cprintf("time goes backwards!");
+ nextInBin->dump();
+ return false;
+ } else if (nextInBin->when() == time &&
+ nextInBin->priority() < priority) {
+ cprintf("priority inverted!");
+ nextInBin->dump();
+ return false;
+ }
+
+ if (map[reinterpret_cast<long>(nextInBin)]) {
+ cprintf("Node already seen");
+ nextInBin->dump();
+ return false;
+ }
+ map[reinterpret_cast<long>(nextInBin)] = true;
+
+ time = nextInBin->when();
+ priority = nextInBin->priority();
+
+ nextInBin = nextInBin->nextInBin;
+ }
+
+ nextBin = nextBin->nextBin;
+ }
+
+ return true;
+}
+
void
dumpMainQueue()
{
@@ -235,7 +375,6 @@ Event::description() const
return "generic";
}
-#if TRACING_ON
void
Event::trace(const char *action)
{
@@ -250,23 +389,21 @@ Event::trace(const char *action)
// needs to be printed.
DPRINTFN("%s event %s @ %d\n", description(), action, when());
}
-#endif
void
-Event::dump()
+Event::dump() const
{
- cprintf("Event (%s)\n", description());
- cprintf("Flags: %#x\n", _flags);
-#if TRACING_ON
- cprintf("Created: %d\n", when_created);
+ cprintf("Event %s (%s)\n", name(), description());
+ cprintf("Flags: %#x\n", flags);
+#ifdef EVENTQ_DEBUG
+ cprintf("Created: %d\n", whenCreated);
#endif
if (scheduled()) {
-#if TRACING_ON
- cprintf("Scheduled at %d\n", when_scheduled);
+#ifdef EVENTQ_DEBUG
+ cprintf("Scheduled at %d\n", whenScheduled);
#endif
cprintf("Scheduled for %d, priority %d\n", when(), _priority);
- }
- else {
+ } else {
cprintf("Not Scheduled\n");
}
}
diff --git a/src/sim/eventq.hh b/src/sim/eventq.hh
index a454e5d64..33bb34252 100644
--- a/src/sim/eventq.hh
+++ b/src/sim/eventq.hh
@@ -36,45 +36,70 @@
#ifndef __SIM_EVENTQ_HH__
#define __SIM_EVENTQ_HH__
-#include <assert.h>
-
#include <algorithm>
+#include <cassert>
+#include <climits>
#include <map>
#include <string>
#include <vector>
-#include "sim/host.hh" // for Tick
-
#include "base/fast_alloc.hh"
+#include "base/flags.hh"
#include "base/misc.hh"
#include "base/trace.hh"
#include "sim/serialize.hh"
+#include "sim/host.hh"
-class EventQueue; // forward declaration
-
-//////////////////////
-//
-// Main Event Queue
-//
-// Events on this queue are processed at the *beginning* of each
-// cycle, before the pipeline simulation is performed.
-//
-// defined in eventq.cc
-//
-//////////////////////
-extern EventQueue mainEventQueue;
+class EventQueue; // forward declaration
+extern EventQueue mainEventQueue;
/*
* An item on an event queue. The action caused by a given
* event is specified by deriving a subclass and overriding the
* process() member function.
+ *
+ * Caution, the order of members is chosen to maximize data packing.
*/
class Event : public Serializable, public FastAlloc
{
friend class EventQueue;
+ protected:
+ typedef short FlagsType;
+ typedef ::Flags<FlagsType> Flags;
+
+ static const FlagsType PublicRead = 0x003f;
+ static const FlagsType PublicWrite = 0x001d;
+ static const FlagsType Squashed = 0x0001;
+ static const FlagsType Scheduled = 0x0002;
+ static const FlagsType AutoDelete = 0x0004;
+ static const FlagsType AutoSerialize = 0x0008;
+ static const FlagsType IsExitEvent = 0x0010;
+ static const FlagsType IsMainQueue = 0x0020;
+#ifdef EVENTQ_DEBUG
+ static const FlagsType Initialized = 0xf000;
+#endif
+
private:
+ // The event queue is now a linked list of linked lists. The
+ // 'nextBin' pointer is to find the bin, where a bin is defined as
+ // when+priority. All events in the same bin will be stored in a
+ // second linked list (a stack) maintained by the 'nextInBin'
+ // pointer. The list will be accessed in LIFO order. The end
+ // result is that the insert/removal in 'nextBin' is
+ // linear/constant, and the lookup/removal in 'nextInBin' is
+ // constant/constant. Hopefully this is a significant improvement
+ // over the current fully linear insertion.
+ Event *nextBin;
+ Event *nextInBin;
+
+ static Event *insertBefore(Event *event, Event *curr);
+ static Event *removeItem(Event *event, Event *last);
+
+ Tick _when; //!< timestamp when event should be processed
+ short _priority; //!< event priority
+ Flags flags;
#ifndef NDEBUG
/// Global counter to generate unique IDs for Event instances
@@ -84,54 +109,85 @@ class Event : public Serializable, public FastAlloc
/// 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
+ Counter instance;
/// queue to which this event belongs (though it may or may not be
/// scheduled on this queue yet)
EventQueue *queue;
+#endif
- Event *next;
+#ifdef EVENTQ_DEBUG
+ Tick whenCreated; //!< time created
+ Tick whenScheduled; //!< time scheduled
+#endif
- Tick _when; //!< timestamp when event should be processed
- int _priority; //!< event priority
- char _flags;
+ void
+ setWhen(Tick when, EventQueue *q)
+ {
+ _when = when;
+#ifndef NDEBUG
+ queue = q;
+#endif
+#ifdef EVENTQ_DEBUG
+ whenScheduled = curTick;
+#endif
+ }
protected:
- enum Flags {
- None = 0x0,
- Squashed = 0x1,
- Scheduled = 0x2,
- AutoDelete = 0x4,
- AutoSerialize = 0x8,
- IsExitEvent = 0x10
- };
+ /// Accessor for flags.
+ Flags
+ getFlags() const
+ {
+ return flags & PublicRead;
+ }
- bool getFlags(Flags f) const { return (_flags & f) == f; }
- void setFlags(Flags f) { _flags |= f; }
- void clearFlags(Flags f) { _flags &= ~f; }
+ Flags
+ getFlags(Flags _flags) const
+ {
+ assert(flags.noneSet(~PublicRead));
+ return flags.isSet(_flags);
+ }
- protected:
- EventQueue *theQueue() const { return queue; }
+ Flags
+ allFlags(Flags _flags) const
+ {
+ assert(_flags.noneSet(~PublicRead));
+ return flags.allSet(_flags);
+ }
-#if TRACING_ON
- Tick when_created; //!< Keep track of creation time For debugging
- Tick when_scheduled; //!< Keep track of creation time For debugging
+ /// Accessor for flags.
+ void
+ setFlags(Flags _flags)
+ {
+ assert(_flags.noneSet(~PublicWrite));
+ flags.set(_flags);
+ }
- virtual void trace(const char *action); //!< trace event activity
-#else
- void trace(const char *) {}
-#endif
+ void
+ clearFlags(Flags _flags)
+ {
+ assert(_flags.noneSet(~PublicWrite));
+ flags.clear(_flags);
+ }
- unsigned annotated_value;
+ void
+ clearFlags()
+ {
+ flags.clear(PublicWrite);
+ }
- public:
+ // This function isn't really useful if TRACING_ON is not defined
+ virtual void trace(const char *action); //!< trace event activity
+ public:
/// Event priorities, to provide tie-breakers for events scheduled
/// at the same cycle. Most events are scheduled at the default
/// priority; these values are used to control events that need to
/// be ordered within a cycle.
enum Priority {
+ /// Minimum priority
+ Minimum_Pri = SHRT_MIN,
+
/// If we enable tracing on a particular cycle, do that as the
/// very first thing so we don't miss any of the events on
/// that cycle (even if we enter the debugger).
@@ -140,81 +196,66 @@ class Event : public Serializable, public FastAlloc
/// Breakpoints should happen before anything else (except
/// enabling trace output), so we don't miss any action when
/// debugging.
- Debug_Break_Pri = -100,
+ Debug_Break_Pri = -100,
/// CPU switches schedule the new CPU's tick event for the
/// same cycle (after unscheduling the old CPU's tick event).
/// The switch needs to come before any tick events to make
/// sure we don't tick both CPUs in the same cycle.
- CPU_Switch_Pri = -31,
+ CPU_Switch_Pri = -31,
/// For some reason "delayed" inter-cluster writebacks are
/// scheduled before regular writebacks (which have default
/// priority). Steve?
- Delayed_Writeback_Pri = -1,
+ Delayed_Writeback_Pri = -1,
/// Default is zero for historical reasons.
- Default_Pri = 0,
+ Default_Pri = 0,
/// Serailization needs to occur before tick events also, so
/// that a serialize/unserialize is identical to an on-line
/// CPU switch.
- Serialize_Pri = 32,
+ Serialize_Pri = 32,
/// CPU ticks must come after other associated CPU events
/// (such as writebacks).
- CPU_Tick_Pri = 50,
+ CPU_Tick_Pri = 50,
/// Statistics events (dump, reset, etc.) come after
/// everything else, but before exit.
- Stat_Event_Pri = 90,
+ 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
+ Sim_Exit_Pri = 100,
+
+ /// Maximum priority
+ Maximum_Pri = SHRT_MAX
};
/*
* Event constructor
* @param queue that the event gets scheduled on
*/
- Event(EventQueue *q, Priority p = Default_Pri)
- : queue(q), next(NULL), _priority(p), _flags(None),
-#if TRACING_ON
- when_created(curTick), when_scheduled(0),
-#endif
- annotated_value(0)
+ Event(Priority p = Default_Pri)
+ : nextBin(NULL), nextInBin(NULL), _priority(p)
{
#ifndef NDEBUG
- instanceId = ++instanceCounter;
+ instance = ++instanceCounter;
+ queue = NULL;
#endif
- }
-
- ~Event() {}
-
- virtual const std::string name() const {
-#ifndef NDEBUG
- return csprintf("Event_%d", instanceId);
-#else
- return csprintf("Event_%x", (uintptr_t)this);
+#ifdef EVENTQ_DEBUG
+ flags.set(Initialized);
+ whenCreated = curTick;
+ whenScheduled = 0;
#endif
}
- /// Determine if the current event is scheduled
- bool scheduled() const { return getFlags(Scheduled); }
-
- /// Schedule the event with the current priority or default priority
- void schedule(Tick t);
-
- /// Reschedule the event with the current priority
- // always parameter means to schedule if not already scheduled
- void reschedule(Tick t, bool always = false);
-
- /// Remove the event from the current schedule
- void deschedule();
+ virtual ~Event();
+ virtual const std::string name() const;
/// Return a C string describing the event. This string should
/// *not* be dynamically allocated; just a const char array
@@ -222,8 +263,9 @@ class Event : public Serializable, public FastAlloc
virtual const char *description() const;
/// Dump the current event data
- void dump();
+ void dump() const;
+ public:
/*
* This member function is invoked when the event is processed
* (occurs). There is no default implementation; each subclass
@@ -236,17 +278,17 @@ class Event : public Serializable, public FastAlloc
*/
virtual void process() = 0;
- void annotate(unsigned value) { annotated_value = value; };
- unsigned annotation() { return annotated_value; }
+ /// Determine if the current event is scheduled
+ bool scheduled() const { return flags.isSet(Scheduled); }
/// Squash the current event
- void squash() { setFlags(Squashed); }
+ void squash() { flags.set(Squashed); }
/// Check whether the event is squashed
- bool squashed() { return getFlags(Squashed); }
+ bool squashed() const { return flags.isSet(Squashed); }
/// See if this is a SimExitEvent (without resorting to RTTI)
- bool isExitEvent() { return getFlags(IsExitEvent); }
+ bool isExitEvent() const { return flags.isSet(IsExitEvent); }
/// Get the time that the event is scheduled
Tick when() const { return _when; }
@@ -254,65 +296,20 @@ class Event : public Serializable, public FastAlloc
/// Get the event priority
int priority() const { return _priority; }
- struct priority_compare :
- public std::binary_function<Event *, Event *, bool>
+#ifndef SWIG
+ struct priority_compare
+ : public std::binary_function<Event *, Event *, bool>
{
- bool operator()(const Event *l, const Event *r) const {
+ bool
+ operator()(const Event *l, const Event *r) const
+ {
return l->when() >= r->when() || l->priority() >= r->priority();
}
};
virtual void serialize(std::ostream &os);
virtual void unserialize(Checkpoint *cp, const std::string &section);
-};
-
-template <class T, void (T::* F)()>
-void
-DelayFunction(Tick when, T *object)
-{
- class DelayEvent : public Event
- {
- private:
- T *object;
-
- public:
- DelayEvent(Tick when, T *o)
- : Event(&mainEventQueue), object(o)
- { setFlags(this->AutoDestroy); schedule(when); }
- void process() { (object->*F)(); }
- const char *description() const { return "delay"; }
- };
-
- new DelayEvent(when, object);
-}
-
-template <class T, void (T::* F)()>
-class EventWrapper : public Event
-{
- private:
- T *object;
-
- public:
- EventWrapper(T *obj, bool del = false,
- EventQueue *q = &mainEventQueue,
- Priority p = Default_Pri)
- : Event(q, p), object(obj)
- {
- if (del)
- setFlags(AutoDelete);
- }
-
- EventWrapper(T *obj, Tick t, bool del = false,
- EventQueue *q = &mainEventQueue,
- Priority p = Default_Pri)
- : Event(q, p), object(obj)
- {
- if (del)
- setFlags(AutoDelete);
- schedule(t);
- }
-
- void process() { (object->*F)(); }
+#endif
};
/*
@@ -320,18 +317,14 @@ class EventWrapper : public Event
*/
class EventQueue : public Serializable
{
- protected:
- std::string objName;
-
private:
+ std::string objName;
Event *head;
void insert(Event *event);
void remove(Event *event);
public:
-
- // constructor
EventQueue(const std::string &n)
: objName(n), head(NULL)
{}
@@ -339,17 +332,19 @@ class EventQueue : public Serializable
virtual const std::string name() const { return objName; }
// schedule the given event on this queue
- void schedule(Event *ev);
- void deschedule(Event *ev);
- void reschedule(Event *ev);
+ void schedule(Event *event, Tick when);
+ void deschedule(Event *event);
+ void reschedule(Event *event, Tick when, bool always = false);
- Tick nextTick() { return head->when(); }
+ Tick nextTick() const { return head->when(); }
Event *serviceOne();
// process all events up to the given timestamp. we inline a
// quick test to see if there are any events to process; if so,
// call the internal out-of-line version to process them all.
- void serviceEvents(Tick when) {
+ void
+ serviceEvents(Tick when)
+ {
while (!empty()) {
if (nextTick() > when)
break;
@@ -367,76 +362,129 @@ class EventQueue : public Serializable
void serviceEvents() { serviceEvents(curTick); }
// return true if no events are queued
- bool empty() { return head == NULL; }
+ bool empty() const { return head == NULL; }
- void dump();
+ void dump() const;
Tick nextEventTime() { return empty() ? curTick : head->when(); }
+ bool debugVerify() const;
+
+#ifndef SWIG
virtual void serialize(std::ostream &os);
virtual void unserialize(Checkpoint *cp, const std::string &section);
+#endif
};
+#ifndef SWIG
+class EventManager
+{
+ protected:
+ /** A pointer to this object's event queue */
+ EventQueue *eventq;
-//////////////////////
-//
-// inline functions
-//
-// can't put these inside declaration due to circular dependence
-// between Event and EventQueue classes.
-//
-//////////////////////
+ public:
+ EventManager(EventManager &em) : eventq(em.queue()) {}
+ EventManager(EventManager *em) : eventq(em ? em->queue() : NULL) {}
+ EventManager(EventQueue *eq) : eventq(eq) {}
-// schedule at specified time (place on event queue specified via
-// constructor)
-inline void
-Event::schedule(Tick t)
-{
- assert(!scheduled());
-// if (t < curTick)
-// warn("t is less than curTick, ensure you don't want cycles");
+ EventQueue *
+ queue() const
+ {
+ return eventq;
+ }
- setFlags(Scheduled);
-#if TRACING_ON
- when_scheduled = curTick;
-#endif
- _when = t;
- queue->schedule(this);
-}
+ void
+ schedule(Event &event, Tick when)
+ {
+ eventq->schedule(&event, when);
+ }
-inline void
-Event::deschedule()
+ void
+ deschedule(Event &event)
+ {
+ eventq->deschedule(&event);
+ }
+
+ void
+ reschedule(Event &event, Tick when, bool always = false)
+ {
+ eventq->reschedule(&event, when, always);
+ }
+
+ void
+ schedule(Event *event, Tick when)
+ {
+ eventq->schedule(event, when);
+ }
+
+ void
+ deschedule(Event *event)
+ {
+ eventq->deschedule(event);
+ }
+
+ void
+ reschedule(Event *event, Tick when, bool always = false)
+ {
+ eventq->reschedule(event, when, always);
+ }
+};
+
+template <class T, void (T::* F)()>
+void
+DelayFunction(EventQueue *eventq, Tick when, T *object)
{
- assert(scheduled());
+ class DelayEvent : public Event
+ {
+ private:
+ T *object;
+
+ public:
+ DelayEvent(T *o)
+ : object(o)
+ { this->setFlags(AutoDelete); }
+ void process() { (object->*F)(); }
+ const char *description() const { return "delay"; }
+ };
- clearFlags(Squashed);
- clearFlags(Scheduled);
- queue->deschedule(this);
+ eventq->schedule(new DelayEvent(object), when);
}
-inline void
-Event::reschedule(Tick t, bool always)
+template <class T, void (T::* F)()>
+class EventWrapper : public Event
{
- assert(scheduled() || always);
+ private:
+ T *object;
-#if TRACING_ON
- when_scheduled = curTick;
-#endif
- _when = t;
-
- if (scheduled()) {
- clearFlags(Squashed);
- queue->reschedule(this);
- } else {
- setFlags(Scheduled);
- queue->schedule(this);
+ public:
+ EventWrapper(T *obj, bool del = false, Priority p = Default_Pri)
+ : Event(p), object(obj)
+ {
+ if (del)
+ setFlags(AutoDelete);
}
-}
+
+ void process() { (object->*F)(); }
+};
inline void
-EventQueue::schedule(Event *event)
+EventQueue::schedule(Event *event, Tick when)
{
+ assert(when >= curTick);
+ assert(!event->scheduled());
+#ifdef EVENTQ_DEBUG
+ assert((event->flags & Event::Initialized) == Event::Initialized);
+#endif
+
+ event->setWhen(when, this);
insert(event);
+ event->flags.set(Event::Scheduled);
+ if (this == &mainEventQueue)
+ event->flags.set(Event::IsMainQueue);
+ else
+ event->flags.clear(Event::IsMainQueue);
+
if (DTRACE(Event))
event->trace("scheduled");
}
@@ -444,20 +492,86 @@ EventQueue::schedule(Event *event)
inline void
EventQueue::deschedule(Event *event)
{
+ assert(event->scheduled());
+#ifdef EVENTQ_DEBUG
+ assert((event->flags & Event::Initialized) == Event::Initialized);
+#endif
+
remove(event);
+
+ event->flags.clear(Event::Squashed);
+ event->flags.clear(Event::Scheduled);
+
+ if (event->flags.isSet(Event::AutoDelete))
+ delete event;
+
if (DTRACE(Event))
event->trace("descheduled");
}
inline void
-EventQueue::reschedule(Event *event)
+EventQueue::reschedule(Event *event, Tick when, bool always)
{
- remove(event);
+ assert(when >= curTick);
+ assert(always || event->scheduled());
+#ifdef EVENTQ_DEBUG
+ assert((event->flags & Event::Initialized) == Event::Initialized);
+#endif
+
+ if (event->scheduled())
+ remove(event);
+
+ event->setWhen(when, this);
insert(event);
+ event->flags.clear(Event::Squashed);
+ event->flags.set(Event::Scheduled);
+ if (this == &mainEventQueue)
+ event->flags.set(Event::IsMainQueue);
+ else
+ event->flags.clear(Event::IsMainQueue);
+
if (DTRACE(Event))
event->trace("rescheduled");
}
+inline bool
+operator<(const Event &l, const Event &r)
+{
+ return l.when() < r.when() ||
+ (l.when() == r.when() && l.priority() < r.priority());
+}
+inline bool
+operator>(const Event &l, const Event &r)
+{
+ return l.when() > r.when() ||
+ (l.when() == r.when() && l.priority() > r.priority());
+}
+
+inline bool
+operator<=(const Event &l, const Event &r)
+{
+ return l.when() < r.when() ||
+ (l.when() == r.when() && l.priority() <= r.priority());
+}
+inline bool
+operator>=(const Event &l, const Event &r)
+{
+ return l.when() > r.when() ||
+ (l.when() == r.when() && l.priority() >= r.priority());
+}
+
+inline bool
+operator==(const Event &l, const Event &r)
+{
+ return l.when() == r.when() && l.priority() == r.priority();
+}
+
+inline bool
+operator!=(const Event &l, const Event &r)
+{
+ return l.when() != r.when() || l.priority() != r.priority();
+}
+#endif
#endif // __SIM_EVENTQ_HH__
diff --git a/src/sim/faults.hh b/src/sim/faults.hh
index cfc6ad105..75696641b 100644
--- a/src/sim/faults.hh
+++ b/src/sim/faults.hh
@@ -41,7 +41,7 @@ class FaultBase;
typedef RefCountingPtr<FaultBase> Fault;
typedef const char * FaultName;
-typedef Stats::Scalar<> FaultStat;
+typedef Stats::Scalar FaultStat;
// Each class has it's name statically define in _name,
// and has a virtual function to access it's name.
diff --git a/src/sim/host.hh b/src/sim/host.hh
index 93a5fe7f2..dd29534fd 100644
--- a/src/sim/host.hh
+++ b/src/sim/host.hh
@@ -38,13 +38,11 @@
#define __HOST_HH__
#include <inttypes.h>
-#include <limits>
-
/** uint64_t constant */
-#define ULL(N) ((uint64_t)N##ULL)
+#define ULL(N) ((uint64_t)N##ULL)
/** int64_t constant */
-#define LL(N) ((int64_t)N##LL)
+#define LL(N) ((int64_t)N##LL)
/** Statistics counter type. Not much excuse for not using a 64-bit
* integer here, but if you're desperate and only run short
@@ -58,7 +56,7 @@ typedef int64_t Counter;
*/
typedef int64_t Tick;
-const Tick MaxTick = std::numeric_limits<Tick>::max();
+const Tick MaxTick = LL(0x7fffffffffffffff);
/**
* Address type
diff --git a/src/sim/init.cc b/src/sim/init.cc
new file mode 100644
index 000000000..66eddfb6f
--- /dev/null
+++ b/src/sim/init.cc
@@ -0,0 +1,209 @@
+/*
+ * Copyright (c) 2000-2005 The Regents of The University of Michigan
+ * Copyright (c) 2008 The Hewlett-Packard Development Company
+ * 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
+ */
+
+#include <Python.h>
+#include <marshal.h>
+#include <signal.h>
+
+#include <iostream>
+#include <string>
+#include <zlib.h>
+
+#include "base/cprintf.hh"
+#include "base/misc.hh"
+#include "sim/async.hh"
+#include "sim/core.hh"
+#include "sim/host.hh"
+#include "sim/init.hh"
+
+using namespace std;
+
+/// Stats signal handler.
+void
+dumpStatsHandler(int sigtype)
+{
+ async_event = true;
+ async_statdump = true;
+}
+
+void
+dumprstStatsHandler(int sigtype)
+{
+ async_event = true;
+ async_statdump = true;
+ async_statreset = true;
+}
+
+/// Exit signal handler.
+void
+exitNowHandler(int sigtype)
+{
+ async_event = true;
+ async_exit = true;
+}
+
+/// Abort signal handler.
+void
+abortHandler(int sigtype)
+{
+ ccprintf(cerr, "Program aborted at cycle %d\n", curTick);
+}
+
+/*
+ * M5 can do several special things when various signals are sent.
+ * None are mandatory.
+ */
+void
+initSignals()
+{
+ // Floating point exceptions may happen on misspeculated paths, so
+ // ignore them
+ signal(SIGFPE, SIG_IGN);
+
+ // We use SIGTRAP sometimes for debugging
+ signal(SIGTRAP, SIG_IGN);
+
+ // Dump intermediate stats
+ signal(SIGUSR1, dumpStatsHandler);
+
+ // Dump intermediate stats and reset them
+ signal(SIGUSR2, dumprstStatsHandler);
+
+ // Exit cleanly on Interrupt (Ctrl-C)
+ signal(SIGINT, exitNowHandler);
+
+ // Print out cycle number on abort
+ signal(SIGABRT, abortHandler);
+}
+
+/*
+ * Uncompress and unmarshal the code object stored in the
+ * EmbeddedPyModule
+ */
+PyObject *
+getCode(const EmbeddedPyModule *pymod)
+{
+ assert(pymod->zlen == pymod->code_end - pymod->code);
+ Bytef *marshalled = new Bytef[pymod->mlen];
+ uLongf unzlen = pymod->mlen;
+ int ret = uncompress(marshalled, &unzlen, (const Bytef *)pymod->code,
+ pymod->zlen);
+ if (ret != Z_OK)
+ panic("Could not uncompress code: %s\n", zError(ret));
+ assert(unzlen == pymod->mlen);
+
+ return PyMarshal_ReadObjectFromString((char *)marshalled, pymod->mlen);
+}
+
+// The python library is totally messed up with respect to constness,
+// so make a simple macro to make life a little easier
+#define PyCC(x) (const_cast<char *>(x))
+
+/*
+ * Load and initialize all of the python parts of M5, including Swig
+ * and the embedded module importer.
+ */
+int
+initM5Python()
+{
+ extern void initSwig();
+
+ // initialize SWIG modules. initSwig() is autogenerated and calls
+ // all of the individual swig initialization functions.
+ initSwig();
+
+ // Load the importer module
+ PyObject *code = getCode(&embeddedPyImporter);
+ PyObject *module = PyImport_ExecCodeModule(PyCC("importer"), code);
+ if (!module) {
+ PyErr_Print();
+ return 1;
+ }
+
+ // Load the rest of the embedded python files into the embedded
+ // python importer
+ const EmbeddedPyModule *pymod = &embeddedPyModules[0];
+ while (pymod->filename) {
+ PyObject *code = getCode(pymod);
+ PyObject *result = PyObject_CallMethod(module, PyCC("add_module"),
+ PyCC("ssO"), pymod->filename, pymod->modpath, code);
+ if (!result) {
+ PyErr_Print();
+ return 1;
+ }
+ Py_DECREF(result);
+ ++pymod;
+ }
+
+ return 0;
+}
+
+/*
+ * Start up the M5 simulator. This mostly vectors into the python
+ * main function.
+ */
+int
+m5Main(int argc, char **argv)
+{
+ PySys_SetArgv(argc, argv);
+
+ // We have to set things up in the special __main__ module
+ PyObject *module = PyImport_AddModule(PyCC("__main__"));
+ if (module == NULL)
+ panic("Could not import __main__");
+ PyObject *dict = PyModule_GetDict(module);
+
+ // import the main m5 module
+ PyObject *result;
+ result = PyRun_String("import m5", Py_file_input, dict, dict);
+ if (!result) {
+ PyErr_Print();
+ return 1;
+ }
+ Py_DECREF(result);
+
+ // Start m5
+ result = PyRun_String("m5.main()", Py_file_input, dict, dict);
+ if (!result) {
+ PyErr_Print();
+ return 1;
+ }
+ Py_DECREF(result);
+
+ return 0;
+}
+
+PyMODINIT_FUNC
+initm5(void)
+{
+ initM5Python();
+ PyImport_ImportModule(PyCC("m5"));
+}
diff --git a/src/sim/init.hh b/src/sim/init.hh
new file mode 100644
index 000000000..b0f29bf30
--- /dev/null
+++ b/src/sim/init.hh
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2008 The Hewlett-Packard Development Company
+ * 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
+ */
+
+#ifndef __SIM_INIT_HH__
+#define __SIM_INIT_HH__
+
+/*
+ * Data structure describing an embedded python file.
+ */
+struct EmbeddedPyModule
+{
+ const char *filename;
+ const char *modpath;
+ const char *code;
+ const char *code_end;
+ int zlen;
+ int mlen;
+};
+
+extern const EmbeddedPyModule embeddedPyImporter;
+extern const EmbeddedPyModule embeddedPyModules[];
+
+void initSignals();
+int initM5Python();
+int m5Main(int argc, char **argv);
+
+#endif // __SIM_INIT_HH__
diff --git a/src/sim/insttracer.hh b/src/sim/insttracer.hh
index 9a20c7c56..9fb5f9f22 100644
--- a/src/sim/insttracer.hh
+++ b/src/sim/insttracer.hh
@@ -34,7 +34,7 @@
#include "base/bigint.hh"
#include "base/trace.hh"
-#include "cpu/inst_seq.hh" // for InstSeqNum
+#include "cpu/inst_seq.hh" // for InstSeqNum
#include "cpu/static_inst.hh"
#include "sim/host.hh"
#include "sim/sim_object.hh"
@@ -55,6 +55,8 @@ class InstRecord
// dump the record
StaticInstPtr staticInst;
Addr PC;
+ StaticInstPtr macroStaticInst;
+ MicroPC upc;
bool misspeculating;
// The remaining fields are only valid for particular instruction
@@ -71,7 +73,7 @@ class InstRecord
} data;
enum {
DataInvalid = 0,
- DataInt8 = 1, // set to equal number of bytes
+ DataInt8 = 1, // set to equal number of bytes
DataInt16 = 2,
DataInt32 = 4,
DataInt64 = 8,
@@ -86,10 +88,13 @@ class InstRecord
public:
InstRecord(Tick _when, ThreadContext *_thread,
- const StaticInstPtr &_staticInst,
- Addr _pc, bool spec)
+ const StaticInstPtr _staticInst,
+ Addr _pc, bool spec,
+ const StaticInstPtr _macroStaticInst = NULL,
+ MicroPC _upc = 0)
: when(_when), thread(_thread),
staticInst(_staticInst), PC(_pc),
+ macroStaticInst(_macroStaticInst), upc(_upc),
misspeculating(spec)
{
data_status = DataInvalid;
@@ -137,7 +142,9 @@ class InstTracer : public SimObject
virtual InstRecord *
getInstRecord(Tick when, ThreadContext *tc,
- const StaticInstPtr staticInst, Addr pc) = 0;
+ const StaticInstPtr staticInst, Addr pc,
+ const StaticInstPtr macroStaticInst = NULL,
+ MicroPC _upc = 0) = 0;
};
diff --git a/src/sim/main.cc b/src/sim/main.cc
index baca556a0..d674e0cff 100644
--- a/src/sim/main.cc
+++ b/src/sim/main.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000-2005 The Regents of The University of Michigan
+ * Copyright (c) 2008 The Hewlett-Packard Development Company
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -29,125 +29,33 @@
*/
#include <Python.h>
-#include <signal.h>
-#include <iostream>
-#include <string>
-
-#include "base/cprintf.hh"
-#include "base/misc.hh"
-#include "config/pythonhome.hh"
-#include "python/swig/init.hh"
-#include "sim/async.hh"
-#include "sim/host.hh"
-#include "sim/core.hh"
-
-using namespace std;
-
-/// Stats signal handler.
-void
-dumpStatsHandler(int sigtype)
-{
- async_event = true;
- async_statdump = true;
-}
-
-void
-dumprstStatsHandler(int sigtype)
-{
- async_event = true;
- async_statdump = true;
- async_statreset = true;
-}
-
-/// Exit signal handler.
-void
-exitNowHandler(int sigtype)
-{
- async_event = true;
- async_exit = true;
-}
-
-/// Abort signal handler.
-void
-abortHandler(int sigtype)
-{
- ccprintf(cerr, "Program aborted at cycle %d\n", curTick);
-}
-
-int
-python_main()
-{
- PyObject *module;
- PyObject *dict;
- PyObject *result;
-
- module = PyImport_AddModule(const_cast<char*>("__main__"));
- if (module == NULL)
- fatal("Could not import __main__");
-
- dict = PyModule_GetDict(module);
-
- result = PyRun_String("import m5.main", Py_file_input, dict, dict);
- if (!result) {
- PyErr_Print();
- return 1;
- }
- Py_DECREF(result);
-
- result = PyRun_String("m5.main.main()", Py_file_input, dict, dict);
- if (!result) {
- PyErr_Print();
- return 1;
- }
- Py_DECREF(result);
-
- if (Py_FlushLine())
- PyErr_Clear();
-
- return 0;
-}
+#include "sim/init.hh"
+// main() is now pretty stripped down and just sets up python and then
+// calls initM5Python which loads the various embedded python modules
+// into the python environment and then starts things running by
+// calling m5Main.
int
main(int argc, char **argv)
{
- signal(SIGFPE, SIG_IGN); // may occur on misspeculated paths
- signal(SIGTRAP, SIG_IGN);
- signal(SIGUSR1, dumpStatsHandler); // dump intermediate stats
- signal(SIGUSR2, dumprstStatsHandler); // dump and reset stats
- signal(SIGINT, exitNowHandler); // dump final stats and exit
- signal(SIGABRT, abortHandler);
-
- Py_SetProgramName(argv[0]);
-
- // default path to m5 python code is the currently executing
- // file... Python ZipImporter will find embedded zip archive.
- // The M5_ARCHIVE environment variable can be used to override this.
- char *m5_archive = getenv("M5_ARCHIVE");
- string pythonpath = m5_archive ? m5_archive : argv[0];
+ int ret;
- char *oldpath = getenv("PYTHONPATH");
- if (oldpath != NULL) {
- pythonpath += ":";
- pythonpath += oldpath;
- }
-
- if (setenv("PYTHONPATH", pythonpath.c_str(), true) == -1)
- fatal("setenv: %s\n", strerror(errno));
+ // Initialize m5 special signal handling.
+ initSignals();
- const char *python_home = getenv("PYTHONHOME");
- if (!python_home)
- python_home = PYTHONHOME;
- Py_SetPythonHome(const_cast<char*>(python_home));
+ Py_SetProgramName(argv[0]);
// initialize embedded Python interpreter
Py_Initialize();
- PySys_SetArgv(argc, argv);
- // initialize SWIG modules
- init_swig();
+ // Initialize the embedded m5 python library
+ ret = initM5Python();
- int ret = python_main();
+ if (ret == 0) {
+ // start m5
+ ret = m5Main(argc, argv);
+ }
// clean up Python intepreter.
Py_Finalize();
diff --git a/src/sim/microcode_rom.hh b/src/sim/microcode_rom.hh
new file mode 100644
index 000000000..be10de86b
--- /dev/null
+++ b/src/sim/microcode_rom.hh
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2008 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: Gabe Black
+ */
+
+#ifndef __SIM_MICROCODE_ROM_HH__
+#define __SIM_MICROCODE_ROM_HH__
+
+/*
+ * This is a generic stub microcode ROM ISAs can use if they don't need
+ * anything more.
+ */
+
+#include "base/misc.hh"
+#include "cpu/static_inst.hh"
+
+class MicrocodeRom
+{
+ public:
+ StaticInstPtr
+ fetchMicroop(MicroPC micropc, StaticInstPtr curMacroop)
+ {
+ panic("ROM based microcode isn't implemented.\n");
+ }
+};
+
+#endif // __SIM_MICROCODE_ROM_HH__
diff --git a/src/sim/process.cc b/src/sim/process.cc
index 16037b2f4..4be97f2f6 100644
--- a/src/sim/process.cc
+++ b/src/sim/process.cc
@@ -46,6 +46,7 @@
#include "mem/translating_port.hh"
#include "params/Process.hh"
#include "params/LiveProcess.hh"
+#include "sim/debug.hh"
#include "sim/process.hh"
#include "sim/process_impl.hh"
#include "sim/stats.hh"
@@ -85,12 +86,23 @@ using namespace TheISA;
// current number of allocated processes
int num_processes = 0;
+template<class IntType>
+AuxVector<IntType>::AuxVector(IntType type, IntType val)
+{
+ a_type = TheISA::htog(type);
+ a_val = TheISA::htog(val);
+}
+
+template class AuxVector<uint32_t>;
+template class AuxVector<uint64_t>;
+
Process::Process(ProcessParams * params)
: SimObject(params), system(params->system), checkpointRestored(false),
max_stack_size(params->max_stack_size)
{
string in = params->input;
string out = params->output;
+ string err = params->errout;
// initialize file descriptors to default: same as simulator
int stdin_fd, stdout_fd, stderr_fd;
@@ -111,7 +123,16 @@ Process::Process(ProcessParams * params)
else
stdout_fd = Process::openOutputFile(out);
- stderr_fd = (stdout_fd != STDOUT_FILENO) ? stdout_fd : STDERR_FILENO;
+ if (err == "stdout" || err == "cout")
+ stderr_fd = STDOUT_FILENO;
+ else if (err == "stderr" || err == "cerr")
+ stderr_fd = STDERR_FILENO;
+ else if (err == "None")
+ stderr_fd = -1;
+ else if (err == out)
+ stderr_fd = stdout_fd;
+ else
+ stderr_fd = Process::openOutputFile(err);
M5_pid = system->allocatePID();
// initialize first 3 fds (stdin, stdout, stderr)
@@ -131,7 +152,7 @@ Process::Process(ProcessParams * params)
fdo = &fd_map[STDERR_FILENO];
fdo->fd = stderr_fd;
- fdo->filename = "STDERR";
+ fdo->filename = err;
fdo->flags = O_WRONLY;
fdo->mode = -1;
fdo->fileOffset = 0;
@@ -182,7 +203,7 @@ Process::openInputFile(const string &filename)
int
Process::openOutputFile(const string &filename)
{
- int fd = open(filename.c_str(), O_WRONLY | O_CREAT | O_TRUNC, 0774);
+ int fd = open(filename.c_str(), O_WRONLY | O_CREAT | O_TRUNC, 0664);
if (fd == -1) {
perror(NULL);
@@ -193,33 +214,29 @@ Process::openOutputFile(const string &filename)
return fd;
}
-
-int
-Process::registerThreadContext(ThreadContext *tc)
+ThreadContext *
+Process::findFreeContext()
{
- // add to list
- int myIndex = threadContexts.size();
- threadContexts.push_back(tc);
-
- RemoteGDB *rgdb = new RemoteGDB(system, tc);
- GDBListener *gdbl = new GDBListener(rgdb, 7000 + myIndex);
- gdbl->listen();
- //gdbl->accept();
-
- remoteGDB.push_back(rgdb);
-
- // return CPU number to caller
- return myIndex;
+ int size = contextIds.size();
+ ThreadContext *tc;
+ for (int i = 0; i < size; ++i) {
+ tc = system->getThreadContext(contextIds[i]);
+ if (tc->status() == ThreadContext::Unallocated) {
+ // inactive context, free to use
+ return tc;
+ }
+ }
+ return NULL;
}
void
Process::startup()
{
- if (threadContexts.empty())
- fatal("Process %s is not associated with any CPUs!\n", name());
+ if (contextIds.empty())
+ fatal("Process %s is not associated with any HW contexts!\n", name());
// first thread context for this process... initialize & enable
- ThreadContext *tc = threadContexts[0];
+ ThreadContext *tc = system->getThreadContext(contextIds[0]);
// mark this context as active so it will start ticking.
tc->activate(0);
@@ -232,17 +249,6 @@ Process::startup()
initVirtMem->setPeer(mem_port);
}
-void
-Process::replaceThreadContext(ThreadContext *tc, int tcIndex)
-{
- if (tcIndex >= threadContexts.size()) {
- panic("replaceThreadContext: bad tcIndex, %d >= %d\n",
- tcIndex, threadContexts.size());
- }
-
- threadContexts[tcIndex] = tc;
-}
-
// map simulator fd sim_fd to target fd tgt_fd
void
Process::dup_fd(int sim_fd, int tgt_fd)
@@ -337,7 +343,7 @@ Process::checkAndAllocNextPage(Addr vaddr)
if(stack_base - stack_min > 8*1024*1024)
fatal("Over max stack size for one thread\n");
pTable->allocate(stack_min, TheISA::PageBytes);
- warn("Increasing stack size by one page.");
+ inform("Increasing stack size by one page.");
};
return true;
}
@@ -352,6 +358,7 @@ Process::fix_file_offsets() {
Process::FdMap *fdo_stderr = &fd_map[STDERR_FILENO];
string in = fdo_stdin->filename;
string out = fdo_stdout->filename;
+ string err = fdo_stderr->filename;
// initialize file descriptors to default: same as simulator
int stdin_fd, stdout_fd, stderr_fd;
@@ -375,11 +382,23 @@ Process::fix_file_offsets() {
stdout_fd = -1;
else{
stdout_fd = Process::openOutputFile(out);
- if (lseek(stdin_fd, fdo_stdout->fileOffset, SEEK_SET) < 0)
- panic("Unable to seek to correct in file: %s", out);
+ if (lseek(stdout_fd, fdo_stdout->fileOffset, SEEK_SET) < 0)
+ panic("Unable to seek to correct location in file: %s", out);
}
- stderr_fd = (stdout_fd != STDOUT_FILENO) ? stdout_fd : STDERR_FILENO;
+ if (err == "stdout" || err == "cout")
+ stderr_fd = STDOUT_FILENO;
+ else if (err == "stderr" || err == "cerr")
+ stderr_fd = STDERR_FILENO;
+ else if (err == "None")
+ stderr_fd = -1;
+ else if (err == out)
+ stderr_fd = stdout_fd;
+ else {
+ stderr_fd = Process::openOutputFile(err);
+ if (lseek(stderr_fd, fdo_stderr->fileOffset, SEEK_SET) < 0)
+ panic("Unable to seek to correct location in file: %s", err);
+ }
fdo_stdin->fd = stdin_fd;
fdo_stdout->fd = stdout_fd;
@@ -597,17 +616,18 @@ LiveProcess::argsInit(int intSize, int pageSize)
copyStringArray(argv, argv_array_base, arg_data_base, initVirtMem);
copyStringArray(envp, envp_array_base, env_data_base, initVirtMem);
- assert(NumArgumentRegs >= 2);
- threadContexts[0]->setIntReg(ArgumentReg[0], argc);
- threadContexts[0]->setIntReg(ArgumentReg[1], argv_array_base);
- threadContexts[0]->setIntReg(StackPointerReg, stack_min);
+ ThreadContext *tc = system->getThreadContext(contextIds[0]);
+
+ setSyscallArg(tc, 0, argc);
+ setSyscallArg(tc, 1, argv_array_base);
+ tc->setIntReg(StackPointerReg, stack_min);
Addr prog_entry = objFile->entryPoint();
- threadContexts[0]->setPC(prog_entry);
- threadContexts[0]->setNextPC(prog_entry + sizeof(MachInst));
+ tc->setPC(prog_entry);
+ tc->setNextPC(prog_entry + sizeof(MachInst));
#if THE_ISA != ALPHA_ISA //e.g. MIPS or Sparc
- threadContexts[0]->setNextNPC(prog_entry + (2 * sizeof(MachInst)));
+ tc->setNextNPC(prog_entry + (2 * sizeof(MachInst)));
#endif
num_processes++;
@@ -643,18 +663,17 @@ LiveProcess::create(LiveProcessParams * params)
"executable as a static binary and try again.\n");
#if THE_ISA == ALPHA_ISA
- if (objFile->hasTLS())
- fatal("Object file has a TLS section and single threaded TLS is not\n"
- " currently supported for Alpha! Please recompile your "
- "executable with \n a non-TLS toolchain.\n");
-
if (objFile->getArch() != ObjectFile::Alpha)
fatal("Object file architecture does not match compiled ISA (Alpha).");
+
switch (objFile->getOpSys()) {
case ObjectFile::Tru64:
process = new AlphaTru64Process(params, objFile);
break;
+ case ObjectFile::UnknownOpSys:
+ warn("Unknown operating system; assuming Linux.");
+ // fall through
case ObjectFile::Linux:
process = new AlphaLinuxProcess(params, objFile);
break;
@@ -663,9 +682,13 @@ LiveProcess::create(LiveProcessParams * params)
fatal("Unknown/unsupported operating system.");
}
#elif THE_ISA == SPARC_ISA
- if (objFile->getArch() != ObjectFile::SPARC64 && objFile->getArch() != ObjectFile::SPARC32)
+ if (objFile->getArch() != ObjectFile::SPARC64 &&
+ objFile->getArch() != ObjectFile::SPARC32)
fatal("Object file architecture does not match compiled ISA (SPARC).");
switch (objFile->getOpSys()) {
+ case ObjectFile::UnknownOpSys:
+ warn("Unknown operating system; assuming Linux.");
+ // fall through
case ObjectFile::Linux:
if (objFile->getArch() == ObjectFile::SPARC64) {
process = new Sparc64LinuxProcess(params, objFile);
@@ -678,16 +701,26 @@ LiveProcess::create(LiveProcessParams * params)
case ObjectFile::Solaris:
process = new SparcSolarisProcess(params, objFile);
break;
+
default:
fatal("Unknown/unsupported operating system.");
}
#elif THE_ISA == X86_ISA
- if (objFile->getArch() != ObjectFile::X86)
+ if (objFile->getArch() != ObjectFile::X86_64 &&
+ objFile->getArch() != ObjectFile::I386)
fatal("Object file architecture does not match compiled ISA (x86).");
switch (objFile->getOpSys()) {
+ case ObjectFile::UnknownOpSys:
+ warn("Unknown operating system; assuming Linux.");
+ // fall through
case ObjectFile::Linux:
- process = new X86LinuxProcess(params, objFile);
+ if (objFile->getArch() == ObjectFile::X86_64) {
+ process = new X86_64LinuxProcess(params, objFile);
+ } else {
+ process = new I386LinuxProcess(params, objFile);
+ }
break;
+
default:
fatal("Unknown/unsupported operating system.");
}
@@ -695,6 +728,9 @@ LiveProcess::create(LiveProcessParams * params)
if (objFile->getArch() != ObjectFile::Mips)
fatal("Object file architecture does not match compiled ISA (MIPS).");
switch (objFile->getOpSys()) {
+ case ObjectFile::UnknownOpSys:
+ warn("Unknown operating system; assuming Linux.");
+ // fall through
case ObjectFile::Linux:
process = new MipsLinuxProcess(params, objFile);
break;
@@ -706,6 +742,9 @@ LiveProcess::create(LiveProcessParams * params)
if (objFile->getArch() != ObjectFile::Arm)
fatal("Object file architecture does not match compiled ISA (ARM).");
switch (objFile->getOpSys()) {
+ case ObjectFile::UnknownOpSys:
+ warn("Unknown operating system; assuming Linux.");
+ // fall through
case ObjectFile::Linux:
process = new ArmLinuxProcess(params, objFile);
break;
diff --git a/src/sim/process.hh b/src/sim/process.hh
index 29d6e5aae..527209467 100644
--- a/src/sim/process.hh
+++ b/src/sim/process.hh
@@ -44,9 +44,11 @@
#include <string>
#include <vector>
+#include "arch/types.hh"
#include "base/statistics.hh"
#include "sim/host.hh"
#include "sim/sim_object.hh"
+#include "sim/syscallreturn.hh"
class GDBListener;
class PageTable;
@@ -61,6 +63,18 @@ namespace TheISA
class RemoteGDB;
}
+template<class IntType>
+struct AuxVector
+{
+ IntType a_type;
+ IntType a_val;
+
+ AuxVector()
+ {}
+
+ AuxVector(IntType type, IntType val);
+};
+
class Process : public SimObject
{
public:
@@ -77,7 +91,7 @@ class Process : public SimObject
bool checkpointRestored;
// thread contexts associated with this process
- std::vector<ThreadContext *> threadContexts;
+ std::vector<int> contextIds;
// remote gdb objects
std::vector<TheISA::RemoteGDB *> remoteGDB;
@@ -85,7 +99,7 @@ class Process : public SimObject
bool breakpoint();
// number of CPUs (esxec contexts, really) assigned to this process.
- unsigned int numCpus() { return threadContexts.size(); }
+ unsigned int numCpus() { return contextIds.size(); }
// record of blocked context
struct WaitRec
@@ -95,17 +109,17 @@ class Process : public SimObject
WaitRec(Addr chan, ThreadContext *ctx)
: waitChan(chan), waitingContext(ctx)
- { }
+ { }
};
// list of all blocked contexts
std::list<WaitRec> waitList;
- Addr brk_point; // top of the data segment
+ Addr brk_point; // top of the data segment
- Addr stack_base; // stack segment base (highest address)
- unsigned stack_size; // initial stack size
- Addr stack_min; // lowest address accessed on the stack
+ Addr stack_base; // stack segment base (highest address)
+ unsigned stack_size; // initial stack size
+ Addr stack_min; // lowest address accessed on the stack
// The maximum size allowed for the stack.
Addr max_stack_size;
@@ -121,9 +135,9 @@ class Process : public SimObject
Addr nxm_start;
Addr nxm_end;
- std::string prog_fname; // file name
+ std::string prog_fname; // file name
- Stats::Scalar<> num_syscalls; // number of syscalls executed
+ Stats::Scalar num_syscalls; // number of syscalls executed
protected:
@@ -187,12 +201,15 @@ class Process : public SimObject
// override of virtual SimObject method: register statistics
virtual void regStats();
- // register a thread context for this process.
- // returns tc's cpu number (index into threadContexts[])
- int registerThreadContext(ThreadContext *tc);
-
+ // After getting registered with system object, tell process which
+ // system-wide context id it is assigned.
+ void assignThreadContext(int context_id)
+ {
+ contextIds.push_back(context_id);
+ }
- void replaceThreadContext(ThreadContext *tc, int tcIndex);
+ // Find a free context to use
+ ThreadContext * findFreeContext();
// map simulator fd sim_fd to target fd tgt_fd
void dup_fd(int sim_fd, int tgt_fd);
@@ -303,7 +320,14 @@ class LiveProcess : public Process
return full + filename;
}
+ std::string getcwd() const { return cwd; }
+
virtual void syscall(int64_t callnum, ThreadContext *tc);
+ virtual TheISA::IntReg getSyscallArg(ThreadContext *tc, int i) = 0;
+ virtual void setSyscallArg(ThreadContext *tc,
+ int i, TheISA::IntReg val) = 0;
+ virtual void setSyscallReturn(ThreadContext *tc,
+ SyscallReturn return_value) = 0;
virtual SyscallDesc* getDesc(int callnum) = 0;
diff --git a/src/sim/pseudo_inst.cc b/src/sim/pseudo_inst.cc
index 157d39e93..3c2a27f54 100644
--- a/src/sim/pseudo_inst.cc
+++ b/src/sim/pseudo_inst.cc
@@ -35,275 +35,291 @@
#include <fstream>
#include <string>
+#include "arch/kernel_stats.hh"
#include "arch/vtophys.hh"
-#include "base/annotate.hh"
+#include "base/debug.hh"
#include "cpu/base.hh"
#include "cpu/thread_context.hh"
#include "cpu/quiesce_event.hh"
-#include "arch/kernel_stats.hh"
+#include "params/BaseCPU.hh"
#include "sim/pseudo_inst.hh"
#include "sim/serialize.hh"
+#include "sim/sim_events.hh"
#include "sim/sim_exit.hh"
#include "sim/stat_control.hh"
#include "sim/stats.hh"
#include "sim/system.hh"
-#include "sim/debug.hh"
+#if FULL_SYSTEM
#include "sim/vptr.hh"
+#endif
using namespace std;
using namespace Stats;
using namespace TheISA;
-namespace PseudoInst
+namespace PseudoInst {
+
+#if FULL_SYSTEM
+
+void
+arm(ThreadContext *tc)
{
- void
- arm(ThreadContext *tc)
- {
- if (tc->getKernelStats())
- tc->getKernelStats()->arm();
- }
+ if (tc->getKernelStats())
+ tc->getKernelStats()->arm();
+}
- void
- quiesce(ThreadContext *tc)
- {
- if (!tc->getCpuPtr()->params->do_quiesce)
- return;
+void
+quiesce(ThreadContext *tc)
+{
+ if (!tc->getCpuPtr()->params()->do_quiesce)
+ return;
- DPRINTF(Quiesce, "%s: quiesce()\n", tc->getCpuPtr()->name());
+ DPRINTF(Quiesce, "%s: quiesce()\n", tc->getCpuPtr()->name());
- tc->suspend();
- if (tc->getKernelStats())
- tc->getKernelStats()->quiesce();
- }
+ tc->suspend();
+ if (tc->getKernelStats())
+ tc->getKernelStats()->quiesce();
+}
- void
- quiesceNs(ThreadContext *tc, uint64_t ns)
- {
- if (!tc->getCpuPtr()->params->do_quiesce || ns == 0)
- return;
+void
+quiesceNs(ThreadContext *tc, uint64_t ns)
+{
+ if (!tc->getCpuPtr()->params()->do_quiesce || ns == 0)
+ return;
- EndQuiesceEvent *quiesceEvent = tc->getQuiesceEvent();
+ EndQuiesceEvent *quiesceEvent = tc->getQuiesceEvent();
- Tick resume = curTick + Clock::Int::ns * ns;
+ Tick resume = curTick + Clock::Int::ns * ns;
- quiesceEvent->reschedule(resume, true);
+ mainEventQueue.reschedule(quiesceEvent, resume, true);
- DPRINTF(Quiesce, "%s: quiesceNs(%d) until %d\n",
- tc->getCpuPtr()->name(), ns, resume);
+ DPRINTF(Quiesce, "%s: quiesceNs(%d) until %d\n",
+ tc->getCpuPtr()->name(), ns, resume);
- tc->suspend();
- if (tc->getKernelStats())
- tc->getKernelStats()->quiesce();
- }
+ tc->suspend();
+ if (tc->getKernelStats())
+ tc->getKernelStats()->quiesce();
+}
- void
- quiesceCycles(ThreadContext *tc, uint64_t cycles)
- {
- if (!tc->getCpuPtr()->params->do_quiesce || cycles == 0)
- return;
+void
+quiesceCycles(ThreadContext *tc, uint64_t cycles)
+{
+ if (!tc->getCpuPtr()->params()->do_quiesce || cycles == 0)
+ return;
- EndQuiesceEvent *quiesceEvent = tc->getQuiesceEvent();
+ EndQuiesceEvent *quiesceEvent = tc->getQuiesceEvent();
- Tick resume = curTick + tc->getCpuPtr()->ticks(cycles);
+ Tick resume = curTick + tc->getCpuPtr()->ticks(cycles);
- quiesceEvent->reschedule(resume, true);
+ mainEventQueue.reschedule(quiesceEvent, resume, true);
- DPRINTF(Quiesce, "%s: quiesceCycles(%d) until %d\n",
- tc->getCpuPtr()->name(), cycles, resume);
+ DPRINTF(Quiesce, "%s: quiesceCycles(%d) until %d\n",
+ tc->getCpuPtr()->name(), cycles, resume);
- tc->suspend();
- if (tc->getKernelStats())
- tc->getKernelStats()->quiesce();
- }
+ tc->suspend();
+ if (tc->getKernelStats())
+ tc->getKernelStats()->quiesce();
+}
- uint64_t
- quiesceTime(ThreadContext *tc)
- {
- return (tc->readLastActivate() - tc->readLastSuspend()) / Clock::Int::ns;
- }
+uint64_t
+quiesceTime(ThreadContext *tc)
+{
+ return (tc->readLastActivate() - tc->readLastSuspend()) / Clock::Int::ns;
+}
- void
- m5exit_old(ThreadContext *tc)
- {
- exitSimLoop("m5_exit_old instruction encountered");
- }
+#endif
- void
- m5exit(ThreadContext *tc, Tick delay)
- {
- Tick when = curTick + delay * Clock::Int::ns;
- schedExitSimLoop("m5_exit instruction encountered", when);
- }
+uint64_t
+rpns(ThreadContext *tc)
+{
+ return curTick / Clock::Int::ns;
+}
+
+void
+wakeCPU(ThreadContext *tc, uint64_t cpuid)
+{
+ System *sys = tc->getSystemPtr();
+ ThreadContext *other_tc = sys->threadContexts[cpuid];
+ if (other_tc->status() == ThreadContext::Suspended)
+ other_tc->activate();
+}
- void
- loadsymbol(ThreadContext *tc)
- {
- const string &filename = tc->getCpuPtr()->system->params()->symbolfile;
- if (filename.empty()) {
- return;
- }
+void
+m5exit(ThreadContext *tc, Tick delay)
+{
+ Tick when = curTick + delay * Clock::Int::ns;
+ Event *event = new SimLoopExitEvent("m5_exit instruction encountered", 0);
+ mainEventQueue.schedule(event, when);
+}
+
+#if FULL_SYSTEM
+
+void
+loadsymbol(ThreadContext *tc)
+{
+ const string &filename = tc->getCpuPtr()->system->params()->symbolfile;
+ if (filename.empty()) {
+ return;
+ }
- std::string buffer;
- ifstream file(filename.c_str());
+ std::string buffer;
+ ifstream file(filename.c_str());
- if (!file)
- fatal("file error: Can't open symbol table file %s\n", filename);
+ if (!file)
+ fatal("file error: Can't open symbol table file %s\n", filename);
- while (!file.eof()) {
- getline(file, buffer);
+ while (!file.eof()) {
+ getline(file, buffer);
- if (buffer.empty())
- continue;
+ if (buffer.empty())
+ continue;
- int idx = buffer.find(' ');
- if (idx == string::npos)
- continue;
+ int idx = buffer.find(' ');
+ if (idx == string::npos)
+ continue;
- string address = "0x" + buffer.substr(0, idx);
- eat_white(address);
- if (address.empty())
- continue;
+ string address = "0x" + buffer.substr(0, idx);
+ eat_white(address);
+ if (address.empty())
+ continue;
- // Skip over letter and space
- string symbol = buffer.substr(idx + 3);
- eat_white(symbol);
- if (symbol.empty())
- continue;
+ // Skip over letter and space
+ string symbol = buffer.substr(idx + 3);
+ eat_white(symbol);
+ if (symbol.empty())
+ continue;
- Addr addr;
- if (!to_number(address, addr))
- continue;
+ Addr addr;
+ if (!to_number(address, addr))
+ continue;
- if (!tc->getSystemPtr()->kernelSymtab->insert(addr, symbol))
- continue;
+ if (!tc->getSystemPtr()->kernelSymtab->insert(addr, symbol))
+ continue;
- DPRINTF(Loader, "Loaded symbol: %s @ %#llx\n", symbol, addr);
- }
- file.close();
+ DPRINTF(Loader, "Loaded symbol: %s @ %#llx\n", symbol, addr);
}
+ file.close();
+}
- void
- resetstats(ThreadContext *tc, Tick delay, Tick period)
- {
- if (!tc->getCpuPtr()->params->do_statistics_insts)
- return;
+void
+addsymbol(ThreadContext *tc, Addr addr, Addr symbolAddr)
+{
+ char symb[100];
+ CopyStringOut(tc, symb, symbolAddr, 100);
+ std::string symbol(symb);
+ DPRINTF(Loader, "Loaded symbol: %s @ %#llx\n", symbol, addr);
- Tick when = curTick + delay * Clock::Int::ns;
- Tick repeat = period * Clock::Int::ns;
+ tc->getSystemPtr()->kernelSymtab->insert(addr,symbol);
+ debugSymbolTable->insert(addr,symbol);
+}
- Stats::StatEvent(false, true, when, repeat);
- }
+#endif
- void
- dumpstats(ThreadContext *tc, Tick delay, Tick period)
- {
- if (!tc->getCpuPtr()->params->do_statistics_insts)
- return;
+void
+resetstats(ThreadContext *tc, Tick delay, Tick period)
+{
+ if (!tc->getCpuPtr()->params()->do_statistics_insts)
+ return;
- Tick when = curTick + delay * Clock::Int::ns;
- Tick repeat = period * Clock::Int::ns;
- Stats::StatEvent(true, false, when, repeat);
- }
+ Tick when = curTick + delay * Clock::Int::ns;
+ Tick repeat = period * Clock::Int::ns;
- void
- addsymbol(ThreadContext *tc, Addr addr, Addr symbolAddr)
- {
- char symb[100];
- CopyStringOut(tc, symb, symbolAddr, 100);
- std::string symbol(symb);
+ Stats::StatEvent(false, true, when, repeat);
+}
- DPRINTF(Loader, "Loaded symbol: %s @ %#llx\n", symbol, addr);
+void
+dumpstats(ThreadContext *tc, Tick delay, Tick period)
+{
+ if (!tc->getCpuPtr()->params()->do_statistics_insts)
+ return;
- tc->getSystemPtr()->kernelSymtab->insert(addr,symbol);
- }
- void
- anBegin(ThreadContext *tc, uint64_t cur)
- {
- Annotate::annotations.add(tc->getSystemPtr(), 0, cur >> 32, cur &
- 0xFFFFFFFF, 0,0);
- }
+ Tick when = curTick + delay * Clock::Int::ns;
+ Tick repeat = period * Clock::Int::ns;
- void
- anWait(ThreadContext *tc, uint64_t cur, uint64_t wait)
- {
- Annotate::annotations.add(tc->getSystemPtr(), 0, cur >> 32, cur &
- 0xFFFFFFFF, wait >> 32, wait & 0xFFFFFFFF);
- }
+ Stats::StatEvent(true, false, when, repeat);
+}
+void
+dumpresetstats(ThreadContext *tc, Tick delay, Tick period)
+{
+ if (!tc->getCpuPtr()->params()->do_statistics_insts)
+ return;
- void
- dumpresetstats(ThreadContext *tc, Tick delay, Tick period)
- {
- if (!tc->getCpuPtr()->params->do_statistics_insts)
- return;
+ Tick when = curTick + delay * Clock::Int::ns;
+ Tick repeat = period * Clock::Int::ns;
- Tick when = curTick + delay * Clock::Int::ns;
- Tick repeat = period * Clock::Int::ns;
+ Stats::StatEvent(true, true, when, repeat);
+}
- Stats::StatEvent(true, true, when, repeat);
- }
+void
+m5checkpoint(ThreadContext *tc, Tick delay, Tick period)
+{
+ if (!tc->getCpuPtr()->params()->do_checkpoint_insts)
+ return;
- void
- m5checkpoint(ThreadContext *tc, Tick delay, Tick period)
- {
- if (!tc->getCpuPtr()->params->do_checkpoint_insts)
- return;
+ Tick when = curTick + delay * Clock::Int::ns;
+ Tick repeat = period * Clock::Int::ns;
- Tick when = curTick + delay * Clock::Int::ns;
- Tick repeat = period * Clock::Int::ns;
+ Event *event = new SimLoopExitEvent("checkpoint", 0, repeat);
+ mainEventQueue.schedule(event, when);
+}
- schedExitSimLoop("checkpoint", when, repeat);
- }
+#if FULL_SYSTEM
- uint64_t
- readfile(ThreadContext *tc, Addr vaddr, uint64_t len, uint64_t offset)
- {
- const string &file = tc->getSystemPtr()->params()->readfile;
- if (file.empty()) {
- return ULL(0);
- }
-
- uint64_t result = 0;
-
- int fd = ::open(file.c_str(), O_RDONLY, 0);
- if (fd < 0)
- panic("could not open file %s\n", file);
-
- if (::lseek(fd, offset, SEEK_SET) < 0)
- panic("could not seek: %s", strerror(errno));
-
- char *buf = new char[len];
- char *p = buf;
- while (len > 0) {
- int bytes = ::read(fd, p, len);
- if (bytes <= 0)
- break;
-
- p += bytes;
- result += bytes;
- len -= bytes;
- }
-
- close(fd);
- CopyIn(tc, vaddr, buf, result);
- delete [] buf;
- return result;
+uint64_t
+readfile(ThreadContext *tc, Addr vaddr, uint64_t len, uint64_t offset)
+{
+ const string &file = tc->getSystemPtr()->params()->readfile;
+ if (file.empty()) {
+ return ULL(0);
}
- void debugbreak(ThreadContext *tc)
- {
- debug_break();
- }
+ uint64_t result = 0;
- void switchcpu(ThreadContext *tc)
- {
- exitSimLoop("switchcpu");
+ int fd = ::open(file.c_str(), O_RDONLY, 0);
+ if (fd < 0)
+ panic("could not open file %s\n", file);
+
+ if (::lseek(fd, offset, SEEK_SET) < 0)
+ panic("could not seek: %s", strerror(errno));
+
+ char *buf = new char[len];
+ char *p = buf;
+ while (len > 0) {
+ int bytes = ::read(fd, p, len);
+ if (bytes <= 0)
+ break;
+
+ p += bytes;
+ result += bytes;
+ len -= bytes;
}
+
+ close(fd);
+ CopyIn(tc, vaddr, buf, result);
+ delete [] buf;
+ return result;
}
+
+#endif
+
+void
+debugbreak(ThreadContext *tc)
+{
+ debug_break();
+}
+
+void
+switchcpu(ThreadContext *tc)
+{
+ exitSimLoop("switchcpu");
+}
+
+/* namespace PseudoInst */ }
diff --git a/src/sim/pseudo_inst.hh b/src/sim/pseudo_inst.hh
index 93021abad..30996fc3b 100644
--- a/src/sim/pseudo_inst.hh
+++ b/src/sim/pseudo_inst.hh
@@ -33,31 +33,35 @@ class ThreadContext;
//We need the "Tick" and "Addr" data types from here
#include "sim/host.hh"
-namespace PseudoInst
-{
- /**
- * @todo these externs are only here for a hack in fullCPU::takeOver...
- */
- extern bool doStatisticsInsts;
- extern bool doCheckpointInsts;
- extern bool doQuiesce;
+namespace PseudoInst {
- void arm(ThreadContext *tc);
- void quiesce(ThreadContext *tc);
- void quiesceNs(ThreadContext *tc, uint64_t ns);
- void quiesceCycles(ThreadContext *tc, uint64_t cycles);
- uint64_t quiesceTime(ThreadContext *tc);
- void m5exit(ThreadContext *tc, Tick delay);
- void m5exit_old(ThreadContext *tc);
- void loadsymbol(ThreadContext *xc);
- void resetstats(ThreadContext *tc, Tick delay, Tick period);
- void dumpstats(ThreadContext *tc, Tick delay, Tick period);
- void dumpresetstats(ThreadContext *tc, Tick delay, Tick period);
- void m5checkpoint(ThreadContext *tc, Tick delay, Tick period);
- uint64_t readfile(ThreadContext *tc, Addr vaddr, uint64_t len, uint64_t offset);
- void debugbreak(ThreadContext *tc);
- void switchcpu(ThreadContext *tc);
- void addsymbol(ThreadContext *tc, Addr addr, Addr symbolAddr);
- void anBegin(ThreadContext *tc, uint64_t cur);
- void anWait(ThreadContext *tc, uint64_t cur, uint64_t wait);
-}
+/**
+ * @todo these externs are only here for a hack in fullCPU::takeOver...
+ */
+extern bool doStatisticsInsts;
+extern bool doCheckpointInsts;
+extern bool doQuiesce;
+
+#if FULL_SYSTEM
+void arm(ThreadContext *tc);
+void quiesce(ThreadContext *tc);
+void quiesceNs(ThreadContext *tc, uint64_t ns);
+void quiesceCycles(ThreadContext *tc, uint64_t cycles);
+uint64_t quiesceTime(ThreadContext *tc);
+uint64_t readfile(ThreadContext *tc, Addr vaddr, uint64_t len,
+ uint64_t offset);
+void loadsymbol(ThreadContext *xc);
+void addsymbol(ThreadContext *tc, Addr addr, Addr symbolAddr);
+#endif
+
+uint64_t rpns(ThreadContext *tc);
+void wakeCPU(ThreadContext *tc, uint64_t cpuid);
+void m5exit(ThreadContext *tc, Tick delay);
+void resetstats(ThreadContext *tc, Tick delay, Tick period);
+void dumpstats(ThreadContext *tc, Tick delay, Tick period);
+void dumpresetstats(ThreadContext *tc, Tick delay, Tick period);
+void m5checkpoint(ThreadContext *tc, Tick delay, Tick period);
+void debugbreak(ThreadContext *tc);
+void switchcpu(ThreadContext *tc);
+
+/* namespace PseudoInst */ }
diff --git a/src/sim/serialize.cc b/src/sim/serialize.cc
index a0d17f489..481b9af3b 100644
--- a/src/sim/serialize.cc
+++ b/src/sim/serialize.cc
@@ -321,23 +321,23 @@ objParamIn(Checkpoint *cp, const std::string &section,
}
-#define INSTANTIATE_PARAM_TEMPLATES(type) \
-template void \
-paramOut(ostream &os, const std::string &name, type const &param); \
-template void \
-paramIn(Checkpoint *cp, const std::string &section, \
- const std::string &name, type & param); \
-template void \
-arrayParamOut(ostream &os, const std::string &name, \
- type const *param, int size); \
-template void \
-arrayParamIn(Checkpoint *cp, const std::string &section, \
+#define INSTANTIATE_PARAM_TEMPLATES(type) \
+template void \
+paramOut(ostream &os, const std::string &name, type const &param); \
+template void \
+paramIn(Checkpoint *cp, const std::string &section, \
+ const std::string &name, type & param); \
+template void \
+arrayParamOut(ostream &os, const std::string &name, \
+ type const *param, int size); \
+template void \
+arrayParamIn(Checkpoint *cp, const std::string &section, \
const std::string &name, type *param, int size); \
-template void \
-arrayParamOut(ostream &os, const std::string &name, \
- const std::vector<type> &param); \
-template void \
-arrayParamIn(Checkpoint *cp, const std::string &section, \
+template void \
+arrayParamOut(ostream &os, const std::string &name, \
+ const std::vector<type> &param); \
+template void \
+arrayParamIn(Checkpoint *cp, const std::string &section, \
const std::string &name, std::vector<type> &param);
INSTANTIATE_PARAM_TEMPLATES(signed char)
@@ -351,6 +351,8 @@ INSTANTIATE_PARAM_TEMPLATES(unsigned long)
INSTANTIATE_PARAM_TEMPLATES(signed long long)
INSTANTIATE_PARAM_TEMPLATES(unsigned long long)
INSTANTIATE_PARAM_TEMPLATES(bool)
+INSTANTIATE_PARAM_TEMPLATES(float)
+INSTANTIATE_PARAM_TEMPLATES(double)
INSTANTIATE_PARAM_TEMPLATES(string)
@@ -394,6 +396,24 @@ Globals::unserialize(Checkpoint *cp)
mainEventQueue.unserialize(cp, "MainEventQueue");
}
+Serializable::Serializable()
+{
+}
+
+Serializable::~Serializable()
+{
+}
+
+void
+Serializable::serialize(std::ostream &os)
+{
+}
+
+void
+Serializable::unserialize(Checkpoint *cp, const std::string &section)
+{
+}
+
void
Serializable::serializeAll(const std::string &cpt_dir)
{
@@ -405,6 +425,8 @@ Serializable::serializeAll(const std::string &cpt_dir)
string cpt_file = dir + Checkpoint::baseFilename;
ofstream outstream(cpt_file.c_str());
time_t t = time(NULL);
+ if (!outstream.is_open())
+ fatal("Unable to open file %s for writing\n", cpt_file.c_str());
outstream << "// checkpoint generated: " << ctime(&t);
globals.serialize(outstream);
diff --git a/src/sim/serialize.hh b/src/sim/serialize.hh
index e72eedb30..c33633065 100644
--- a/src/sim/serialize.hh
+++ b/src/sim/serialize.hh
@@ -82,33 +82,33 @@ objParamIn(Checkpoint *cp, const std::string &section,
// These macros are streamlined to use in serialize/unserialize
// functions. It's assumed that serialize() has a parameter 'os' for
// the ostream, and unserialize() has parameters 'cp' and 'section'.
-#define SERIALIZE_SCALAR(scalar) paramOut(os, #scalar, scalar)
+#define SERIALIZE_SCALAR(scalar) paramOut(os, #scalar, scalar)
-#define UNSERIALIZE_SCALAR(scalar) paramIn(cp, section, #scalar, scalar)
+#define UNSERIALIZE_SCALAR(scalar) paramIn(cp, section, #scalar, scalar)
// ENUMs are like SCALARs, but we cast them to ints on the way out
-#define SERIALIZE_ENUM(scalar) paramOut(os, #scalar, (int)scalar)
+#define SERIALIZE_ENUM(scalar) paramOut(os, #scalar, (int)scalar)
-#define UNSERIALIZE_ENUM(scalar) \
- do { \
- int tmp; \
- paramIn(cp, section, #scalar, tmp); \
- scalar = (typeof(scalar))tmp; \
+#define UNSERIALIZE_ENUM(scalar) \
+ do { \
+ int tmp; \
+ paramIn(cp, section, #scalar, tmp); \
+ scalar = (typeof(scalar))tmp; \
} while (0)
-#define SERIALIZE_ARRAY(member, size) \
+#define SERIALIZE_ARRAY(member, size) \
arrayParamOut(os, #member, member, size)
-#define UNSERIALIZE_ARRAY(member, size) \
+#define UNSERIALIZE_ARRAY(member, size) \
arrayParamIn(cp, section, #member, member, size)
-#define SERIALIZE_OBJPTR(objptr) paramOut(os, #objptr, (objptr)->name())
+#define SERIALIZE_OBJPTR(objptr) paramOut(os, #objptr, (objptr)->name())
-#define UNSERIALIZE_OBJPTR(objptr) \
- do { \
- SimObject *sptr; \
- objParamIn(cp, section, #objptr, sptr); \
- objptr = dynamic_cast<typeof(objptr)>(sptr); \
+#define UNSERIALIZE_OBJPTR(objptr) \
+ do { \
+ SimObject *sptr; \
+ objParamIn(cp, section, #objptr, sptr); \
+ objptr = dynamic_cast<typeof(objptr)>(sptr); \
} while (0)
/*
@@ -121,17 +121,16 @@ class Serializable
void nameOut(std::ostream &os, const std::string &_name);
public:
- Serializable() {}
- virtual ~Serializable() {}
+ Serializable();
+ virtual ~Serializable();
// manditory virtual function, so objects must provide names
virtual const std::string name() const = 0;
- virtual void serialize(std::ostream &os) {}
- virtual void unserialize(Checkpoint *cp, const std::string &section) {}
+ virtual void serialize(std::ostream &os);
+ virtual void unserialize(Checkpoint *cp, const std::string &section);
- static Serializable *create(Checkpoint *cp,
- const std::string &section);
+ static Serializable *create(Checkpoint *cp, const std::string &section);
static int ckptCount;
static int ckptMaxCount;
@@ -211,8 +210,8 @@ class SerializableClass
// SerializableBuilder and SerializableClass objects
//
-#define REGISTER_SERIALIZEABLE(CLASS_NAME, OBJ_CLASS) \
-SerializableClass the##OBJ_CLASS##Class(CLASS_NAME, \
+#define REGISTER_SERIALIZEABLE(CLASS_NAME, OBJ_CLASS) \
+SerializableClass the##OBJ_CLASS##Class(CLASS_NAME, \
OBJ_CLASS::createForUnserialize);
void
diff --git a/src/sim/sim_events.cc b/src/sim/sim_events.cc
index 09087ef84..a6e3f0af3 100644
--- a/src/sim/sim_events.cc
+++ b/src/sim/sim_events.cc
@@ -40,6 +40,13 @@
using namespace std;
+SimLoopExitEvent::SimLoopExitEvent(const std::string &_cause, int c, Tick r)
+ : Event(Sim_Exit_Pri), cause(_cause), code(c), repeat(r)
+{
+ setFlags(IsExitEvent);
+}
+
+
//
// handle termination event
//
@@ -49,7 +56,7 @@ SimLoopExitEvent::process()
// if this got scheduled on a different queue (e.g. the committed
// instruction queue) then make a corresponding event on the main
// queue.
- if (theQueue() != &mainEventQueue) {
+ if (!getFlags(IsMainQueue)) {
exitSimLoop(cause, code);
delete this;
}
@@ -59,7 +66,8 @@ SimLoopExitEvent::process()
// but if you are doing this on intervals, don't forget to make another
if (repeat) {
- schedule(curTick + repeat);
+ assert(getFlags(IsMainQueue));
+ mainEventQueue.schedule(this, curTick + repeat);
}
}
@@ -70,43 +78,32 @@ SimLoopExitEvent::description() const
return "simulation loop exit";
}
-SimLoopExitEvent *
-schedExitSimLoop(const std::string &message, Tick when, Tick repeat,
- EventQueue *q, int exit_code)
-{
- if (q == NULL)
- q = &mainEventQueue;
-
- return new SimLoopExitEvent(q, when, repeat, message, exit_code);
-}
-
void
exitSimLoop(const std::string &message, int exit_code)
{
- schedExitSimLoop(message, curTick, 0, NULL, exit_code);
+ Event *event = new SimLoopExitEvent(message, exit_code);
+ mainEventQueue.schedule(event, curTick);
}
+CountedDrainEvent::CountedDrainEvent()
+ : SimLoopExitEvent("Finished drain", 0), count(0)
+{ }
+
void
CountedDrainEvent::process()
{
- if (--count == 0) {
- exitSimLoop("Finished drain");
- }
+ if (--count == 0)
+ exitSimLoop(cause, code);
}
//
// constructor: automatically schedules at specified time
//
-CountedExitEvent::CountedExitEvent(EventQueue *q, const std::string &_cause,
- Tick _when, int &_downCounter)
- : Event(q, Sim_Exit_Pri),
- cause(_cause),
- downCounter(_downCounter)
+CountedExitEvent::CountedExitEvent(const std::string &_cause, int &counter)
+ : Event(Sim_Exit_Pri), cause(_cause), downCounter(counter)
{
// catch stupid mistakes
assert(downCounter > 0);
-
- schedule(_when);
}
@@ -128,9 +125,11 @@ CountedExitEvent::description() const
return "counted exit";
}
-#ifdef CHECK_SWAP_CYCLES
-new CheckSwapEvent(&mainEventQueue, CHECK_SWAP_CYCLES);
-#endif
+CheckSwapEvent::CheckSwapEvent(int ival)
+ : interval(ival)
+{
+ mainEventQueue.schedule(this, curTick + interval);
+}
void
CheckSwapEvent::process()
@@ -149,7 +148,8 @@ CheckSwapEvent::process()
exitSimLoop("Lack of swap space");
}
- schedule(curTick + interval);
+ assert(getFlags(IsMainQueue));
+ mainEventQueue.schedule(this, curTick + interval);
}
const char *
diff --git a/src/sim/sim_events.hh b/src/sim/sim_events.hh
index 58ec963c0..ffd31f385 100644
--- a/src/sim/sim_events.hh
+++ b/src/sim/sim_events.hh
@@ -38,35 +38,19 @@
//
class SimLoopExitEvent : public Event
{
- private:
+ protected:
// string explaining why we're terminating
std::string cause;
int code;
Tick repeat;
public:
- // Default constructor. Only really used for derived classes.
- SimLoopExitEvent()
- : Event(&mainEventQueue, Sim_Exit_Pri)
- { }
-
- SimLoopExitEvent(EventQueue *q,
- Tick _when, Tick _repeat, const std::string &_cause,
- int c = 0)
- : Event(q, Sim_Exit_Pri), cause(_cause),
- code(c), repeat(_repeat)
- { setFlags(IsExitEvent); schedule(_when); }
-
-// SimLoopExitEvent(EventQueue *q,
-// Tick _when, const std::string &_cause,
-// Tick _repeat = 0, int c = 0)
-// : Event(q, Sim_Exit_Pri), cause(_cause), code(c), repeat(_repeat)
-// { setFlags(IsExitEvent); schedule(_when); }
+ SimLoopExitEvent(const std::string &_cause, int c, Tick repeat = 0);
std::string getCause() { return cause; }
int getCode() { return code; }
- void process(); // process event
+ void process(); // process event
virtual const char *description() const;
};
@@ -76,10 +60,10 @@ class CountedDrainEvent : public SimLoopExitEvent
private:
// Count of how many objects have not yet drained
int count;
+
public:
- CountedDrainEvent()
- : count(0)
- { }
+ CountedDrainEvent();
+
void process();
void setCount(int _count) { count = _count; }
@@ -95,14 +79,13 @@ class CountedDrainEvent : public SimLoopExitEvent
class CountedExitEvent : public Event
{
private:
- std::string cause; // string explaining why we're terminating
- int &downCounter; // decrement & terminate if zero
+ std::string cause; // string explaining why we're terminating
+ int &downCounter; // decrement & terminate if zero
public:
- CountedExitEvent(EventQueue *q, const std::string &_cause,
- Tick _when, int &_downCounter);
+ CountedExitEvent(const std::string &_cause, int &_downCounter);
- void process(); // process event
+ void process(); // process event
virtual const char *description() const;
};
@@ -116,11 +99,8 @@ class CheckSwapEvent : public Event
int interval;
public:
- CheckSwapEvent(EventQueue *q, int ival)
- : Event(q), interval(ival)
- { schedule(curTick + interval); }
-
- void process(); // process event
+ CheckSwapEvent(int ival);
+ void process(); // process event
virtual const char *description() const;
};
diff --git a/src/sim/sim_exit.hh b/src/sim/sim_exit.hh
index d4b31d1ea..174b00024 100644
--- a/src/sim/sim_exit.hh
+++ b/src/sim/sim_exit.hh
@@ -46,14 +46,6 @@ class SimLoopExitEvent;
void registerExitCallback(Callback *);
/// Schedule an event to exit the simulation loop (returning to
-/// Python) at the indicated tick. The message and exit_code
-/// parameters are saved in the SimLoopExitEvent to indicate why the
-/// exit occurred.
-SimLoopExitEvent *schedExitSimLoop(const std::string &message, Tick when,
- Tick repeat = 0, EventQueue *q = NULL,
- int exit_code = 0);
-
-/// Schedule an event to exit the simulation loop (returning to
/// Python) at the end of the current cycle (curTick). The message
/// and exit_code parameters are saved in the SimLoopExitEvent to
/// indicate why the exit occurred.
diff --git a/src/sim/sim_object.cc b/src/sim/sim_object.cc
index a835aee5b..dad8f6e8b 100644
--- a/src/sim/sim_object.cc
+++ b/src/sim/sim_object.cc
@@ -59,7 +59,7 @@ SimObject::SimObjectList SimObject::simObjectList;
// SimObject constructor: used to maintain static simObjectList
//
SimObject::SimObject(const Params *p)
- : _params(p)
+ : EventManager(p->eventq), _params(p)
{
#ifdef DEBUG
doDebugBreak = false;
@@ -69,14 +69,6 @@ SimObject::SimObject(const Params *p)
state = Running;
}
-SimObjectParams *
-SimObject::makeParams(const std::string &name)
-{
- SimObjectParams *params = new SimObjectParams;
- params->name = name;
- return params;
-}
-
void
SimObject::init()
{
diff --git a/src/sim/sim_object.hh b/src/sim/sim_object.hh
index ec565ce82..d6d08f255 100644
--- a/src/sim/sim_object.hh
+++ b/src/sim/sim_object.hh
@@ -36,12 +36,14 @@
#ifndef __SIM_OBJECT_HH__
#define __SIM_OBJECT_HH__
-#include <map>
+#include <iostream>
#include <list>
+#include <map>
+#include <string>
#include <vector>
-#include <iostream>
#include "params/SimObject.hh"
+#include "sim/eventq.hh"
#include "sim/serialize.hh"
#include "sim/startup.hh"
@@ -53,7 +55,8 @@ class Event;
* correspond to physical components and can be specified via the
* config file (CPUs, caches, etc.).
*/
-class SimObject : public Serializable, protected StartupCallback
+class SimObject
+ : public EventManager, public Serializable, protected StartupCallback
{
public:
enum State {
@@ -86,10 +89,6 @@ class SimObject : public Serializable, protected StartupCallback
SimObject(const Params *_params);
virtual ~SimObject() {}
- protected:
- // static: support for old-style constructors (call manually)
- static Params *makeParams(const std::string &name);
-
public:
virtual const std::string name() const { return params()->name; }
diff --git a/src/sim/sim_object_params.hh b/src/sim/sim_object_params.hh
new file mode 100644
index 000000000..750181135
--- /dev/null
+++ b/src/sim/sim_object_params.hh
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2001-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: Steve Reinhardt
+ * Nathan Binkert
+ */
+
+#ifndef __SIM_SIM_OBJECT_PARAMS_HH__
+#define __SIM_SIM_OBJECT_PARAMS_HH__
+
+#ifndef PY_VERSION
+struct PyObject;
+#endif
+
+#include <string>
+
+struct EventQueue;
+
+struct SimObjectParams
+{
+ SimObjectParams()
+ {
+ extern EventQueue mainEventQueue;
+ eventq = &mainEventQueue;
+ }
+ virtual ~SimObjectParams() {}
+
+ std::string name;
+ PyObject *pyobj;
+ EventQueue *eventq;
+};
+
+
+#endif // __SIM_SIM_OBJECT_PARAMS_HH__
diff --git a/src/sim/simulate.cc b/src/sim/simulate.cc
index 36bdff45e..1ac2c80df 100644
--- a/src/sim/simulate.cc
+++ b/src/sim/simulate.cc
@@ -47,7 +47,7 @@
SimLoopExitEvent *
simulate(Tick num_cycles)
{
- warn("Entering event queue @ %d. Starting simulation...\n", curTick);
+ inform("Entering event queue @ %d. Starting simulation...\n", curTick);
if (num_cycles < 0)
fatal("simulate: num_cycles must be >= 0 (was %d)\n", num_cycles);
@@ -56,8 +56,9 @@ simulate(Tick num_cycles)
else
num_cycles = curTick + num_cycles;
- Event *limit_event;
- limit_event = schedExitSimLoop("simulate() limit reached", num_cycles);
+ Event *limit_event =
+ new SimLoopExitEvent("simulate() limit reached", 0);
+ mainEventQueue.schedule(limit_event, num_cycles);
while (1) {
// there should always be at least one event (the SimLoopExitEvent
@@ -82,8 +83,8 @@ simulate(Tick num_cycles)
// if we didn't hit limit_event, delete it
if (se_event != limit_event) {
assert(limit_event->scheduled());
- limit_event->deschedule();
- delete limit_event;
+ limit_event->squash();
+ hack_once("be nice to actually delete the event here");
}
return se_event;
diff --git a/src/sim/stat_control.cc b/src/sim/stat_control.cc
index 228c83898..2dcf4798d 100644
--- a/src/sim/stat_control.cc
+++ b/src/sim/stat_control.cc
@@ -44,14 +44,6 @@
using namespace std;
-Stats::Formula hostInstRate;
-Stats::Formula hostTickRate;
-Stats::Value hostMemory;
-Stats::Value hostSeconds;
-
-Stats::Value simTicks;
-Stats::Value simInsts;
-Stats::Value simFreq;
Stats::Formula simSeconds;
namespace Stats {
@@ -84,8 +76,21 @@ statElapsedTicks()
SimTicksReset simTicksReset;
-void
-initSimStats()
+struct Global
+{
+ Stats::Formula hostInstRate;
+ Stats::Formula hostTickRate;
+ Stats::Value hostMemory;
+ Stats::Value hostSeconds;
+
+ Stats::Value simTicks;
+ Stats::Value simInsts;
+ Stats::Value simFreq;
+
+ Global();
+};
+
+Global::Global()
{
simInsts
.functor(BaseCPU::numSimulatedInstructions)
@@ -146,6 +151,12 @@ initSimStats()
registerResetCallback(&simTicksReset);
}
+void
+initSimStats()
+{
+ static Global global;
+}
+
class _StatEvent : public Event
{
private:
@@ -154,12 +165,10 @@ class _StatEvent : public Event
Tick repeat;
public:
- _StatEvent(bool _dump, bool _reset, Tick _when, Tick _repeat)
- : Event(&mainEventQueue, Stat_Event_Pri), dump(_dump), reset(_reset),
- repeat(_repeat)
+ _StatEvent(bool _dump, bool _reset, Tick _repeat)
+ : Event(Stat_Event_Pri), dump(_dump), reset(_reset), repeat(_repeat)
{
setFlags(AutoDelete);
- schedule(_when);
}
virtual void
@@ -171,15 +180,18 @@ class _StatEvent : public Event
if (reset)
Stats::reset();
- if (repeat)
- new _StatEvent(dump, reset, curTick + repeat, repeat);
+ if (repeat) {
+ Event *event = new _StatEvent(dump, reset, repeat);
+ mainEventQueue.schedule(event, curTick + repeat);
+ }
}
};
void
StatEvent(bool dump, bool reset, Tick when, Tick repeat)
{
- new _StatEvent(dump, reset, when, repeat);
+ Event *event = new _StatEvent(dump, reset, repeat);
+ mainEventQueue.schedule(event, when);
}
/* namespace Stats */ }
diff --git a/src/sim/stats.hh b/src/sim/stats.hh
index 97251283d..481c36cf6 100644
--- a/src/sim/stats.hh
+++ b/src/sim/stats.hh
@@ -34,6 +34,5 @@
#include "base/statistics.hh"
extern Stats::Formula simSeconds;
-extern Stats::Value simTicks;
#endif // __SIM_SIM_STATS_HH__
diff --git a/src/sim/syscall_emul.cc b/src/sim/syscall_emul.cc
index f4b9b7ae3..5fe30c269 100644
--- a/src/sim/syscall_emul.cc
+++ b/src/sim/syscall_emul.cc
@@ -53,8 +53,8 @@ SyscallDesc::doSyscall(int callnum, LiveProcess *process, ThreadContext *tc)
{
DPRINTFR(SyscallVerbose, "%d: %s: syscall %s called w/arguments %d,%d,%d,%d\n",
curTick,tc->getCpuPtr()->name(), name,
- tc->getSyscallArg(0),tc->getSyscallArg(1),
- tc->getSyscallArg(2),tc->getSyscallArg(3));
+ process->getSyscallArg(tc, 0), process->getSyscallArg(tc, 1),
+ process->getSyscallArg(tc, 2), process->getSyscallArg(tc, 3));
SyscallReturn retval = (*funcPtr)(this, callnum, process, tc);
@@ -62,7 +62,7 @@ SyscallDesc::doSyscall(int callnum, LiveProcess *process, ThreadContext *tc)
curTick,tc->getCpuPtr()->name(), name, retval.value());
if (!(flags & SyscallDesc::SuppressReturnValue))
- tc->setSyscallReturn(retval);
+ process->setSyscallReturn(tc, retval);
}
@@ -81,7 +81,7 @@ ignoreFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
ThreadContext *tc)
{
warn("ignoring syscall %s(%d, %d, ...)", desc->name,
- tc->getSyscallArg(0), tc->getSyscallArg(1));
+ process->getSyscallArg(tc, 0), process->getSyscallArg(tc, 1));
return 0;
}
@@ -92,7 +92,8 @@ exitFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
ThreadContext *tc)
{
if (tc->exit()) {
- exitSimLoop("target called exit()", tc->getSyscallArg(0) & 0xff);
+ exitSimLoop("target called exit()",
+ process->getSyscallArg(tc, 0) & 0xff);
}
return 1;
@@ -107,21 +108,27 @@ getpagesizeFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc)
SyscallReturn
-obreakFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc)
+brkFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc)
{
- Addr junk;
-
// change brk addr to first arg
- Addr new_brk = tc->getSyscallArg(0);
- if (new_brk != 0) {
+ Addr new_brk = p->getSyscallArg(tc, 0);
+
+ // in Linux at least, brk(0) returns the current break value
+ // (note that the syscall and the glibc function have different behavior)
+ if (new_brk == 0)
+ return p->brk_point;
+
+ if (new_brk > p->brk_point) {
+ // might need to allocate some new pages
for (ChunkGenerator gen(p->brk_point, new_brk - p->brk_point,
VMPageSize); !gen.done(); gen.next()) {
- if (!p->pTable->translate(gen.addr(), junk))
+ if (!p->pTable->translate(gen.addr()))
p->pTable->allocate(roundDown(gen.addr(), VMPageSize),
VMPageSize);
}
- p->brk_point = new_brk;
}
+
+ p->brk_point = new_brk;
DPRINTF(SyscallVerbose, "Break Point changed to: %#X\n", p->brk_point);
return p->brk_point;
}
@@ -130,7 +137,7 @@ obreakFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc)
SyscallReturn
closeFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc)
{
- int target_fd = tc->getSyscallArg(0);
+ int target_fd = p->getSyscallArg(tc, 0);
int status = close(p->sim_fd(target_fd));
if (status >= 0)
p->free_fd(target_fd);
@@ -141,9 +148,9 @@ closeFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc)
SyscallReturn
readFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc)
{
- int fd = p->sim_fd(tc->getSyscallArg(0));
- int nbytes = tc->getSyscallArg(2);
- BufferArg bufArg(tc->getSyscallArg(1), nbytes);
+ int fd = p->sim_fd(p->getSyscallArg(tc, 0));
+ int nbytes = p->getSyscallArg(tc, 2);
+ BufferArg bufArg(p->getSyscallArg(tc, 1), nbytes);
int bytes_read = read(fd, bufArg.bufferPtr(), nbytes);
@@ -156,9 +163,9 @@ readFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc)
SyscallReturn
writeFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc)
{
- int fd = p->sim_fd(tc->getSyscallArg(0));
- int nbytes = tc->getSyscallArg(2);
- BufferArg bufArg(tc->getSyscallArg(1), nbytes);
+ int fd = p->sim_fd(p->getSyscallArg(tc, 0));
+ int nbytes = p->getSyscallArg(tc, 2);
+ BufferArg bufArg(p->getSyscallArg(tc, 1), nbytes);
bufArg.copyIn(tc->getMemPort());
@@ -173,9 +180,9 @@ writeFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc)
SyscallReturn
lseekFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc)
{
- int fd = p->sim_fd(tc->getSyscallArg(0));
- uint64_t offs = tc->getSyscallArg(1);
- int whence = tc->getSyscallArg(2);
+ int fd = p->sim_fd(p->getSyscallArg(tc, 0));
+ uint64_t offs = p->getSyscallArg(tc, 1);
+ int whence = p->getSyscallArg(tc, 2);
off_t result = lseek(fd, offs, whence);
@@ -186,11 +193,11 @@ 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);
+ int fd = p->sim_fd(p->getSyscallArg(tc, 0));
+ uint64_t offset_high = p->getSyscallArg(tc, 1);
+ uint32_t offset_low = p->getSyscallArg(tc, 2);
+ Addr result_ptr = p->getSyscallArg(tc, 3);
+ int whence = p->getSyscallArg(tc, 4);
uint64_t offset = (offset_high << 32) | offset_low;
@@ -229,8 +236,8 @@ const char *hostname = "m5.eecs.umich.edu";
SyscallReturn
gethostnameFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc)
{
- int name_len = tc->getSyscallArg(1);
- BufferArg name(tc->getSyscallArg(0), name_len);
+ int name_len = p->getSyscallArg(tc, 1);
+ BufferArg name(p->getSyscallArg(tc, 0), name_len);
strncpy((char *)name.bufferPtr(), hostname, name_len);
@@ -240,11 +247,64 @@ gethostnameFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc)
}
SyscallReturn
+getcwdFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc)
+{
+ int result = 0;
+ unsigned long size = p->getSyscallArg(tc, 1);
+ BufferArg buf(p->getSyscallArg(tc, 0), size);
+
+ // Is current working directory defined?
+ string cwd = p->getcwd();
+ if (!cwd.empty()) {
+ if (cwd.length() >= size) {
+ // Buffer too small
+ return -ERANGE;
+ }
+ strncpy((char *)buf.bufferPtr(), cwd.c_str(), size);
+ result = cwd.length();
+ }
+ else {
+ if (getcwd((char *)buf.bufferPtr(), size) != NULL) {
+ result = strlen((char *)buf.bufferPtr());
+ }
+ else {
+ result = -1;
+ }
+ }
+
+ buf.copyOut(tc->getMemPort());
+
+ return (result == -1) ? -errno : result;
+}
+
+
+SyscallReturn
+readlinkFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc)
+{
+ string path;
+
+ if (!tc->getMemPort()->tryReadString(path, p->getSyscallArg(tc, 0)))
+ return (TheISA::IntReg)-EFAULT;
+
+ // Adjust path for current working directory
+ path = p->fullPath(path);
+
+ size_t bufsiz = p->getSyscallArg(tc, 2);
+ BufferArg buf(p->getSyscallArg(tc, 1), bufsiz);
+
+ int result = readlink(path.c_str(), (char *)buf.bufferPtr(), bufsiz);
+
+ buf.copyOut(tc->getMemPort());
+
+ return (result == -1) ? -errno : result;
+}
+
+SyscallReturn
unlinkFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc)
{
string path;
- if (!tc->getMemPort()->tryReadString(path, tc->getSyscallArg(0)))
+ if (!tc->getMemPort()->tryReadString(path, p->getSyscallArg(tc, 0)))
return (TheISA::IntReg)-EFAULT;
// Adjust path for current working directory
@@ -254,17 +314,35 @@ unlinkFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc)
return (result == -1) ? -errno : result;
}
+
+SyscallReturn
+mkdirFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc)
+{
+ string path;
+
+ if (!tc->getMemPort()->tryReadString(path, p->getSyscallArg(tc, 0)))
+ return (TheISA::IntReg)-EFAULT;
+
+ // Adjust path for current working directory
+ path = p->fullPath(path);
+
+ mode_t mode = p->getSyscallArg(tc, 1);
+
+ int result = mkdir(path.c_str(), mode);
+ return (result == -1) ? -errno : result;
+}
+
SyscallReturn
renameFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc)
{
string old_name;
- if (!tc->getMemPort()->tryReadString(old_name, tc->getSyscallArg(0)))
+ if (!tc->getMemPort()->tryReadString(old_name, p->getSyscallArg(tc, 0)))
return -EFAULT;
string new_name;
- if (!tc->getMemPort()->tryReadString(new_name, tc->getSyscallArg(1)))
+ if (!tc->getMemPort()->tryReadString(new_name, p->getSyscallArg(tc, 1)))
return -EFAULT;
// Adjust path for current working directory
@@ -280,10 +358,10 @@ truncateFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc)
{
string path;
- if (!tc->getMemPort()->tryReadString(path, tc->getSyscallArg(0)))
+ if (!tc->getMemPort()->tryReadString(path, p->getSyscallArg(tc, 0)))
return -EFAULT;
- off_t length = tc->getSyscallArg(1);
+ off_t length = p->getSyscallArg(tc, 1);
// Adjust path for current working directory
path = p->fullPath(path);
@@ -295,29 +373,40 @@ truncateFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc)
SyscallReturn
ftruncateFunc(SyscallDesc *desc, int num, LiveProcess *process, ThreadContext *tc)
{
- int fd = process->sim_fd(tc->getSyscallArg(0));
+ int fd = process->sim_fd(process->getSyscallArg(tc, 0));
if (fd < 0)
return -EBADF;
- off_t length = tc->getSyscallArg(1);
+ off_t length = process->getSyscallArg(tc, 1);
int result = ftruncate(fd, length);
return (result == -1) ? -errno : result;
}
SyscallReturn
+umaskFunc(SyscallDesc *desc, int num, LiveProcess *process, ThreadContext *tc)
+{
+ // Letting the simulated program change the simulator's umask seems like
+ // a bad idea. Compromise by just returning the current umask but not
+ // changing anything.
+ mode_t oldMask = umask(0);
+ umask(oldMask);
+ return (int)oldMask;
+}
+
+SyscallReturn
chownFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc)
{
string path;
- if (!tc->getMemPort()->tryReadString(path, tc->getSyscallArg(0)))
+ if (!tc->getMemPort()->tryReadString(path, p->getSyscallArg(tc, 0)))
return -EFAULT;
/* XXX endianess */
- uint32_t owner = tc->getSyscallArg(1);
+ uint32_t owner = p->getSyscallArg(tc, 1);
uid_t hostOwner = owner;
- uint32_t group = tc->getSyscallArg(2);
+ uint32_t group = p->getSyscallArg(tc, 2);
gid_t hostGroup = group;
// Adjust path for current working directory
@@ -330,15 +419,15 @@ chownFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc)
SyscallReturn
fchownFunc(SyscallDesc *desc, int num, LiveProcess *process, ThreadContext *tc)
{
- int fd = process->sim_fd(tc->getSyscallArg(0));
+ int fd = process->sim_fd(process->getSyscallArg(tc, 0));
if (fd < 0)
return -EBADF;
/* XXX endianess */
- uint32_t owner = tc->getSyscallArg(1);
+ uint32_t owner = process->getSyscallArg(tc, 1);
uid_t hostOwner = owner;
- uint32_t group = tc->getSyscallArg(2);
+ uint32_t group = process->getSyscallArg(tc, 2);
gid_t hostGroup = group;
int result = fchown(fd, hostOwner, hostGroup);
@@ -349,11 +438,11 @@ fchownFunc(SyscallDesc *desc, int num, LiveProcess *process, ThreadContext *tc)
SyscallReturn
dupFunc(SyscallDesc *desc, int num, LiveProcess *process, ThreadContext *tc)
{
- int fd = process->sim_fd(tc->getSyscallArg(0));
+ int fd = process->sim_fd(process->getSyscallArg(tc, 0));
if (fd < 0)
return -EBADF;
- Process::FdMap *fdo = process->sim_fd_obj(tc->getSyscallArg(0));
+ Process::FdMap *fdo = process->sim_fd_obj(process->getSyscallArg(tc, 0));
int result = dup(fd);
return (result == -1) ? -errno : process->alloc_fd(result, fdo->filename, fdo->flags, fdo->mode, false);
@@ -364,12 +453,12 @@ SyscallReturn
fcntlFunc(SyscallDesc *desc, int num, LiveProcess *process,
ThreadContext *tc)
{
- int fd = tc->getSyscallArg(0);
+ int fd = process->getSyscallArg(tc, 0);
if (fd < 0 || process->sim_fd(fd) < 0)
return -EBADF;
- int cmd = tc->getSyscallArg(1);
+ int cmd = process->getSyscallArg(tc, 1);
switch (cmd) {
case 0: // F_DUPFD
// if we really wanted to support this, we'd need to do it
@@ -406,12 +495,12 @@ SyscallReturn
fcntl64Func(SyscallDesc *desc, int num, LiveProcess *process,
ThreadContext *tc)
{
- int fd = tc->getSyscallArg(0);
+ int fd = process->getSyscallArg(tc, 0);
if (fd < 0 || process->sim_fd(fd) < 0)
return -EBADF;
- int cmd = tc->getSyscallArg(1);
+ int cmd = process->getSyscallArg(tc, 1);
switch (cmd) {
case 33: //F_GETLK64
warn("fcntl64(%d, F_GETLK64) not supported, error returned\n", fd);
@@ -476,7 +565,7 @@ getuidPseudoFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
// EUID goes in r20.
tc->setIntReg(SyscallPseudoReturnReg, process->euid()); //EUID
- return process->uid(); // UID
+ return process->uid(); // UID
}
@@ -495,7 +584,7 @@ setuidFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
ThreadContext *tc)
{
// can't fathom why a benchmark would call this.
- warn("Ignoring call to setuid(%d)\n", tc->getSyscallArg(0));
+ warn("Ignoring call to setuid(%d)\n", process->getSyscallArg(tc, 0));
return 0;
}
@@ -522,14 +611,14 @@ SyscallReturn
getuidFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
ThreadContext *tc)
{
- return process->uid(); // UID
+ return process->uid(); // UID
}
SyscallReturn
geteuidFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
ThreadContext *tc)
{
- return process->euid(); // UID
+ return process->euid(); // UID
}
SyscallReturn
diff --git a/src/sim/syscall_emul.hh b/src/sim/syscall_emul.hh
index e35b0a75b..0b0e73692 100644
--- a/src/sim/syscall_emul.hh
+++ b/src/sim/syscall_emul.hh
@@ -44,15 +44,15 @@
#include <errno.h>
#include <string>
#ifdef __CYGWIN32__
-#include <sys/fcntl.h> // for O_BINARY
+#include <sys/fcntl.h> // for O_BINARY
#endif
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/uio.h>
-#include "sim/host.hh" // for Addr
+#include "sim/host.hh" // for Addr
#include "base/chunk_generator.hh"
-#include "base/intmath.hh" // for RoundUp
+#include "base/intmath.hh" // for RoundUp
#include "base/misc.hh"
#include "base/trace.hh"
#include "cpu/base.hh"
@@ -72,9 +72,9 @@ class SyscallDesc {
typedef SyscallReturn (*FuncPtr)(SyscallDesc *, int num,
LiveProcess *, ThreadContext *);
- const char *name; //!< Syscall name (e.g., "open").
- FuncPtr funcPtr; //!< Pointer to emulation function.
- int flags; //!< Flags (see Flags enum).
+ const char *name; //!< Syscall name (e.g., "open").
+ FuncPtr funcPtr; //!< Pointer to emulation function.
+ int flags; //!< Flags (see Flags enum).
/// Flag values for controlling syscall behavior.
enum Flags {
@@ -117,7 +117,7 @@ class BaseBufferArg {
virtual bool copyIn(TranslatingPort *memport)
{
memport->readBlob(addr, bufPtr, size);
- return true; // no EFAULT detection for now
+ return true; // no EFAULT detection for now
}
//
@@ -126,7 +126,7 @@ class BaseBufferArg {
virtual bool copyOut(TranslatingPort *memport)
{
memport->writeBlob(addr, bufPtr, size);
- return true; // no EFAULT detection for now
+ return true; // no EFAULT detection for now
}
protected:
@@ -140,7 +140,7 @@ class BufferArg : public BaseBufferArg
{
public:
BufferArg(Addr _addr, int _size) : BaseBufferArg(_addr, _size) { }
- void *bufferPtr() { return bufPtr; }
+ void *bufferPtr() { return bufPtr; }
};
template <class T>
@@ -158,8 +158,8 @@ class TypedBufferArg : public BaseBufferArg
operator T*() { return (T *)bufPtr; }
// dereference operators
- T &operator*() { return *((T *)bufPtr); }
- T* operator->() { return (T *)bufPtr; }
+ T &operator*() { return *((T *)bufPtr); }
+ T* operator->() { return (T *)bufPtr; }
T &operator[](int i) { return ((T *)bufPtr)[i]; }
};
@@ -191,9 +191,9 @@ SyscallReturn exitFunc(SyscallDesc *desc, int num,
SyscallReturn getpagesizeFunc(SyscallDesc *desc, int num,
LiveProcess *p, ThreadContext *tc);
-/// Target obreak() handler: set brk address.
-SyscallReturn obreakFunc(SyscallDesc *desc, int num,
- LiveProcess *p, ThreadContext *tc);
+/// Target brk() handler: set brk address.
+SyscallReturn brkFunc(SyscallDesc *desc, int num,
+ LiveProcess *p, ThreadContext *tc);
/// Target close() handler.
SyscallReturn closeFunc(SyscallDesc *desc, int num,
@@ -223,10 +223,22 @@ SyscallReturn munmapFunc(SyscallDesc *desc, int num,
SyscallReturn gethostnameFunc(SyscallDesc *desc, int num,
LiveProcess *p, ThreadContext *tc);
+/// Target getcwd() handler.
+SyscallReturn getcwdFunc(SyscallDesc *desc, int num,
+ LiveProcess *p, ThreadContext *tc);
+
+/// Target unlink() handler.
+SyscallReturn readlinkFunc(SyscallDesc *desc, int num,
+ LiveProcess *p, ThreadContext *tc);
+
/// Target unlink() handler.
SyscallReturn unlinkFunc(SyscallDesc *desc, int num,
LiveProcess *p, ThreadContext *tc);
+/// Target mkdir() handler.
+SyscallReturn mkdirFunc(SyscallDesc *desc, int num,
+ LiveProcess *p, ThreadContext *tc);
+
/// Target rename() handler.
SyscallReturn renameFunc(SyscallDesc *desc, int num,
LiveProcess *p, ThreadContext *tc);
@@ -242,6 +254,11 @@ SyscallReturn ftruncateFunc(SyscallDesc *desc, int num,
LiveProcess *p, ThreadContext *tc);
+/// Target umask() handler.
+SyscallReturn umaskFunc(SyscallDesc *desc, int num,
+ LiveProcess *p, ThreadContext *tc);
+
+
/// Target chown() handler.
SyscallReturn chownFunc(SyscallDesc *desc, int num,
LiveProcess *p, ThreadContext *tc);
@@ -363,6 +380,11 @@ convertStatBuf(target_stat &tgt, host_stat *host, bool fakeTTY = false)
tgt->st_ino = host->st_ino;
tgt->st_ino = htog(tgt->st_ino);
tgt->st_mode = host->st_mode;
+ if (fakeTTY) {
+ // Claim to be a character device
+ tgt->st_mode &= ~S_IFMT; // Clear S_IFMT
+ tgt->st_mode |= S_IFCHR; // Set S_IFCHR
+ }
tgt->st_mode = htog(tgt->st_mode);
tgt->st_nlink = host->st_nlink;
tgt->st_nlink = htog(tgt->st_nlink);
@@ -445,8 +467,8 @@ SyscallReturn
ioctlFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
ThreadContext *tc)
{
- int fd = tc->getSyscallArg(0);
- unsigned req = tc->getSyscallArg(1);
+ int fd = process->getSyscallArg(tc, 0);
+ unsigned req = process->getSyscallArg(tc, 1);
DPRINTF(SyscallVerbose, "ioctl(%d, 0x%x, ...)\n", fd, req);
@@ -480,7 +502,7 @@ openFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
{
std::string path;
- if (!tc->getMemPort()->tryReadString(path, tc->getSyscallArg(0)))
+ if (!tc->getMemPort()->tryReadString(path, process->getSyscallArg(tc, 0)))
return -EFAULT;
if (path == "/dev/sysdev0") {
@@ -490,8 +512,8 @@ openFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
return -ENOENT;
}
- int tgtFlags = tc->getSyscallArg(1);
- int mode = tc->getSyscallArg(2);
+ int tgtFlags = process->getSyscallArg(tc, 1);
+ int mode = process->getSyscallArg(tc, 2);
int hostFlags = 0;
// translate open flags
@@ -515,10 +537,18 @@ openFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
DPRINTF(SyscallVerbose, "opening file %s\n", path.c_str());
- // open the file
- int fd = open(path.c_str(), hostFlags, mode);
+ int fd;
+ if (!path.compare(0, 6, "/proc/") || !path.compare(0, 8, "/system/") ||
+ !path.compare(0, 10, "/platform/") || !path.compare(0, 5, "/sys/")) {
+ // It's a proc/sys entery and requires special handling
+ fd = OS::openSpecialFile(path, process, tc);
+ return (fd == -1) ? -1 : process->alloc_fd(fd,path.c_str(),hostFlags,mode, false);
+ } else {
+ // open the file
+ fd = open(path.c_str(), hostFlags, mode);
+ return (fd == -1) ? -errno : process->alloc_fd(fd,path.c_str(),hostFlags,mode, false);
+ }
- return (fd == -1) ? -errno : process->alloc_fd(fd,path.c_str(),hostFlags,mode, false);
}
@@ -530,10 +560,10 @@ chmodFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
{
std::string path;
- if (!tc->getMemPort()->tryReadString(path, tc->getSyscallArg(0)))
+ if (!tc->getMemPort()->tryReadString(path, process->getSyscallArg(tc, 0)))
return -EFAULT;
- uint32_t mode = tc->getSyscallArg(1);
+ uint32_t mode = process->getSyscallArg(tc, 1);
mode_t hostMode = 0;
// XXX translate mode flags via OS::something???
@@ -557,13 +587,13 @@ SyscallReturn
fchmodFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
ThreadContext *tc)
{
- int fd = tc->getSyscallArg(0);
+ int fd = process->getSyscallArg(tc, 0);
if (fd < 0 || process->sim_fd(fd) < 0) {
// doesn't map to any simulator fd: not a valid target fd
return -EBADF;
}
- uint32_t mode = tc->getSyscallArg(1);
+ uint32_t mode = process->getSyscallArg(tc, 1);
mode_t hostMode = 0;
// XXX translate mode flags via OS::someting???
@@ -577,6 +607,51 @@ fchmodFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
return 0;
}
+/// Target mremap() handler.
+template <class OS>
+SyscallReturn
+mremapFunc(SyscallDesc *desc, int callnum, LiveProcess *process, ThreadContext *tc)
+{
+ Addr start = process->getSyscallArg(tc, 0);
+ uint64_t old_length = process->getSyscallArg(tc, 1);
+ uint64_t new_length = process->getSyscallArg(tc, 2);
+ uint64_t flags = process->getSyscallArg(tc, 3);
+
+ if ((start % TheISA::VMPageSize != 0) ||
+ (new_length % TheISA::VMPageSize != 0)) {
+ warn("mremap failing: arguments not page aligned");
+ return -EINVAL;
+ }
+
+ if (new_length > old_length) {
+ if ((start + old_length) == process->mmap_end) {
+ uint64_t diff = new_length - old_length;
+ process->pTable->allocate(process->mmap_end, diff);
+ process->mmap_end += diff;
+ return start;
+ } else {
+ // sys/mman.h defined MREMAP_MAYMOVE
+ if (!(flags & 1)) {
+ warn("can't remap here and MREMAP_MAYMOVE flag not set\n");
+ return -ENOMEM;
+ } else {
+ process->pTable->remap(start, old_length, process->mmap_end);
+ warn("mremapping to totally new vaddr %08p-%08p, adding %d\n",
+ process->mmap_end, process->mmap_end + new_length, new_length);
+ start = process->mmap_end;
+ // add on the remaining unallocated pages
+ process->pTable->allocate(start + old_length, new_length - old_length);
+ process->mmap_end += new_length;
+ warn("returning %08p as start\n", start);
+ return start;
+ }
+ }
+ } else {
+ process->pTable->deallocate(start + new_length, old_length -
+ new_length);
+ return start;
+ }
+}
/// Target stat() handler.
template <class OS>
@@ -586,7 +661,7 @@ statFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
{
std::string path;
- if (!tc->getMemPort()->tryReadString(path, tc->getSyscallArg(0)))
+ if (!tc->getMemPort()->tryReadString(path, process->getSyscallArg(tc, 0)))
return -EFAULT;
// Adjust path for current working directory
@@ -598,7 +673,8 @@ statFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
if (result < 0)
return -errno;
- copyOutStatBuf<OS>(tc->getMemPort(), tc->getSyscallArg(1), &hostBuf);
+ copyOutStatBuf<OS>(tc->getMemPort(), process->getSyscallArg(tc, 1),
+ &hostBuf);
return 0;
}
@@ -612,7 +688,7 @@ stat64Func(SyscallDesc *desc, int callnum, LiveProcess *process,
{
std::string path;
- if (!tc->getMemPort()->tryReadString(path, tc->getSyscallArg(0)))
+ if (!tc->getMemPort()->tryReadString(path, process->getSyscallArg(tc, 0)))
return -EFAULT;
// Adjust path for current working directory
@@ -629,7 +705,8 @@ stat64Func(SyscallDesc *desc, int callnum, LiveProcess *process,
if (result < 0)
return -errno;
- copyOutStat64Buf<OS>(tc->getMemPort(), tc->getSyscallArg(1), &hostBuf);
+ copyOutStat64Buf<OS>(tc->getMemPort(), process->getSyscallArg(tc, 1),
+ &hostBuf);
return 0;
}
@@ -641,7 +718,7 @@ SyscallReturn
fstat64Func(SyscallDesc *desc, int callnum, LiveProcess *process,
ThreadContext *tc)
{
- int fd = tc->getSyscallArg(0);
+ int fd = process->getSyscallArg(tc, 0);
if (fd < 0 || process->sim_fd(fd) < 0) {
// doesn't map to any simulator fd: not a valid target fd
return -EBADF;
@@ -658,7 +735,7 @@ fstat64Func(SyscallDesc *desc, int callnum, LiveProcess *process,
if (result < 0)
return -errno;
- copyOutStat64Buf<OS>(tc->getMemPort(), tc->getSyscallArg(1),
+ copyOutStat64Buf<OS>(tc->getMemPort(), process->getSyscallArg(tc, 1),
&hostBuf, (fd == 1));
return 0;
@@ -673,7 +750,7 @@ lstatFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
{
std::string path;
- if (!tc->getMemPort()->tryReadString(path, tc->getSyscallArg(0)))
+ if (!tc->getMemPort()->tryReadString(path, process->getSyscallArg(tc, 0)))
return -EFAULT;
// Adjust path for current working directory
@@ -685,7 +762,8 @@ lstatFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
if (result < 0)
return -errno;
- copyOutStatBuf<OS>(tc->getMemPort(), tc->getSyscallArg(1), &hostBuf);
+ copyOutStatBuf<OS>(tc->getMemPort(), process->getSyscallArg(tc, 1),
+ &hostBuf);
return 0;
}
@@ -698,7 +776,7 @@ lstat64Func(SyscallDesc *desc, int callnum, LiveProcess *process,
{
std::string path;
- if (!tc->getMemPort()->tryReadString(path, tc->getSyscallArg(0)))
+ if (!tc->getMemPort()->tryReadString(path, process->getSyscallArg(tc, 0)))
return -EFAULT;
// Adjust path for current working directory
@@ -715,7 +793,8 @@ lstat64Func(SyscallDesc *desc, int callnum, LiveProcess *process,
if (result < 0)
return -errno;
- copyOutStat64Buf<OS>(tc->getMemPort(), tc->getSyscallArg(1), &hostBuf);
+ copyOutStat64Buf<OS>(tc->getMemPort(), process->getSyscallArg(tc, 1),
+ &hostBuf);
return 0;
}
@@ -726,7 +805,7 @@ SyscallReturn
fstatFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
ThreadContext *tc)
{
- int fd = process->sim_fd(tc->getSyscallArg(0));
+ int fd = process->sim_fd(process->getSyscallArg(tc, 0));
DPRINTF(SyscallVerbose, "fstat(%d, ...)\n", fd);
@@ -739,7 +818,7 @@ fstatFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
if (result < 0)
return -errno;
- copyOutStatBuf<OS>(tc->getMemPort(), tc->getSyscallArg(1),
+ copyOutStatBuf<OS>(tc->getMemPort(), process->getSyscallArg(tc, 1),
&hostBuf, (fd == 1));
return 0;
@@ -754,7 +833,7 @@ statfsFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
{
std::string path;
- if (!tc->getMemPort()->tryReadString(path, tc->getSyscallArg(0)))
+ if (!tc->getMemPort()->tryReadString(path, process->getSyscallArg(tc, 0)))
return -EFAULT;
// Adjust path for current working directory
@@ -767,7 +846,7 @@ statfsFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
return -errno;
OS::copyOutStatfsBuf(tc->getMemPort(),
- (Addr)(tc->getSyscallArg(1)), &hostBuf);
+ (Addr)(process->getSyscallArg(tc, 1)), &hostBuf);
return 0;
}
@@ -779,7 +858,7 @@ SyscallReturn
fstatfsFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
ThreadContext *tc)
{
- int fd = process->sim_fd(tc->getSyscallArg(0));
+ int fd = process->sim_fd(process->getSyscallArg(tc, 0));
if (fd < 0)
return -EBADF;
@@ -790,7 +869,7 @@ fstatfsFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
if (result < 0)
return -errno;
- OS::copyOutStatfsBuf(tc->getMemPort(), tc->getSyscallArg(1),
+ OS::copyOutStatfsBuf(tc->getMemPort(), process->getSyscallArg(tc, 1),
&hostBuf);
return 0;
@@ -803,15 +882,15 @@ SyscallReturn
writevFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
ThreadContext *tc)
{
- int fd = tc->getSyscallArg(0);
+ int fd = process->getSyscallArg(tc, 0);
if (fd < 0 || process->sim_fd(fd) < 0) {
// doesn't map to any simulator fd: not a valid target fd
return -EBADF;
}
TranslatingPort *p = tc->getMemPort();
- uint64_t tiov_base = tc->getSyscallArg(1);
- size_t count = tc->getSyscallArg(2);
+ uint64_t tiov_base = process->getSyscallArg(tc, 1);
+ size_t count = process->getSyscallArg(tc, 2);
struct iovec hiov[count];
for (int i = 0; i < count; ++i)
{
@@ -855,12 +934,13 @@ template <class OS>
SyscallReturn
mmapFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc)
{
- Addr start = tc->getSyscallArg(0);
- uint64_t length = tc->getSyscallArg(1);
- // int prot = tc->getSyscallArg(2);
- int flags = tc->getSyscallArg(3);
- // int fd = p->sim_fd(tc->getSyscallArg(4));
- // int offset = tc->getSyscallArg(5);
+ Addr start = p->getSyscallArg(tc, 0);
+ uint64_t length = p->getSyscallArg(tc, 1);
+ // int prot = p->getSyscallArg(tc, 2);
+ int flags = p->getSyscallArg(tc, 3);
+ // int fd = p->sim_fd(p->getSyscallArg(tc, 4));
+ // int offset = p->getSyscallArg(tc, 5);
+
if ((start % TheISA::VMPageSize) != 0 ||
(length % TheISA::VMPageSize) != 0) {
@@ -882,7 +962,7 @@ mmapFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc)
if (!(flags & OS::TGT_MAP_ANONYMOUS)) {
warn("allowing mmap of file @ fd %d. "
- "This will break if not /dev/zero.", tc->getSyscallArg(4));
+ "This will break if not /dev/zero.", p->getSyscallArg(tc, 4));
}
return start;
@@ -894,17 +974,24 @@ SyscallReturn
getrlimitFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
ThreadContext *tc)
{
- unsigned resource = tc->getSyscallArg(0);
- TypedBufferArg<typename OS::rlimit> rlp(tc->getSyscallArg(1));
+ unsigned resource = process->getSyscallArg(tc, 0);
+ TypedBufferArg<typename OS::rlimit> rlp(process->getSyscallArg(tc, 1));
switch (resource) {
case OS::TGT_RLIMIT_STACK:
- // max stack size in bytes: make up a number (2MB for now)
+ // max stack size in bytes: make up a number (8MB for now)
rlp->rlim_cur = rlp->rlim_max = 8 * 1024 * 1024;
rlp->rlim_cur = htog(rlp->rlim_cur);
rlp->rlim_max = htog(rlp->rlim_max);
break;
+ case OS::TGT_RLIMIT_DATA:
+ // max data segment size in bytes: make up a number
+ rlp->rlim_cur = rlp->rlim_max = 256 * 1024 * 1024;
+ rlp->rlim_cur = htog(rlp->rlim_cur);
+ rlp->rlim_max = htog(rlp->rlim_max);
+ break;
+
default:
std::cerr << "getrlimitFunc: unimplemented resource " << resource
<< std::endl;
@@ -922,7 +1009,7 @@ SyscallReturn
gettimeofdayFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
ThreadContext *tc)
{
- TypedBufferArg<typename OS::timeval> tp(tc->getSyscallArg(0));
+ TypedBufferArg<typename OS::timeval> tp(process->getSyscallArg(tc, 0));
getElapsedTime(tp->tv_sec, tp->tv_usec);
tp->tv_sec += seconds_since_epoch;
@@ -943,10 +1030,10 @@ utimesFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
{
std::string path;
- if (!tc->getMemPort()->tryReadString(path, tc->getSyscallArg(0)))
+ if (!tc->getMemPort()->tryReadString(path, process->getSyscallArg(tc, 0)))
return -EFAULT;
- TypedBufferArg<typename OS::timeval [2]> tp(tc->getSyscallArg(1));
+ TypedBufferArg<typename OS::timeval [2]> tp(process->getSyscallArg(tc, 1));
tp.copyIn(tc->getMemPort());
struct timeval hostTimeval[2];
@@ -972,8 +1059,8 @@ SyscallReturn
getrusageFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
ThreadContext *tc)
{
- int who = tc->getSyscallArg(0); // THREAD, SELF, or CHILDREN
- TypedBufferArg<typename OS::rusage> rup(tc->getSyscallArg(1));
+ int who = process->getSyscallArg(tc, 0); // THREAD, SELF, or CHILDREN
+ TypedBufferArg<typename OS::rusage> rup(process->getSyscallArg(tc, 1));
rup->ru_utime.tv_sec = 0;
rup->ru_utime.tv_usec = 0;
diff --git a/src/sim/system.cc b/src/sim/system.cc
index 10b9b1217..d16524c41 100644
--- a/src/sim/system.cc
+++ b/src/sim/system.cc
@@ -42,6 +42,7 @@
#include "mem/physical.hh"
#include "sim/byteswap.hh"
#include "sim/system.hh"
+#include "sim/debug.hh"
#if FULL_SYSTEM
#include "arch/vtophys.hh"
#include "kern/kernel_stats.hh"
@@ -57,7 +58,7 @@ vector<System *> System::systemList;
int System::numSystemsRunning = 0;
System::System(Params *p)
- : SimObject(p), physmem(p->physmem), numcpus(0),
+ : SimObject(p), physmem(p->physmem), _numContexts(0),
#if FULL_SYSTEM
init_param(p->init_param),
functionalPort(p->name + "-fport"),
@@ -94,12 +95,12 @@ System::System(Params *p)
* Load the kernel code into memory
*/
if (params()->kernel == "") {
- warn("No kernel set for full system simulation. Assuming you know what"
+ inform("No kernel set for full system simulation. Assuming you know what"
" you're doing...\n");
} else {
// Load kernel code
kernel = createObjectFile(params()->kernel);
- warn("kernel located at: %s", params()->kernel);
+ inform("kernel located at: %s", params()->kernel);
if (kernel == NULL)
fatal("Could not load kernel file %s", params()->kernel);
@@ -114,16 +115,16 @@ System::System(Params *p)
// load symbols
if (!kernel->loadGlobalSymbols(kernelSymtab))
- panic("could not load kernel symbols\n");
+ fatal("could not load kernel symbols\n");
if (!kernel->loadLocalSymbols(kernelSymtab))
- panic("could not load kernel local symbols\n");
+ fatal("could not load kernel local symbols\n");
if (!kernel->loadGlobalSymbols(debugSymbolTable))
- panic("could not load kernel symbols\n");
+ fatal("could not load kernel symbols\n");
if (!kernel->loadLocalSymbols(debugSymbolTable))
- panic("could not load kernel local symbols\n");
+ fatal("could not load kernel local symbols\n");
DPRINTF(Loader, "Kernel start = %#x\n", kernelStart);
DPRINTF(Loader, "Kernel end = %#x\n", kernelEnd);
@@ -165,27 +166,33 @@ bool System::breakpoint()
}
int
-System::registerThreadContext(ThreadContext *tc, int id)
+System::registerThreadContext(ThreadContext *tc, int assigned)
{
- if (id == -1) {
+ int id;
+ if (assigned == -1) {
for (id = 0; id < threadContexts.size(); id++) {
if (!threadContexts[id])
break;
}
- }
- if (threadContexts.size() <= id)
- threadContexts.resize(id + 1);
+ if (threadContexts.size() <= id)
+ threadContexts.resize(id + 1);
+ } else {
+ if (threadContexts.size() <= assigned)
+ threadContexts.resize(assigned + 1);
+ id = assigned;
+ }
if (threadContexts[id])
- panic("Cannot have two CPUs with the same id (%d)\n", id);
+ fatal("Cannot have two CPUs with the same id (%d)\n", id);
threadContexts[id] = tc;
- numcpus++;
+ _numContexts++;
- if (rgdb_enable) {
+ int port = getRemoteGDBPort();
+ if (rgdb_enable && port) {
RemoteGDB *rgdb = new RemoteGDB(this, tc);
- GDBListener *gdbl = new GDBListener(rgdb, 7000 + id);
+ GDBListener *gdbl = new GDBListener(rgdb, port + id);
gdbl->listen();
/**
* Uncommenting this line waits for a remote debugger to
@@ -207,22 +214,24 @@ System::registerThreadContext(ThreadContext *tc, int id)
void
System::startup()
{
+#if FULL_SYSTEM
int i;
for (i = 0; i < threadContexts.size(); i++)
TheISA::startupCPU(threadContexts[i], i);
+#endif
}
void
-System::replaceThreadContext(ThreadContext *tc, int id)
+System::replaceThreadContext(ThreadContext *tc, int context_id)
{
- if (id >= threadContexts.size()) {
+ if (context_id >= threadContexts.size()) {
panic("replaceThreadContext: bad id, %d >= %d\n",
- id, threadContexts.size());
+ context_id, threadContexts.size());
}
- threadContexts[id] = tc;
- if (id < remoteGDB.size())
- remoteGDB[id]->replaceThreadContext(tc);
+ threadContexts[context_id] = tc;
+ if (context_id < remoteGDB.size())
+ remoteGDB[context_id]->replaceThreadContext(tc);
}
#if !FULL_SYSTEM
@@ -235,6 +244,19 @@ System::new_page()
fatal("Out of memory, please increase size of physical memory.");
return return_addr;
}
+
+Addr
+System::memSize()
+{
+ return physmem->size();
+}
+
+Addr
+System::freeMemSize()
+{
+ return physmem->size() - (page_ptr << LogVMPageSize);
+}
+
#endif
void
@@ -283,11 +305,7 @@ const char *System::MemoryModeStrings[3] = {"invalid", "atomic",
System *
SystemParams::create()
{
- System::Params *p = new System::Params;
- p->name = name;
- p->physmem = physmem;
- p->mem_mode = mem_mode;
- return new System(p);
+ return new System(this);
}
#endif
diff --git a/src/sim/system.hh b/src/sim/system.hh
index cdd5bebb0..bfa5ea8bb 100644
--- a/src/sim/system.hh
+++ b/src/sim/system.hh
@@ -87,14 +87,19 @@ class System : public SimObject
PCEventQueue pcEventQueue;
std::vector<ThreadContext *> threadContexts;
- int numcpus;
+ int _numContexts;
- int getNumCPUs()
+ ThreadContext * getThreadContext(int tid)
{
- if (numcpus != threadContexts.size())
+ return threadContexts[tid];
+ }
+
+ int numContexts()
+ {
+ if (_numContexts != threadContexts.size())
panic("cpu array not fully populated!");
- return numcpus;
+ return _numContexts;
}
#if FULL_SYSTEM
@@ -134,6 +139,12 @@ class System : public SimObject
return next_PID++;
}
+ /** Amount of physical memory that is still free */
+ Addr freeMemSize();
+
+ /** Amount of physical memory that exists */
+ Addr memSize();
+
#endif // FULL_SYSTEM
@@ -219,8 +230,8 @@ class System : public SimObject
#endif // FULL_SYSTEM
- int registerThreadContext(ThreadContext *tc, int tcIndex);
- void replaceThreadContext(ThreadContext *tc, int tcIndex);
+ int registerThreadContext(ThreadContext *tc, int assigned=-1);
+ void replaceThreadContext(ThreadContext *tc, int context_id);
void serialize(std::ostream &os);
void unserialize(Checkpoint *cp, const std::string &section);
diff --git a/src/sim/tlb.cc b/src/sim/tlb.cc
index 7292a69e0..e82e4f277 100644
--- a/src/sim/tlb.cc
+++ b/src/sim/tlb.cc
@@ -34,7 +34,7 @@
#include "sim/tlb.hh"
Fault
-GenericTLB::translate(RequestPtr req, ThreadContext * tc, bool)
+GenericTLB::translateAtomic(RequestPtr req, ThreadContext * tc, bool)
{
#if FULL_SYSTEM
panic("Generic translation shouldn't be used in full system mode.\n");
@@ -50,6 +50,14 @@ GenericTLB::translate(RequestPtr req, ThreadContext * tc, bool)
}
void
+GenericTLB::translateTiming(RequestPtr req, ThreadContext *tc,
+ Translation *translation, bool write)
+{
+ assert(translation);
+ translation->finish(translateAtomic(req, tc, write), req, tc, write);
+}
+
+void
GenericTLB::demapPage(Addr vaddr, uint64_t asn)
{
warn("Demapping pages in the generic TLB is unnecessary.\n");
diff --git a/src/sim/tlb.hh b/src/sim/tlb.hh
index 011cc1144..8893f8c97 100644
--- a/src/sim/tlb.hh
+++ b/src/sim/tlb.hh
@@ -47,6 +47,21 @@ class BaseTLB : public SimObject
public:
virtual void demapPage(Addr vaddr, uint64_t asn) = 0;
+
+ class Translation
+ {
+ public:
+ virtual ~Translation()
+ {}
+
+ /*
+ * The memory for this object may be dynamically allocated, and it may
+ * be responsible for cleaning itself up which will happen in this
+ * function. Once it's called, the object is no longer valid.
+ */
+ virtual void finish(Fault fault, RequestPtr req,
+ ThreadContext *tc, bool write=false) = 0;
+ };
};
class GenericTLB : public BaseTLB
@@ -58,7 +73,9 @@ class GenericTLB : public BaseTLB
public:
void demapPage(Addr vaddr, uint64_t asn);
- Fault translate(RequestPtr req, ThreadContext *tc, bool=false);
+ Fault translateAtomic(RequestPtr req, ThreadContext *tc, bool=false);
+ void translateTiming(RequestPtr req, ThreadContext *tc,
+ Translation *translation, bool=false);
};
#endif // __ARCH_SPARC_TLB_HH__
diff --git a/src/sim/vptr.hh b/src/sim/vptr.hh
index 383f65351..09aa2d213 100644
--- a/src/sim/vptr.hh
+++ b/src/sim/vptr.hh
@@ -71,9 +71,8 @@ class VPtr
if (!ptr)
return;
- VirtualPort *port = tc->getVirtPort(tc);
+ VirtualPort *port = tc->getVirtPort();
port->readBlob(ptr, buffer, sizeof(T));
- tc->delVirtPort(port);
}
bool