Adding gem5 source to svn.

git-svn-id: https://www4.informatik.uni-erlangen.de/i4svn/danceos/trunk/devel/fail@1819 8c4709b5-6ec9-48aa-a5cd-a96041d1645a
This commit is contained in:
friemel
2012-10-24 19:18:57 +00:00
parent f7ff71bd46
commit b41eec3f65
3222 changed files with 658579 additions and 1 deletions

View File

@ -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

View File

@ -0,0 +1,35 @@
# Copyright (c) 2007 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
from m5.SimObject import SimObject
from m5.params import *
class InstTracer(SimObject):
type = 'InstTracer'
cxx_class = 'Trace::InstTracer'
abstract = True

View File

@ -0,0 +1,54 @@
# Copyright (c) 2005-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: Nathan Binkert
from m5.SimObject import SimObject
from m5.params import *
from m5.proxy import *
class Process(SimObject):
type = 'Process'
abstract = True
input = Param.String('cin', "filename for stdin")
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')
class LiveProcess(Process):
type = 'LiveProcess'
executable = Param.String('', "executable (overrides cmd[0] if set)")
cmd = VectorParam.String("command line (executable plus arguments)")
env = VectorParam.String([], "environment settings")
cwd = Param.String('', "current working directory")
uid = Param.Int(100, 'user id')
euid = Param.Int(100, 'effective user id')
gid = Param.Int(100, 'group id')
egid = Param.Int(100, 'effective group id')
pid = Param.Int(100, 'process id')
ppid = Param.Int(99, 'parent process id')
simpoint = Param.UInt64(0, 'simulation point at which to start simulation')

View File

@ -0,0 +1,68 @@
# Copyright (c) 2005-2007 The Regents of The University of Michigan
# Copyright (c) 2010 Advanced Micro Devices, Inc.
# 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
from m5.SimObject import SimObject
from m5.defines import buildEnv
from m5.params import *
from m5.util import fatal
class Root(SimObject):
_the_instance = None
def __new__(cls, **kwargs):
if Root._the_instance:
fatal("Attempt to allocate multiple instances of Root.")
return None
# first call: allocate the unique instance
#
# If SimObject ever implements __new__, we may want to pass
# kwargs here, but for now this goes straight to
# object.__new__ which prints an ugly warning if you pass it
# args. Seems like a bad design but that's the way it is.
Root._the_instance = SimObject.__new__(cls)
return Root._the_instance
@classmethod
def getInstance(cls):
return Root._the_instance
def path(self):
return 'root'
type = 'Root'
full_system = Param.Bool("if this is a full system simulation")
# Time syncing prevents the simulation from running faster than real time.
time_sync_enable = Param.Bool(False, "whether time syncing is enabled")
time_sync_period = Param.Clock("100ms", "how often to sync with real time")
time_sync_spin_threshold = \
Param.Clock("100us", "when less than this much time is left, spin")

View File

@ -0,0 +1,79 @@
# -*- mode:python -*-
# Copyright (c) 2006 The Regents of The University of Michigan
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met: redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer;
# redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution;
# neither the name of the copyright holders nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# Authors: Nathan Binkert
Import('*')
SimObject('BaseTLB.py')
SimObject('Root.py')
SimObject('InstTracer.py')
Source('arguments.cc')
Source('async.cc')
Source('core.cc')
Source('debug.cc')
Source('eventq.cc')
Source('init.cc')
Source('main.cc', main=True, skip_lib=True)
Source('root.cc')
Source('serialize.cc')
Source('sim_events.cc')
Source('sim_object.cc')
Source('simulate.cc')
Source('stat_control.cc')
Source('syscall_emul.cc')
if env['TARGET_ISA'] != 'no':
SimObject('Process.py')
SimObject('System.py')
Source('faults.cc')
Source('process.cc')
Source('pseudo_inst.cc')
Source('system.cc')
if env['TARGET_ISA'] != 'no':
Source('tlb.cc')
DebugFlag('Checkpoint')
DebugFlag('Config')
DebugFlag('Event')
DebugFlag('Fault')
DebugFlag('Flow')
DebugFlag('IPI')
DebugFlag('IPR')
DebugFlag('Interrupt')
DebugFlag('Loader')
DebugFlag('Stack')
DebugFlag('SyscallVerbose')
DebugFlag('TimeSync')
DebugFlag('TLB')
DebugFlag('Thread')
DebugFlag('Timer')
DebugFlag('VtoPhys')
DebugFlag('WorkItems')

View File

@ -0,0 +1,79 @@
# Copyright (c) 2005-2007 The Regents of The University of Michigan
# Copyright (c) 2011 Regents of the University of California
# 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
# Rick Strong
from m5.SimObject import SimObject
from m5.defines import buildEnv
from m5.params import *
from m5.proxy import *
from SimpleMemory import *
class MemoryMode(Enum): vals = ['invalid', 'atomic', 'timing']
class System(MemObject):
type = 'System'
system_port = MasterPort("System port")
@classmethod
def export_method_cxx_predecls(cls, code):
code('#include "sim/system.hh"')
@classmethod
def export_methods(cls, code):
code('''
Enums::MemoryMode getMemoryMode();
void setMemoryMode(Enums::MemoryMode mode);
''')
memories = VectorParam.AbstractMemory(Self.all,
"All memories in the system")
mem_mode = Param.MemoryMode('atomic', "The mode the memory system is in")
work_item_id = Param.Int(-1, "specific work item id")
num_work_ids = Param.Int(16, "Number of distinct work item types")
work_begin_cpu_id_exit = Param.Int(-1,
"work started on specific id, now exit simulation")
work_begin_ckpt_count = Param.Counter(0,
"create checkpoint when work items begin count value is reached")
work_begin_exit_count = Param.Counter(0,
"exit simulation when work items begin count value is reached")
work_end_ckpt_count = Param.Counter(0,
"create checkpoint when work items end count value is reached")
work_end_exit_count = Param.Counter(0,
"exit simulation when work items end count value is reached")
work_cpus_ckpt_count = Param.Counter(0,
"create checkpoint when active cpu count value is reached")
init_param = Param.UInt64(0, "numerical value to pass into simulator")
boot_osflags = Param.String("a", "boot flags to pass to the kernel")
kernel = Param.String("", "file that contains the kernel code")
readfile = Param.String("", "file to read startup script from")
symbolfile = Param.String("", "file to get the symbols from")
load_addr_mask = Param.UInt64(0xffffffffff,
"Address to mask loading binaries with");

View File

@ -0,0 +1,57 @@
/*
* Copyright (c) 2003-2005 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Nathan Binkert
*/
#include "arch/utility.hh"
#include "config/the_isa.hh"
#include "cpu/thread_context.hh"
#include "sim/arguments.hh"
Arguments::Data::~Data()
{
while (!data.empty()) {
delete [] data.front();
data.pop_front();
}
}
char *
Arguments::Data::alloc(size_t size)
{
char *buf = new char[size];
data.push_back(buf);
return buf;
}
uint64_t
Arguments::getArg(uint16_t size, bool fp)
{
return TheISA::getArgument(tc, number, size, fp);
}

View File

@ -0,0 +1,151 @@
/*
* Copyright (c) 2003-2005 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Nathan Binkert
*/
#ifndef __SIM_ARGUMENTS_HH__
#define __SIM_ARGUMENTS_HH__
#include <cassert>
#include "arch/vtophys.hh"
#include "base/refcnt.hh"
#include "base/types.hh"
#include "mem/fs_translating_port_proxy.hh"
class ThreadContext;
class Arguments
{
protected:
ThreadContext *tc;
int number;
uint64_t getArg(uint16_t size = (uint16_t)(-1), bool fp = false);
protected:
class Data : public RefCounted
{
public:
Data(){}
~Data();
private:
std::list<char *> data;
public:
char *alloc(size_t size);
};
RefCountingPtr<Data> data;
public:
Arguments(ThreadContext *ctx, int n = 0)
: tc(ctx), number(n), data(NULL)
{ assert(number >= 0); data = new Data;}
Arguments(const Arguments &args)
: tc(args.tc), number(args.number), data(args.data) {}
~Arguments() {}
ThreadContext *getThreadContext() const { return tc; }
const Arguments &operator=(const Arguments &args) {
tc = args.tc;
number = args.number;
data = args.data;
return *this;
}
// for checking if an argument is NULL
bool operator!() {
return getArg() == 0;
}
Arguments &operator++() {
++number;
assert(number >= 0);
return *this;
}
Arguments operator++(int) {
Arguments args = *this;
++number;
assert(number >= 0);
return args;
}
Arguments &operator--() {
--number;
assert(number >= 0);
return *this;
}
Arguments operator--(int) {
Arguments args = *this;
--number;
assert(number >= 0);
return args;
}
const Arguments &operator+=(int index) {
number += index;
assert(number >= 0);
return *this;
}
const Arguments &operator-=(int index) {
number -= index;
assert(number >= 0);
return *this;
}
Arguments operator[](int index) {
return Arguments(tc, index);
}
template <class T>
operator T() {
assert(sizeof(T) <= sizeof(uint64_t));
T data = static_cast<T>(getArg(sizeof(T)));
return data;
}
template <class T>
operator T *() {
T *buf = (T *)data->alloc(sizeof(T));
CopyOut(tc, buf, getArg(sizeof(T)), sizeof(T));
return buf;
}
operator char *() {
char *buf = data->alloc(2048);
CopyStringOut(tc, buf, getArg(), 2048);
return buf;
}
};
#endif // __SIM_ARGUMENTS_HH__

View File

@ -0,0 +1,38 @@
/*
* Copyright (c) 2000-2005 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Nathan Binkert
*/
volatile bool async_event = false;
volatile bool async_statdump = false;
volatile bool async_statreset = false;
volatile bool async_exit = false;
volatile bool async_io = false;
volatile bool async_alarm = false;
volatile bool async_exception = false;

View File

@ -0,0 +1,54 @@
/*
* Copyright (c) 2003-2005 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Nathan Binkert
* Steve Reinhardt
*/
#ifndef __ASYNC_HH__
#define __ASYNC_HH__
///
/// @file sim/async.hh
/// This file defines flags used to handle asynchronous simulator events.
///
/// @name Asynchronous event flags.
/// To avoid races, signal handlers simply set these flags, which are
/// 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_exception; ///< Python exception.
//@}
#endif // __ASYNC_HH__

View File

@ -0,0 +1,201 @@
/*
* Copyright (c) 2004 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Gabe Black
* Ali Saidi
* Nathan Binkert
*/
//The purpose of this file is to provide endainness conversion utility
//functions. Depending on the endianness of the guest system, either
//the LittleEndianGuest or BigEndianGuest namespace is used.
#ifndef __SIM_BYTE_SWAP_HH__
#define __SIM_BYTE_SWAP_HH__
#include "base/bigint.hh"
#include "base/misc.hh"
#include "base/types.hh"
// This lets us figure out what the byte order of the host system is
#if defined(__linux__)
#include <endian.h>
// If this is a linux system, lets used the optimized definitions if they exist.
// If one doesn't exist, we pretty much get what is listed below, so it all
// works out
#include <byteswap.h>
#elif defined (__sun)
#include <sys/isa_defs.h>
#else
#include <machine/endian.h>
#endif
#if defined(__APPLE__)
#include <libkern/OSByteOrder.h>
#endif
enum ByteOrder {BigEndianByteOrder, LittleEndianByteOrder};
//These functions actually perform the swapping for parameters
//of various bit lengths
inline uint64_t
swap_byte64(uint64_t x)
{
#if defined(__linux__)
return bswap_64(x);
#elif defined(__APPLE__)
return OSSwapInt64(x);
#else
return (uint64_t)((((uint64_t)(x) & 0xff) << 56) |
((uint64_t)(x) & 0xff00ULL) << 40 |
((uint64_t)(x) & 0xff0000ULL) << 24 |
((uint64_t)(x) & 0xff000000ULL) << 8 |
((uint64_t)(x) & 0xff00000000ULL) >> 8 |
((uint64_t)(x) & 0xff0000000000ULL) >> 24 |
((uint64_t)(x) & 0xff000000000000ULL) >> 40 |
((uint64_t)(x) & 0xff00000000000000ULL) >> 56) ;
#endif
}
inline uint32_t
swap_byte32(uint32_t x)
{
#if defined(__linux__)
return bswap_32(x);
#elif defined(__APPLE__)
return OSSwapInt32(x);
#else
return (uint32_t)(((uint32_t)(x) & 0xff) << 24 |
((uint32_t)(x) & 0xff00) << 8 | ((uint32_t)(x) & 0xff0000) >> 8 |
((uint32_t)(x) & 0xff000000) >> 24);
#endif
}
inline uint16_t
swap_byte16(uint16_t x)
{
#if defined(__linux__)
return bswap_16(x);
#elif defined(__APPLE__)
return OSSwapInt16(x);
#else
return (uint16_t)(((uint16_t)(x) & 0xff) << 8 |
((uint16_t)(x) & 0xff00) >> 8);
#endif
}
// This function lets the compiler figure out how to call the
// swap_byte functions above for different data types. Since the
// sizeof() values are known at compile time, it should inline to a
// direct call to the right swap_byteNN() function.
template <typename T>
inline T swap_byte(T x) {
if (sizeof(T) == 8)
return swap_byte64((uint64_t)x);
else if (sizeof(T) == 4)
return swap_byte32((uint32_t)x);
else if (sizeof(T) == 2)
return swap_byte16((uint16_t)x);
else if (sizeof(T) == 1)
return x;
else
panic("Can't byte-swap values larger than 64 bits");
}
template<>
inline Twin64_t swap_byte<Twin64_t>(Twin64_t x)
{
x.a = swap_byte(x.a);
x.b = swap_byte(x.b);
return x;
}
template<>
inline Twin32_t swap_byte<Twin32_t>(Twin32_t x)
{
x.a = swap_byte(x.a);
x.b = swap_byte(x.b);
return x;
}
//The conversion functions with fixed endianness on both ends don't need to
//be in a namespace
template <typename T> 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> 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> 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
namespace BigEndianGuest
{
const ByteOrder GuestByteOrder = BigEndianByteOrder;
template <typename T>
inline T gtole(T value) {return betole(value);}
template <typename T>
inline T letog(T value) {return letobe(value);}
template <typename T>
inline T gtobe(T value) {return value;}
template <typename T>
inline T betog(T value) {return value;}
template <typename T>
inline T htog(T value) {return htobe(value);}
template <typename T>
inline T gtoh(T value) {return betoh(value);}
}
namespace LittleEndianGuest
{
const ByteOrder GuestByteOrder = LittleEndianByteOrder;
template <typename T>
inline T gtole(T value) {return value;}
template <typename T>
inline T letog(T value) {return value;}
template <typename T>
inline T gtobe(T value) {return letobe(value);}
template <typename T>
inline T betog(T value) {return betole(value);}
template <typename T>
inline T htog(T value) {return htole(value);}
template <typename T>
inline T gtoh(T value) {return letoh(value);}
}
#endif // __SIM_BYTE_SWAP_HH__

View File

@ -0,0 +1,131 @@
/*
* Copyright (c) 2006 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Nathan Binkert
* Steve Reinhardt
*/
#include <iostream>
#include <string>
#include "base/callback.hh"
#include "base/output.hh"
#include "sim/core.hh"
using namespace std;
Tick _curTick = 0;
namespace SimClock {
/// The simulated frequency of curTick(). (In ticks per second)
Tick Frequency;
namespace Float {
double s;
double ms;
double us;
double ns;
double ps;
double Hz;
double kHz;
double MHz;
double GHZ;
} // namespace Float
namespace Int {
Tick s;
Tick ms;
Tick us;
Tick ns;
Tick ps;
} // namespace Float
} // namespace SimClock
void
setClockFrequency(Tick ticksPerSecond)
{
using namespace SimClock;
Frequency = ticksPerSecond;
Float::s = static_cast<double>(Frequency);
Float::ms = Float::s / 1.0e3;
Float::us = Float::s / 1.0e6;
Float::ns = Float::s / 1.0e9;
Float::ps = Float::s / 1.0e12;
Float::Hz = 1.0 / Float::s;
Float::kHz = 1.0 / Float::ms;
Float::MHz = 1.0 / Float::us;
Float::GHZ = 1.0 / Float::ns;
Int::s = Frequency;
Int::ms = Int::s / 1000;
Int::us = Int::ms / 1000;
Int::ns = Int::us / 1000;
Int::ps = Int::ns / 1000;
}
void
setOutputDir(const string &dir)
{
simout.setDirectory(dir);
}
/**
* Queue of C++ callbacks to invoke on simulator exit.
*/
inline CallbackQueue &
exitCallbacks()
{
static CallbackQueue theQueue;
return theQueue;
}
/**
* Register an exit callback.
*/
void
registerExitCallback(Callback *callback)
{
exitCallbacks().add(callback);
}
/**
* Do C++ simulator exit processing. Exported to SWIG to be invoked
* when simulator terminates via Python's atexit mechanism.
*/
void
doExitCleanup()
{
exitCallbacks().process();
exitCallbacks().clear();
cout.flush();
}

View File

@ -0,0 +1,102 @@
/*
* Copyright (c) 2006 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Nathan Binkert
* Steve Reinhardt
*/
#ifndef __SIM_CORE_HH__
#define __SIM_CORE_HH__
/** @file This header provides some core simulator functionality such as time
* information, output directory and exit events
*/
#include <string>
#include "base/types.hh"
/// The universal simulation clock.
extern Tick _curTick;
inline Tick curTick() { return _curTick; }
inline void curTick(Tick newVal) { _curTick = newVal; }
const Tick retryTime = 1000;
/// These are variables that are set based on the simulator frequency
///@{
namespace SimClock {
extern Tick Frequency; ///< The number of ticks that equal one second
namespace Float {
/** These variables equal the number of ticks in the unit of time they're
* named after in a double.
* @{
*/
extern double s; ///< second
extern double ms; ///< millisecond
extern double us; ///< microsecond
extern double ns; ///< nanosecond
extern double ps; ///< picosecond
/** @} */
/** These variables the inverse of above. They're all < 1.
* @{
*/
extern double Hz; ///< Hz
extern double kHz; ///< kHz
extern double MHz; ///< MHz
extern double GHZ; ///< GHz
/** @}*/
} // namespace Float
/** These variables equal the number of ticks in the unit of time they're
* named after in a 64 bit integer.
*
* @{
*/
namespace Int {
extern Tick s; ///< second
extern Tick ms; ///< millisecond
extern Tick us; ///< microsecond
extern Tick ns; ///< nanosecond
extern Tick ps; ///< picosecond
/** @} */
} // namespace Int
} // namespace SimClock
/** @} */
void setClockFrequency(Tick ticksPerSecond);
void setOutputDir(const std::string &dir);
class Callback;
void registerExitCallback(Callback *callback);
void doExitCleanup();
#endif /* __SIM_CORE_HH__ */

View File

@ -0,0 +1,140 @@
/*
* Copyright (c) 2003-2005 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Nathan Binkert
* Steve Reinhardt
*/
#include <Python.h>
#include <string>
#include <vector>
#include "base/debug.hh"
#include "sim/debug.hh"
#include "sim/eventq.hh"
#include "sim/sim_events.hh"
#include "sim/sim_exit.hh"
using namespace std;
//
// Debug event: place a breakpoint on the process function and
// schedule the event to break at a particular cycle
//
struct DebugBreakEvent : public Event
{
DebugBreakEvent();
void process(); // process event
virtual const char *description() const;
};
//
// constructor: schedule at specified time
//
DebugBreakEvent::DebugBreakEvent()
: Event(Debug_Break_Pri, AutoDelete)
{
}
//
// handle debug event: set debugger breakpoint on this function
//
void
DebugBreakEvent::process()
{
Debug::breakpoint();
}
const char *
DebugBreakEvent::description() const
{
return "debug breakpoint";
}
//
// handy function to schedule DebugBreakEvent on main event queue
// (callable from debugger)
//
void
schedBreakCycle(Tick when)
{
mainEventQueue.schedule(new DebugBreakEvent, when);
warn("need to stop all queues");
}
///
/// Function to cause the simulator to take a checkpoint from the debugger
///
void
takeCheckpoint(Tick when)
{
if (!when)
when = curTick() + 1;
exitSimLoop("checkpoint", 0, when, 0);
}
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;
}

View File

@ -0,0 +1,60 @@
/*
* Copyright (c) 2003-2005 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Nathan Binkert
*/
#ifndef __SIM_DEBUG_HH__
#define __SIM_DEBUG_HH__
#include "base/types.hh"
/** @file This file provides the definitions for some useful debugging
* functions. These are intended to be called from a debugger such as
* gdb.
*/
/** Cause the simulator to execute a breakpoint
* @param when the cycle to break
*/
void schedBreakCycle(Tick when);
/** Cause the simulator to return to python to create a checkpoint
* @param when the cycle to break
*/
void takeCheckpoint(Tick when);
/** Dump all the events currently on the event queue
*/
void eventqDump();
int getRemoteGDBPort();
// Remote gdb base port. 0 disables remote gdb.
void setRemoteGDBPort(int port);
#endif // __SIM_DEBUG_HH__

View File

