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:
33
simulators/gem5/src/sim/BaseTLB.py
Normal file
33
simulators/gem5/src/sim/BaseTLB.py
Normal 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
|
||||
35
simulators/gem5/src/sim/InstTracer.py
Normal file
35
simulators/gem5/src/sim/InstTracer.py
Normal 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
|
||||
54
simulators/gem5/src/sim/Process.py
Normal file
54
simulators/gem5/src/sim/Process.py
Normal 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')
|
||||
68
simulators/gem5/src/sim/Root.py
Normal file
68
simulators/gem5/src/sim/Root.py
Normal 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")
|
||||
79
simulators/gem5/src/sim/SConscript
Normal file
79
simulators/gem5/src/sim/SConscript
Normal 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')
|
||||
79
simulators/gem5/src/sim/System.py
Normal file
79
simulators/gem5/src/sim/System.py
Normal 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");
|
||||
57
simulators/gem5/src/sim/arguments.cc
Normal file
57
simulators/gem5/src/sim/arguments.cc
Normal 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);
|
||||
}
|
||||
|
||||
151
simulators/gem5/src/sim/arguments.hh
Normal file
151
simulators/gem5/src/sim/arguments.hh
Normal 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__
|
||||
38
simulators/gem5/src/sim/async.cc
Normal file
38
simulators/gem5/src/sim/async.cc
Normal 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;
|
||||
|
||||
54
simulators/gem5/src/sim/async.hh
Normal file
54
simulators/gem5/src/sim/async.hh
Normal 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__
|
||||
201
simulators/gem5/src/sim/byteswap.hh
Normal file
201
simulators/gem5/src/sim/byteswap.hh
Normal 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__
|
||||
131
simulators/gem5/src/sim/core.cc
Normal file
131
simulators/gem5/src/sim/core.cc
Normal 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();
|
||||
}
|
||||
|
||||
102
simulators/gem5/src/sim/core.hh
Normal file
102
simulators/gem5/src/sim/core.hh
Normal 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__ */
|
||||
140
simulators/gem5/src/sim/debug.cc
Normal file
140
simulators/gem5/src/sim/debug.cc
Normal 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;
|
||||
}
|
||||
|
||||
60
simulators/gem5/src/sim/debug.hh
Normal file
60
simulators/gem5/src/sim/debug.hh
Normal 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__
|
||||
432
simulators/gem5/src/sim/eventq.cc
Normal file
432
simulators/gem5/src/sim/eventq.cc
Normal 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 §ion)
|
||||
{
|
||||
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 §ion)
|
||||
{
|
||||
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)
|
||||
{}
|
||||
603
simulators/gem5/src/sim/eventq.hh
Normal file
603
simulators/gem5/src/sim/eventq.hh
Normal 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 §ion);
|
||||
#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 §ion);
|
||||
#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__
|
||||
40
simulators/gem5/src/sim/fault_fwd.hh
Normal file
40
simulators/gem5/src/sim/fault_fwd.hh
Normal 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__
|
||||
77
simulators/gem5/src/sim/faults.cc
Normal file
77
simulators/gem5/src/sim/faults.cc
Normal 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);
|
||||
}
|
||||
106
simulators/gem5/src/sim/faults.hh
Normal file
106
simulators/gem5/src/sim/faults.hh
Normal 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__
|
||||
48
simulators/gem5/src/sim/full_system.hh
Normal file
48
simulators/gem5/src/sim/full_system.hh
Normal 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__
|
||||
274
simulators/gem5/src/sim/init.cc
Normal file
274
simulators/gem5/src/sim/init.cc
Normal 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"));
|
||||
}
|
||||
81
simulators/gem5/src/sim/init.hh
Normal file
81
simulators/gem5/src/sim/init.hh
Normal 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__
|
||||
175
simulators/gem5/src/sim/insttracer.hh
Normal file
175
simulators/gem5/src/sim/insttracer.hh
Normal 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__
|
||||
64
simulators/gem5/src/sim/main.cc
Normal file
64
simulators/gem5/src/sim/main.cc
Normal 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;
|
||||
}
|
||||
52
simulators/gem5/src/sim/microcode_rom.hh
Normal file
52
simulators/gem5/src/sim/microcode_rom.hh
Normal 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__
|
||||
736
simulators/gem5/src/sim/process.cc
Normal file
736
simulators/gem5/src/sim/process.cc
Normal 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 §ion)
|
||||
{
|
||||
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 §ion)
|
||||
{
|
||||
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);
|
||||
}
|
||||
314
simulators/gem5/src/sim/process.hh
Normal file
314
simulators/gem5/src/sim/process.hh
Normal 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 §ion);
|
||||
};
|
||||
|
||||
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 §ion);
|
||||
};
|
||||
|
||||
//
|
||||
// "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__
|
||||
63
simulators/gem5/src/sim/process_impl.hh
Normal file
63
simulators/gem5/src/sim/process_impl.hh
Normal 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
|
||||
553
simulators/gem5/src/sim/pseudo_inst.cc
Normal file
553
simulators/gem5/src/sim/pseudo_inst.cc
Normal 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
|
||||
75
simulators/gem5/src/sim/pseudo_inst.hh
Normal file
75
simulators/gem5/src/sim/pseudo_inst.hh
Normal 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__
|
||||
180
simulators/gem5/src/sim/root.cc
Normal file
180
simulators/gem5/src/sim/root.cc
Normal 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 §ion)
|
||||
{
|
||||
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);
|
||||
}
|
||||
120
simulators/gem5/src/sim/root.hh
Normal file
120
simulators/gem5/src/sim/root.hh
Normal 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 §ion);
|
||||
|
||||
};
|
||||
|
||||
#endif // __SIM_ROOT_HH__
|
||||
642
simulators/gem5/src/sim/serialize.cc
Normal file
642
simulators/gem5/src/sim/serialize.cc
Normal 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 ¶m)
|
||||
{
|
||||
os << name << "=";
|
||||
showParam(os, param);
|
||||
os << "\n";
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void
|
||||
arrayParamOut(ostream &os, const string &name, const vector<T> ¶m)
|
||||
{
|
||||
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> ¶m)
|
||||
{
|
||||
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 §ion, const string &name, T ¶m)
|
||||
{
|
||||
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 §ion, const string &name, T ¶m)
|
||||
{
|
||||
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 §ion, 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 §ion,
|
||||
const string &name, vector<T> ¶m)
|
||||
{
|
||||
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 §ion,
|
||||
const string &name, list<T> ¶m)
|
||||
{
|
||||
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 §ion,
|
||||
const string &name, SimObject * ¶m)
|
||||
{
|
||||
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 ¶m); \
|
||||
template void \
|
||||
paramIn(Checkpoint *cp, const string §ion, \
|
||||
const string &name, type & param); \
|
||||
template bool \
|
||||
optParamIn(Checkpoint *cp, const string §ion, \
|
||||
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 §ion, \
|
||||
const string &name, type *param, unsigned size); \
|
||||
template void \
|
||||
arrayParamOut(ostream &os, const string &name, \
|
||||
const vector<type> ¶m); \
|
||||
template void \
|
||||
arrayParamIn(Checkpoint *cp, const string §ion, \
|
||||
const string &name, vector<type> ¶m); \
|
||||
template void \
|
||||
arrayParamOut(ostream &os, const string &name, \
|
||||
const list<type> ¶m); \
|
||||
template void \
|
||||
arrayParamIn(Checkpoint *cp, const string §ion, \
|
||||
const string &name, list<type> ¶m);
|
||||
|
||||
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 §ion);
|
||||
};
|
||||
|
||||
/// 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 §ion)
|
||||
{
|
||||
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 §ion)
|
||||
{
|
||||
}
|
||||
|
||||
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 §ion)
|
||||
{
|
||||
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 §ion)
|
||||
{
|
||||
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 §ion, const string &entry, string &value)
|
||||
{
|
||||
return db->find(section, entry, value);
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
Checkpoint::findObj(const string §ion, 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 §ion)
|
||||
{
|
||||
return db->sectionExists(section);
|
||||
}
|
||||
295
simulators/gem5/src/sim/serialize.hh
Normal file
295
simulators/gem5/src/sim/serialize.hh
Normal 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 ¶m);
|
||||
|
||||
template <class T>
|
||||
void paramIn(Checkpoint *cp, const std::string §ion,
|
||||
const std::string &name, T ¶m);
|
||||
|
||||
template <class T>
|
||||
bool optParamIn(Checkpoint *cp, const std::string §ion,
|
||||
const std::string &name, T ¶m);
|
||||
|
||||
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> ¶m);
|
||||
|
||||
template <class T>
|
||||
void arrayParamOut(std::ostream &os, const std::string &name,
|
||||
const std::list<T> ¶m);
|
||||
|
||||
template <class T>
|
||||
void arrayParamIn(Checkpoint *cp, const std::string §ion,
|
||||
const std::string &name, T *param, unsigned size);
|
||||
|
||||
template <class T>
|
||||
void arrayParamIn(Checkpoint *cp, const std::string §ion,
|
||||
const std::string &name, std::vector<T> ¶m);
|
||||
|
||||
template <class T>
|
||||
void arrayParamIn(Checkpoint *cp, const std::string §ion,
|
||||
const std::string &name, std::list<T> ¶m);
|
||||
|
||||
void
|
||||
objParamIn(Checkpoint *cp, const std::string §ion,
|
||||
const std::string &name, SimObject * ¶m);
|
||||
|
||||
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 §ion);
|
||||
|
||||
static Serializable *create(Checkpoint *cp, const std::string §ion);
|
||||
|
||||
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 §ion);
|
||||
|
||||
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 §ion);
|
||||
};
|
||||
|
||||
//
|
||||
// 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 §ion, const std::string &entry,
|
||||
std::string &value);
|
||||
|
||||
bool findObj(const std::string §ion, const std::string &entry,
|
||||
SimObject *&value);
|
||||
|
||||
bool sectionExists(const std::string §ion);
|
||||
|
||||
// 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__
|
||||
124
simulators/gem5/src/sim/sim_events.cc
Normal file
124
simulators/gem5/src/sim/sim_events.cc
Normal 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";
|
||||
}
|
||||
94
simulators/gem5/src/sim/sim_events.hh
Normal file
94
simulators/gem5/src/sim/sim_events.hh
Normal 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__
|
||||
56
simulators/gem5/src/sim/sim_exit.hh
Normal file
56
simulators/gem5/src/sim/sim_exit.hh
Normal 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__
|
||||
203
simulators/gem5/src/sim/sim_object.cc
Normal file
203
simulators/gem5/src/sim/sim_object.cc
Normal 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;
|
||||
}
|
||||
168
simulators/gem5/src/sim/sim_object.hh
Normal file
168
simulators/gem5/src/sim/sim_object.hh
Normal 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__
|
||||
121
simulators/gem5/src/sim/simulate.cc
Normal file
121
simulators/gem5/src/sim/simulate.cc
Normal 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
|
||||
}
|
||||
|
||||
35
simulators/gem5/src/sim/simulate.hh
Normal file
35
simulators/gem5/src/sim/simulate.hh
Normal 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);
|
||||
237
simulators/gem5/src/sim/stat_control.cc
Normal file
237
simulators/gem5/src/sim/stat_control.cc
Normal 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
|
||||
42
simulators/gem5/src/sim/stat_control.hh
Normal file
42
simulators/gem5/src/sim/stat_control.hh
Normal 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__
|
||||
40
simulators/gem5/src/sim/stats.hh
Normal file
40
simulators/gem5/src/sim/stats.hh
Normal 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__
|
||||
853
simulators/gem5/src/sim/syscall_emul.cc
Normal file
853
simulators/gem5/src/sim/syscall_emul.cc
Normal 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;
|
||||
}
|
||||
}
|
||||
|
||||
1268
simulators/gem5/src/sim/syscall_emul.hh
Normal file
1268
simulators/gem5/src/sim/syscall_emul.hh
Normal file
File diff suppressed because it is too large
Load Diff
70
simulators/gem5/src/sim/syscallreturn.hh
Normal file
70
simulators/gem5/src/sim/syscallreturn.hh
Normal 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
|
||||
445
simulators/gem5/src/sim/system.cc
Normal file
445
simulators/gem5/src/sim/system.cc
Normal 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 §ion)
|
||||
{
|
||||
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);
|
||||
}
|
||||
406
simulators/gem5/src/sim/system.hh
Normal file
406
simulators/gem5/src/sim/system.hh
Normal 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 §ion);
|
||||
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__
|
||||
65
simulators/gem5/src/sim/tlb.cc
Normal file
65
simulators/gem5/src/sim/tlb.cc
Normal 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");
|
||||
}
|
||||
115
simulators/gem5/src/sim/tlb.hh
Normal file
115
simulators/gem5/src/sim/tlb.hh
Normal 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__
|
||||
137
simulators/gem5/src/sim/vptr.hh
Normal file
137
simulators/gem5/src/sim/vptr.hh
Normal 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__
|
||||
Reference in New Issue
Block a user