@ -0,0 +1,432 @@
/*
* 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: Steve Reinhardt
* Nathan Binkert
* Steve Raasch
*/
#include <cassert>
#include <iostream>
#include <string>
#include <vector>
#include "base/hashmap.hh"
#include "base/misc.hh"
#include "base/trace.hh"
#include "cpu/smt.hh"
#include "debug/Config.hh"
#include "sim/core.hh"
#include "sim/eventq.hh"
using namespace std;
//
// Main Event Queue
//
// Events on this queue are processed at the *beginning* of each
// cycle, before the pipeline simulation is performed.
//
EventQueue mainEventQueue("Main Event Queue");
#ifndef NDEBUG
Counter Event::instanceCounter = 0;
#endif
Event::~Event()
{
assert(!scheduled());
flags = 0;
}
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)
{
// Deal with the head case
if (!head || *event <= *head) {
head = Event::insertBefore(event, head);
return;
}
// 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;
}
// 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!");
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)
panic("event not found!");
// 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->nextBin;
while (curr && *curr < *event) {
prev = curr;
curr = curr->nextBin;
}
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 *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->flags.isSet(Event::AutoDelete)); // would be silly
return event;
}
} else {
event->flags.clear(Event::Squashed);
}
if (event->flags.isSet(Event::AutoDelete) && !event->scheduled())
delete event;
return NULL;
}
void
Event::serialize(std::ostream &os)
{
SERIALIZE_SCALAR(_when);
SERIALIZE_SCALAR(_priority);
short _flags = flags;
SERIALIZE_SCALAR(_flags);
}
void
Event::unserialize(Checkpoint *cp, const string &section)
{
if (scheduled())
mainEventQueue.deschedule(this);
UNSERIALIZE_SCALAR(_when);
UNSERIALIZE_SCALAR(_priority);
short _flags;
UNSERIALIZE_SCALAR(_flags);
// Old checkpoints had no concept of the Initialized flag
// so restoring from old checkpoints always fail.
// Events are initialized on construction but original code
// "flags = _flags" would just overwrite the initialization.
// So, read in the checkpoint flags, but then set the Initialized
// flag on top of it in order to avoid failures.
assert(initialized());
flags = _flags;
flags.set(Initialized);
// 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)
bool wasScheduled = flags.isSet(Scheduled) && !flags.isSet(Squashed);
flags.clear(Squashed | Scheduled);
if (wasScheduled) {
DPRINTF(Config, "rescheduling at %d\n", _when);
mainEventQueue.schedule(this, _when);
}
}
void
EventQueue::serialize(ostream &os)
{
std::list<Event *> eventPtrs;
int numEvents = 0;
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;
}
nextBin = nextBin->nextBin;
}
SERIALIZE_SCALAR(numEvents);
for (std::list<Event *>::iterator it = eventPtrs.begin();
it != eventPtrs.end(); ++it) {
(*it)->nameOut(os);
(*it)->serialize(os);
}
}
void
EventQueue::unserialize(Checkpoint *cp, const std::string &section)
{
int numEvents;
UNSERIALIZE_SCALAR(numEvents);
std::string eventName;
for (int i = 0; i < numEvents; i++) {
// get the pointer value associated with the event
paramIn(cp, section, csprintf("event%d", i), eventName);
// create the event based on its pointer value
Serializable::create(cp, eventName);
}
}
void
EventQueue::dump() const
{
cprintf("============================================================\n");
cprintf("EventQueue Dump (cycle %d)\n", curTick());
cprintf("------------------------------------------------------------\n");
if (empty())
cprintf("<No Events>\n");
else {
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;
}
Event*
EventQueue::replaceHead(Event* s)
{
Event* t = head;
head = s;
return t;
}
void
dumpMainQueue()
{
mainEventQueue.dump();
}
const char *
Event::description() const
{
return "generic";
}
void
Event::trace(const char *action)
{
// This DPRINTF is unconditional because calls to this function
// are protected by an 'if (DTRACE(Event))' in the inlined Event
// methods.
//
// This is just a default implementation for derived classes where
// it's not worth doing anything special. If you want to put a
// more informative message in the trace, override this method on
// the particular subclass where you have the information that
// needs to be printed.
DPRINTFN("%s event %s @ %d\n", description(), action, when());
}
void
Event::dump() const
{
cprintf("Event %s (%s)\n", name(), description());
cprintf("Flags: %#x\n", flags);
#ifdef EVENTQ_DEBUG
cprintf("Created: %d\n", whenCreated);
#endif
if (scheduled()) {
#ifdef EVENTQ_DEBUG
cprintf("Scheduled at %d\n", whenScheduled);
#endif
cprintf("Scheduled for %d, priority %d\n", when(), _priority);
} else {
cprintf("Not Scheduled\n");
}
}
EventQueue::EventQueue(const string &n)
: objName(n), head(NULL)
{}

View File

@ -0,0 +1,603 @@
/*
* Copyright (c) 2000-2005 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Steve Reinhardt
* Nathan Binkert
*/
/* @file
* EventQueue interfaces
*/
#ifndef __SIM_EVENTQ_HH__
#define __SIM_EVENTQ_HH__
#include <algorithm>
#include <cassert>
#include <climits>
#include <iosfwd>
#include <string>
#include "base/flags.hh"
#include "base/misc.hh"
#include "base/trace.hh"
#include "base/types.hh"
#include "debug/Event.hh"
#include "sim/serialize.hh"
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
{
friend class EventQueue;
protected:
typedef unsigned short FlagsType;
typedef ::Flags<FlagsType> Flags;
static const FlagsType PublicRead = 0x003f; // public readable flags
static const FlagsType PublicWrite = 0x001d; // public writable flags
static const FlagsType Squashed = 0x0001; // has been squashed
static const FlagsType Scheduled = 0x0002; // has been scheduled
static const FlagsType AutoDelete = 0x0004; // delete after dispatch
static const FlagsType AutoSerialize = 0x0008; // must be serialized
static const FlagsType IsExitEvent = 0x0010; // special exit event
static const FlagsType IsMainQueue = 0x0020; // on main event queue
static const FlagsType Initialized = 0x7a40; // somewhat random bits
static const FlagsType InitMask = 0xffc0; // mask for init bits
bool
initialized() const
{
return this && (flags & InitMask) == Initialized;
}
public:
typedef int8_t Priority;
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
Priority _priority; //!< event priority
Flags flags;
#ifndef NDEBUG
/// Global counter to generate unique IDs for Event instances
static Counter instanceCounter;
/// This event's unique ID. We can also use pointer values for
/// this but they're not consistent across runs making debugging
/// more difficult. Thus we use a global counter value when
/// debugging.
Counter instance;
/// queue to which this event belongs (though it may or may not be
/// scheduled on this queue yet)
EventQueue *queue;
#endif
#ifdef EVENTQ_DEBUG
Tick whenCreated; //!< time created
Tick whenScheduled; //!< time scheduled
#endif
void
setWhen(Tick when, EventQueue *q)
{
_when = when;
#ifndef NDEBUG
queue = q;
#endif
#ifdef EVENTQ_DEBUG
whenScheduled = curTick();
#endif
}
protected:
/// Accessor for flags.
Flags
getFlags() const
{
return flags & PublicRead;
}
bool
isFlagSet(Flags _flags) const
{
assert(_flags.noneSet(~PublicRead));
return flags.isSet(_flags);
}
/// Accessor for flags.
void
setFlags(Flags _flags)
{
assert(_flags.noneSet(~PublicWrite));
flags.set(_flags);
}
void
clearFlags(Flags _flags)
{
assert(_flags.noneSet(~PublicWrite));
flags.clear(_flags);
}
void
clearFlags()
{
flags.clear(PublicWrite);
}
// 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.
/// Minimum priority
static const Priority Minimum_Pri = SCHAR_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).
static const Priority Trace_Enable_Pri = -101;
/// Breakpoints should happen before anything else (except
/// enabling trace output), so we don't miss any action when
/// debugging.
static const Priority 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.
static const Priority CPU_Switch_Pri = -31;
/// For some reason "delayed" inter-cluster writebacks are
/// scheduled before regular writebacks (which have default
/// priority). Steve?
static const Priority Delayed_Writeback_Pri = -1;
/// Default is zero for historical reasons.
static const Priority Default_Pri = 0;
/// Serailization needs to occur before tick events also, so
/// that a serialize/unserialize is identical to an on-line
/// CPU switch.
static const Priority Serialize_Pri = 32;
/// CPU ticks must come after other associated CPU events
/// (such as writebacks).
static const Priority CPU_Tick_Pri = 50;
/// Statistics events (dump, reset, etc.) come after
/// everything else, but before exit.
static const Priority Stat_Event_Pri = 90;
/// Progress events come at the end.
static const Priority Progress_Event_Pri = 95;
/// If we want to exit on this cycle, it's the very last thing
/// we do.
static const Priority Sim_Exit_Pri = 100;
/// Maximum priority
static const Priority Maximum_Pri = SCHAR_MAX;
/*
* Event constructor
* @param queue that the event gets scheduled on
*/
Event(Priority p = Default_Pri, Flags f = 0)
: nextBin(NULL), nextInBin(NULL), _priority(p),
flags(Initialized | f)
{
assert(f.noneSet(~PublicWrite));
#ifndef NDEBUG
instance = ++instanceCounter;
queue = NULL;
#endif
#ifdef EVENTQ_DEBUG
whenCreated = curTick();
whenScheduled = 0;
#endif
}
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
/// describing the event class.
virtual const char *description() const;
/// Dump the current event data
void dump() const;
public:
/*
* This member function is invoked when the event is processed
* (occurs). There is no default implementation; each subclass
* must provide its own implementation. The event is not
* automatically deleted after it is processed (to allow for
* statically allocated event objects).
*
* If the AutoDestroy flag is set, the object is deleted once it
* is processed.
*/
virtual void process() = 0;
/// Determine if the current event is scheduled
bool scheduled() const { return flags.isSet(Scheduled); }
/// Squash the current event
void squash() { flags.set(Squashed); }
/// Check whether the event is squashed
bool squashed() const { return flags.isSet(Squashed); }
/// See if this is a SimExitEvent (without resorting to RTTI)
bool isExitEvent() const { return flags.isSet(IsExitEvent); }
/// Get the time that the event is scheduled
Tick when() const { return _when; }
/// Get the event priority
Priority priority() const { return _priority; }
#ifndef SWIG
struct priority_compare
: public std::binary_function<Event *, Event *, bool>
{
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);
#endif
};
#ifndef SWIG
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
/*
* Queue of events sorted in time order
*/
class EventQueue : public Serializable
{
private:
std::string objName;
Event *head;
void insert(Event *event);
void remove(Event *event);
EventQueue(const EventQueue &);
const EventQueue &operator=(const EventQueue &);
public:
EventQueue(const std::string &n);
virtual const std::string name() const { return objName; }
// schedule the given event on this queue
void schedule(Event *event, Tick when);
void deschedule(Event *event);
void reschedule(Event *event, Tick when, bool always = false);
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)
{
while (!empty()) {
if (nextTick() > when)
break;
/**
* @todo this assert is a good bug catcher. I need to
* make it true again.
*/
//assert(head->when() >= when && "event scheduled in the past");
serviceOne();
}
}
// return true if no events are queued
bool empty() const { return head == NULL; }
void dump() const;
bool debugVerify() const;
/**
* function for replacing the head of the event queue, so that a
* different set of events can run without disturbing events that have
* already been scheduled. Already scheduled events can be processed
* by replacing the original head back.
* USING THIS FUNCTION CAN BE DANGEROUS TO THE HEALTH OF THE SIMULATOR.
* NOT RECOMMENDED FOR USE.
*/
Event* replaceHead(Event* s);
#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;
public:
EventManager(EventManager &em) : eventq(em.queue()) {}
EventManager(EventManager *em) : eventq(em ? em->queue() : NULL) {}
EventManager(EventQueue *eq) : eventq(eq) {}
EventQueue *
queue() const
{
return eventq;
}
operator EventQueue *() const
{
return eventq;
}
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);
}
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);
}
};
inline void
EventQueue::schedule(Event *event, Tick when)
{
// Typecasting Tick->Utick here since gcc
// complains about signed overflow
assert((UTick)when >= (UTick)curTick());
assert(!event->scheduled());
assert(event->initialized());
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");
}
inline void
EventQueue::deschedule(Event *event)
{
assert(event->scheduled());
assert(event->initialized());
remove(event);
event->flags.clear(Event::Squashed);
event->flags.clear(Event::Scheduled);
if (DTRACE(Event))
event->trace("descheduled");
if (event->flags.isSet(Event::AutoDelete))
delete event;
}
inline void
EventQueue::reschedule(Event *event, Tick when, bool always)
{
// Typecasting Tick->Utick here since gcc
// complains about signed overflow
assert((UTick)when >= (UTick)curTick());
assert(always || event->scheduled());
assert(event->initialized());
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");
}
template <class T, void (T::* F)()>
void
DelayFunction(EventQueue *eventq, Tick when, T *object)
{
class DelayEvent : public Event
{
private:
T *object;
public:
DelayEvent(T *o)
: Event(Default_Pri, AutoDelete), object(o)
{ }
void process() { (object->*F)(); }
const char *description() const { return "delay"; }
};
eventq->schedule(new DelayEvent(object), when);
}
template <class T, void (T::* F)()>
class EventWrapper : public Event
{
private:
T *object;
public:
EventWrapper(T *obj, bool del = false, Priority p = Default_Pri)
: Event(p), object(obj)
{
if (del)
setFlags(AutoDelete);
}
EventWrapper(T &obj, bool del = false, Priority p = Default_Pri)
: Event(p), object(&obj)
{
if (del)
setFlags(AutoDelete);
}
void process() { (object->*F)(); }
const std::string
name() const
{
return object->name() + ".wrapped_event";
}
const char *description() const { return "EventWrapped"; }
};
#endif
#endif // __SIM_EVENTQ_HH__

View File

@ -0,0 +1,40 @@
/*
* Copyright (c) 2010 Advanced Micro Devices, Inc.
* 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_FAULT_FWD_HH__
#define __SIM_FAULT_FWD_HH__
class FaultBase;
template <class T> class RefCountingPtr;
typedef RefCountingPtr<FaultBase> Fault;
FaultBase * const NoFault = 0;
#endif // __SIM_FAULT_FWD_HH__

View File

@ -0,0 +1,77 @@
/*
* Copyright (c) 2003-2005 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Nathan Binkert
* Gabe Black
*/
#include "arch/isa_traits.hh"
#include "base/misc.hh"
#include "cpu/base.hh"
#include "cpu/thread_context.hh"
#include "debug/Fault.hh"
#include "mem/page_table.hh"
#include "sim/faults.hh"
#include "sim/full_system.hh"
#include "sim/process.hh"
void FaultBase::invoke(ThreadContext * tc, StaticInstPtr inst)
{
if (FullSystem) {
DPRINTF(Fault, "Fault %s at PC: %s\n", name(), tc->pcState());
assert(!tc->misspeculating());
} else {
panic("fault (%s) detected @ PC %s", name(), tc->pcState());
}
}
void UnimpFault::invoke(ThreadContext * tc, StaticInstPtr inst)
{
panic("Unimpfault: %s\n", panicStr.c_str());
}
void ReExec::invoke(ThreadContext *tc, StaticInstPtr inst)
{
tc->pcState(tc->pcState());
}
void GenericPageTableFault::invoke(ThreadContext *tc, StaticInstPtr inst)
{
bool handled = false;
if (!FullSystem) {
Process *p = tc->getProcessPtr();
handled = p->fixupStackFault(vaddr);
}
if (!handled)
panic("Page table fault when accessing virtual address %#x\n", vaddr);
}
void GenericAlignmentFault::invoke(ThreadContext *tc, StaticInstPtr inst)
{
panic("Alignment fault when accessing virtual address %#x\n", vaddr);
}

View File

@ -0,0 +1,106 @@
/*
* Copyright (c) 2003-2005 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Nathan Binkert
* Gabe Black
*/
#ifndef __FAULTS_HH__
#define __FAULTS_HH__
#include "base/refcnt.hh"
#include "base/types.hh"
#include "cpu/static_inst.hh"
#include "sim/fault_fwd.hh"
#include "sim/stats.hh"
class ThreadContext;
typedef const char * FaultName;
typedef Stats::Scalar FaultStat;
// Each class has it's name statically define in _name,
// and has a virtual function to access it's name.
// The function is necessary because otherwise, all objects
// which are being accessed cast as a FaultBase * (namely
// all faults returned using the Fault type) will use the
// generic FaultBase name.
class FaultBase : public RefCounted
{
public:
virtual FaultName name() const = 0;
virtual void invoke(ThreadContext * tc,
StaticInstPtr inst = StaticInst::nullStaticInstPtr);
};
class UnimpFault : public FaultBase
{
private:
std::string panicStr;
public:
UnimpFault(std::string _str)
: panicStr(_str)
{ }
FaultName name() const {return "Unimplemented simulator feature";}
void invoke(ThreadContext * tc,
StaticInstPtr inst = StaticInst::nullStaticInstPtr);
};
class ReExec : public FaultBase
{
public:
virtual FaultName name() const { return "Re-execution fault";}
ReExec() {}
void invoke(ThreadContext *tc,
StaticInstPtr inst = StaticInst::nullStaticInstPtr);
};
class GenericPageTableFault : public FaultBase
{
private:
Addr vaddr;
public:
FaultName name() const {return "Generic page table fault";}
GenericPageTableFault(Addr va) : vaddr(va) {}
void invoke(ThreadContext * tc,
StaticInstPtr inst = StaticInst::nullStaticInstPtr);
};
class GenericAlignmentFault : public FaultBase
{
private:
Addr vaddr;
public:
FaultName name() const {return "Generic alignment fault";}
GenericAlignmentFault(Addr va) : vaddr(va) {}
void invoke(ThreadContext * tc,
StaticInstPtr inst = StaticInst::nullStaticInstPtr);
};
#endif // __FAULTS_HH__

View File

@ -0,0 +1,48 @@
/*
* Copyright (c) 2011 Google
* 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_FULL_SYSTEM_HH__
#define __SIM_FULL_SYSTEM_HH__
/**
* The FullSystem variable can be used to determine the current mode
* of simulation.
*/
extern bool FullSystem;
/**
* In addition to the boolean flag we make use of an unsigned int
* since the CPU instruction decoder makes use of the variable in
* switch statements. A value of 0 signifies syscall emulation, and
* any other value full system.
*/
extern unsigned int FullSystemInt;
#endif // __SIM_FULL_SYSTEM_HH__

View File

@ -0,0 +1,274 @@
/*
* 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 <zlib.h>
#include <csignal>
#include <iostream>
#include <list>
#include <string>
#include "base/cprintf.hh"
#include "base/misc.hh"
#include "base/types.hh"
#include "sim/async.hh"
#include "sim/core.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);
}
// 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))
EmbeddedPython *EmbeddedPython::importer = NULL;
PyObject *EmbeddedPython::importerModule = NULL;
EmbeddedPython::EmbeddedPython(const char *filename, const char *abspath,
const char *modpath, const unsigned char *code, int zlen, int len)
: filename(filename), abspath(abspath), modpath(modpath), code(code),
zlen(zlen), len(len)
{
// if we've added the importer keep track of it because we need it
// to bootstrap.
if (string(modpath) == string("importer"))
importer = this;
else
getList().push_back(this);
}
list<EmbeddedPython *> &
EmbeddedPython::getList()
{
static list<EmbeddedPython *> the_list;
return the_list;
}
/*
* Uncompress and unmarshal the code object stored in the
* EmbeddedPython
*/
PyObject *
EmbeddedPython::getCode() const
{
Bytef marshalled[len];
uLongf unzlen = len;
int ret = uncompress(marshalled, &unzlen, (const Bytef *)code, zlen);
if (ret != Z_OK)
panic("Could not uncompress code: %s\n", zError(ret));
assert(unzlen == (uLongf)len);
return PyMarshal_ReadObjectFromString((char *)marshalled, len);
}
bool
EmbeddedPython::addModule() const
{
PyObject *code = getCode();
PyObject *result = PyObject_CallMethod(importerModule, PyCC("add_module"),
PyCC("sssO"), filename, abspath, modpath, code);
if (!result) {
PyErr_Print();
return false;
}
Py_DECREF(result);
return true;
}
/*
* Load and initialize all of the python parts of M5, including Swig
* and the embedded module importer.
*/
int
EmbeddedPython::initAll()
{
// Load the importer module
PyObject *code = importer->getCode();
importerModule = PyImport_ExecCodeModule(PyCC("importer"), code);
if (!importerModule) {
PyErr_Print();
return 1;
}
// Load the rest of the embedded python files into the embedded
// python importer
list<EmbeddedPython *>::iterator i = getList().begin();
list<EmbeddedPython *>::iterator end = getList().end();
for (; i != end; ++i)
if (!(*i)->addModule())
return 1;
return 0;
}
EmbeddedSwig::EmbeddedSwig(void (*init_func)())
: initFunc(init_func)
{
getList().push_back(this);
}
list<EmbeddedSwig *> &
EmbeddedSwig::getList()
{
static list<EmbeddedSwig *> the_list;
return the_list;
}
void
EmbeddedSwig::initAll()
{
// initialize SWIG modules. initSwig() is autogenerated and calls
// all of the individual swig initialization functions.
list<EmbeddedSwig *>::iterator i = getList().begin();
list<EmbeddedSwig *>::iterator end = getList().end();
for (; i != end; ++i)
(*i)->initFunc();
}
int
initM5Python()
{
EmbeddedSwig::initAll();
return EmbeddedPython::initAll();
}
/*
* Make the commands array weak so that they can be overridden (used
* by unit tests to specify a different python main function.
*/
const char * __attribute__((weak)) m5MainCommands[] = {
"import m5",
"m5.main()",
0 // sentinel is required
};
/*
* 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;
const char **command = m5MainCommands;
// evaluate each command in the m5MainCommands array (basically a
// bunch of python statements.
while (*command) {
result = PyRun_String(*command, Py_file_input, dict, dict);
if (!result) {
PyErr_Print();
return 1;
}
Py_DECREF(result);
command++;
}
return 0;
}
PyMODINIT_FUNC
initm5(void)
{
initM5Python();
PyImport_ImportModule(PyCC("m5"));
}

View File

@ -0,0 +1,81 @@
/*
* 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.
*/
#include <list>
#include <inttypes.h>
#ifndef PyObject_HEAD
struct _object;
typedef _object PyObject;
#endif
struct EmbeddedPython
{
const char *filename;
const char *abspath;
const char *modpath;
const uint8_t *code;
int zlen;
int len;
EmbeddedPython(const char *filename, const char *abspath,
const char *modpath, const uint8_t *code, int zlen, int len);
PyObject *getCode() const;
bool addModule() const;
static EmbeddedPython *importer;
static PyObject *importerModule;
static std::list<EmbeddedPython *> &getList();
static int initAll();
};
struct EmbeddedSwig
{
void (*initFunc)();
EmbeddedSwig(void (*init_func)());
static std::list<EmbeddedSwig *> &getList();
static void initAll();
};
void initSignals();
int initM5Python();
int m5Main(int argc, char **argv);
#endif // __SIM_INIT_HH__

View File

@ -0,0 +1,175 @@
/*
* 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 __INSTRECORD_HH__
#define __INSTRECORD_HH__
#include "base/bigint.hh"
#include "base/trace.hh"
#include "base/types.hh"
#include "cpu/inst_seq.hh" // for InstSeqNum
#include "cpu/static_inst.hh"
#include "sim/sim_object.hh"
class ThreadContext;
namespace Trace {
class InstRecord
{
protected:
Tick when;
// The following fields are initialized by the constructor and
// thus guaranteed to be valid.
ThreadContext *thread;
// need to make this ref-counted so it doesn't go away before we
// dump the record
StaticInstPtr staticInst;
TheISA::PCState pc;
StaticInstPtr macroStaticInst;
bool misspeculating;
bool predicate;
// The remaining fields are only valid for particular instruction
// types (e.g, addresses for memory ops) or when particular
// options are enabled (e.g., tracing full register contents).
// Each data field has an associated valid flag to indicate
// whether the data field is valid.
Addr addr;
bool addr_valid;
union {
uint64_t as_int;
double as_double;
} data;
enum {
DataInvalid = 0,
DataInt8 = 1, // set to equal number of bytes
DataInt16 = 2,
DataInt32 = 4,
DataInt64 = 8,
DataDouble = 3
} data_status;
InstSeqNum fetch_seq;
bool fetch_seq_valid;
InstSeqNum cp_seq;
bool cp_seq_valid;
public:
InstRecord(Tick _when, ThreadContext *_thread,
const StaticInstPtr _staticInst,
TheISA::PCState _pc, bool spec,
const StaticInstPtr _macroStaticInst = NULL)
: when(_when), thread(_thread),
staticInst(_staticInst), pc(_pc),
macroStaticInst(_macroStaticInst),
misspeculating(spec), predicate(true)
{
data_status = DataInvalid;
addr_valid = false;
fetch_seq_valid = false;
cp_seq_valid = false;
}
virtual ~InstRecord() { }
void setAddr(Addr a) { addr = a; addr_valid = true; }
void setData(Twin64_t d) { data.as_int = d.a; data_status = DataInt64; }
void setData(Twin32_t d) { data.as_int = d.a; data_status = DataInt32; }
void setData(uint64_t d) { data.as_int = d; data_status = DataInt64; }
void setData(uint32_t d) { data.as_int = d; data_status = DataInt32; }
void setData(uint16_t d) { data.as_int = d; data_status = DataInt16; }
void setData(uint8_t d) { data.as_int = d; data_status = DataInt8; }
void setData(int64_t d) { setData((uint64_t)d); }
void setData(int32_t d) { setData((uint32_t)d); }
void setData(int16_t d) { setData((uint16_t)d); }
void setData(int8_t d) { setData((uint8_t)d); }
void setData(double d) { data.as_double = d; data_status = DataDouble; }
void setFetchSeq(InstSeqNum seq)
{ fetch_seq = seq; fetch_seq_valid = true; }
void setCPSeq(InstSeqNum seq)
{ cp_seq = seq; cp_seq_valid = true; }
void setPredicate(bool val) { predicate = val; }
virtual void dump() = 0;
public:
Tick getWhen() { return when; }
ThreadContext *getThread() { return thread; }
StaticInstPtr getStaticInst() { return staticInst; }
TheISA::PCState getPCState() { return pc; }
StaticInstPtr getMacroStaticInst() { return macroStaticInst; }
bool getMisspeculating() { return misspeculating; }
Addr getAddr() { return addr; }
bool getAddrValid() { return addr_valid; }
uint64_t getIntData() { return data.as_int; }
double getFloatData() { return data.as_double; }
int getDataStatus() { return data_status; }
InstSeqNum getFetchSeq() { return fetch_seq; }
bool getFetchSeqValid() { return fetch_seq_valid; }
InstSeqNum getCpSeq() { return cp_seq; }
bool getCpSeqValid() { return cp_seq_valid; }
};
class InstTracer : public SimObject
{
public:
InstTracer(const Params *p) : SimObject(p)
{}
virtual ~InstTracer()
{};
virtual InstRecord *
getInstRecord(Tick when, ThreadContext *tc,
const StaticInstPtr staticInst, TheISA::PCState pc,
const StaticInstPtr macroStaticInst = NULL) = 0;
};
} // namespace Trace
#endif // __INSTRECORD_HH__

View File

@ -0,0 +1,64 @@
/*
* 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 "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)
{
int ret;
// Initialize m5 special signal handling.
initSignals();
Py_SetProgramName(argv[0]);
// initialize embedded Python interpreter
Py_Initialize();
// Initialize the embedded m5 python library
ret = initM5Python();
if (ret == 0) {
// start m5
ret = m5Main(argc, argv);
}
// clean up Python intepreter.
Py_Finalize();
return ret;
}

View File

@ -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__

View File

@ -0,0 +1,736 @@
/*
* Copyright (c) 2012 ARM Limited
* All rights reserved
*
* The license below extends only to copyright in the software and shall
* not be construed as granting a license to any other intellectual
* property including but not limited to intellectual property relating
* to a hardware implementation of the functionality of the software
* licensed hereunder. You may use the software subject to the license
* terms below provided that you ensure that this notice is replicated
* unmodified and in its entirety in all distributions of the software,
* modified or unmodified, in source code or in binary form.
*
* 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: Nathan Binkert
* Steve Reinhardt
* Ali Saidi
*/
#include <fcntl.h>
#include <unistd.h>
#include <cstdio>
#include <string>
#include "base/loader/object_file.hh"
#include "base/loader/symtab.hh"
#include "base/intmath.hh"
#include "base/statistics.hh"
#include "config/the_isa.hh"
#include "cpu/thread_context.hh"
#include "mem/page_table.hh"
#include "mem/se_translating_port_proxy.hh"
#include "params/LiveProcess.hh"
#include "params/Process.hh"
#include "sim/debug.hh"
#include "sim/process.hh"
#include "sim/process_impl.hh"
#include "sim/stats.hh"
#include "sim/syscall_emul.hh"
#include "sim/system.hh"
#if THE_ISA == ALPHA_ISA
#include "arch/alpha/linux/process.hh"
#include "arch/alpha/tru64/process.hh"
#elif THE_ISA == SPARC_ISA
#include "arch/sparc/linux/process.hh"
#include "arch/sparc/solaris/process.hh"
#elif THE_ISA == MIPS_ISA
#include "arch/mips/linux/process.hh"
#elif THE_ISA == ARM_ISA
#include "arch/arm/linux/process.hh"
#elif THE_ISA == X86_ISA
#include "arch/x86/linux/process.hh"
#elif THE_ISA == POWER_ISA
#include "arch/power/linux/process.hh"
#else
#error "THE_ISA not set"
#endif
using namespace std;
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 struct AuxVector<uint32_t>;
template struct AuxVector<uint64_t>;
Process::Process(ProcessParams * params)
: SimObject(params), system(params->system),
max_stack_size(params->max_stack_size),
M5_pid(system->allocatePID()),
pTable(new PageTable(name(), M5_pid)),
initVirtMem(system->getSystemPort(), this,
SETranslatingPortProxy::Always)
{
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;
if (in == "stdin" || in == "cin")
stdin_fd = STDIN_FILENO;
else if (in == "None")
stdin_fd = -1;
else
stdin_fd = Process::openInputFile(in);
if (out == "stdout" || out == "cout")
stdout_fd = STDOUT_FILENO;
else if (out == "stderr" || out == "cerr")
stdout_fd = STDERR_FILENO;
else if (out == "None")
stdout_fd = -1;
else
stdout_fd = Process::openOutputFile(out);
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);
// initialize first 3 fds (stdin, stdout, stderr)
Process::FdMap *fdo = &fd_map[STDIN_FILENO];
fdo->fd = stdin_fd;
fdo->filename = in;
fdo->flags = O_RDONLY;
fdo->mode = -1;
fdo->fileOffset = 0;
fdo = &fd_map[STDOUT_FILENO];
fdo->fd = stdout_fd;
fdo->filename = out;
fdo->flags = O_WRONLY | O_CREAT | O_TRUNC;
fdo->mode = 0774;
fdo->fileOffset = 0;
fdo = &fd_map[STDERR_FILENO];
fdo->fd = stderr_fd;
fdo->filename = err;
fdo->flags = O_WRONLY;
fdo->mode = -1;
fdo->fileOffset = 0;
// mark remaining fds as free
for (int i = 3; i <= MAX_FD; ++i) {
Process::FdMap *fdo = &fd_map[i];
fdo->fd = -1;
}
mmap_start = mmap_end = 0;
nxm_start = nxm_end = 0;
// other parameters will be initialized when the program is loaded
}
void
Process::regStats()
{
using namespace Stats;
num_syscalls
.name(name() + ".num_syscalls")
.desc("Number of system calls")
;
}
//
// static helper functions
//
int
Process::openInputFile(const string &filename)
{
int fd = open(filename.c_str(), O_RDONLY);
if (fd == -1) {
perror(NULL);
cerr << "unable to open \"" << filename << "\" for reading\n";
fatal("can't open input file");
}
return fd;
}
int
Process::openOutputFile(const string &filename)
{
int fd = open(filename.c_str(), O_WRONLY | O_CREAT | O_TRUNC, 0664);
if (fd == -1) {
perror(NULL);
cerr << "unable to open \"" << filename << "\" for writing\n";
fatal("can't open output file");
}
return fd;
}
ThreadContext *
Process::findFreeContext()
{
int size = contextIds.size();
ThreadContext *tc;
for (int i = 0; i < size; ++i) {
tc = system->getThreadContext(contextIds[i]);
if (tc->status() == ThreadContext::Halted) {
// inactive context, free to use
return tc;
}
}
return NULL;
}
void
Process::initState()
{
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 = system->getThreadContext(contextIds[0]);
// mark this context as active so it will start ticking.
tc->activate(0);
}
// map simulator fd sim_fd to target fd tgt_fd
void
Process::dup_fd(int sim_fd, int tgt_fd)
{
if (tgt_fd < 0 || tgt_fd > MAX_FD)
panic("Process::dup_fd tried to dup past MAX_FD (%d)", tgt_fd);
Process::FdMap *fdo = &fd_map[tgt_fd];
fdo->fd = sim_fd;
}
// generate new target fd for sim_fd
int
Process::alloc_fd(int sim_fd, string filename, int flags, int mode, bool pipe)
{
// in case open() returns an error, don't allocate a new fd
if (sim_fd == -1)
return -1;
// find first free target fd
for (int free_fd = 0; free_fd <= MAX_FD; ++free_fd) {
Process::FdMap *fdo = &fd_map[free_fd];
if (fdo->fd == -1) {
fdo->fd = sim_fd;
fdo->filename = filename;
fdo->mode = mode;
fdo->fileOffset = 0;
fdo->flags = flags;
fdo->isPipe = pipe;
fdo->readPipeSource = 0;
return free_fd;
}
}
panic("Process::alloc_fd: out of file descriptors!");
}
// free target fd (e.g., after close)
void
Process::free_fd(int tgt_fd)
{
Process::FdMap *fdo = &fd_map[tgt_fd];
if (fdo->fd == -1)
warn("Process::free_fd: request to free unused fd %d", tgt_fd);
fdo->fd = -1;
fdo->filename = "NULL";
fdo->mode = 0;
fdo->fileOffset = 0;
fdo->flags = 0;
fdo->isPipe = false;
fdo->readPipeSource = 0;
}
// look up simulator fd for given target fd
int
Process::sim_fd(int tgt_fd)
{
if (tgt_fd < 0 || tgt_fd > MAX_FD)
return -1;
return fd_map[tgt_fd].fd;
}
Process::FdMap *
Process::sim_fd_obj(int tgt_fd)
{
if (tgt_fd < 0 || tgt_fd > MAX_FD)
return NULL;
return &fd_map[tgt_fd];
}
void
Process::allocateMem(Addr vaddr, int64_t size, bool clobber)
{
int npages = divCeil(size, (int64_t)VMPageSize);
Addr paddr = system->allocPhysPages(npages);
pTable->map(vaddr, paddr, size, clobber);
}
bool
Process::fixupStackFault(Addr vaddr)
{
// Check if this is already on the stack and there's just no page there
// yet.
if (vaddr >= stack_min && vaddr < stack_base) {
allocateMem(roundDown(vaddr, VMPageSize), VMPageSize);
return true;
}
// We've accessed the next page of the stack, so extend it to include
// this address.
if (vaddr < stack_min && vaddr >= stack_base - max_stack_size) {
while (vaddr < stack_min) {
stack_min -= TheISA::PageBytes;
if (stack_base - stack_min > max_stack_size)
fatal("Maximum stack size exceeded\n");
if (stack_base - stack_min > 8 * 1024 * 1024)
fatal("Over max stack size for one thread\n");
allocateMem(stack_min, TheISA::PageBytes);
inform("Increasing stack size by one page.");
};
return true;
}
return false;
}
// find all offsets for currently open files and save them
void
Process::fix_file_offsets()
{
Process::FdMap *fdo_stdin = &fd_map[STDIN_FILENO];
Process::FdMap *fdo_stdout = &fd_map[STDOUT_FILENO];
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;
if (in == "stdin" || in == "cin")
stdin_fd = STDIN_FILENO;
else if (in == "None")
stdin_fd = -1;
else {
// open standard in and seek to the right location
stdin_fd = Process::openInputFile(in);
if (lseek(stdin_fd, fdo_stdin->fileOffset, SEEK_SET) < 0)
panic("Unable to seek to correct location in file: %s", in);
}
if (out == "stdout" || out == "cout")
stdout_fd = STDOUT_FILENO;
else if (out == "stderr" || out == "cerr")
stdout_fd = STDERR_FILENO;
else if (out == "None")
stdout_fd = -1;
else {
stdout_fd = Process::openOutputFile(out);
if (lseek(stdout_fd, fdo_stdout->fileOffset, SEEK_SET) < 0)
panic("Unable to seek to correct location in file: %s", out);
}
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;
fdo_stderr->fd = stderr_fd;
for (int free_fd = 3; free_fd <= MAX_FD; ++free_fd) {
Process::FdMap *fdo = &fd_map[free_fd];
if (fdo->fd != -1) {
if (fdo->isPipe){
if (fdo->filename == "PIPE-WRITE")
continue;
else {
assert (fdo->filename == "PIPE-READ");
//create a new pipe
int fds[2];
int pipe_retval = pipe(fds);
if (pipe_retval < 0) {
// error
panic("Unable to create new pipe.");
}
fdo->fd = fds[0]; //set read pipe
Process::FdMap *fdo_write = &fd_map[fdo->readPipeSource];
if (fdo_write->filename != "PIPE-WRITE")
panic ("Couldn't find write end of the pipe");
fdo_write->fd = fds[1];//set write pipe
}
} else {
//Open file
int fd = open(fdo->filename.c_str(), fdo->flags, fdo->mode);
if (fd == -1)
panic("Unable to open file: %s", fdo->filename);
fdo->fd = fd;
//Seek to correct location before checkpoint
if (lseek(fd,fdo->fileOffset, SEEK_SET) < 0)
panic("Unable to seek to correct location in file: %s",
fdo->filename);
}
}
}
}
void
Process::find_file_offsets()
{
for (int free_fd = 0; free_fd <= MAX_FD; ++free_fd) {
Process::FdMap *fdo = &fd_map[free_fd];
if (fdo->fd != -1) {
fdo->fileOffset = lseek(fdo->fd, 0, SEEK_CUR);
} else {
fdo->filename = "NULL";
fdo->fileOffset = 0;
}
}
}
void
Process::setReadPipeSource(int read_pipe_fd, int source_fd)
{
Process::FdMap *fdo = &fd_map[read_pipe_fd];
fdo->readPipeSource = source_fd;
}
void
Process::FdMap::serialize(std::ostream &os)
{
SERIALIZE_SCALAR(fd);
SERIALIZE_SCALAR(isPipe);
SERIALIZE_SCALAR(filename);
SERIALIZE_SCALAR(flags);
SERIALIZE_SCALAR(readPipeSource);
SERIALIZE_SCALAR(fileOffset);
}
void
Process::FdMap::unserialize(Checkpoint *cp, const std::string &section)
{
UNSERIALIZE_SCALAR(fd);
UNSERIALIZE_SCALAR(isPipe);
UNSERIALIZE_SCALAR(filename);
UNSERIALIZE_SCALAR(flags);
UNSERIALIZE_SCALAR(readPipeSource);
UNSERIALIZE_SCALAR(fileOffset);
}
void
Process::serialize(std::ostream &os)
{
SERIALIZE_SCALAR(brk_point);
SERIALIZE_SCALAR(stack_base);
SERIALIZE_SCALAR(stack_size);
SERIALIZE_SCALAR(stack_min);
SERIALIZE_SCALAR(next_thread_stack_base);
SERIALIZE_SCALAR(mmap_start);
SERIALIZE_SCALAR(mmap_end);
SERIALIZE_SCALAR(nxm_start);
SERIALIZE_SCALAR(nxm_end);
find_file_offsets();
pTable->serialize(os);
for (int x = 0; x <= MAX_FD; x++) {
nameOut(os, csprintf("%s.FdMap%d", name(), x));
fd_map[x].serialize(os);
}
SERIALIZE_SCALAR(M5_pid);
}
void
Process::unserialize(Checkpoint *cp, const std::string &section)
{
UNSERIALIZE_SCALAR(brk_point);
UNSERIALIZE_SCALAR(stack_base);
UNSERIALIZE_SCALAR(stack_size);
UNSERIALIZE_SCALAR(stack_min);
UNSERIALIZE_SCALAR(next_thread_stack_base);
UNSERIALIZE_SCALAR(mmap_start);
UNSERIALIZE_SCALAR(mmap_end);
UNSERIALIZE_SCALAR(nxm_start);
UNSERIALIZE_SCALAR(nxm_end);
pTable->unserialize(cp, section);
for (int x = 0; x <= MAX_FD; x++) {
fd_map[x].unserialize(cp, csprintf("%s.FdMap%d", section, x));
}
fix_file_offsets();
UNSERIALIZE_OPT_SCALAR(M5_pid);
// The above returns a bool so that you could do something if you don't
// find the param in the checkpoint if you wanted to, like set a default
// but in this case we'll just stick with the instantianted value if not
// found.
}
////////////////////////////////////////////////////////////////////////
//
// LiveProcess member definitions
//
////////////////////////////////////////////////////////////////////////
LiveProcess::LiveProcess(LiveProcessParams * params, ObjectFile *_objFile)
: Process(params), objFile(_objFile),
argv(params->cmd), envp(params->env), cwd(params->cwd)
{
__uid = params->uid;
__euid = params->euid;
__gid = params->gid;
__egid = params->egid;
__pid = params->pid;
__ppid = params->ppid;
prog_fname = params->cmd[0];
// load up symbols, if any... these may be used for debugging or
// profiling.
if (!debugSymbolTable) {
debugSymbolTable = new SymbolTable();
if (!objFile->loadGlobalSymbols(debugSymbolTable) ||
!objFile->loadLocalSymbols(debugSymbolTable)) {
// didn't load any symbols
delete debugSymbolTable;
debugSymbolTable = NULL;
}
}
}
void
LiveProcess::syscall(int64_t callnum, ThreadContext *tc)
{
num_syscalls++;
SyscallDesc *desc = getDesc(callnum);
if (desc == NULL)
fatal("Syscall %d out of range", callnum);
desc->doSyscall(callnum, this, tc);
}
IntReg
LiveProcess::getSyscallArg(ThreadContext *tc, int &i, int width)
{
return getSyscallArg(tc, i);
}
LiveProcess *
LiveProcess::create(LiveProcessParams * params)
{
LiveProcess *process = NULL;
string executable =
params->executable == "" ? params->cmd[0] : params->executable;
ObjectFile *objFile = createObjectFile(executable);
if (objFile == NULL) {
fatal("Can't load object file %s", executable);
}
if (objFile->isDynamic())
fatal("Object file is a dynamic executable however only static "
"executables are supported!\n Please recompile your "
"executable as a static binary and try again.\n");
#if THE_ISA == ALPHA_ISA
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;
default:
fatal("Unknown/unsupported operating system.");
}
#elif THE_ISA == SPARC_ISA
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);
} else {
process = new Sparc32LinuxProcess(params, objFile);
}
break;
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_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:
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.");
}
#elif THE_ISA == MIPS_ISA
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;
default:
fatal("Unknown/unsupported operating system.");
}
#elif THE_ISA == ARM_ISA
if (objFile->getArch() != ObjectFile::Arm &&
objFile->getArch() != ObjectFile::Thumb)
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, objFile->getArch());
break;
case ObjectFile::LinuxArmOABI:
fatal("M5 does not support ARM OABI binaries. Please recompile with an"
" EABI compiler.");
default:
fatal("Unknown/unsupported operating system.");
}
#elif THE_ISA == POWER_ISA
if (objFile->getArch() != ObjectFile::Power)
fatal("Object file architecture does not match compiled ISA (Power).");
switch (objFile->getOpSys()) {
case ObjectFile::UnknownOpSys:
warn("Unknown operating system; assuming Linux.");
// fall through
case ObjectFile::Linux:
process = new PowerLinuxProcess(params, objFile);
break;
default:
fatal("Unknown/unsupported operating system.");
}
#else
#error "THE_ISA not set"
#endif
if (process == NULL)
fatal("Unknown error creating process object.");
return process;
}
LiveProcess *
LiveProcessParams::create()
{
return LiveProcess::create(this);
}

View File

@ -0,0 +1,314 @@
/*
* 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: Nathan Binkert
* Steve Reinhardt
*/
#ifndef __PROCESS_HH__
#define __PROCESS_HH__
#include <string>
#include <vector>
#include "arch/registers.hh"
#include "base/statistics.hh"
#include "base/types.hh"
#include "config/the_isa.hh"
#include "mem/se_translating_port_proxy.hh"
#include "sim/sim_object.hh"
#include "sim/syscallreturn.hh"
class PageTable;
struct ProcessParams;
struct LiveProcessParams;
class SyscallDesc;
class System;
class ThreadContext;
template<class IntType>
struct AuxVector
{
IntType a_type;
IntType a_val;
AuxVector()
{}
AuxVector(IntType type, IntType val);
};
class Process : public SimObject
{
public:
/// Pointer to object representing the system this process is
/// running on.
System *system;
// thread contexts associated with this process
std::vector<int> contextIds;
// number of CPUs (esxec contexts, really) assigned to this process.
unsigned int numCpus() { return contextIds.size(); }
// record of blocked context
struct WaitRec
{
Addr waitChan;
ThreadContext *waitingContext;
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 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;
// addr to use for next stack region (for multithreaded apps)
Addr next_thread_stack_base;
// Base of region for mmaps (when user doesn't specify an address).
Addr mmap_start;
Addr mmap_end;
// Base of region for nxm data
Addr nxm_start;
Addr nxm_end;
std::string prog_fname; // file name
Stats::Scalar num_syscalls; // number of syscalls executed
protected:
// constructor
Process(ProcessParams *params);
virtual void initState();
public:
//This id is assigned by m5 and is used to keep process' tlb entries
//separated.
uint64_t M5_pid;
PageTable* pTable;
class FdMap
{
public:
int fd;
std::string filename;
int mode;
int flags;
bool isPipe;
int readPipeSource;
uint64_t fileOffset;
FdMap()
: fd(-1), filename("NULL"), mode(0), flags(0),
isPipe(false), readPipeSource(0), fileOffset(0)
{ }
void serialize(std::ostream &os);
void unserialize(Checkpoint *cp, const std::string &section);
};
protected:
/// Memory proxy for initialization (image loading)
SETranslatingPortProxy initVirtMem;
private:
// file descriptor remapping support
static const int MAX_FD = 256; // max legal fd value
FdMap fd_map[MAX_FD+1];
public:
// static helper functions to generate file descriptors for constructor
static int openInputFile(const std::string &filename);
static int openOutputFile(const std::string &filename);
// override of virtual SimObject method: register statistics
virtual void regStats();
// 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);
}
// 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);
// generate new target fd for sim_fd
int alloc_fd(int sim_fd, std::string filename, int flags, int mode,
bool pipe);
// free target fd (e.g., after close)
void free_fd(int tgt_fd);
// look up simulator fd for given target fd
int sim_fd(int tgt_fd);
// look up simulator fd_map object for a given target fd
FdMap *sim_fd_obj(int tgt_fd);
// fix all offsets for currently open files and save them
void fix_file_offsets();
// find all offsets for currently open files and save them
void find_file_offsets();
// set the source of this read pipe for a checkpoint resume
void setReadPipeSource(int read_pipe_fd, int source_fd);
virtual void syscall(int64_t callnum, ThreadContext *tc) = 0;
void allocateMem(Addr vaddr, int64_t size, bool clobber = false);
/// Attempt to fix up a fault at vaddr by allocating a page on the stack.
/// @return Whether the fault has been fixed.
bool fixupStackFault(Addr vaddr);
void serialize(std::ostream &os);
void unserialize(Checkpoint *cp, const std::string &section);
};
//
// "Live" process with system calls redirected to host system
//
class ObjectFile;
class LiveProcess : public Process
{
protected:
ObjectFile *objFile;
std::vector<std::string> argv;
std::vector<std::string> envp;
std::string cwd;
LiveProcess(LiveProcessParams *params, ObjectFile *objFile);
// Id of the owner of the process
uint64_t __uid;
uint64_t __euid;
uint64_t __gid;
uint64_t __egid;
// pid of the process and it's parent
uint64_t __pid;
uint64_t __ppid;
public:
enum AuxiliaryVectorType {
M5_AT_NULL = 0,
M5_AT_IGNORE = 1,
M5_AT_EXECFD = 2,
M5_AT_PHDR = 3,
M5_AT_PHENT = 4,
M5_AT_PHNUM = 5,
M5_AT_PAGESZ = 6,
M5_AT_BASE = 7,
M5_AT_FLAGS = 8,
M5_AT_ENTRY = 9,
M5_AT_NOTELF = 10,
M5_AT_UID = 11,
M5_AT_EUID = 12,
M5_AT_GID = 13,
M5_AT_EGID = 14,
// The following may be specific to Linux
M5_AT_PLATFORM = 15,
M5_AT_HWCAP = 16,
M5_AT_CLKTCK = 17,
M5_AT_SECURE = 23,
M5_BASE_PLATFORM = 24,
M5_AT_RANDOM = 25,
M5_AT_EXECFN = 31,
M5_AT_VECTOR_SIZE = 44
};
inline uint64_t uid() {return __uid;}
inline uint64_t euid() {return __euid;}
inline uint64_t gid() {return __gid;}
inline uint64_t egid() {return __egid;}
inline uint64_t pid() {return __pid;}
inline uint64_t ppid() {return __ppid;}
std::string
fullPath(const std::string &filename)
{
if (filename[0] == '/' || cwd.empty())
return filename;
std::string full = cwd;
if (cwd[cwd.size() - 1] != '/')
full += '/';
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 TheISA::IntReg getSyscallArg(ThreadContext *tc, int &i, int width);
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;
// this function is used to create the LiveProcess object, since
// we can't tell which subclass of LiveProcess to use until we
// open and look at the object file.
static LiveProcess *create(LiveProcessParams *params);
};
#endif // __PROCESS_HH__

View File

@ -0,0 +1,63 @@
/*
* 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: Nathan Binkert
* Steve Reinhardt
*/
#ifndef __SIM_PROCESS_IMPL_HH__
#define __SIM_PROCESS_IMPL_HH__
#include <string>
#include <vector>
#include "mem/se_translating_port_proxy.hh"
#include "sim/byteswap.hh"
//This needs to be templated for cases where 32 bit pointers are needed.
template<class AddrType>
void
copyStringArray(std::vector<std::string> &strings,
AddrType array_ptr, AddrType data_ptr,
SETranslatingPortProxy& memProxy)
{
AddrType data_ptr_swap;
for (std::vector<std::string>::size_type i = 0; i < strings.size(); ++i) {
data_ptr_swap = TheISA::htog(data_ptr);
memProxy.writeBlob(array_ptr, (uint8_t*)&data_ptr_swap,
sizeof(AddrType));
memProxy.writeString(data_ptr, strings[i].c_str());
array_ptr += sizeof(AddrType);
data_ptr += strings[i].size() + 1;
}
// add NULL terminator
data_ptr = 0;
memProxy.writeBlob(array_ptr, (uint8_t*)&data_ptr, sizeof(AddrType));
}
#endif

View File

@ -0,0 +1,553 @@
/*
* Copyright (c) 2010-2011 ARM Limited
* All rights reserved
*
* The license below extends only to copyright in the software and shall
* not be construed as granting a license to any other intellectual
* property including but not limited to intellectual property relating
* to a hardware implementation of the functionality of the software
* licensed hereunder. You may use the software subject to the license
* terms below provided that you ensure that this notice is replicated
* unmodified and in its entirety in all distributions of the software,
* modified or unmodified, in source code or in binary form.
*
* Copyright (c) 2011 Advanced Micro Devices, Inc.
* Copyright (c) 2003-2006 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Nathan Binkert
*/
#include <fcntl.h>
#include <unistd.h>
#include <cerrno>
#include <fstream>
#include <string>
#include "arch/kernel_stats.hh"
#include "arch/vtophys.hh"
#include "base/debug.hh"
#include "base/output.hh"
#include "config/the_isa.hh"
#include "cpu/base.hh"
#include "cpu/quiesce_event.hh"
#include "cpu/thread_context.hh"
#include "debug/Loader.hh"
#include "debug/Quiesce.hh"
#include "debug/WorkItems.hh"
#include "params/BaseCPU.hh"
#include "sim/full_system.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/vptr.hh"
using namespace std;
using namespace Stats;
using namespace TheISA;
namespace PseudoInst {
static inline void
panicFsOnlyPseudoInst(const char *name)
{
panic("Pseudo inst \"%s\" is only available in Full System mode.");
}
void
arm(ThreadContext *tc)
{
if (!FullSystem)
panicFsOnlyPseudoInst("arm");
if (tc->getKernelStats())
tc->getKernelStats()->arm();
}
void
quiesce(ThreadContext *tc)
{
if (!FullSystem)
panicFsOnlyPseudoInst("quiesce");
if (!tc->getCpuPtr()->params()->do_quiesce)
return;
DPRINTF(Quiesce, "%s: quiesce()\n", tc->getCpuPtr()->name());
tc->suspend();
if (tc->getKernelStats())
tc->getKernelStats()->quiesce();
}
void
quiesceSkip(ThreadContext *tc)
{
if (!FullSystem)
panicFsOnlyPseudoInst("quiesceSkip");
BaseCPU *cpu = tc->getCpuPtr();
if (!cpu->params()->do_quiesce)
return;
EndQuiesceEvent *quiesceEvent = tc->getQuiesceEvent();
Tick resume = curTick() + 1;
cpu->reschedule(quiesceEvent, resume, true);
DPRINTF(Quiesce, "%s: quiesceSkip() until %d\n",
cpu->name(), resume);
tc->suspend();
if (tc->getKernelStats())
tc->getKernelStats()->quiesce();
}
void
quiesceNs(ThreadContext *tc, uint64_t ns)
{
if (!FullSystem)
panicFsOnlyPseudoInst("quiesceNs");
BaseCPU *cpu = tc->getCpuPtr();
if (!cpu->params()->do_quiesce || ns == 0)
return;
EndQuiesceEvent *quiesceEvent = tc->getQuiesceEvent();
Tick resume = curTick() + SimClock::Int::ns * ns;
cpu->reschedule(quiesceEvent, resume, true);
DPRINTF(Quiesce, "%s: quiesceNs(%d) until %d\n",
cpu->name(), ns, resume);
tc->suspend();
if (tc->getKernelStats())
tc->getKernelStats()->quiesce();
}
void
quiesceCycles(ThreadContext *tc, uint64_t cycles)
{
if (!FullSystem)
panicFsOnlyPseudoInst("quiesceCycles");
BaseCPU *cpu = tc->getCpuPtr();
if (!cpu->params()->do_quiesce || cycles == 0)
return;
EndQuiesceEvent *quiesceEvent = tc->getQuiesceEvent();
Tick resume = curTick() + cpu->ticks(cycles);
cpu->reschedule(quiesceEvent, resume, true);
DPRINTF(Quiesce, "%s: quiesceCycles(%d) until %d\n",
cpu->name(), cycles, resume);
tc->suspend();
if (tc->getKernelStats())
tc->getKernelStats()->quiesce();
}
uint64_t
quiesceTime(ThreadContext *tc)
{
if (!FullSystem) {
panicFsOnlyPseudoInst("quiesceTime");
return 0;
}
return (tc->readLastActivate() - tc->readLastSuspend()) /
SimClock::Int::ns;
}
uint64_t
rpns(ThreadContext *tc)
{
return curTick() / SimClock::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
m5exit(ThreadContext *tc, Tick delay)
{
Tick when = curTick() + delay * SimClock::Int::ns;
exitSimLoop("m5_exit instruction encountered", 0, when);
}
void
loadsymbol(ThreadContext *tc)
{
if (!FullSystem)
panicFsOnlyPseudoInst("loadsymbol");
const string &filename = tc->getCpuPtr()->system->params()->symbolfile;
if (filename.empty()) {
return;
}
std::string buffer;
ifstream file(filename.c_str());
if (!file)
fatal("file error: Can't open symbol table file %s\n", filename);
while (!file.eof()) {
getline(file, buffer);
if (buffer.empty())
continue;
string::size_type idx = buffer.find(' ');
if (idx == string::npos)
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;
Addr addr;
if (!to_number(address, addr))
continue;
if (!tc->getSystemPtr()->kernelSymtab->insert(addr, symbol))
continue;
DPRINTF(Loader, "Loaded symbol: %s @ %#llx\n", symbol, addr);
}
file.close();
}
void
addsymbol(ThreadContext *tc, Addr addr, Addr symbolAddr)
{
if (!FullSystem)
panicFsOnlyPseudoInst("addSymbol");
char symb[100];
CopyStringOut(tc, symb, symbolAddr, 100);
std::string symbol(symb);
DPRINTF(Loader, "Loaded symbol: %s @ %#llx\n", symbol, addr);
tc->getSystemPtr()->kernelSymtab->insert(addr,symbol);
debugSymbolTable->insert(addr,symbol);
}
uint64_t
initParam(ThreadContext *tc)
{
if (!FullSystem) {
panicFsOnlyPseudoInst("initParam");
return 0;
}
return tc->getCpuPtr()->system->init_param;
}
void
resetstats(ThreadContext *tc, Tick delay, Tick period)
{
if (!tc->getCpuPtr()->params()->do_statistics_insts)
return;
Tick when = curTick() + delay * SimClock::Int::ns;
Tick repeat = period * SimClock::Int::ns;
Stats::schedStatEvent(false, true, when, repeat);
}
void
dumpstats(ThreadContext *tc, Tick delay, Tick period)
{
if (!tc->getCpuPtr()->params()->do_statistics_insts)
return;
Tick when = curTick() + delay * SimClock::Int::ns;
Tick repeat = period * SimClock::Int::ns;
Stats::schedStatEvent(true, false, when, repeat);
}
void
dumpresetstats(ThreadContext *tc, Tick delay, Tick period)
{
if (!tc->getCpuPtr()->params()->do_statistics_insts)
return;
Tick when = curTick() + delay * SimClock::Int::ns;
Tick repeat = period * SimClock::Int::ns;
Stats::schedStatEvent(true, true, when, repeat);
}
void
m5checkpoint(ThreadContext *tc, Tick delay, Tick period)
{
if (!tc->getCpuPtr()->params()->do_checkpoint_insts)
return;
Tick when = curTick() + delay * SimClock::Int::ns;
Tick repeat = period * SimClock::Int::ns;
exitSimLoop("checkpoint", 0, when, repeat);
}
uint64_t
readfile(ThreadContext *tc, Addr vaddr, uint64_t len, uint64_t offset)
{
if (!FullSystem) {
panicFsOnlyPseudoInst("readfile");
return 0;
}
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
writefile(ThreadContext *tc, Addr vaddr, uint64_t len, uint64_t offset,
Addr filename_addr)
{
ostream *os;
// copy out target filename
char fn[100];
std::string filename;
CopyStringOut(tc, fn, filename_addr, 100);
filename = std::string(fn);
if (offset == 0) {
// create a new file (truncate)
os = simout.create(filename, true);
} else {
// do not truncate file if offset is non-zero
// (ios::in flag is required as well to keep the existing data
// intact, otherwise existing data will be zeroed out.)
os = simout.openFile(simout.directory() + filename,
ios::in | ios::out | ios::binary);
}
if (!os)
panic("could not open file %s\n", filename);
// seek to offset
os->seekp(offset);
// copy out data and write to file
char *buf = new char[len];
CopyOut(tc, buf, vaddr, len);
os->write(buf, len);
if (os->fail() || os->bad())
panic("Error while doing writefile!\n");
simout.close(os);
delete [] buf;
return len;
}
void
debugbreak(ThreadContext *tc)
{
Debug::breakpoint();
}
void
switchcpu(ThreadContext *tc)
{
exitSimLoop("switchcpu");
}
//
// This function is executed when annotated work items begin. Depending on
// what the user specified at the command line, the simulation may exit and/or
// take a checkpoint when a certain work item begins.
//
void
workbegin(ThreadContext *tc, uint64_t workid, uint64_t threadid)
{
tc->getCpuPtr()->workItemBegin();
System *sys = tc->getSystemPtr();
const System::Params *params = sys->params();
sys->workItemBegin(threadid, workid);
DPRINTF(WorkItems, "Work Begin workid: %d, threadid %d\n", workid,
threadid);
//
// If specified, determine if this is the specific work item the user
// identified
//
if (params->work_item_id == -1 || params->work_item_id == workid) {
uint64_t systemWorkBeginCount = sys->incWorkItemsBegin();
int cpuId = tc->getCpuPtr()->cpuId();
if (params->work_cpus_ckpt_count != 0 &&
sys->markWorkItem(cpuId) >= params->work_cpus_ckpt_count) {
//
// If active cpus equals checkpoint count, create checkpoint
//
exitSimLoop("checkpoint");
}
if (systemWorkBeginCount == params->work_begin_ckpt_count) {
//
// Note: the string specified as the cause of the exit event must
// exactly equal "checkpoint" inorder to create a checkpoint
//
exitSimLoop("checkpoint");
}
if (systemWorkBeginCount == params->work_begin_exit_count) {
//
// If a certain number of work items started, exit simulation
//
exitSimLoop("work started count reach");
}
if (cpuId == params->work_begin_cpu_id_exit) {
//
// If work started on the cpu id specified, exit simulation
//
exitSimLoop("work started on specific cpu");
}
}
}
//
// This function is executed when annotated work items end. Depending on
// what the user specified at the command line, the simulation may exit and/or
// take a checkpoint when a certain work item ends.
//
void
workend(ThreadContext *tc, uint64_t workid, uint64_t threadid)
{
tc->getCpuPtr()->workItemEnd();
System *sys = tc->getSystemPtr();
const System::Params *params = sys->params();
sys->workItemEnd(threadid, workid);
DPRINTF(WorkItems, "Work End workid: %d, threadid %d\n", workid, threadid);
//
// If specified, determine if this is the specific work item the user
// identified
//
if (params->work_item_id == -1 || params->work_item_id == workid) {
uint64_t systemWorkEndCount = sys->incWorkItemsEnd();
int cpuId = tc->getCpuPtr()->cpuId();
if (params->work_cpus_ckpt_count != 0 &&
sys->markWorkItem(cpuId) >= params->work_cpus_ckpt_count) {
//
// If active cpus equals checkpoint count, create checkpoint
//
exitSimLoop("checkpoint");
}
if (params->work_end_ckpt_count != 0 &&
systemWorkEndCount == params->work_end_ckpt_count) {
//
// If total work items completed equals checkpoint count, create
// checkpoint
//
exitSimLoop("checkpoint");
}
if (params->work_end_exit_count != 0 &&
systemWorkEndCount == params->work_end_exit_count) {
//
// If total work items completed equals exit count, exit simulation
//
exitSimLoop("work items exit count reached");
}
}
}
} // namespace PseudoInst

View File

@ -0,0 +1,75 @@
/*
* Copyright (c) 2003-2006 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Nathan Binkert
*/
#ifndef __SIM_PSEUDO_INST_HH__
#define __SIM_PSEUDO_INST_HH__
class ThreadContext;
//We need the "Tick" and "Addr" data types from here
#include "base/types.hh"
namespace PseudoInst {
/**
* @todo these externs are only here for a hack in fullCPU::takeOver...
*/
extern bool doStatisticsInsts;
extern bool doCheckpointInsts;
extern bool doQuiesce;
void arm(ThreadContext *tc);
void quiesce(ThreadContext *tc);
void quiesceSkip(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);
uint64_t writefile(ThreadContext *tc, Addr vaddr, uint64_t len,
uint64_t offset, Addr filenameAddr);
void loadsymbol(ThreadContext *xc);
void addsymbol(ThreadContext *tc, Addr addr, Addr symbolAddr);
uint64_t initParam(ThreadContext *xc);
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);
void workbegin(ThreadContext *tc, uint64_t workid, uint64_t threadid);
void workend(ThreadContext *tc, uint64_t workid, uint64_t threadid);
} // namespace PseudoInst
#endif // __SIM_PSEUDO_INST_HH__

View File

@ -0,0 +1,180 @@
/*
* Copyright (c) 2002-2005 The Regents of The University of Michigan
* Copyright (c) 2011 Advanced Micro Devices, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Nathan Binkert
* Steve Reinhardt
* Gabe Black
*/
#include "base/misc.hh"
#include "config/the_isa.hh"
#include "debug/TimeSync.hh"
#include "sim/full_system.hh"
#include "sim/root.hh"
Root *Root::_root = NULL;
/*
* This function is called periodically by an event in M5 and ensures that
* at least as much real time has passed between invocations as simulated time.
* If not, the function either sleeps, or if the difference is small enough
* spin waits.
*/
void
Root::timeSync()
{
Time cur_time, diff, period = timeSyncPeriod();
do {
cur_time.setTimer();
diff = cur_time - lastTime;
Time remainder = period - diff;
if (diff < period && remainder > _spinThreshold) {
DPRINTF(TimeSync, "Sleeping to sync with real time.\n");
// Sleep until the end of the period, or until a signal.
sleep(remainder);
// Refresh the current time.
cur_time.setTimer();
}
} while (diff < period);
lastTime = cur_time;
schedule(&syncEvent, curTick() + _periodTick);
}
void
Root::timeSyncEnable(bool en)
{
if (en == _enabled)
return;
_enabled = en;
if (_enabled) {
// Get event going.
Tick periods = ((curTick() + _periodTick - 1) / _periodTick);
Tick nextPeriod = periods * _periodTick;
schedule(&syncEvent, nextPeriod);
} else {
// Stop event.
deschedule(&syncEvent);
}
}
/// Configure the period for time sync events.
void
Root::timeSyncPeriod(Time newPeriod)
{
bool en = timeSyncEnabled();
_period = newPeriod;
_periodTick = _period.getTick();
timeSyncEnable(en);
}
/// Set the threshold for time remaining to spin wait.
void
Root::timeSyncSpinThreshold(Time newThreshold)
{
bool en = timeSyncEnabled();
_spinThreshold = newThreshold;
timeSyncEnable(en);
}
Root::Root(RootParams *p) : SimObject(p), _enabled(false),
_periodTick(p->time_sync_period), syncEvent(this)
{
_period.setTick(p->time_sync_period);
_spinThreshold.setTick(p->time_sync_spin_threshold);
assert(_root == NULL);
_root = this;
lastTime.setTimer();
}
void
Root::initState()
{
timeSyncEnable(params()->time_sync_enable);
}
void
Root::loadState(Checkpoint *cp)
{
SimObject::loadState(cp);
timeSyncEnable(params()->time_sync_enable);
}
void
Root::serialize(std::ostream &os)
{
uint64_t cpt_ver = gem5CheckpointVersion;
SERIALIZE_SCALAR(cpt_ver);
SERIALIZE_SCALAR(FullSystem);
std::string isa = THE_ISA_STR;
SERIALIZE_SCALAR(isa);
}
void
Root::unserialize(Checkpoint *cp, const std::string &section)
{
uint64_t cpt_ver = 0;
UNSERIALIZE_OPT_SCALAR(cpt_ver);
if (cpt_ver < gem5CheckpointVersion) {
warn("**********************************************************\n");
warn("!!!! Checkpoint ver %#x is older than current ver %#x !!!!\n",
cpt_ver, gem5CheckpointVersion);
warn("You might experience some issues when restoring and should run "
"the checkpoint upgrader (util/cpt_upgrade.py) on your "
"checkpoint\n");
warn("**********************************************************\n");
} else if (cpt_ver > gem5CheckpointVersion) {
warn("**********************************************************\n");
warn("!!!! Checkpoint ver %#x is newer than current ver %#x !!!!\n",
cpt_ver, gem5CheckpointVersion);
warn("Running a new checkpoint with an older version of gem5 is not "
"supported. While it might work, you may experience incorrect "
"behavior or crashes.\n");
warn("**********************************************************\n");
}
}
bool FullSystem;
unsigned int FullSystemInt;
Root *
RootParams::create()
{
static bool created = false;
if (created)
panic("only one root object allowed!");
created = true;
FullSystem = full_system;
FullSystemInt = full_system ? 1 : 0;
return new Root(this);
}

View File

@ -0,0 +1,120 @@
/*
* Copyright (c) 2011 Advanced Micro Devices, Inc.
* 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
*/
/**
* @file This file defines the Root simobject and the methods used to control
* the time syncing mechanism provided through it.
*
* Time syncing prevents simulated time from passing faster than real time. It
* works by scheduling a periodic event that checks to see if its simulated
* period is shorter than its real period. If it is, it stalls the simulation
* until they're equal.
*/
#ifndef __SIM_ROOT_HH__
#define __SIM_ROOT_HH__
#include "base/time.hh"
#include "params/Root.hh"
#include "sim/eventq.hh"
#include "sim/sim_object.hh"
class Root : public SimObject
{
private:
static Root *_root;
protected:
bool _enabled;
Time _period;
Tick _periodTick;
Time _spinThreshold;
Time lastTime;
void timeSync();
EventWrapper<Root, &Root::timeSync> syncEvent;
friend class EventWrapper<Root, &Root::timeSync>;
public:
/**
* Use this function to get a pointer to the single Root object in the
* simulation. This function asserts that such an object has actual been
* constructed to avoid having to perform that check everywhere the root
* is used. This is to allow calling the functions below.
*
* @return Pointer to the single root object.
*/
static Root *
root()
{
assert(_root);
return _root;
}
public:
/// Check whether time syncing is enabled.
bool timeSyncEnabled() const { return _enabled; }
/// Retrieve the period for the sync event.
const Time timeSyncPeriod() const { return _period; }
/// Retrieve the threshold for time remaining to spin wait.
const Time timeSyncSpinThreshold() const { return _spinThreshold; }
/// Enable or disable time syncing.
void timeSyncEnable(bool en);
/// Configure the period for time sync events.
void timeSyncPeriod(Time newPeriod);
/// Set the threshold for time remaining to spin wait.
void timeSyncSpinThreshold(Time newThreshold);
typedef RootParams Params;
const Params *
params() const
{
return dynamic_cast<const Params *>(_params);
}
Root(Params *p);
/** Schedule the timesync event at loadState() so that curTick is correct
*/
void loadState(Checkpoint *cp);
/** Schedule the timesync event at initState() when not unserializing
*/
void initState();
virtual void serialize(std::ostream &os);
virtual void unserialize(Checkpoint *cp, const std::string &section);
};
#endif // __SIM_ROOT_HH__

View File

@ -0,0 +1,642 @@
/*
* Copyright (c) 2002-2005 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Nathan Binkert
* Erik Hallnor
* Steve Reinhardt
*/
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/types.h>
#include <cerrno>
#include <fstream>
#include <list>
#include <string>
#include <vector>
#include "base/inifile.hh"
#include "base/misc.hh"
#include "base/output.hh"
#include "base/str.hh"
#include "base/trace.hh"
#include "sim/eventq.hh"
#include "sim/serialize.hh"
#include "sim/sim_events.hh"
#include "sim/sim_exit.hh"
#include "sim/sim_object.hh"
// For stat reset hack
#include "sim/stat_control.hh"
using namespace std;
extern SimObject *resolveSimObject(const string &);
//
// The base implementations use to_number for parsing and '<<' for
// displaying, suitable for integer types.
//
template <class T>
bool
parseParam(const string &s, T &value)
{
return to_number(s, value);
}
template <class T>
void
showParam(ostream &os, const T &value)
{
os << value;
}
//
// Template specializations:
// - char (8-bit integer)
// - floating-point types
// - bool
// - string
//
// Treat 8-bit ints (chars) as ints on output, not as chars
template <>
void
showParam(ostream &os, const char &value)
{
os << (int)value;
}
template <>
void
showParam(ostream &os, const signed char &value)
{
os << (int)value;
}
template <>
void
showParam(ostream &os, const unsigned char &value)
{
os << (unsigned int)value;
}
// Use sscanf() for FP types as to_number() only handles integers
template <>
bool
parseParam(const string &s, float &value)
{
return (sscanf(s.c_str(), "%f", &value) == 1);
}
template <>
bool
parseParam(const string &s, double &value)
{
return (sscanf(s.c_str(), "%lf", &value) == 1);
}
template <>
bool
parseParam(const string &s, bool &value)
{
const string &ls = to_lower(s);
if (ls == "true") {
value = true;
return true;
}
if (ls == "false") {
value = false;
return true;
}
return false;
}
// Display bools as strings
template <>
void
showParam(ostream &os, const bool &value)
{
os << (value ? "true" : "false");
}
// String requires no processing to speak of
template <>
bool
parseParam(const string &s, string &value)
{
value = s;
return true;
}
int Serializable::ckptMaxCount = 0;
int Serializable::ckptCount = 0;
int Serializable::ckptPrevCount = -1;
void
Serializable::nameOut(ostream &os)
{
os << "\n[" << name() << "]\n";
}
void
Serializable::nameOut(ostream &os, const string &_name)
{
os << "\n[" << _name << "]\n";
}
template <class T>
void
paramOut(ostream &os, const string &name, const T &param)
{
os << name << "=";
showParam(os, param);
os << "\n";
}
template <class T>
void
arrayParamOut(ostream &os, const string &name, const vector<T> &param)
{
typename vector<T>::size_type size = param.size();
os << name << "=";
if (size > 0)
showParam(os, param[0]);
for (typename vector<T>::size_type i = 1; i < size; ++i) {
os << " ";
showParam(os, param[i]);
}
os << "\n";
}
template <class T>
void
arrayParamOut(ostream &os, const string &name, const list<T> &param)
{
typename list<T>::const_iterator it = param.begin();
os << name << "=";
if (param.size() > 0)
showParam(os, *it);
it++;
while (it != param.end()) {
os << " ";
showParam(os, *it);
it++;
}
os << "\n";
}
template <class T>
void
paramIn(Checkpoint *cp, const string &section, const string &name, T &param)
{
string str;
if (!cp->find(section, name, str) || !parseParam(str, param)) {
fatal("Can't unserialize '%s:%s'\n", section, name);
}
}
template <class T>
bool
optParamIn(Checkpoint *cp, const string &section, const string &name, T &param)
{
string str;
if (!cp->find(section, name, str) || !parseParam(str, param)) {
warn("optional parameter %s:%s not present\n", section, name);
return false;
} else {
return true;
}
}
template <class T>
void
arrayParamOut(ostream &os, const string &name, const T *param, unsigned size)
{
os << name << "=";
if (size > 0)
showParam(os, param[0]);
for (unsigned i = 1; i < size; ++i) {
os << " ";
showParam(os, param[i]);
}
os << "\n";
}
template <class T>
void
arrayParamIn(Checkpoint *cp, const string &section, const string &name,
T *param, unsigned size)
{
string str;
if (!cp->find(section, name, str)) {
fatal("Can't unserialize '%s:%s'\n", section, name);
}
// code below stolen from VectorParam<T>::parse().
// it would be nice to unify these somehow...
vector<string> tokens;
tokenize(tokens, str, ' ');
// Need this if we were doing a vector
// value.resize(tokens.size());
if (tokens.size() != size) {
fatal("Array size mismatch on %s:%s'\n", section, name);
}
for (vector<string>::size_type i = 0; i < tokens.size(); i++) {
// need to parse into local variable to handle vector<bool>,
// for which operator[] returns a special reference class
// that's not the same as 'bool&', (since it's a packed
// vector)
T scalar_value = 0;
if (!parseParam(tokens[i], scalar_value)) {
string err("could not parse \"");
err += str;
err += "\"";
fatal(err);
}
// assign parsed value to vector
param[i] = scalar_value;
}
}
template <class T>
void
arrayParamIn(Checkpoint *cp, const string &section,
const string &name, vector<T> &param)
{
string str;
if (!cp->find(section, name, str)) {
fatal("Can't unserialize '%s:%s'\n", section, name);
}
// code below stolen from VectorParam<T>::parse().
// it would be nice to unify these somehow...
vector<string> tokens;
tokenize(tokens, str, ' ');
// Need this if we were doing a vector
// value.resize(tokens.size());
param.resize(tokens.size());
for (vector<string>::size_type i = 0; i < tokens.size(); i++) {
// need to parse into local variable to handle vector<bool>,
// for which operator[] returns a special reference class
// that's not the same as 'bool&', (since it's a packed
// vector)
T scalar_value = 0;
if (!parseParam(tokens[i], scalar_value)) {
string err("could not parse \"");
err += str;
err += "\"";
fatal(err);
}
// assign parsed value to vector
param[i] = scalar_value;
}
}
template <class T>
void
arrayParamIn(Checkpoint *cp, const string &section,
const string &name, list<T> &param)
{
string str;
if (!cp->find(section, name, str)) {
fatal("Can't unserialize '%s:%s'\n", section, name);
}
param.clear();
vector<string> tokens;
tokenize(tokens, str, ' ');
for (vector<string>::size_type i = 0; i < tokens.size(); i++) {
T scalar_value = 0;
if (!parseParam(tokens[i], scalar_value)) {
string err("could not parse \"");
err += str;
err += "\"";
fatal(err);
}
// assign parsed value to vector
param.push_back(scalar_value);
}
}
void
objParamIn(Checkpoint *cp, const string &section,
const string &name, SimObject * &param)
{
if (!cp->findObj(section, name, param)) {
fatal("Can't unserialize '%s:%s'\n", section, name);
}
}
#define INSTANTIATE_PARAM_TEMPLATES(type) \
template void \
paramOut(ostream &os, const string &name, type const &param); \
template void \
paramIn(Checkpoint *cp, const string &section, \
const string &name, type & param); \
template bool \
optParamIn(Checkpoint *cp, const string &section, \
const string &name, type & param); \
template void \
arrayParamOut(ostream &os, const string &name, \
type const *param, unsigned size); \
template void \
arrayParamIn(Checkpoint *cp, const string &section, \
const string &name, type *param, unsigned size); \
template void \
arrayParamOut(ostream &os, const string &name, \
const vector<type> &param); \
template void \
arrayParamIn(Checkpoint *cp, const string &section, \
const string &name, vector<type> &param); \
template void \
arrayParamOut(ostream &os, const string &name, \
const list<type> &param); \
template void \
arrayParamIn(Checkpoint *cp, const string &section, \
const string &name, list<type> &param);
INSTANTIATE_PARAM_TEMPLATES(char)
INSTANTIATE_PARAM_TEMPLATES(signed char)
INSTANTIATE_PARAM_TEMPLATES(unsigned char)
INSTANTIATE_PARAM_TEMPLATES(signed short)
INSTANTIATE_PARAM_TEMPLATES(unsigned short)
INSTANTIATE_PARAM_TEMPLATES(signed int)
INSTANTIATE_PARAM_TEMPLATES(unsigned int)
INSTANTIATE_PARAM_TEMPLATES(signed long)
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)
/////////////////////////////
/// Container for serializing global variables (not associated with
/// any serialized object).
class Globals : public Serializable
{
public:
const string name() const;
void serialize(ostream &os);
void unserialize(Checkpoint *cp, const std::string &section);
};
/// The one and only instance of the Globals class.
Globals globals;
const string
Globals::name() const
{
return "Globals";
}
void
Globals::serialize(ostream &os)
{
nameOut(os);
paramOut(os, "curTick", curTick());
nameOut(os, "MainEventQueue");
mainEventQueue.serialize(os);
}
void
Globals::unserialize(Checkpoint *cp, const std::string &section)
{
Tick tick;
paramIn(cp, section, "curTick", tick);
curTick(tick);
mainEventQueue.unserialize(cp, "MainEventQueue");
}
Serializable::Serializable()
{
}
Serializable::~Serializable()
{
}
void
Serializable::serialize(ostream &os)
{
}
void
Serializable::unserialize(Checkpoint *cp, const string &section)
{
}
void
Serializable::serializeAll(const string &cpt_dir)
{
string dir = Checkpoint::setDir(cpt_dir);
if (mkdir(dir.c_str(), 0775) == -1 && errno != EEXIST)
fatal("couldn't mkdir %s\n", 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);
SimObject::serializeAll(outstream);
}
void
Serializable::unserializeGlobals(Checkpoint *cp)
{
globals.unserialize(cp, globals.name());
}
void
debug_serialize(const string &cpt_dir)
{
Serializable::serializeAll(cpt_dir);
}
////////////////////////////////////////////////////////////////////////
//
// SerializableClass member definitions
//
////////////////////////////////////////////////////////////////////////
// Map of class names to SerializableBuilder creation functions.
// Need to make this a pointer so we can force initialization on the
// first reference; otherwise, some SerializableClass constructors
// may be invoked before the classMap constructor.
map<string, SerializableClass::CreateFunc> *SerializableClass::classMap = 0;
// SerializableClass constructor: add mapping to classMap
SerializableClass::SerializableClass(const string &className,
CreateFunc createFunc)
{
if (classMap == NULL)
classMap = new map<string, SerializableClass::CreateFunc>();
if ((*classMap)[className])
fatal("Error: simulation object class %s redefined\n", className);
// add className --> createFunc to class map
(*classMap)[className] = createFunc;
}
//
//
Serializable *
SerializableClass::createObject(Checkpoint *cp, const string &section)
{
string className;
if (!cp->find(section, "type", className)) {
fatal("Serializable::create: no 'type' entry in section '%s'.\n",
section);
}
CreateFunc createFunc = (*classMap)[className];
if (createFunc == NULL) {
fatal("Serializable::create: no create function for class '%s'.\n",
className);
}
Serializable *object = createFunc(cp, section);
assert(object != NULL);
return object;
}
Serializable *
Serializable::create(Checkpoint *cp, const string &section)
{
Serializable *object = SerializableClass::createObject(cp, section);
object->unserialize(cp, section);
return object;
}
const char *Checkpoint::baseFilename = "m5.cpt";
string Checkpoint::currentDirectory;
string
Checkpoint::setDir(const string &name)
{
// use csprintf to insert curTick() into directory name if it
// appears to have a format placeholder in it.
currentDirectory = (name.find("%") != string::npos) ?
csprintf(name, curTick()) : name;
if (currentDirectory[currentDirectory.size() - 1] != '/')
currentDirectory += "/";
return currentDirectory;
}
string
Checkpoint::dir()
{
return currentDirectory;
}
Checkpoint::Checkpoint(const string &cpt_dir)
: db(new IniFile), cptDir(setDir(cpt_dir))
{
string filename = cptDir + "/" + Checkpoint::baseFilename;
if (!db->load(filename)) {
fatal("Can't load checkpoint file '%s'\n", filename);
}
}
bool
Checkpoint::find(const string &section, const string &entry, string &value)
{
return db->find(section, entry, value);
}
bool
Checkpoint::findObj(const string &section, const string &entry,
SimObject *&value)
{
string path;
if (!db->find(section, entry, path))
return false;
value = resolveSimObject(path);
return true;
}
bool
Checkpoint::sectionExists(const string &section)
{
return db->sectionExists(section);
}

View File

@ -0,0 +1,295 @@
/*
* Copyright (c) 2002-2005 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Nathan Binkert
* Erik Hallnor
* Steve Reinhardt
*/
/* @file
* Serialization Interface Declarations
*/
#ifndef __SERIALIZE_HH__
#define __SERIALIZE_HH__
#include <iostream>
#include <list>
#include <map>
#include <vector>
#include "base/types.hh"
class IniFile;
class Serializable;
class Checkpoint;
class SimObject;
/** The current version of the checkpoint format.
* This should be incremented by 1 and only 1 for every new version, where a new
* version is defined as a checkpoint created before this version won't work on
* the current version until the checkpoint format is updated. Adding a new
* SimObject shouldn't cause the version number to increase, only changes to
* existing objects such as serializing/unserializing more state, changing sizes
* of serialized arrays, etc. */
static const uint64_t gem5CheckpointVersion = 0x0000000000000001;
template <class T>
void paramOut(std::ostream &os, const std::string &name, const T &param);
template <class T>
void paramIn(Checkpoint *cp, const std::string &section,
const std::string &name, T &param);
template <class T>
bool optParamIn(Checkpoint *cp, const std::string &section,
const std::string &name, T &param);
template <class T>
void arrayParamOut(std::ostream &os, const std::string &name,
const T *param, unsigned size);
template <class T>
void arrayParamOut(std::ostream &os, const std::string &name,
const std::vector<T> &param);
template <class T>
void arrayParamOut(std::ostream &os, const std::string &name,
const std::list<T> &param);
template <class T>
void arrayParamIn(Checkpoint *cp, const std::string &section,
const std::string &name, T *param, unsigned size);
template <class T>
void arrayParamIn(Checkpoint *cp, const std::string &section,
const std::string &name, std::vector<T> &param);
template <class T>
void arrayParamIn(Checkpoint *cp, const std::string &section,
const std::string &name, std::list<T> &param);
void
objParamIn(Checkpoint *cp, const std::string &section,
const std::string &name, SimObject * &param);
template <typename T>
void fromInt(T &t, int i)
{
t = (T)i;
}
template <typename T>
void fromSimObject(T &t, SimObject *s)
{
t = dynamic_cast<T>(s);
}
//
// 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 UNSERIALIZE_SCALAR(scalar) paramIn(cp, section, #scalar, scalar)
#define UNSERIALIZE_OPT_SCALAR(scalar) optParamIn(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 UNSERIALIZE_ENUM(scalar) \
do { \
int tmp; \
paramIn(cp, section, #scalar, tmp); \
fromInt(scalar, tmp); \
} while (0)
#define SERIALIZE_ARRAY(member, size) \
arrayParamOut(os, #member, member, size)
#define UNSERIALIZE_ARRAY(member, size) \
arrayParamIn(cp, section, #member, member, size)
#define SERIALIZE_OBJPTR(objptr) paramOut(os, #objptr, (objptr)->name())
#define UNSERIALIZE_OBJPTR(objptr) \
do { \
SimObject *sptr; \
objParamIn(cp, section, #objptr, sptr); \
fromSimObject(objptr, sptr); \
} while (0)
/*
* Basic support for object serialization.
*/
class Serializable
{
protected:
void nameOut(std::ostream &os);
void nameOut(std::ostream &os, const std::string &_name);
public:
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);
static Serializable *create(Checkpoint *cp, const std::string &section);
static int ckptCount;
static int ckptMaxCount;
static int ckptPrevCount;
static void serializeAll(const std::string &cpt_dir);
static void unserializeGlobals(Checkpoint *cp);
};
//
// A SerializableBuilder serves as an evaluation context for a set of
// parameters that describe a specific instance of a Serializable. This
// evaluation context corresponds to a section in the .ini file (as
// with the base ParamContext) plus an optional node in the
// configuration hierarchy (the configNode member) for resolving
// Serializable references. SerializableBuilder is an abstract superclass;
// derived classes specialize the class for particular subclasses of
// Serializable (e.g., BaseCache).
//
// For typical usage, see the definition of
// SerializableClass::createObject().
//
class SerializableBuilder
{
public:
SerializableBuilder() {}
virtual ~SerializableBuilder() {}
// Create the actual Serializable corresponding to the parameter
// values in this context. This function is overridden in derived
// classes to call a specific constructor for a particular
// subclass of Serializable.
virtual Serializable *create() = 0;
};
//
// An instance of SerializableClass corresponds to a class derived from
// Serializable. The SerializableClass instance serves to bind the string
// name (found in the config file) to a function that creates an
// instance of the appropriate derived class.
//
// This would be much cleaner in Smalltalk or Objective-C, where types
// are first-class objects themselves.
//
class SerializableClass
{
public:
// Type CreateFunc is a pointer to a function that creates a new
// simulation object builder based on a .ini-file parameter
// section (specified by the first string argument), a unique name
// for the object (specified by the second string argument), and
// an optional config hierarchy node (specified by the third
// argument). A pointer to the new SerializableBuilder is returned.
typedef Serializable *(*CreateFunc)(Checkpoint *cp,
const std::string &section);
static std::map<std::string,CreateFunc> *classMap;
// Constructor. For example:
//
// SerializableClass baseCacheSerializableClass("BaseCacheSerializable",
// newBaseCacheSerializableBuilder);
//
SerializableClass(const std::string &className, CreateFunc createFunc);
// create Serializable given name of class and pointer to
// configuration hierarchy node
static Serializable *createObject(Checkpoint *cp,
const std::string &section);
};
//
// Macros to encapsulate the magic of declaring & defining
// SerializableBuilder and SerializableClass objects
//
#define REGISTER_SERIALIZEABLE(CLASS_NAME, OBJ_CLASS) \
SerializableClass the##OBJ_CLASS##Class(CLASS_NAME, \
OBJ_CLASS::createForUnserialize);
class Checkpoint
{
private:
IniFile *db;
public:
Checkpoint(const std::string &cpt_dir);
const std::string cptDir;
bool find(const std::string &section, const std::string &entry,
std::string &value);
bool findObj(const std::string &section, const std::string &entry,
SimObject *&value);
bool sectionExists(const std::string &section);
// The following static functions have to do with checkpoint
// creation rather than restoration. This class makes a handy
// namespace for them though. Currently no Checkpoint object is
// created on serialization (only unserialization) so we track the
// directory name as a global. It would be nice to change this
// someday
private:
// current directory we're serializing into.
static std::string currentDirectory;
public:
// Set the current directory. This function takes care of
// inserting curTick() if there's a '%d' in the argument, and
// appends a '/' if necessary. The final name is returned.
static std::string setDir(const std::string &base_name);
// Export current checkpoint directory name so other objects can
// derive filenames from it (e.g., memory). The return value is
// guaranteed to end in '/' so filenames can be directly appended.
// This function is only valid while a checkpoint is being created.
static std::string dir();
// Filename for base checkpoint file within directory.
static const char *baseFilename;
};
#endif // __SERIALIZE_HH__

View File

@ -0,0 +1,124 @@
/*
* Copyright (c) 2002-2005 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Nathan Binkert
*/
#include <string>
#include "base/callback.hh"
#include "base/hostinfo.hh"
#include "sim/eventq.hh"
#include "sim/sim_events.hh"
#include "sim/sim_exit.hh"
#include "sim/stats.hh"
using namespace std;
SimLoopExitEvent::SimLoopExitEvent(const std::string &_cause, int c, Tick r)
: Event(Sim_Exit_Pri, IsExitEvent), cause(_cause), code(c), repeat(r)
{
}
//
// handle termination event
//
void
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 (!isFlagSet(IsMainQueue)) {
exitSimLoop(cause, code);
delete this;
}
// otherwise do nothing... the IsExitEvent flag takes care of
// exiting the simulation loop and returning this object to Python
// but if you are doing this on intervals, don't forget to make another
if (repeat) {
assert(isFlagSet(IsMainQueue));
mainEventQueue.schedule(this, curTick() + repeat);
}
}
const char *
SimLoopExitEvent::description() const
{
return "simulation loop exit";
}
void
exitSimLoop(const std::string &message, int exit_code, Tick when, Tick repeat)
{
Event *event = new SimLoopExitEvent(message, exit_code, repeat);
mainEventQueue.schedule(event, when);
}
CountedDrainEvent::CountedDrainEvent()
: count(0)
{ }
void
CountedDrainEvent::process()
{
if (--count == 0)
exitSimLoop("Finished drain", 0);
}
//
// constructor: automatically schedules at specified time
//
CountedExitEvent::CountedExitEvent(const std::string &_cause, int &counter)
: Event(Sim_Exit_Pri), cause(_cause), downCounter(counter)
{
// catch stupid mistakes
assert(downCounter > 0);
}
//
// handle termination event
//
void
CountedExitEvent::process()
{
if (--downCounter == 0) {
exitSimLoop(cause, 0);
}
}
const char *
CountedExitEvent::description() const
{
return "counted exit";
}

View File

@ -0,0 +1,94 @@
/*
* Copyright (c) 2002-2005 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Nathan Binkert
*/
#ifndef __SIM_SIM_EVENTS_HH__
#define __SIM_SIM_EVENTS_HH__
#include "sim/eventq.hh"
//
// Event to terminate simulation at a particular cycle/instruction
//
class SimLoopExitEvent : public Event
{
protected:
// string explaining why we're terminating
std::string cause;
int code;
Tick repeat;
public:
SimLoopExitEvent(const std::string &_cause, int c, Tick repeat = 0);
std::string getCause() { return cause; }
int getCode() { return code; }
void process(); // process event
virtual const char *description() const;
};
class CountedDrainEvent : public Event
{
private:
// Count of how many objects have not yet drained
int count;
public:
CountedDrainEvent();
void process();
void setCount(int _count) { count = _count; }
int getCount() { return count; }
};
//
// Event class to terminate simulation after 'n' related events have
// occurred using a shared counter: used to terminate when *all*
// threads have reached a particular instruction count
//
class CountedExitEvent : public Event
{
private:
std::string cause; // string explaining why we're terminating
int &downCounter; // decrement & terminate if zero
public:
CountedExitEvent(const std::string &_cause, int &_downCounter);
void process(); // process event
virtual const char *description() const;
};
#endif // __SIM_SIM_EVENTS_HH__

View File

@ -0,0 +1,56 @@
/*
* Copyright (c) 2003-2005 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Nathan Binkert
* Steve Reinhardt
*/
#ifndef __SIM_EXIT_HH__
#define __SIM_EXIT_HH__
#include <string>
#include "base/types.hh"
#include "sim/core.hh"
// forward declaration
class Callback;
class EventQueue;
class SimLoopExitEvent;
/// Register a callback to be called when Python exits. Defined in
/// sim/main.cc.
void registerExitCallback(Callback *);
/// 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.
void exitSimLoop(const std::string &message, int exit_code = 0,
Tick when = curTick(), Tick repeat = 0);
#endif // __SIM_EXIT_HH__

View File

@ -0,0 +1,203 @@
/*
* Copyright (c) 2001-2005 The Regents of The University of Michigan
* Copyright (c) 2010 Advanced Micro Devices, Inc.
* 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
*/
#include <cassert>
#include "base/callback.hh"
#include "base/inifile.hh"
#include "base/match.hh"
#include "base/misc.hh"
#include "base/trace.hh"
#include "base/types.hh"
#include "debug/Checkpoint.hh"
#include "sim/sim_object.hh"
#include "sim/stats.hh"
using namespace std;
////////////////////////////////////////////////////////////////////////
//
// SimObject member definitions
//
////////////////////////////////////////////////////////////////////////
//
// static list of all SimObjects, used for initialization etc.
//
SimObject::SimObjectList SimObject::simObjectList;
//
// SimObject constructor: used to maintain static simObjectList
//
SimObject::SimObject(const Params *p)
: EventManager(p->eventq), _params(p)
{
#ifdef DEBUG
doDebugBreak = false;
#endif
simObjectList.push_back(this);
state = Running;
}
void
SimObject::init()
{
}
void
SimObject::loadState(Checkpoint *cp)
{
if (cp->sectionExists(name())) {
DPRINTF(Checkpoint, "unserializing\n");
unserialize(cp, name());
} else {
DPRINTF(Checkpoint, "no checkpoint section found\n");
}
}
void
SimObject::initState()
{
}
void
SimObject::startup()
{
}
//
// no default statistics, so nothing to do in base implementation
//
void
SimObject::regStats()
{
}
void
SimObject::regFormulas()
{
}
void
SimObject::resetStats()
{
}
//
// static function: serialize all SimObjects.
//
void
SimObject::serializeAll(ostream &os)
{
SimObjectList::reverse_iterator ri = simObjectList.rbegin();
SimObjectList::reverse_iterator rend = simObjectList.rend();
for (; ri != rend; ++ri) {
SimObject *obj = *ri;
obj->nameOut(os);
obj->serialize(os);
}
}
#ifdef DEBUG
//
// static function: flag which objects should have the debugger break
//
void
SimObject::debugObjectBreak(const string &objs)
{
SimObjectList::const_iterator i = simObjectList.begin();
SimObjectList::const_iterator end = simObjectList.end();
ObjectMatch match(objs);
for (; i != end; ++i) {
SimObject *obj = *i;
obj->doDebugBreak = match.match(obj->name());
}
}
void
debugObjectBreak(const char *objs)
{
SimObject::debugObjectBreak(string(objs));
}
#endif
unsigned int
SimObject::drain(Event *drain_event)
{
state = Drained;
return 0;
}
void
SimObject::resume()
{
state = Running;
}
void
SimObject::setMemoryMode(Enums::MemoryMode new_mode)
{
panic("setMemoryMode() should only be called on systems");
}
void
SimObject::switchOut()
{
panic("Unimplemented!");
}
void
SimObject::takeOverFrom(BaseCPU *cpu)
{
panic("Unimplemented!");
}
SimObject *
SimObject::find(const char *name)
{
SimObjectList::const_iterator i = simObjectList.begin();
SimObjectList::const_iterator end = simObjectList.end();
for (; i != end; ++i) {
SimObject *obj = *i;
if (obj->name() == name)
return obj;
}
return NULL;
}

View File

@ -0,0 +1,168 @@
/*
* Copyright (c) 2001-2005 The Regents of The University of Michigan
* Copyright (c) 2010 Advanced Micro Devices, Inc.
* 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
*/
/* @file
* User Console Definitions
*/
#ifndef __SIM_OBJECT_HH__
#define __SIM_OBJECT_HH__
#include <iostream>
#include <list>
#include <map>
#include <string>
#include <vector>
#include "enums/MemoryMode.hh"
#include "params/SimObject.hh"
#include "sim/eventq.hh"
#include "sim/serialize.hh"
class BaseCPU;
class Event;
/*
* Abstract superclass for simulation objects. Represents things that
* correspond to physical components and can be specified via the
* config file (CPUs, caches, etc.).
*/
class SimObject : public EventManager, public Serializable
{
public:
enum State {
Running,
Draining,
Drained
};
private:
State state;
protected:
void changeState(State new_state) { state = new_state; }
public:
State getState() { return state; }
private:
typedef std::vector<SimObject *> SimObjectList;
// list of all instantiated simulation objects
static SimObjectList simObjectList;
protected:
const SimObjectParams *_params;
public:
typedef SimObjectParams Params;
const Params *params() const { return _params; }
SimObject(const Params *_params);
virtual ~SimObject() {}
public:
virtual const std::string name() const { return params()->name; }
// The following SimObject initialization methods are called from
// the instantiate() method in src/python/m5/simulate.py. See
// that function for details on how/when these methods are
// invoked.
/**
* init() is called after all C++ SimObjects have been created and
* all ports are connected. Initializations that are independent
* of unserialization but rely on a fully instantiated and
* connected SimObject graph should be done here.
*/
virtual void init();
/**
* loadState() is called on each SimObject when restoring from a
* checkpoint. The default implementation simply calls
* unserialize() if there is a corresponding section in the
* checkpoint. However, objects can override loadState() to get
* other behaviors, e.g., doing other programmed initializations
* after unserialize(), or complaining if no checkpoint section is
* found.
*/
virtual void loadState(Checkpoint *cp);
/**
* initState() is called on each SimObject when *not* restoring
* from a checkpoint. This provides a hook for state
* initializations that are only required for a "cold start".
*/
virtual void initState();
// register statistics for this object
virtual void regStats();
virtual void regFormulas();
virtual void resetStats();
/**
* startup() is the final initialization call before simulation.
* All state is initialized (including unserialized state, if any,
* such as the curTick() value), so this is the appropriate place to
* schedule initial event(s) for objects that need them.
*/
virtual void startup();
// static: call nameOut() & serialize() on all SimObjects
static void serializeAll(std::ostream &);
// Methods to drain objects in order to take checkpoints
// Or switch from timing -> atomic memory model
// Drain returns 0 if the simobject can drain immediately or
// the number of times the drain_event's process function will be called
// before the object will be done draining. Normally this should be 1
virtual unsigned int drain(Event *drain_event);
virtual void resume();
virtual void setMemoryMode(Enums::MemoryMode new_mode);
virtual void switchOut();
virtual void takeOverFrom(BaseCPU *cpu);
#ifdef DEBUG
public:
bool doDebugBreak;
static void debugObjectBreak(const std::string &objs);
#endif
/**
* Find the SimObject with the given name and return a pointer to
* it. Primarily used for interactive debugging. Argument is
* char* rather than std::string to make it callable from gdb.
*/
static SimObject *find(const char *name);
};
#endif // __SIM_OBJECT_HH__

View File

@ -0,0 +1,121 @@
/*
* Copyright (c) 2006 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Nathan Binkert
* Steve Reinhardt
*/
#include "base/misc.hh"
#include "base/pollevent.hh"
#include "base/types.hh"
#include "sim/async.hh"
#include "sim/eventq.hh"
#include "sim/sim_events.hh"
#include "sim/sim_exit.hh"
#include "sim/simulate.hh"
#include "sim/stat_control.hh"
/** Simulate for num_cycles additional cycles. If num_cycles is -1
* (the default), do not limit simulation; some other event must
* terminate the loop. Exported to Python via SWIG.
* @return The SimLoopExitEvent that caused the loop to exit.
*/
SimLoopExitEvent *
simulate(Tick num_cycles)
{
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);
else if (curTick() + num_cycles < 0) //Overflow
num_cycles = MaxTick;
else
num_cycles = curTick() + 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
// we just scheduled) in the queue
assert(!mainEventQueue.empty());
assert(curTick() <= mainEventQueue.nextTick() &&
"event scheduled in the past");
// forward current cycle to the time of the first event on the
// queue
curTick(mainEventQueue.nextTick());
Event *exit_event = mainEventQueue.serviceOne();
if (exit_event != NULL) {
// hit some kind of exit event; return to Python
// event must be subclass of SimLoopExitEvent...
SimLoopExitEvent *se_event;
se_event = dynamic_cast<SimLoopExitEvent *>(exit_event);
if (se_event == NULL)
panic("Bogus exit event class!");
// if we didn't hit limit_event, delete it
if (se_event != limit_event) {
assert(limit_event->scheduled());
limit_event->squash();
hack_once("be nice to actually delete the event here");
}
return se_event;
}
if (async_event) {
async_event = false;
if (async_statdump || async_statreset) {
Stats::schedStatEvent(async_statdump, async_statreset);
async_statdump = false;
async_statreset = false;
}
if (async_exit) {
async_exit = false;
exitSimLoop("user interrupt received");
}
if (async_io || async_alarm) {
async_io = false;
async_alarm = false;
pollQueue.service();
}
if (async_exception) {
async_exception = false;
return NULL;
}
}
}
// not reached... only exit is return on SimLoopExitEvent
}

View File

@ -0,0 +1,35 @@
/*
* Copyright (c) 2006 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Nathan Binkert
* Steve Reinhardt
*/
#include "base/types.hh"
#include "sim/sim_events.hh"
SimLoopExitEvent *simulate(Tick num_cycles = MaxTick);

View File

@ -0,0 +1,237 @@
/*
* Copyright (c) 2004-2005 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Nathan Binkert
*/
// This file will contain default statistics for the simulator that
// don't really belong to a specific simulator object
#include <fstream>
#include <iostream>
#include <list>
#include "base/callback.hh"
#include "base/hostinfo.hh"
#include "base/statistics.hh"
#include "base/time.hh"
#include "config/the_isa.hh"
#if THE_ISA == NO_ISA
#include "arch/noisa/cpu_dummy.hh"
#else
#include "cpu/base.hh"
#endif
#include "sim/eventq.hh"
#include "sim/stat_control.hh"
using namespace std;
Stats::Formula simSeconds;
Stats::Value simTicks;
Stats::Value finalTick;
Stats::Value simFreq;
namespace Stats {
Time statTime(true);
Tick startTick;
struct SimTicksReset : public Callback
{
void process()
{
statTime.setTimer();
startTick = curTick();
}
};
double
statElapsedTime()
{
Time now;
now.setTimer();
Time elapsed = now - statTime;
return elapsed;
}
Tick
statElapsedTicks()
{
return curTick() - startTick;
}
Tick
statFinalTick()
{
return curTick();
}
SimTicksReset simTicksReset;
struct Global
{
Stats::Formula hostInstRate;
Stats::Formula hostOpRate;
Stats::Formula hostTickRate;
Stats::Value hostMemory;
Stats::Value hostSeconds;
Stats::Value simInsts;
Stats::Value simOps;
Global();
};
Global::Global()
{
simInsts
.functor(BaseCPU::numSimulatedInsts)
.name("sim_insts")
.desc("Number of instructions simulated")
.precision(0)
.prereq(simInsts)
;
simOps
.functor(BaseCPU::numSimulatedOps)
.name("sim_ops")
.desc("Number of ops (including micro ops) simulated")
.precision(0)
.prereq(simOps)
;
simSeconds
.name("sim_seconds")
.desc("Number of seconds simulated")
;
simFreq
.scalar(SimClock::Frequency)
.name("sim_freq")
.desc("Frequency of simulated ticks")
;
simTicks
.functor(statElapsedTicks)
.name("sim_ticks")
.desc("Number of ticks simulated")
;
finalTick
.functor(statFinalTick)
.name("final_tick")
.desc("Number of ticks from beginning of simulation \
(restored from checkpoints and never reset)")
;
hostInstRate
.name("host_inst_rate")
.desc("Simulator instruction rate (inst/s)")
.precision(0)
.prereq(simInsts)
;
hostOpRate
.name("host_op_rate")
.desc("Simulator op (including micro ops) rate (op/s)")
.precision(0)
.prereq(simOps)
;
hostMemory
.functor(memUsage)
.name("host_mem_usage")
.desc("Number of bytes of host memory used")
.prereq(hostMemory)
;
hostSeconds
.functor(statElapsedTime)
.name("host_seconds")
.desc("Real time elapsed on the host")
.precision(2)
;
hostTickRate
.name("host_tick_rate")
.desc("Simulator tick rate (ticks/s)")
.precision(0)
;
simSeconds = simTicks / simFreq;
hostInstRate = simInsts / hostSeconds;
hostOpRate = simOps / hostSeconds;
hostTickRate = simTicks / hostSeconds;
registerResetCallback(&simTicksReset);
}
void
initSimStats()
{
static Global global;
}
class StatEvent : public Event
{
private:
bool dump;
bool reset;
Tick repeat;
public:
StatEvent(bool _dump, bool _reset, Tick _repeat)
: Event(Stat_Event_Pri, AutoDelete),
dump(_dump), reset(_reset), repeat(_repeat)
{
}
virtual void
process()
{
if (dump)
Stats::dump();
if (reset)
Stats::reset();
if (repeat) {
Stats::schedStatEvent(dump, reset, curTick() + repeat, repeat);
}
}
};
void
schedStatEvent(bool dump, bool reset, Tick when, Tick repeat)
{
Event *event = new StatEvent(dump, reset, repeat);
mainEventQueue.schedule(event, when);
}
} // namespace Stats

View File

@ -0,0 +1,42 @@
/*
* Copyright (c) 2004-2005 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Nathan Binkert
*/
#ifndef __SIM_STAT_CONTROL_HH__
#define __SIM_STAT_CONTROL_HH__
namespace Stats {
void initSimStats();
void schedStatEvent(bool dump, bool reset, Tick when = curTick(),
Tick repeat = 0);
} // namespace Stats
#endif // __SIM_STAT_CONTROL_HH__

View File

@ -0,0 +1,40 @@
/*
* Copyright (c) 2004-2005 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Nathan Binkert
*/
#ifndef __SIM_STATS_HH__
#define __SIM_STATS_HH__
#include "base/statistics.hh"
extern Stats::Formula simSeconds;
extern Stats::Value simTicks;
extern Stats::Value simFreq;
#endif // __SIM_SIM_STATS_HH__

View File

@ -0,0 +1,853 @@
/*
* Copyright (c) 2003-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
* Ali Saidi
*/
#include <fcntl.h>
#include <unistd.h>
#include <cstdio>
#include <iostream>
#include <string>
#include "arch/utility.hh"
#include "base/chunk_generator.hh"
#include "base/trace.hh"
#include "config/the_isa.hh"
#include "cpu/base.hh"
#include "cpu/thread_context.hh"
#include "debug/SyscallVerbose.hh"
#include "mem/page_table.hh"
#include "sim/process.hh"
#include "sim/sim_exit.hh"
#include "sim/syscall_emul.hh"
#include "sim/system.hh"
using namespace std;
using namespace TheISA;
void
SyscallDesc::doSyscall(int callnum, LiveProcess *process, ThreadContext *tc)
{
#if TRACING_ON
int index = 0;
#endif
DPRINTFR(SyscallVerbose,
"%d: %s: syscall %s called w/arguments %d,%d,%d,%d\n",
curTick(), tc->getCpuPtr()->name(), name,
process->getSyscallArg(tc, index),
process->getSyscallArg(tc, index),
process->getSyscallArg(tc, index),
process->getSyscallArg(tc, index));
SyscallReturn retval = (*funcPtr)(this, callnum, process, tc);
DPRINTFR(SyscallVerbose, "%d: %s: syscall %s returns %d\n",
curTick(),tc->getCpuPtr()->name(), name, retval.value());
if (!(flags & SyscallDesc::SuppressReturnValue))
process->setSyscallReturn(tc, retval);
}
SyscallReturn
unimplementedFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
ThreadContext *tc)
{
fatal("syscall %s (#%d) unimplemented.", desc->name, callnum);
return 1;
}
SyscallReturn
ignoreFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
ThreadContext *tc)
{
int index = 0;
warn("ignoring syscall %s(%d, %d, ...)", desc->name,
process->getSyscallArg(tc, index), process->getSyscallArg(tc, index));
return 0;
}
SyscallReturn
ignoreWarnOnceFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
ThreadContext *tc)
{
int index = 0;
warn_once("ignoring syscall %s(%d, %d, ...)", desc->name,
process->getSyscallArg(tc, index), process->getSyscallArg(tc, index));
return 0;
}
SyscallReturn
exitFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
ThreadContext *tc)
{
if (process->system->numRunningContexts() == 1) {
// Last running context... exit simulator
int index = 0;
exitSimLoop("target called exit()",
process->getSyscallArg(tc, index) & 0xff);
} else {
// other running threads... just halt this one
tc->halt();
}
return 1;
}
SyscallReturn
exitGroupFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
ThreadContext *tc)
{
// really should just halt all thread contexts belonging to this
// process in case there's another process running...
int index = 0;
exitSimLoop("target called exit()",
process->getSyscallArg(tc, index) & 0xff);
return 1;
}
SyscallReturn
getpagesizeFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc)
{
return (int)VMPageSize;
}
SyscallReturn
brkFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc)
{
// change brk addr to first arg
int index = 0;
Addr new_brk = p->getSyscallArg(tc, index);
// 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()))
p->allocateMem(roundDown(gen.addr(), VMPageSize), VMPageSize);
// if the address is already there, zero it out
else {
uint8_t zero = 0;
SETranslatingPortProxy &tp = tc->getMemProxy();
// split non-page aligned accesses
Addr next_page = roundUp(gen.addr(), VMPageSize);
uint32_t size_needed = next_page - gen.addr();
tp.memsetBlob(gen.addr(), zero, size_needed);
if (gen.addr() + VMPageSize > next_page &&
next_page < new_brk &&
p->pTable->translate(next_page))
{
size_needed = VMPageSize - size_needed;
tp.memsetBlob(next_page, zero, size_needed);
}
}
}
}
p->brk_point = new_brk;
DPRINTF(SyscallVerbose, "Break Point changed to: %#X\n", p->brk_point);
return p->brk_point;
}
SyscallReturn
closeFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc)
{
int index = 0;
int target_fd = p->getSyscallArg(tc, index);
int sim_fd = p->sim_fd(target_fd);
int status = 0;
if (sim_fd > 2)
status = close(sim_fd);
if (status >= 0)
p->free_fd(target_fd);
return status;
}
SyscallReturn
readFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc)
{
int index = 0;
int fd = p->sim_fd(p->getSyscallArg(tc, index));
Addr bufPtr = p->getSyscallArg(tc, index);
int nbytes = p->getSyscallArg(tc, index);
BufferArg bufArg(bufPtr, nbytes);
int bytes_read = read(fd, bufArg.bufferPtr(), nbytes);
if (bytes_read != -1)
bufArg.copyOut(tc->getMemProxy());
return bytes_read;
}
SyscallReturn
writeFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc)
{
int index = 0;
int fd = p->sim_fd(p->getSyscallArg(tc, index));
Addr bufPtr = p->getSyscallArg(tc, index);
int nbytes = p->getSyscallArg(tc, index);
BufferArg bufArg(bufPtr, nbytes);
bufArg.copyIn(tc->getMemProxy());
int bytes_written = write(fd, bufArg.bufferPtr(), nbytes);
fsync(fd);
return bytes_written;
}
SyscallReturn
lseekFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc)
{
int index = 0;
int fd = p->sim_fd(p->getSyscallArg(tc, index));
uint64_t offs = p->getSyscallArg(tc, index);
int whence = p->getSyscallArg(tc, index);
off_t result = lseek(fd, offs, whence);
return (result == (off_t)-1) ? -errno : result;
}
SyscallReturn
_llseekFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc)
{
int index = 0;
int fd = p->sim_fd(p->getSyscallArg(tc, index));
uint64_t offset_high = p->getSyscallArg(tc, index);
uint32_t offset_low = p->getSyscallArg(tc, index);
Addr result_ptr = p->getSyscallArg(tc, index);
int whence = p->getSyscallArg(tc, index);
uint64_t offset = (offset_high << 32) | offset_low;
uint64_t result = lseek(fd, offset, whence);
result = TheISA::htog(result);
if (result == (off_t)-1) {
//The seek failed.
return -errno;
} else {
// The seek succeeded.
// Copy "result" to "result_ptr"
// XXX We'll assume that the size of loff_t is 64 bits on the
// target platform
BufferArg result_buf(result_ptr, sizeof(result));
memcpy(result_buf.bufferPtr(), &result, sizeof(result));
result_buf.copyOut(tc->getMemProxy());
return 0;
}
return (result == (off_t)-1) ? -errno : result;
}
SyscallReturn
munmapFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc)
{
// given that we don't really implement mmap, munmap is really easy
return 0;
}
const char *hostname = "m5.eecs.umich.edu";
SyscallReturn
gethostnameFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc)
{
int index = 0;
Addr bufPtr = p->getSyscallArg(tc, index);
int name_len = p->getSyscallArg(tc, index);
BufferArg name(bufPtr, name_len);
strncpy((char *)name.bufferPtr(), hostname, name_len);
name.copyOut(tc->getMemProxy());
return 0;
}
SyscallReturn
getcwdFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc)
{
int result = 0;
int index = 0;
Addr bufPtr = p->getSyscallArg(tc, index);
unsigned long size = p->getSyscallArg(tc, index);
BufferArg buf(bufPtr, 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->getMemProxy());
return (result == -1) ? -errno : result;
}
SyscallReturn
readlinkFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc)
{
string path;
int index = 0;
if (!tc->getMemProxy().tryReadString(path, p->getSyscallArg(tc, index)))
return (TheISA::IntReg)-EFAULT;
// Adjust path for current working directory
path = p->fullPath(path);
Addr bufPtr = p->getSyscallArg(tc, index);
size_t bufsiz = p->getSyscallArg(tc, index);
BufferArg buf(bufPtr, bufsiz);
int result = readlink(path.c_str(), (char *)buf.bufferPtr(), bufsiz);
buf.copyOut(tc->getMemProxy());
return (result == -1) ? -errno : result;
}
SyscallReturn
unlinkFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc)
{
string path;
int index = 0;
if (!tc->getMemProxy().tryReadString(path, p->getSyscallArg(tc, index)))
return (TheISA::IntReg)-EFAULT;
// Adjust path for current working directory
path = p->fullPath(path);
int result = unlink(path.c_str());
return (result == -1) ? -errno : result;
}
SyscallReturn
mkdirFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc)
{
string path;
int index = 0;
if (!tc->getMemProxy().tryReadString(path, p->getSyscallArg(tc, index)))
return (TheISA::IntReg)-EFAULT;
// Adjust path for current working directory
path = p->fullPath(path);
mode_t mode = p->getSyscallArg(tc, index);
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;
int index = 0;
if (!tc->getMemProxy().tryReadString(old_name, p->getSyscallArg(tc, index)))
return -EFAULT;
string new_name;
if (!tc->getMemProxy().tryReadString(new_name, p->getSyscallArg(tc, index)))
return -EFAULT;
// Adjust path for current working directory
old_name = p->fullPath(old_name);
new_name = p->fullPath(new_name);
int64_t result = rename(old_name.c_str(), new_name.c_str());
return (result == -1) ? -errno : result;
}
SyscallReturn
truncateFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc)
{
string path;
int index = 0;
if (!tc->getMemProxy().tryReadString(path, p->getSyscallArg(tc, index)))
return -EFAULT;
off_t length = p->getSyscallArg(tc, index);
// Adjust path for current working directory
path = p->fullPath(path);
int result = truncate(path.c_str(), length);
return (result == -1) ? -errno : result;
}
SyscallReturn
ftruncateFunc(SyscallDesc *desc, int num,
LiveProcess *process, ThreadContext *tc)
{
int index = 0;
int fd = process->sim_fd(process->getSyscallArg(tc, index));
if (fd < 0)
return -EBADF;
off_t length = process->getSyscallArg(tc, index);
int result = ftruncate(fd, length);
return (result == -1) ? -errno : result;
}
SyscallReturn
truncate64Func(SyscallDesc *desc, int num,
LiveProcess *process, ThreadContext *tc)
{
int index = 0;
string path;
if (!tc->getMemProxy().tryReadString(path, process->getSyscallArg(tc, index)))
return -EFAULT;
int64_t length = process->getSyscallArg(tc, index, 64);
// Adjust path for current working directory
path = process->fullPath(path);
#if NO_STAT64
int result = truncate(path.c_str(), length);
#else
int result = truncate64(path.c_str(), length);
#endif
return (result == -1) ? -errno : result;
}
SyscallReturn
ftruncate64Func(SyscallDesc *desc, int num,
LiveProcess *process, ThreadContext *tc)
{
int index = 0;
int fd = process->sim_fd(process->getSyscallArg(tc, index));
if (fd < 0)
return -EBADF;
int64_t length = process->getSyscallArg(tc, index, 64);
#if NO_STAT64
int result = ftruncate(fd, length);
#else
int result = ftruncate64(fd, length);
#endif
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;
int index = 0;
if (!tc->getMemProxy().tryReadString(path, p->getSyscallArg(tc, index)))
return -EFAULT;
/* XXX endianess */
uint32_t owner = p->getSyscallArg(tc, index);
uid_t hostOwner = owner;
uint32_t group = p->getSyscallArg(tc, index);
gid_t hostGroup = group;
// Adjust path for current working directory
path = p->fullPath(path);
int result = chown(path.c_str(), hostOwner, hostGroup);
return (result == -1) ? -errno : result;
}
SyscallReturn
fchownFunc(SyscallDesc *desc, int num, LiveProcess *process, ThreadContext *tc)
{
int index = 0;
int fd = process->sim_fd(process->getSyscallArg(tc, index));
if (fd < 0)
return -EBADF;
/* XXX endianess */
uint32_t owner = process->getSyscallArg(tc, index);
uid_t hostOwner = owner;
uint32_t group = process->getSyscallArg(tc, index);
gid_t hostGroup = group;
int result = fchown(fd, hostOwner, hostGroup);
return (result == -1) ? -errno : result;
}
SyscallReturn
dupFunc(SyscallDesc *desc, int num, LiveProcess *process, ThreadContext *tc)
{
int index = 0;
int fd = process->sim_fd(process->getSyscallArg(tc, index));
if (fd < 0)
return -EBADF;
Process::FdMap *fdo = process->sim_fd_obj(fd);
int result = dup(fd);
return (result == -1) ? -errno :
process->alloc_fd(result, fdo->filename, fdo->flags, fdo->mode, false);
}
SyscallReturn
fcntlFunc(SyscallDesc *desc, int num, LiveProcess *process,
ThreadContext *tc)
{
int index = 0;
int fd = process->getSyscallArg(tc, index);
if (fd < 0 || process->sim_fd(fd) < 0)
return -EBADF;
int cmd = process->getSyscallArg(tc, index);
switch (cmd) {
case 0: // F_DUPFD
// if we really wanted to support this, we'd need to do it
// in the target fd space.
warn("fcntl(%d, F_DUPFD) not supported, error returned\n", fd);
return -EMFILE;
case 1: // F_GETFD (get close-on-exec flag)
case 2: // F_SETFD (set close-on-exec flag)
return 0;
case 3: // F_GETFL (get file flags)
case 4: // F_SETFL (set file flags)
// not sure if this is totally valid, but we'll pass it through
// to the underlying OS
warn("fcntl(%d, %d) passed through to host\n", fd, cmd);
return fcntl(process->sim_fd(fd), cmd);
// return 0;
case 7: // F_GETLK (get lock)
case 8: // F_SETLK (set lock)
case 9: // F_SETLKW (set lock and wait)
// don't mess with file locking... just act like it's OK
warn("File lock call (fcntl(%d, %d)) ignored.\n", fd, cmd);
return 0;
default:
warn("Unknown fcntl command %d\n", cmd);
return 0;
}
}
SyscallReturn
fcntl64Func(SyscallDesc *desc, int num, LiveProcess *process,
ThreadContext *tc)
{
int index = 0;
int fd = process->getSyscallArg(tc, index);
if (fd < 0 || process->sim_fd(fd) < 0)
return -EBADF;
int cmd = process->getSyscallArg(tc, index);
switch (cmd) {
case 33: //F_GETLK64
warn("fcntl64(%d, F_GETLK64) not supported, error returned\n", fd);
return -EMFILE;
case 34: // F_SETLK64
case 35: // F_SETLKW64
warn("fcntl64(%d, F_SETLK(W)64) not supported, error returned\n", fd);
return -EMFILE;
default:
// not sure if this is totally valid, but we'll pass it through
// to the underlying OS
warn("fcntl64(%d, %d) passed through to host\n", fd, cmd);
return fcntl(process->sim_fd(fd), cmd);
// return 0;
}
}
SyscallReturn
pipePseudoFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
ThreadContext *tc)
{
int fds[2], sim_fds[2];
int pipe_retval = pipe(fds);
if (pipe_retval < 0) {
// error
return pipe_retval;
}
sim_fds[0] = process->alloc_fd(fds[0], "PIPE-READ", O_WRONLY, -1, true);
sim_fds[1] = process->alloc_fd(fds[1], "PIPE-WRITE", O_RDONLY, -1, true);
process->setReadPipeSource(sim_fds[0], sim_fds[1]);
// Alpha Linux convention for pipe() is that fd[0] is returned as
// the return value of the function, and fd[1] is returned in r20.
tc->setIntReg(SyscallPseudoReturnReg, sim_fds[1]);
return sim_fds[0];
}
SyscallReturn
getpidPseudoFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
ThreadContext *tc)
{
// Make up a PID. There's no interprocess communication in
// fake_syscall mode, so there's no way for a process to know it's
// not getting a unique value.
tc->setIntReg(SyscallPseudoReturnReg, process->ppid());
return process->pid();
}
SyscallReturn
getuidPseudoFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
ThreadContext *tc)
{
// Make up a UID and EUID... it shouldn't matter, and we want the
// simulation to be deterministic.
// EUID goes in r20.
tc->setIntReg(SyscallPseudoReturnReg, process->euid()); //EUID
return process->uid(); // UID
}
SyscallReturn
getgidPseudoFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
ThreadContext *tc)
{
// Get current group ID. EGID goes in r20.
tc->setIntReg(SyscallPseudoReturnReg, process->egid()); //EGID
return process->gid();
}
SyscallReturn
setuidFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
ThreadContext *tc)
{
// can't fathom why a benchmark would call this.
int index = 0;
warn("Ignoring call to setuid(%d)\n", process->getSyscallArg(tc, index));
return 0;
}
SyscallReturn
getpidFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
ThreadContext *tc)
{
// Make up a PID. There's no interprocess communication in
// fake_syscall mode, so there's no way for a process to know it's
// not getting a unique value.
tc->setIntReg(SyscallPseudoReturnReg, process->ppid()); //PID
return process->pid();
}
SyscallReturn
getppidFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
ThreadContext *tc)
{
return process->ppid();
}
SyscallReturn
getuidFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
ThreadContext *tc)
{
return process->uid(); // UID
}
SyscallReturn
geteuidFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
ThreadContext *tc)
{
return process->euid(); // UID
}
SyscallReturn
getgidFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
ThreadContext *tc)
{
return process->gid();
}
SyscallReturn
getegidFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
ThreadContext *tc)
{
return process->egid();
}
SyscallReturn
cloneFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
ThreadContext *tc)
{
int index = 0;
IntReg flags = process->getSyscallArg(tc, index);
IntReg newStack = process->getSyscallArg(tc, index);
DPRINTF(SyscallVerbose, "In sys_clone:\n");
DPRINTF(SyscallVerbose, " Flags=%llx\n", flags);
DPRINTF(SyscallVerbose, " Child stack=%llx\n", newStack);
if (flags != 0x10f00) {
warn("This sys_clone implementation assumes flags "
"CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD "
"(0x10f00), and may not work correctly with given flags "
"0x%llx\n", flags);
}
ThreadContext* ctc; // child thread context
if ( ( ctc = process->findFreeContext() ) != NULL ) {
DPRINTF(SyscallVerbose, " Found unallocated thread context\n");
ctc->clearArchRegs();
// Arch-specific cloning code
#if THE_ISA == ALPHA_ISA or THE_ISA == X86_ISA
// Cloning the misc. regs for these archs is enough
TheISA::copyMiscRegs(tc, ctc);
#elif THE_ISA == SPARC_ISA
TheISA::copyRegs(tc, ctc);
// TODO: Explain what this code actually does :-)
ctc->setIntReg(NumIntArchRegs + 6, 0);
ctc->setIntReg(NumIntArchRegs + 4, 0);
ctc->setIntReg(NumIntArchRegs + 3, NWindows - 2);
ctc->setIntReg(NumIntArchRegs + 5, NWindows);
ctc->setMiscReg(MISCREG_CWP, 0);
ctc->setIntReg(NumIntArchRegs + 7, 0);
ctc->setMiscRegNoEffect(MISCREG_TL, 0);
ctc->setMiscRegNoEffect(MISCREG_ASI, ASI_PRIMARY);
for (int y = 8; y < 32; y++)
ctc->setIntReg(y, tc->readIntReg(y));
#elif THE_ISA == ARM_ISA
TheISA::copyRegs(tc, ctc);
#else
fatal("sys_clone is not implemented for this ISA\n");
#endif
// Set up stack register
ctc->setIntReg(TheISA::StackPointerReg, newStack);
// Set up syscall return values in parent and child
ctc->setIntReg(ReturnValueReg, 0); // return value, child
// Alpha needs SyscallSuccessReg=0 in child
#if THE_ISA == ALPHA_ISA
ctc->setIntReg(TheISA::SyscallSuccessReg, 0);
#endif
// In SPARC/Linux, clone returns 0 on pseudo-return register if
// parent, non-zero if child
#if THE_ISA == SPARC_ISA
tc->setIntReg(TheISA::SyscallPseudoReturnReg, 0);
ctc->setIntReg(TheISA::SyscallPseudoReturnReg, 1);
#endif
ctc->pcState(tc->nextInstAddr());
ctc->activate();
// Should return nonzero child TID in parent's syscall return register,
// but for our pthread library any non-zero value will work
return 1;
} else {
fatal("Called sys_clone, but no unallocated thread contexts found!\n");
return 0;
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,70 @@
/*
* Copyright (c) 2003-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: Gabe Black
*/
#ifndef __SIM_SYSCALLRETURN_HH__
#define __SIM_SYSCALLRETURN_HH__
#include "base/types.hh"
class SyscallReturn
{
public:
template <class T>
SyscallReturn(T v, bool s)
{
retval = (uint64_t)v;
success = s;
}
template <class T>
SyscallReturn(T v)
{
success = (v >= 0);
retval = (uint64_t)v;
}
~SyscallReturn() {}
SyscallReturn& operator=(const SyscallReturn& s)
{
retval = s.retval;
success = s.success;
return *this;
}
bool successful() { return success; }
uint64_t value() { return retval; }
private:
uint64_t retval;
bool success;
};
#endif

View File

@ -0,0 +1,445 @@
/*
* Copyright (c) 2011-2012 ARM Limited
* All rights reserved
*
* The license below extends only to copyright in the software and shall
* not be construed as granting a license to any other intellectual
* property including but not limited to intellectual property relating
* to a hardware implementation of the functionality of the software
* licensed hereunder. You may use the software subject to the license
* terms below provided that you ensure that this notice is replicated
* unmodified and in its entirety in all distributions of the software,
* modified or unmodified, in source code or in binary form.
*
* Copyright (c) 2003-2006 The Regents of The University of Michigan
* Copyright (c) 2011 Regents of the University of California
* 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
* Lisa Hsu
* Nathan Binkert
* Ali Saidi
* Rick Strong
*/
#include "arch/isa_traits.hh"
#include "arch/remote_gdb.hh"
#include "arch/utility.hh"
#include "arch/vtophys.hh"
#include "base/loader/object_file.hh"
#include "base/loader/symtab.hh"
#include "base/trace.hh"
#include "config/the_isa.hh"
#include "cpu/thread_context.hh"
#include "debug/Loader.hh"
#include "debug/WorkItems.hh"
#include "kern/kernel_stats.hh"
#include "mem/physical.hh"
#include "params/System.hh"
#include "sim/byteswap.hh"
#include "sim/debug.hh"
#include "sim/full_system.hh"
#include "sim/system.hh"
using namespace std;
using namespace TheISA;
vector<System *> System::systemList;
int System::numSystemsRunning = 0;
System::System(Params *p)
: MemObject(p), _systemPort("system_port", this),
_numContexts(0),
pagePtr(0),
init_param(p->init_param),
physProxy(_systemPort),
virtProxy(_systemPort),
loadAddrMask(p->load_addr_mask),
nextPID(0),
physmem(p->memories),
memoryMode(p->mem_mode),
workItemsBegin(0),
workItemsEnd(0),
numWorkIds(p->num_work_ids),
_params(p),
totalNumInsts(0),
instEventQueue("system instruction-based event queue")
{
// add self to global system list
systemList.push_back(this);
if (FullSystem) {
kernelSymtab = new SymbolTable;
if (!debugSymbolTable)
debugSymbolTable = new SymbolTable;
}
// Get the generic system master IDs
MasterID tmp_id M5_VAR_USED;
tmp_id = getMasterId("writebacks");
assert(tmp_id == Request::wbMasterId);
tmp_id = getMasterId("functional");
assert(tmp_id == Request::funcMasterId);
tmp_id = getMasterId("interrupt");
assert(tmp_id == Request::intMasterId);
if (FullSystem) {
if (params()->kernel == "") {
inform("No kernel set for full system simulation. "
"Assuming you know what you're doing if not SPARC ISA\n");
} else {
// Get the kernel code
kernel = createObjectFile(params()->kernel);
inform("kernel located at: %s", params()->kernel);
if (kernel == NULL)
fatal("Could not load kernel file %s", params()->kernel);
// setup entry points
kernelStart = kernel->textBase();
kernelEnd = kernel->bssBase() + kernel->bssSize();
kernelEntry = kernel->entryPoint();
// load symbols
if (!kernel->loadGlobalSymbols(kernelSymtab))
fatal("could not load kernel symbols\n");
if (!kernel->loadLocalSymbols(kernelSymtab))
fatal("could not load kernel local symbols\n");
if (!kernel->loadGlobalSymbols(debugSymbolTable))
fatal("could not load kernel symbols\n");
if (!kernel->loadLocalSymbols(debugSymbolTable))
fatal("could not load kernel local symbols\n");
// Loading only needs to happen once and after memory system is
// connected so it will happen in initState()
}
}
// increment the number of running systms
numSystemsRunning++;
// Set back pointers to the system in all memories
for (int x = 0; x < params()->memories.size(); x++)
params()->memories[x]->system(this);
}
System::~System()
{
delete kernelSymtab;
delete kernel;
for (uint32_t j = 0; j < numWorkIds; j++)
delete workItemStats[j];
}
void
System::init()
{
// check that the system port is connected
if (!_systemPort.isConnected())
panic("System port on %s is not connected.\n", name());
}
MasterPort&
System::getMasterPort(const std::string &if_name, int idx)
{
// no need to distinguish at the moment (besides checking)
return _systemPort;
}
void
System::setMemoryMode(Enums::MemoryMode mode)
{
assert(getState() == Drained);
memoryMode = mode;
}
bool System::breakpoint()
{
if (remoteGDB.size())
return remoteGDB[0]->breakpoint();
return false;
}
/**
* Setting rgdb_wait to a positive integer waits for a remote debugger to
* connect to that context ID before continuing. This should really
be a parameter on the CPU object or something...
*/
int rgdb_wait = -1;
int
System::registerThreadContext(ThreadContext *tc, int assigned)
{
int id;
if (assigned == -1) {
for (id = 0; id < threadContexts.size(); id++) {
if (!threadContexts[id])
break;
}
if (threadContexts.size() <= id)
threadContexts.resize(id + 1);
} else {
if (threadContexts.size() <= assigned)
threadContexts.resize(assigned + 1);
id = assigned;
}
if (threadContexts[id])
fatal("Cannot have two CPUs with the same id (%d)\n", id);
threadContexts[id] = tc;
_numContexts++;
int port = getRemoteGDBPort();
if (port) {
RemoteGDB *rgdb = new RemoteGDB(this, tc);
GDBListener *gdbl = new GDBListener(rgdb, port + id);
gdbl->listen();
if (rgdb_wait != -1 && rgdb_wait == id)
gdbl->accept();
if (remoteGDB.size() <= id) {
remoteGDB.resize(id + 1);
}
remoteGDB[id] = rgdb;
}
activeCpus.push_back(false);
return id;
}
int
System::numRunningContexts()
{
int running = 0;
for (int i = 0; i < _numContexts; ++i) {
if (threadContexts[i]->status() != ThreadContext::Halted)
++running;
}
return running;
}
void
System::initState()
{
int i;
if (FullSystem) {
for (i = 0; i < threadContexts.size(); i++)
TheISA::startupCPU(threadContexts[i], i);
// Moved from the constructor to here since it relies on the
// address map being resolved in the interconnect
/**
* Load the kernel code into memory
*/
if (params()->kernel != "") {
// Load program sections into memory
kernel->loadSections(physProxy, loadAddrMask);
DPRINTF(Loader, "Kernel start = %#x\n", kernelStart);
DPRINTF(Loader, "Kernel end = %#x\n", kernelEnd);
DPRINTF(Loader, "Kernel entry = %#x\n", kernelEntry);
DPRINTF(Loader, "Kernel loaded...\n");
}
}
activeCpus.clear();
if (!FullSystem)
return;
for (i = 0; i < threadContexts.size(); i++)
TheISA::startupCPU(threadContexts[i], i);
}
void
System::replaceThreadContext(ThreadContext *tc, int context_id)
{
if (context_id >= threadContexts.size()) {
panic("replaceThreadContext: bad id, %d >= %d\n",
context_id, threadContexts.size());
}
threadContexts[context_id] = tc;
if (context_id < remoteGDB.size())
remoteGDB[context_id]->replaceThreadContext(tc);
}
Addr
System::allocPhysPages(int npages)
{
Addr return_addr = pagePtr << LogVMPageSize;
pagePtr += npages;
if ((pagePtr << LogVMPageSize) > physmem.totalSize())
fatal("Out of memory, please increase size of physical memory.");
return return_addr;
}
Addr
System::memSize() const
{
return physmem.totalSize();
}
Addr
System::freeMemSize() const
{
return physmem.totalSize() - (pagePtr << LogVMPageSize);
}
bool
System::isMemAddr(Addr addr) const
{
return physmem.isMemAddr(addr);
}
void
System::resume()
{
SimObject::resume();
totalNumInsts = 0;
}
void
System::serialize(ostream &os)
{
if (FullSystem)
kernelSymtab->serialize("kernel_symtab", os);
SERIALIZE_SCALAR(pagePtr);
SERIALIZE_SCALAR(nextPID);
}
void
System::unserialize(Checkpoint *cp, const string &section)
{
if (FullSystem)
kernelSymtab->unserialize("kernel_symtab", cp, section);
UNSERIALIZE_SCALAR(pagePtr);
UNSERIALIZE_SCALAR(nextPID);
}
void
System::regStats()
{
for (uint32_t j = 0; j < numWorkIds ; j++) {
workItemStats[j] = new Stats::Histogram();
stringstream namestr;
ccprintf(namestr, "work_item_type%d", j);
workItemStats[j]->init(20)
.name(name() + "." + namestr.str())
.desc("Run time stat for" + namestr.str())
.prereq(*workItemStats[j]);
}
}
void
System::workItemEnd(uint32_t tid, uint32_t workid)
{
std::pair<uint32_t,uint32_t> p(tid, workid);
if (!lastWorkItemStarted.count(p))
return;
Tick samp = curTick() - lastWorkItemStarted[p];
DPRINTF(WorkItems, "Work item end: %d\t%d\t%lld\n", tid, workid, samp);
if (workid >= numWorkIds)
fatal("Got workid greater than specified in system configuration\n");
workItemStats[workid]->sample(samp);
lastWorkItemStarted.erase(p);
}
void
System::printSystems()
{
vector<System *>::iterator i = systemList.begin();
vector<System *>::iterator end = systemList.end();
for (; i != end; ++i) {
System *sys = *i;
cerr << "System " << sys->name() << ": " << hex << sys << endl;
}
}
void
printSystems()
{
System::printSystems();
}
MasterID
System::getMasterId(std::string master_name)
{
// strip off system name if the string starts with it
if (master_name.size() > name().size() &&
master_name.compare(0, name().size(), name()) == 0)
master_name = master_name.erase(0, name().size() + 1);
// CPUs in switch_cpus ask for ids again after switching
for (int i = 0; i < masterIds.size(); i++) {
if (masterIds[i] == master_name) {
return i;
}
}
// Verify that the statistics haven't been enabled yet
// Otherwise objects will have sized their stat buckets and
// they will be too small
if (Stats::enabled())
fatal("Can't request a masterId after regStats(). \
You must do so in init().\n");
masterIds.push_back(master_name);
return masterIds.size() - 1;
}
std::string
System::getMasterName(MasterID master_id)
{
if (master_id >= masterIds.size())
fatal("Invalid master_id passed to getMasterName()\n");
return masterIds[master_id];
}
const char *System::MemoryModeStrings[3] = {"invalid", "atomic",
"timing"};
System *
SystemParams::create()
{
return new System(this);
}

View File

@ -0,0 +1,406 @@
/*
* Copyright (c) 2012 ARM Limited
* All rights reserved
*
* The license below extends only to copyright in the software and shall
* not be construed as granting a license to any other intellectual
* property including but not limited to intellectual property relating
* to a hardware implementation of the functionality of the software
* licensed hereunder. You may use the software subject to the license
* terms below provided that you ensure that this notice is replicated
* unmodified and in its entirety in all distributions of the software,
* modified or unmodified, in source code or in binary form.
*
* Copyright (c) 2002-2005 The Regents of The University of Michigan
* Copyright (c) 2011 Regents of the University of California
* 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
* Lisa Hsu
* Nathan Binkert
* Rick Strong
*/
#ifndef __SYSTEM_HH__
#define __SYSTEM_HH__
#include <string>
#include <vector>
#include "base/loader/symtab.hh"
#include "base/misc.hh"
#include "base/statistics.hh"
#include "cpu/pc_event.hh"
#include "enums/MemoryMode.hh"
#include "kern/system_events.hh"
#include "mem/fs_translating_port_proxy.hh"
#include "mem/mem_object.hh"
#include "mem/port.hh"
#include "mem/physical.hh"
#include "params/System.hh"
class BaseCPU;
class BaseRemoteGDB;
class GDBListener;
class ObjectFile;
class Platform;
class ThreadContext;
class System : public MemObject
{
private:
/**
* Private class for the system port which is only used as a
* master for debug access and for non-structural entities that do
* not have a port of their own.
*/
class SystemPort : public MasterPort
{
public:
/**
* Create a system port with a name and an owner.
*/
SystemPort(const std::string &_name, MemObject *_owner)
: MasterPort(_name, _owner)
{ }
bool recvTimingResp(PacketPtr pkt)
{ panic("SystemPort does not receive timing!\n"); return false; }
void recvRetry()
{ panic("SystemPort does not expect retry!\n"); }
};
SystemPort _systemPort;
public:
/**
* After all objects have been created and all ports are
* connected, check that the system port is connected.
*/
virtual void init();
/**
* Get a reference to the system port that can be used by
* non-structural simulation objects like processes or threads, or
* external entities like loaders and debuggers, etc, to access
* the memory system.
*
* @return a reference to the system port we own
*/
MasterPort& getSystemPort() { return _systemPort; }
/**
* Additional function to return the Port of a memory object.
*/
MasterPort& getMasterPort(const std::string &if_name, int idx = -1);
static const char *MemoryModeStrings[3];
Enums::MemoryMode
getMemoryMode()
{
assert(memoryMode);
return memoryMode;
}
/** Change the memory mode of the system. This should only be called by the
* python!!
* @param mode Mode to change to (atomic/timing)
*/
void setMemoryMode(Enums::MemoryMode mode);
PCEventQueue pcEventQueue;
std::vector<ThreadContext *> threadContexts;
int _numContexts;
ThreadContext *getThreadContext(ThreadID tid)
{
return threadContexts[tid];
}
int numContexts()
{
assert(_numContexts == (int)threadContexts.size());
return _numContexts;
}
/** Return number of running (non-halted) thread contexts in
* system. These threads could be Active or Suspended. */
int numRunningContexts();
Addr pagePtr;
uint64_t init_param;
/** Port to physical memory used for writing object files into ram at
* boot.*/
PortProxy physProxy;
FSTranslatingPortProxy virtProxy;
/** kernel symbol table */
SymbolTable *kernelSymtab;
/** Object pointer for the kernel code */
ObjectFile *kernel;
/** Begining of kernel code */
Addr kernelStart;
/** End of kernel code */
Addr kernelEnd;
/** Entry point in the kernel to start at */
Addr kernelEntry;
/** Mask that should be anded for binary/symbol loading.
* This allows one two different OS requirements for the same ISA to be
* handled. Some OSes are compiled for a virtual address and need to be
* loaded into physical memory that starts at address 0, while other
* bare metal tools generate images that start at address 0.
*/
Addr loadAddrMask;
protected:
uint64_t nextPID;
public:
uint64_t allocatePID()
{
return nextPID++;
}
/** Get a pointer to access the physical memory of the system */
PhysicalMemory& getPhysMem() { return physmem; }
/** Amount of physical memory that is still free */
Addr freeMemSize() const;
/** Amount of physical memory that exists */
Addr memSize() const;
/**
* Check if a physical address is within a range of a memory that
* is part of the global address map.
*
* @param addr A physical address
* @return Whether the address corresponds to a memory
*/
bool isMemAddr(Addr addr) const;
protected:
PhysicalMemory physmem;
Enums::MemoryMode memoryMode;
uint64_t workItemsBegin;
uint64_t workItemsEnd;
uint32_t numWorkIds;
std::vector<bool> activeCpus;
/** This array is a per-sytem list of all devices capable of issuing a
* memory system request and an associated string for each master id.
* It's used to uniquely id any master in the system by name for things
* like cache statistics.
*/
std::vector<std::string> masterIds;
public:
/** Request an id used to create a request object in the system. All objects
* that intend to issues requests into the memory system must request an id
* in the init() phase of startup. All master ids must be fixed by the
* regStats() phase that immediately preceeds it. This allows objects in the
* memory system to understand how many masters may exist and
* appropriately name the bins of their per-master stats before the stats
* are finalized
*/
MasterID getMasterId(std::string req_name);
/** Get the name of an object for a given request id.
*/
std::string getMasterName(MasterID master_id);
/** Get the number of masters registered in the system */
MasterID maxMasters()
{
return masterIds.size();
}
virtual void regStats();
/**
* Called by pseudo_inst to track the number of work items started by this
* system.
*/
uint64_t
incWorkItemsBegin()
{
return ++workItemsBegin;
}
/**
* Called by pseudo_inst to track the number of work items completed by
* this system.
*/
uint64_t
incWorkItemsEnd()
{
return ++workItemsEnd;
}
/**
* Called by pseudo_inst to mark the cpus actively executing work items.
* Returns the total number of cpus that have executed work item begin or
* ends.
*/
int
markWorkItem(int index)
{
int count = 0;
assert(index < activeCpus.size());
activeCpus[index] = true;
for (std::vector<bool>::iterator i = activeCpus.begin();
i < activeCpus.end(); i++) {
if (*i) count++;
}
return count;
}
inline void workItemBegin(uint32_t tid, uint32_t workid)
{
std::pair<uint32_t,uint32_t> p(tid, workid);
lastWorkItemStarted[p] = curTick();
}
void workItemEnd(uint32_t tid, uint32_t workid);
/**
* Fix up an address used to match PCs for hooking simulator
* events on to target function executions. See comment in
* system.cc for details.
*/
virtual Addr fixFuncEventAddr(Addr addr)
{
panic("Base fixFuncEventAddr not implemented.\n");
}
/**
* Add a function-based event to the given function, to be looked
* up in the specified symbol table.
*/
template <class T>
T *addFuncEvent(SymbolTable *symtab, const char *lbl)
{
Addr addr = 0; // initialize only to avoid compiler warning
if (symtab->findAddress(lbl, addr)) {
T *ev = new T(&pcEventQueue, lbl, fixFuncEventAddr(addr));
return ev;
}
return NULL;
}
/** Add a function-based event to kernel code. */
template <class T>
T *addKernelFuncEvent(const char *lbl)
{
return addFuncEvent<T>(kernelSymtab, lbl);
}
public:
std::vector<BaseRemoteGDB *> remoteGDB;
std::vector<GDBListener *> gdbListen;
bool breakpoint();
public:
typedef SystemParams Params;
protected:
Params *_params;
public:
System(Params *p);
~System();
void initState();
const Params *params() const { return (const Params *)_params; }
public:
/**
* Returns the addess the kernel starts at.
* @return address the kernel starts at
*/
Addr getKernelStart() const { return kernelStart; }
/**
* Returns the addess the kernel ends at.
* @return address the kernel ends at
*/
Addr getKernelEnd() const { return kernelEnd; }
/**
* Returns the addess the entry point to the kernel code.
* @return entry point of the kernel code
*/
Addr getKernelEntry() const { return kernelEntry; }
/// Allocate npages contiguous unused physical pages
/// @return Starting address of first page
Addr allocPhysPages(int npages);
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);
virtual void resume();
public:
Counter totalNumInsts;
EventQueue instEventQueue;
std::map<std::pair<uint32_t,uint32_t>, Tick> lastWorkItemStarted;
std::map<uint32_t, Stats::Histogram*> workItemStats;
////////////////////////////////////////////
//
// STATIC GLOBAL SYSTEM LIST
//
////////////////////////////////////////////
static std::vector<System *> systemList;
static int numSystemsRunning;
static void printSystems();
};
#endif // __SYSTEM_HH__

View File

@ -0,0 +1,65 @@
/*
* 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: Gabe Black
*/
#include "cpu/thread_context.hh"
#include "mem/page_table.hh"
#include "sim/faults.hh"
#include "sim/full_system.hh"
#include "sim/process.hh"
#include "sim/tlb.hh"
Fault
GenericTLB::translateAtomic(RequestPtr req, ThreadContext *tc, Mode)
{
if (FullSystem)
panic("Generic translation shouldn't be used in full system mode.\n");
Process * p = tc->getProcessPtr();
Fault fault = p->pTable->translate(req);
if(fault != NoFault)
return fault;
return NoFault;
}
void
GenericTLB::translateTiming(RequestPtr req, ThreadContext *tc,
Translation *translation, Mode mode)
{
assert(translation);
translation->finish(translateAtomic(req, tc, mode), req, tc, mode);
}
void
GenericTLB::demapPage(Addr vaddr, uint64_t asn)
{
warn("Demapping pages in the generic TLB is unnecessary.\n");
}

View File

@ -0,0 +1,115 @@
/*
* Copyright (c) 2011 ARM Limited
* All rights reserved.
*
* The license below extends only to copyright in the software and shall
* not be construed as granting a license to any other intellectual
* property including but not limited to intellectual property relating
* to a hardware implementation of the functionality of the software
* licensed hereunder. You may use the software subject to the license
* terms below provided that you ensure that this notice is replicated
* unmodified and in its entirety in all distributions of the software,
* modified or unmodified, in source code or in binary form.
*
* Copyright (c) 2006 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Gabe Black
*/
#ifndef __SIM_TLB_HH__
#define __SIM_TLB_HH__
#include "base/misc.hh"
#include "mem/request.hh"
#include "sim/fault_fwd.hh"
#include "sim/sim_object.hh"
class ThreadContext;
class MasterPort;
class BaseTLB : public SimObject
{
protected:
BaseTLB(const Params *p)
: SimObject(p)
{}
public:
enum Mode { Read, Write, Execute };
public:
virtual void demapPage(Addr vaddr, uint64_t asn) = 0;
/**
* Get the table walker master port if present. This is used for
* migrating port connections during a CPU takeOverFrom()
* call. For architectures that do not have a table walker, NULL
* is returned, hence the use of a pointer rather than a
* reference.
*
* @return A pointer to the walker master port or NULL if not present
*/
virtual MasterPort* getMasterPort() { return NULL; }
class Translation
{
public:
virtual ~Translation()
{}
/**
* Signal that the translation has been delayed due to a hw page table
* walk.
*/
virtual void markDelayed() = 0;
/*
* 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,
Mode mode) = 0;
};
};
class GenericTLB : public BaseTLB
{
protected:
GenericTLB(const Params *p)
: BaseTLB(p)
{}
public:
void demapPage(Addr vaddr, uint64_t asn);
Fault translateAtomic(RequestPtr req, ThreadContext *tc, Mode mode);
void translateTiming(RequestPtr req, ThreadContext *tc,
Translation *translation, Mode mode);
};
#endif // __ARCH_SPARC_TLB_HH__

View File

@ -0,0 +1,137 @@
/*
* Copyright (c) 2004-2005 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Nathan Binkert
*/
#ifndef __ARCH_ALPHA_VPTR_HH__
#define __ARCH_ALPHA_VPTR_HH__
#include "arch/isa_traits.hh"
#include "arch/vtophys.hh"
#include "mem/fs_translating_port_proxy.hh"
class ThreadContext;
template <class T>
class VPtr
{
public:
typedef T Type;
protected:
ThreadContext *tc;
Addr ptr;
Addr buffer[(sizeof(T)-1)/sizeof(Addr) + 1];
public:
explicit VPtr(ThreadContext *_tc, Addr p = 0)
: tc(_tc), ptr(p)
{
refresh();
}
template <class U>
VPtr(const VPtr<U> &vp)
: tc(vp.tc), ptr(vp.ptr)
{
refresh();
}
~VPtr()
{}
void
refresh()
{
if (!ptr)
return;
FSTranslatingPortProxy &proxy = tc->getVirtProxy();
proxy.readBlob(ptr, buffer, sizeof(T));
}
bool
operator!() const
{
return ptr == 0;
}
VPtr<T>
operator+(int offset)
{
return VPtr<T>(tc, ptr + offset);
}
const VPtr<T> &
operator+=(int offset)
{
ptr += offset;
refresh();
return *this;
}
const VPtr<T> &
operator=(Addr p)
{
ptr = p;
refresh();
return *this;
}
template <class U>
const VPtr<T> &
operator=(const VPtr<U> &vp)
{
tc = vp.tc;
ptr = vp.ptr;
refresh();
return *this;
}
operator T *()
{
return (T *)buffer;
}
T *
operator->()
{
return (T *)buffer;
}
T &
operator*()
{
return *(T *)buffer;
}
};
#endif // __ARCH_ALPHA_VPTR_HH__