summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--SConscript89
-rw-r--r--arch/alpha/alpha_linux_process.cc26
-rw-r--r--arch/alpha/alpha_memory.cc31
-rw-r--r--arch/alpha/alpha_tru64_process.cc50
-rw-r--r--arch/alpha/isa_desc293
-rw-r--r--arch/alpha/isa_traits.hh42
-rw-r--r--arch/alpha/pseudo_inst.cc2
-rw-r--r--arch/alpha/vptr.hh11
-rwxr-xr-xarch/isa_parser.py6
-rw-r--r--base/inifile.cc41
-rw-r--r--base/inifile.hh18
-rw-r--r--base/misc.cc5
-rw-r--r--base/output.cc129
-rw-r--r--base/output.hh61
-rw-r--r--base/random.hh20
-rw-r--r--base/range.hh1
-rw-r--r--base/res_list.hh2
-rw-r--r--base/statistics.cc7
-rw-r--r--base/statistics.hh136
-rw-r--r--base/stats/events.cc2
-rw-r--r--base/stats/text.cc2
-rw-r--r--base/str.cc30
-rw-r--r--base/str.hh14
-rw-r--r--base/trace.cc4
-rw-r--r--base/trace.hh6
-rw-r--r--base/traceflags.py3
-rw-r--r--configs/boot/devtime.rcS8
-rw-r--r--configs/boot/micro_memlat.rcS3
-rw-r--r--configs/boot/micro_memlat2mb.rcS3
-rw-r--r--configs/boot/micro_memlat8mb.rcS3
-rw-r--r--configs/boot/micro_syscall.rcS3
-rw-r--r--configs/boot/micro_tlblat.rcS3
-rw-r--r--configs/boot/nat-netperf-maerts-client.rcS3
-rw-r--r--configs/boot/nat-netperf-server.rcS4
-rw-r--r--configs/boot/nat-netperf-stream-client.rcS1
-rw-r--r--configs/boot/nat-spec-surge-client.rcS1
-rwxr-xr-xconfigs/boot/nat-spec-surge-server.rcS1
-rw-r--r--configs/boot/natbox-netperf.rcS2
-rw-r--r--configs/boot/natbox-spec-surge.rcS1
-rw-r--r--configs/boot/netperf-server.rcS1
-rwxr-xr-xconfigs/boot/nfs-client.rcS2
-rwxr-xr-xconfigs/boot/nfs-server.rcS2
-rw-r--r--cpu/base_cpu.cc68
-rw-r--r--cpu/base_cpu.hh38
-rw-r--r--cpu/exec_context.hh8
-rw-r--r--cpu/exetrace.cc2
-rw-r--r--cpu/full_cpu/op_class.hh1
-rw-r--r--cpu/memtest/memtest.cc49
-rw-r--r--cpu/memtest/memtest.hh17
-rw-r--r--cpu/pc_event.cc7
-rw-r--r--cpu/simple_cpu/simple_cpu.cc221
-rw-r--r--cpu/simple_cpu/simple_cpu.hh94
-rw-r--r--cpu/static_inst.cc4
-rw-r--r--cpu/static_inst.hh26
-rw-r--r--cpu/trace/opt_cpu.cc2
-rw-r--r--cpu/trace/opt_cpu.hh11
-rw-r--r--cpu/trace/trace_cpu.cc2
-rw-r--r--cpu/trace/trace_cpu.hh11
-rw-r--r--dev/alpha_console.cc8
-rw-r--r--dev/alpha_console.hh3
-rw-r--r--dev/baddev.cc7
-rw-r--r--dev/baddev.hh6
-rw-r--r--dev/etherdump.cc19
-rw-r--r--dev/etherdump.hh4
-rw-r--r--dev/etherlink.cc121
-rw-r--r--dev/etherlink.hh38
-rw-r--r--dev/ethertap.cc6
-rw-r--r--dev/ide_ctrl.cc2
-rw-r--r--dev/ide_disk.cc13
-rw-r--r--dev/io_device.cc8
-rw-r--r--dev/io_device.hh12
-rw-r--r--dev/ns_gige.cc43
-rw-r--r--dev/ns_gige.hh14
-rw-r--r--dev/pciconfigall.cc5
-rw-r--r--dev/pcidev.cc14
-rw-r--r--dev/pcidev.hh9
-rw-r--r--dev/pktfifo.cc3
-rw-r--r--dev/platform.hh2
-rw-r--r--dev/rtcreg.h44
-rw-r--r--dev/simconsole.cc21
-rw-r--r--dev/sinic.cc31
-rw-r--r--dev/sinic.hh12
-rw-r--r--dev/tsunami.cc2
-rw-r--r--dev/tsunami.hh35
-rw-r--r--dev/tsunami_cchip.cc9
-rw-r--r--dev/tsunami_io.cc26
-rw-r--r--dev/tsunami_io.hh79
-rw-r--r--dev/tsunami_pchip.cc2
-rw-r--r--dev/tsunamireg.h17
-rw-r--r--dev/uart.cc4
-rw-r--r--dev/uart.hh1
-rw-r--r--kern/linux/linux_syscalls.hh7
-rw-r--r--kern/linux/linux_system.cc35
-rw-r--r--kern/linux/linux_system.hh5
-rw-r--r--kern/tru64/tru64_syscalls.hh7
-rw-r--r--kern/tru64/tru64_system.cc24
-rw-r--r--objects/AlphaConsole.mpy9
-rw-r--r--objects/AlphaTLB.mpy12
-rw-r--r--objects/BadDevice.mpy5
-rw-r--r--objects/BaseCPU.mpy25
-rw-r--r--objects/BaseCache.mpy38
-rw-r--r--objects/BaseSystem.mpy15
-rw-r--r--objects/Bus.mpy6
-rw-r--r--objects/CoherenceProtocol.mpy6
-rw-r--r--objects/Device.mpy33
-rw-r--r--objects/DiskImage.mpy14
-rw-r--r--objects/Ethernet.mpy86
-rw-r--r--objects/Ide.mpy14
-rw-r--r--objects/IntrControl.mpy3
-rw-r--r--objects/MemTest.mpy18
-rw-r--r--objects/Pci.mpy52
-rw-r--r--objects/PhysicalMemory.mpy7
-rw-r--r--objects/Platform.mpy5
-rw-r--r--objects/Process.mpy15
-rw-r--r--objects/Repl.mpy9
-rw-r--r--objects/Root.mpy15
-rw-r--r--objects/SimConsole.mpy11
-rw-r--r--objects/SimpleDisk.mpy4
-rw-r--r--objects/Tsunami.mpy25
-rw-r--r--objects/Uart.mpy6
-rw-r--r--sim/builder.cc66
-rw-r--r--sim/builder.hh46
-rw-r--r--sim/eventq.hh34
-rw-r--r--sim/main.cc246
-rw-r--r--sim/param.cc63
-rw-r--r--sim/param.hh9
-rw-r--r--sim/process.cc68
-rw-r--r--sim/process.hh15
-rw-r--r--sim/pyconfig/SConscript195
-rw-r--r--sim/pyconfig/m5config.py1303
-rw-r--r--sim/pyconfig/m5configbase.py723
-rw-r--r--sim/serialize.cc8
-rw-r--r--sim/startup.cc24
-rw-r--r--sim/syscall_emul.cc41
-rw-r--r--sim/syscall_emul.hh138
-rw-r--r--sim/universe.cc123
-rwxr-xr-xtest/genini.py64
-rwxr-xr-xutil/pbs/job.py183
-rw-r--r--util/pbs/jobfile.py92
-rwxr-xr-xutil/pbs/pbs.py176
-rwxr-xr-xutil/pbs/send.py190
-rw-r--r--util/stats/db.py35
-rw-r--r--util/stats/info.py28
-rwxr-xr-xutil/stats/stats.py99
-rwxr-xr-xutil/tracediff15
145 files changed, 4557 insertions, 2191 deletions
diff --git a/SConscript b/SConscript
index f6c472216..19f84f913 100644
--- a/SConscript
+++ b/SConscript
@@ -54,6 +54,7 @@ base_sources = Split('''
base/circlebuf.cc
base/copyright.cc
base/cprintf.cc
+ base/embedfile.cc
base/fast_alloc.cc
base/fifo_buffer.cc
base/hostinfo.cc
@@ -62,6 +63,7 @@ base_sources = Split('''
base/intmath.cc
base/match.cc
base/misc.cc
+ base/output.cc
base/pollevent.cc
base/python.cc
base/range.cc
@@ -198,42 +200,9 @@ base_sources = Split('''
sim/trace_context.cc
sim/universe.cc
sim/pyconfig/pyconfig.cc
- sim/pyconfig/code.cc
+ sim/pyconfig/embedded_py.cc
''')
-base_obj_desc_files = Split('''
- cpu/full_cpu/iq/segmented/SegmentedIQ.od
- cpu/full_cpu/iq/seznec/SeznecIQ.od
- cpu/full_cpu/iq/standard/StandardIQ.od
- cpu/full_cpu/iq/BaseIQ.od
- cpu/full_cpu/BranchPred.od
- cpu/full_cpu/FUDesc.od
- cpu/full_cpu/FullCPU.od
- cpu/full_cpu/FuncUnitPool.od
- cpu/full_cpu/OpDesc.od
- cpu/full_cpu/PipeTrace.od
- cpu/sampling_cpu/SamplingCPU.od
- cpu/simple_cpu/SimpleCPU.od
- cpu/inorder_cpu/InorderCPU.od
- cpu/BaseCPU.od
- cpu/IntrControl.od
- mem/bus/Bus.od
- mem/bus/BusBridge.od
- mem/cache/coherence/CoherenceProtocol.od
- mem/cache/tags/repl/GenRepl.od
- mem/cache/tags/repl/Repl.od
- mem/cache/BaseCache.od
- mem/functional_mem/FunctionalMemory.od
- mem/functional_mem/MainMemory.od
- mem/functional_mem/MemoryController.od
- mem/functional_mem/PhysicalMemory.od
- mem/timing_mem/BaseMemory.od
- mem/BaseHier.od
- mem/BaseMem.od
- mem/HierParams.od
- ''')
-
-
# MySql sources
mysql_sources = Split('''
base/mysql.cc
@@ -316,44 +285,6 @@ full_system_sources = Split('''
sim/system.cc
''')
-full_system_obj_desc_files = Split('''
- arch/alpha/AlphaDTB.od
- arch/alpha/AlphaITB.od
- arch/alpha/AlphaTLB.od
- dev/AlphaConsole.od
- dev/ConsoleListener.od
- dev/CowDiskImage.od
- dev/DiskImage.od
- dev/DmaDevice.od
- dev/DmaEngine.od
- dev/EtherBus.od
- dev/EtherDev.od
- dev/EtherDevInt.od
- dev/EtherDump.od
- dev/EtherInt.od
- dev/EtherLink.od
- dev/EtherTap.od
- dev/PioDevice.od
- dev/RawDiskImage.od
- dev/ScsiController.od
- dev/ScsiDevice.od
- dev/ScsiDisk.od
- dev/SimConsole.od
- dev/SimpleDisk.od
- dev/TlaserClock.od
- dev/TlaserIpi.od
- dev/TlaserMBox.od
- dev/TlaserMC146818.od
- dev/TlaserNode.od
- dev/TlaserPciDev.od
- dev/TlaserPcia.od
- dev/TlaserSerial.od
- dev/TlaserUart.od
- dev/Turbolaser.od
- kern/tru64/Tru64System.od
- sim/System.od
- ''')
-
# Syscall emulation (non-full-system) sources
syscall_emulation_sources = Split('''
arch/alpha/alpha_common_syscall_emul.cc
@@ -369,13 +300,6 @@ syscall_emulation_sources = Split('''
sim/syscall_emul.cc
''')
-syscall_emulation_obj_desc_files = Split('''
- cpu/memtest/MemTest.od
- eio/EioProcess.od
- sim/LiveProcess.od
- sim/Process.od
- ''')
-
targetarch_files = Split('''
alpha_common_syscall_emul.hh
alpha_linux_process.hh
@@ -404,14 +328,11 @@ for f in targetarch_files:
# Set up complete list of sources based on configuration.
sources = base_sources
-obj_desc_files = base_obj_desc_files
if env['FULL_SYSTEM']:
sources += full_system_sources
- obj_desc_files += full_system_obj_desc_files
else:
sources += syscall_emulation_sources
- obj_desc_files += syscall_emulation_obj_desc_files
extra_libraries = []
env.Append(LIBS=['z'])
@@ -455,9 +376,7 @@ env.Command(Split('''arch/alpha/decoder.cc
# SConscript-local is the per-config build, which just copies some
# header files into a place where they can be found.
SConscript('libelf/SConscript-local', exports = 'env', duplicate=0)
-
-SConscript('sim/pyconfig/SConscript', exports = ['env', 'obj_desc_files'],
- duplicate=0)
+SConscript('sim/pyconfig/SConscript', exports = ['env'], duplicate=0)
# This function adds the specified sources to the given build
diff --git a/arch/alpha/alpha_linux_process.cc b/arch/alpha/alpha_linux_process.cc
index 67bb0ab3b..600de4447 100644
--- a/arch/alpha/alpha_linux_process.cc
+++ b/arch/alpha/alpha_linux_process.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2004 The Regents of The University of Michigan
+ * 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
@@ -26,24 +26,24 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+#include <dirent.h>
#include <errno.h>
-#include <unistd.h>
#include <fcntl.h> // for host open() flags
-#include <sys/types.h>
-#include <sys/stat.h>
#include <string.h> // for memset()
-#include <dirent.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
-#include "sim/host.hh"
#include "cpu/base_cpu.hh"
-#include "mem/functional_mem/functional_memory.hh"
-#include "sim/process.hh"
#include "cpu/exec_context.hh"
+#include "mem/functional_mem/functional_memory.hh"
#include "sim/fake_syscall.hh"
+#include "sim/host.hh"
+#include "sim/process.hh"
#include "sim/sim_events.hh"
-#include "sim/syscall_emul.hh"
#include "arch/alpha/alpha_common_syscall_emul.hh"
+#include "sim/syscall_emul.hh"
#include "sim/universe.hh" // for curTick & ticksPerSecond
#include "arch/alpha/alpha_linux_process.hh"
@@ -232,7 +232,7 @@ class Linux {
static const char *hostname;
/// Target uname() handler.
- static int
+ static SyscallReturn
unameFunc(SyscallDesc *desc, int callnum, Process *process,
ExecContext *xc)
{
@@ -251,7 +251,7 @@ class Linux {
/// Target osf_getsysyinfo() handler. Even though this call is
/// borrowed from Tru64, the subcases that get used appear to be
/// different in practice from those used by Tru64 processes.
- static int
+ static SyscallReturn
osf_getsysinfoFunc(SyscallDesc *desc, int callnum, Process *process,
ExecContext *xc)
{
@@ -278,7 +278,7 @@ class Linux {
}
/// Target osf_setsysinfo() handler.
- static int
+ static SyscallReturn
osf_setsysinfoFunc(SyscallDesc *desc, int callnum, Process *process,
ExecContext *xc)
{
@@ -306,7 +306,7 @@ class Linux {
}
/// Target fnctl() handler.
- static int
+ static SyscallReturn
fcntlFunc(SyscallDesc *desc, int callnum, Process *process,
ExecContext *xc)
{
diff --git a/arch/alpha/alpha_memory.cc b/arch/alpha/alpha_memory.cc
index 81a1902a0..8f6d7a51a 100644
--- a/arch/alpha/alpha_memory.cc
+++ b/arch/alpha/alpha_memory.cc
@@ -68,24 +68,27 @@ AlphaTLB::~AlphaTLB()
AlphaISA::PTE *
AlphaTLB::lookup(Addr vpn, uint8_t asn) const
{
- DPRINTF(TLB, "lookup %#x, asn %#x\n", vpn, (int)asn);
+ // assume not found...
+ AlphaISA::PTE *retval = NULL;
PageTable::const_iterator i = lookupTable.find(vpn);
- if (i == lookupTable.end())
- return NULL;
-
- while (i->first == vpn) {
- int index = i->second;
- AlphaISA::PTE *pte = &table[index];
- assert(pte->valid);
- if (vpn == pte->tag && (pte->asma || pte->asn == asn))
- return pte;
+ if (i != lookupTable.end()) {
+ while (i->first == vpn) {
+ int index = i->second;
+ AlphaISA::PTE *pte = &table[index];
+ assert(pte->valid);
+ if (vpn == pte->tag && (pte->asma || pte->asn == asn)) {
+ retval = pte;
+ break;
+ }
- ++i;
+ ++i;
+ }
}
- // not found...
- return NULL;
+ DPRINTF(TLB, "lookup %#x, asn %#x -> %s ppn %#x\n", vpn, (int)asn,
+ retval ? "hit" : "miss", retval ? retval->ppn : 0);
+ return retval;
}
@@ -501,6 +504,8 @@ AlphaDTB::translate(MemReqPtr &req, bool write) const
*/
if (req->vaddr & (req->size - 1)) {
fault(req, write ? MM_STAT_WR_MASK : 0);
+ DPRINTF(TLB, "Alignment Fault on %#x, size = %d", req->vaddr,
+ req->size);
return Alignment_Fault;
}
diff --git a/arch/alpha/alpha_tru64_process.cc b/arch/alpha/alpha_tru64_process.cc
index 149569f14..22e74cb40 100644
--- a/arch/alpha/alpha_tru64_process.cc
+++ b/arch/alpha/alpha_tru64_process.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001-2004 The Regents of The University of Michigan
+ * 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
@@ -476,7 +476,7 @@ class Tru64 {
static const char *hostname;
/// Target uname() handler.
- static int
+ static SyscallReturn
unameFunc(SyscallDesc *desc, int callnum, Process *process,
ExecContext *xc)
{
@@ -494,7 +494,7 @@ class Tru64 {
/// Target getsysyinfo() handler.
- static int
+ static SyscallReturn
getsysinfoFunc(SyscallDesc *desc, int callnum, Process *process,
ExecContext *xc)
{
@@ -574,7 +574,7 @@ class Tru64 {
}
/// Target fnctl() handler.
- static int
+ static SyscallReturn
fcntlFunc(SyscallDesc *desc, int callnum, Process *process,
ExecContext *xc)
{
@@ -618,7 +618,7 @@ class Tru64 {
/// Target getdirentries() handler.
- static int
+ static SyscallReturn
getdirentriesFunc(SyscallDesc *desc, int callnum, Process *process,
ExecContext *xc)
{
@@ -669,11 +669,11 @@ class Tru64 {
*basep = host_basep;
basep.copyOut(xc->mem);
- return (tgt_buf_ptr - tgt_buf);
+ return tgt_buf_ptr - tgt_buf;
}
/// Target sigreturn() handler.
- static int
+ static SyscallReturn
sigreturnFunc(SyscallDesc *desc, int callnum, Process *process,
ExecContext *xc)
{
@@ -699,7 +699,7 @@ class Tru64 {
}
/// Target table() handler.
- static int
+ static SyscallReturn
tableFunc(SyscallDesc *desc, int callnum, Process *process,
ExecContext *xc)
{
@@ -749,7 +749,7 @@ class Tru64 {
//
/// Create a stack region for a thread.
- static int
+ static SyscallReturn
stack_createFunc(SyscallDesc *desc, int callnum, Process *process,
ExecContext *xc)
{
@@ -776,7 +776,7 @@ class Tru64 {
/// This call sets up the interface between the user and kernel
/// schedulers by creating a shared-memory region. The shared memory
/// region has several structs, some global, some per-RAD, some per-VP.
- static int
+ static SyscallReturn
nxm_task_initFunc(SyscallDesc *desc, int callnum, Process *process,
ExecContext *xc)
{
@@ -899,7 +899,7 @@ class Tru64 {
}
/// Create thread.
- static int
+ static SyscallReturn
nxm_thread_createFunc(SyscallDesc *desc, int callnum, Process *process,
ExecContext *xc)
{
@@ -1011,7 +1011,7 @@ class Tru64 {
}
/// Thread idle call (like yield()).
- static int
+ static SyscallReturn
nxm_idleFunc(SyscallDesc *desc, int callnum, Process *process,
ExecContext *xc)
{
@@ -1019,7 +1019,7 @@ class Tru64 {
}
/// Block thread.
- static int
+ static SyscallReturn
nxm_thread_blockFunc(SyscallDesc *desc, int callnum, Process *process,
ExecContext *xc)
{
@@ -1036,7 +1036,7 @@ class Tru64 {
}
/// block.
- static int
+ static SyscallReturn
nxm_blockFunc(SyscallDesc *desc, int callnum, Process *process,
ExecContext *xc)
{
@@ -1057,7 +1057,7 @@ class Tru64 {
}
/// Unblock thread.
- static int
+ static SyscallReturn
nxm_unblockFunc(SyscallDesc *desc, int callnum, Process *process,
ExecContext *xc)
{
@@ -1070,7 +1070,7 @@ class Tru64 {
}
/// Switch thread priority.
- static int
+ static SyscallReturn
swtch_priFunc(SyscallDesc *desc, int callnum, Process *process,
ExecContext *xc)
{
@@ -1081,7 +1081,7 @@ class Tru64 {
//
// Since we assume at most one "kernel" thread per CPU, it's
// always safe to return false here.
- return false;
+ return 0; //false;
}
@@ -1154,7 +1154,7 @@ class Tru64 {
}
/// Lock acquire syscall handler.
- static int
+ static SyscallReturn
m5_mutex_lockFunc(SyscallDesc *desc, int callnum, Process *process,
ExecContext *xc)
{
@@ -1169,7 +1169,7 @@ class Tru64 {
}
/// Try lock (non-blocking).
- static int
+ static SyscallReturn
m5_mutex_trylockFunc(SyscallDesc *desc, int callnum, Process *process,
ExecContext *xc)
{
@@ -1189,7 +1189,7 @@ class Tru64 {
}
/// Unlock syscall handler.
- static int
+ static SyscallReturn
m5_mutex_unlockFunc(SyscallDesc *desc, int callnum, Process *process,
ExecContext *xc)
{
@@ -1201,7 +1201,7 @@ class Tru64 {
}
/// Signal ocndition.
- static int
+ static SyscallReturn
m5_cond_signalFunc(SyscallDesc *desc, int callnum, Process *process,
ExecContext *xc)
{
@@ -1214,7 +1214,7 @@ class Tru64 {
}
/// Wake up all processes waiting on the condition variable.
- static int
+ static SyscallReturn
m5_cond_broadcastFunc(SyscallDesc *desc, int callnum, Process *process,
ExecContext *xc)
{
@@ -1226,7 +1226,7 @@ class Tru64 {
}
/// Wait on a condition.
- static int
+ static SyscallReturn
m5_cond_waitFunc(SyscallDesc *desc, int callnum, Process *process,
ExecContext *xc)
{
@@ -1248,7 +1248,7 @@ class Tru64 {
}
/// Thread exit.
- static int
+ static SyscallReturn
m5_thread_exitFunc(SyscallDesc *desc, int callnum, Process *process,
ExecContext *xc)
{
@@ -1291,7 +1291,7 @@ class Tru64 {
}
/// Indirect syscall invocation (call #0).
- static int
+ static SyscallReturn
indirectSyscallFunc(SyscallDesc *desc, int callnum, Process *process,
ExecContext *xc)
{
diff --git a/arch/alpha/isa_desc b/arch/alpha/isa_desc
index 5154d78d1..0e07400d3 100644
--- a/arch/alpha/isa_desc
+++ b/arch/alpha/isa_desc
@@ -187,15 +187,16 @@ output header {{
/// Print a register name for disassembly given the unique
/// dependence tag number (FP or int).
- void printReg(std::ostream &os, int reg);
+ void printReg(std::ostream &os, int reg) const;
- std::string generateDisassembly(Addr pc, const SymbolTable *symtab);
+ std::string
+ generateDisassembly(Addr pc, const SymbolTable *symtab) const;
};
}};
output decoder {{
void
- AlphaStaticInst::printReg(std::ostream &os, int reg)
+ AlphaStaticInst::printReg(std::ostream &os, int reg) const
{
if (reg < FP_Base_DepTag) {
ccprintf(os, "r%d", reg);
@@ -206,7 +207,8 @@ output decoder {{
}
std::string
- AlphaStaticInst::generateDisassembly(Addr pc, const SymbolTable *symtab)
+ AlphaStaticInst::generateDisassembly(Addr pc,
+ const SymbolTable *symtab) const
{
std::stringstream ss;
@@ -237,7 +239,7 @@ output decoder {{
// Declarations for execute() methods.
def template BasicExecDeclare {{
- Fault execute(%(CPU_exec_context)s *, Trace::InstRecord *);
+ Fault execute(%(CPU_exec_context)s *, Trace::InstRecord *) const;
}};
// Basic instruction class declaration template.
@@ -267,7 +269,7 @@ def template BasicConstructor {{
// Basic instruction class execute method template.
def template BasicExecute {{
Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
- Trace::InstRecord *traceData)
+ Trace::InstRecord *traceData) const
{
Fault fault = No_Fault;
@@ -330,14 +332,16 @@ output header {{
~Nop() { }
- std::string generateDisassembly(Addr pc, const SymbolTable *symtab);
+ std::string
+ generateDisassembly(Addr pc, const SymbolTable *symtab) const;
%(BasicExecDeclare)s
};
}};
output decoder {{
- std::string Nop::generateDisassembly(Addr pc, const SymbolTable *symtab)
+ std::string Nop::generateDisassembly(Addr pc,
+ const SymbolTable *symtab) const
{
#ifdef SS_COMPATIBLE_DISASSEMBLY
return originalDisassembly;
@@ -360,7 +364,7 @@ output decoder {{
output exec {{
Fault
- Nop::execute(%(CPU_exec_context)s *, Trace::InstRecord *)
+ Nop::execute(%(CPU_exec_context)s *, Trace::InstRecord *) const
{
return No_Fault;
}
@@ -410,13 +414,14 @@ output header {{
{
}
- std::string generateDisassembly(Addr pc, const SymbolTable *symtab);
+ std::string
+ generateDisassembly(Addr pc, const SymbolTable *symtab) const;
};
}};
output decoder {{
std::string
- IntegerImm::generateDisassembly(Addr pc, const SymbolTable *symtab)
+ IntegerImm::generateDisassembly(Addr pc, const SymbolTable *symtab) const
{
std::stringstream ss;
@@ -588,12 +593,13 @@ output header {{
}
#if defined(linux)
- int getC99RoundingMode(uint64_t fpcr_val);
+ int getC99RoundingMode(uint64_t fpcr_val) const;
#endif
// This differs from the AlphaStaticInst version only in
// printing suffixes for non-default rounding & trapping modes.
- std::string generateDisassembly(Addr pc, const SymbolTable *symtab);
+ std::string
+ generateDisassembly(Addr pc, const SymbolTable *symtab) const;
};
}};
@@ -618,7 +624,7 @@ def template FloatingPointDecode {{
output decoder {{
#if defined(linux)
int
- AlphaFP::getC99RoundingMode(uint64_t fpcr_val)
+ AlphaFP::getC99RoundingMode(uint64_t fpcr_val) const
{
if (roundingMode == Dynamic) {
return alphaToC99RoundingMode[bits(fpcr_val, 59, 58)];
@@ -630,7 +636,7 @@ output decoder {{
#endif
std::string
- AlphaFP::generateDisassembly(Addr pc, const SymbolTable *symtab)
+ AlphaFP::generateDisassembly(Addr pc, const SymbolTable *symtab) const
{
std::string mnem_str(mnemonic);
@@ -751,7 +757,8 @@ output header {{
{
}
- std::string generateDisassembly(Addr pc, const SymbolTable *symtab);
+ std::string
+ generateDisassembly(Addr pc, const SymbolTable *symtab) const;
public:
@@ -790,81 +797,33 @@ output header {{
protected:
/// Constructor
MemoryNoDisp(const char *mnem, MachInst _machInst, OpClass __opClass,
- StaticInstPtr<AlphaISA> _eaCompPtr,
- StaticInstPtr<AlphaISA> _memAccPtr)
+ StaticInstPtr<AlphaISA> _eaCompPtr = nullStaticInstPtr,
+ StaticInstPtr<AlphaISA> _memAccPtr = nullStaticInstPtr)
: Memory(mnem, _machInst, __opClass, _eaCompPtr, _memAccPtr)
{
}
- std::string generateDisassembly(Addr pc, const SymbolTable *symtab);
- };
-
-
- /**
- * Base class for "fake" effective-address computation
- * instructions returnded by eaCompInst().
- */
- class EACompBase : public AlphaStaticInst
- {
- public:
- /// Constructor
- EACompBase(MachInst machInst)
- : AlphaStaticInst("(eacomp)", machInst, IntAluOp)
- {
- }
-
- %(BasicExecDeclare)s
- };
-
- /**
- * Base class for "fake" memory-access instructions returnded by
- * memAccInst().
- */
- class MemAccBase : public AlphaStaticInst
- {
- public:
- /// Constructor
- MemAccBase(MachInst machInst, OpClass __opClass)
- : AlphaStaticInst("(memacc)", machInst, __opClass)
- {
- }
-
- %(BasicExecDeclare)s
+ std::string
+ generateDisassembly(Addr pc, const SymbolTable *symtab) const;
};
-
}};
output decoder {{
std::string
- Memory::generateDisassembly(Addr pc, const SymbolTable *symtab)
+ Memory::generateDisassembly(Addr pc, const SymbolTable *symtab) const
{
return csprintf("%-10s %c%d,%d(r%d)", mnemonic,
flags[IsFloating] ? 'f' : 'r', RA, MEMDISP, RB);
}
std::string
- MemoryNoDisp::generateDisassembly(Addr pc, const SymbolTable *symtab)
+ MemoryNoDisp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
{
return csprintf("%-10s (r%d)", mnemonic, RB);
}
}};
-output exec {{
- Fault
- EACompBase::execute(%(CPU_exec_context)s *, Trace::InstRecord *)
- {
- panic("attempt to execute eacomp");
- }
-
- Fault
- MemAccBase::execute(%(CPU_exec_context)s *, Trace::InstRecord *)
- {
- panic("attempt to execute memacc");
- }
-}};
-
-
def format LoadAddress(code) {{
iop = InstObjParams(name, Name, 'MemoryDisp32', CodeBlock(code))
header_output = BasicDeclare.subst(iop)
@@ -885,21 +844,25 @@ def template LoadStoreDeclare {{
/**
* "Fake" effective address computation class for "%(mnemonic)s".
*/
- class EAComp : public EACompBase
+ class EAComp : public %(base_class)s
{
public:
/// Constructor
EAComp(MachInst machInst);
+
+ %(BasicExecDeclare)s
};
/**
* "Fake" memory access instruction class for "%(mnemonic)s".
*/
- class MemAcc : public MemAccBase
+ class MemAcc : public %(base_class)s
{
public:
/// Constructor
MemAcc(MachInst machInst);
+
+ %(BasicExecDeclare)s
};
public:
@@ -912,14 +875,17 @@ def template LoadStoreDeclare {{
}};
def template LoadStoreConstructor {{
+ /** TODO: change op_class to AddrGenOp or something (requires
+ * creating new member of OpClass enum in op_class.hh, updating
+ * config files, etc.). */
inline %(class_name)s::EAComp::EAComp(MachInst machInst)
- : EACompBase(machInst)
+ : %(base_class)s("%(mnemonic)s (EAComp)", machInst, IntAluOp)
{
%(ea_constructor)s;
}
inline %(class_name)s::MemAcc::MemAcc(MachInst machInst)
- : MemAccBase(machInst, %(op_class)s)
+ : %(base_class)s("%(mnemonic)s (MemAcc)", machInst, %(op_class)s)
{
%(memacc_constructor)s;
}
@@ -932,9 +898,67 @@ def template LoadStoreConstructor {{
}
}};
+
+def template EACompExecute {{
+ Fault
+ %(class_name)s::EAComp::execute(%(CPU_exec_context)s *xc,
+ Trace::InstRecord *traceData) const
+ {
+ Addr EA;
+ Fault fault = No_Fault;
+
+ %(fp_enable_check)s;
+ %(op_decl)s;
+ %(op_rd)s;
+ %(code)s;
+
+ if (fault == No_Fault) {
+ %(op_wb)s;
+ xc->setEA(EA);
+ }
+
+ return fault;
+ }
+}};
+
+def template MemAccExecute {{
+ Fault
+ %(class_name)s::MemAcc::execute(%(CPU_exec_context)s *xc,
+ Trace::InstRecord *traceData) const
+ {
+ Addr EA;
+ Fault fault = No_Fault;
+
+ %(fp_enable_check)s;
+ %(op_decl)s;
+ %(op_nonmem_rd)s;
+ EA = xc->getEA();
+
+ if (fault == No_Fault) {
+ %(op_mem_rd)s;
+ %(code)s;
+ }
+
+ if (fault == No_Fault) {
+ %(op_mem_wb)s;
+ }
+
+ if (fault == No_Fault) {
+ %(postacc_code)s;
+ }
+
+ if (fault == No_Fault) {
+ %(op_nonmem_wb)s;
+ }
+
+ return fault;
+ }
+}};
+
+
def template LoadStoreExecute {{
Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
- Trace::InstRecord *traceData)
+ Trace::InstRecord *traceData) const
{
Addr EA;
Fault fault = No_Fault;
@@ -968,7 +992,7 @@ def template LoadStoreExecute {{
def template PrefetchExecute {{
Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
- Trace::InstRecord *traceData)
+ Trace::InstRecord *traceData) const
{
Addr EA;
Fault fault = No_Fault;
@@ -1022,18 +1046,33 @@ def LoadStoreBase(name, Name, ea_code, memacc_code, postacc_code = '',
# Would be nice to autogenerate this list, but oh well.
valid_mem_flags = ['LOCKED', 'NO_FAULT', 'EVICT_NEXT', 'PF_EXCLUSIVE']
- inst_flags = []
- mem_flags = []
- for f in flags:
- if f in valid_mem_flags:
- mem_flags.append(f)
- else:
- inst_flags.append(f)
+ mem_flags = [f for f in flags if f in valid_mem_flags]
+ inst_flags = [f for f in flags if f not in valid_mem_flags]
+
+ # add hook to get effective addresses into execution trace output.
+ ea_code += '\nif (traceData) { traceData->setAddr(EA); }\n'
+ # generate code block objects
ea_cblk = CodeBlock(ea_code)
memacc_cblk = CodeBlock(memacc_code)
postacc_cblk = CodeBlock(postacc_code)
+ # Some CPU models execute the memory operation as an atomic unit,
+ # while others want to separate them into an effective address
+ # computation and a memory access operation. As a result, we need
+ # to generate three StaticInst objects. Note that the latter two
+ # are nested inside the larger "atomic" one.
+
+ # generate InstObjParams for EAComp object
+ ea_iop = InstObjParams(name, Name, base_class, ea_cblk, inst_flags)
+
+ # generate InstObjParams for MemAcc object
+ memacc_iop = InstObjParams(name, Name, base_class, memacc_cblk, inst_flags)
+ # in the split execution model, the MemAcc portion is responsible
+ # for the post-access code.
+ memacc_iop.postacc_code = postacc_cblk.code
+
+ # generate InstObjParams for unified execution
cblk = CodeBlock(ea_code + memacc_code + postacc_code)
iop = InstObjParams(name, Name, base_class, cblk, inst_flags)
@@ -1043,13 +1082,17 @@ def LoadStoreBase(name, Name, ea_code, memacc_code, postacc_code = '',
iop.memacc_code = memacc_cblk.code
iop.postacc_code = postacc_cblk.code
- mem_flags = string.join(mem_flags, '|')
- if mem_flags != '':
- iop.constructor += '\n\tmemAccessFlags = ' + mem_flags + ';'
+ if mem_flags:
+ s = '\n\tmemAccessFlags = ' + string.join(mem_flags, '|') + ';'
+ iop.constructor += s
+ memacc_iop.constructor += s
# (header_output, decoder_output, decode_block, exec_output)
return (LoadStoreDeclare.subst(iop), LoadStoreConstructor.subst(iop),
- decode_template.subst(iop), exec_template.subst(iop))
+ decode_template.subst(iop),
+ EACompExecute.subst(ea_iop)
+ + MemAccExecute.subst(memacc_iop)
+ + exec_template.subst(iop))
}};
@@ -1123,9 +1166,9 @@ output header {{
{
protected:
/// Cached program counter from last disassembly
- Addr cachedPC;
+ mutable Addr cachedPC;
/// Cached symbol table pointer from last disassembly
- const SymbolTable *cachedSymtab;
+ mutable const SymbolTable *cachedSymtab;
/// Constructor
PCDependentDisassembly(const char *mnem, MachInst _machInst,
@@ -1135,7 +1178,8 @@ output header {{
{
}
- const std::string &disassemble(Addr pc, const SymbolTable *symtab);
+ const std::string &
+ disassemble(Addr pc, const SymbolTable *symtab) const;
};
/**
@@ -1157,7 +1201,8 @@ output header {{
Addr branchTarget(Addr branchPC) const;
- std::string generateDisassembly(Addr pc, const SymbolTable *symtab);
+ std::string
+ generateDisassembly(Addr pc, const SymbolTable *symtab) const;
};
/**
@@ -1181,7 +1226,8 @@ output header {{
Addr branchTarget(ExecContext *xc) const;
- std::string generateDisassembly(Addr pc, const SymbolTable *symtab);
+ std::string
+ generateDisassembly(Addr pc, const SymbolTable *symtab) const;
};
}};
@@ -1201,7 +1247,8 @@ output decoder {{
}
const std::string &
- PCDependentDisassembly::disassemble(Addr pc, const SymbolTable *symtab)
+ PCDependentDisassembly::disassemble(Addr pc,
+ const SymbolTable *symtab) const
{
if (!cachedDisassembly ||
pc != cachedPC || symtab != cachedSymtab)
@@ -1219,7 +1266,7 @@ output decoder {{
}
std::string
- Branch::generateDisassembly(Addr pc, const SymbolTable *symtab)
+ Branch::generateDisassembly(Addr pc, const SymbolTable *symtab) const
{
std::stringstream ss;
@@ -1257,7 +1304,7 @@ output decoder {{
}
std::string
- Jump::generateDisassembly(Addr pc, const SymbolTable *symtab)
+ Jump::generateDisassembly(Addr pc, const SymbolTable *symtab) const
{
std::stringstream ss;
@@ -1356,13 +1403,15 @@ output header {{
{
}
- std::string generateDisassembly(Addr pc, const SymbolTable *symtab);
+ std::string
+ generateDisassembly(Addr pc, const SymbolTable *symtab) const;
};
}};
output decoder {{
std::string
- EmulatedCallPal::generateDisassembly(Addr pc, const SymbolTable *symtab)
+ EmulatedCallPal::generateDisassembly(Addr pc,
+ const SymbolTable *symtab) const
{
#ifdef SS_COMPATIBLE_DISASSEMBLY
return csprintf("%s %s", "call_pal", mnemonic);
@@ -1398,7 +1447,8 @@ output header {{
CallPalBase(const char *mnem, MachInst _machInst,
OpClass __opClass);
- std::string generateDisassembly(Addr pc, const SymbolTable *symtab);
+ std::string
+ generateDisassembly(Addr pc, const SymbolTable *symtab) const;
};
}};
@@ -1428,7 +1478,7 @@ output decoder {{
}
std::string
- CallPalBase::generateDisassembly(Addr pc, const SymbolTable *symtab)
+ CallPalBase::generateDisassembly(Addr pc, const SymbolTable *symtab) const
{
return csprintf("%-10s %#x", "call_pal", palFunc);
}
@@ -1460,10 +1510,11 @@ output header {{
/// Constructor
HwLoadStore(const char *mnem, MachInst _machInst, OpClass __opClass,
- StaticInstPtr<AlphaISA> _eaCompPtr,
- StaticInstPtr<AlphaISA> _memAccPtr);
+ StaticInstPtr<AlphaISA> _eaCompPtr = nullStaticInstPtr,
+ StaticInstPtr<AlphaISA> _memAccPtr = nullStaticInstPtr);
- std::string generateDisassembly(Addr pc, const SymbolTable *symtab);
+ std::string
+ generateDisassembly(Addr pc, const SymbolTable *symtab) const;
};
}};
@@ -1485,7 +1536,7 @@ output decoder {{
}
std::string
- HwLoadStore::generateDisassembly(Addr pc, const SymbolTable *symtab)
+ HwLoadStore::generateDisassembly(Addr pc, const SymbolTable *symtab) const
{
#ifdef SS_COMPATIBLE_DISASSEMBLY
return csprintf("%-10s r%d,%d(r%d)", mnemonic, RA, disp, RB);
@@ -1536,13 +1587,14 @@ output header {{
{
}
- std::string generateDisassembly(Addr pc, const SymbolTable *symtab);
+ std::string
+ generateDisassembly(Addr pc, const SymbolTable *symtab) const;
};
}};
output decoder {{
std::string
- HwMoveIPR::generateDisassembly(Addr pc, const SymbolTable *symtab)
+ HwMoveIPR::generateDisassembly(Addr pc, const SymbolTable *symtab) const
{
if (_numSrcRegs > 0) {
// must be mtpr
@@ -1558,7 +1610,8 @@ output decoder {{
}};
def format HwMoveIPR(code) {{
- iop = InstObjParams(name, Name, 'HwMoveIPR', CodeBlock(code))
+ iop = InstObjParams(name, Name, 'HwMoveIPR', CodeBlock(code),
+ ['IprAccessOp'])
header_output = BasicDeclare.subst(iop)
decoder_output = BasicConstructor.subst(iop)
decode_block = BasicDecode.subst(iop)
@@ -1593,7 +1646,8 @@ output header {{
%(BasicExecDeclare)s
- std::string generateDisassembly(Addr pc, const SymbolTable *symtab);
+ std::string
+ generateDisassembly(Addr pc, const SymbolTable *symtab) const;
};
/**
@@ -1609,7 +1663,7 @@ output header {{
{
private:
/// Have we warned on this instruction yet?
- bool warned;
+ mutable bool warned;
public:
/// Constructor
@@ -1623,19 +1677,22 @@ output header {{
%(BasicExecDeclare)s
- std::string generateDisassembly(Addr pc, const SymbolTable *symtab);
+ std::string
+ generateDisassembly(Addr pc, const SymbolTable *symtab) const;
};
}};
output decoder {{
std::string
- FailUnimplemented::generateDisassembly(Addr pc, const SymbolTable *symtab)
+ FailUnimplemented::generateDisassembly(Addr pc,
+ const SymbolTable *symtab) const
{
return csprintf("%-10s (unimplemented)", mnemonic);
}
std::string
- WarnUnimplemented::generateDisassembly(Addr pc, const SymbolTable *symtab)
+ WarnUnimplemented::generateDisassembly(Addr pc,
+ const SymbolTable *symtab) const
{
#ifdef SS_COMPATIBLE_DISASSEMBLY
return csprintf("%-10s", mnemonic);
@@ -1648,7 +1705,7 @@ output decoder {{
output exec {{
Fault
FailUnimplemented::execute(%(CPU_exec_context)s *xc,
- Trace::InstRecord *traceData)
+ Trace::InstRecord *traceData) const
{
panic("attempt to execute unimplemented instruction '%s' "
"(inst 0x%08x, opcode 0x%x)", mnemonic, machInst, OPCODE);
@@ -1657,7 +1714,7 @@ output exec {{
Fault
WarnUnimplemented::execute(%(CPU_exec_context)s *xc,
- Trace::InstRecord *traceData)
+ Trace::InstRecord *traceData) const
{
if (!warned) {
warn("instruction '%s' unimplemented\n", mnemonic);
@@ -1699,7 +1756,8 @@ output header {{
%(BasicExecDeclare)s
- std::string generateDisassembly(Addr pc, const SymbolTable *symtab);
+ std::string
+ generateDisassembly(Addr pc, const SymbolTable *symtab) const;
};
}};
@@ -1710,7 +1768,7 @@ output header {{
output decoder {{
std::string
- Unknown::generateDisassembly(Addr pc, const SymbolTable *symtab)
+ Unknown::generateDisassembly(Addr pc, const SymbolTable *symtab) const
{
return csprintf("%-10s (inst 0x%x, opcode 0x%x)",
"unknown", machInst, OPCODE);
@@ -1719,7 +1777,8 @@ output decoder {{
output exec {{
Fault
- Unknown::execute(%(CPU_exec_context)s *xc, Trace::InstRecord *traceData)
+ Unknown::execute(%(CPU_exec_context)s *xc,
+ Trace::InstRecord *traceData) const
{
panic("attempt to execute unknown instruction "
"(inst 0x%08x, opcode 0x%x)", machInst, OPCODE);
@@ -2507,7 +2566,7 @@ decode OPCODE default Unknown::unknown() {
}
format BasicOperate {
- 0x1e: hw_rei({{ xc->hwrei(); }});
+ 0x1e: hw_rei({{ xc->hwrei(); }}, IsSerializing);
// M5 special opcodes use the reserved 0x01 opcode space
0x01: decode M5FUNC {
diff --git a/arch/alpha/isa_traits.hh b/arch/alpha/isa_traits.hh
index ff3da1502..9327fa88b 100644
--- a/arch/alpha/isa_traits.hh
+++ b/arch/alpha/isa_traits.hh
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2004 The Regents of The University of Michigan
+ * 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
@@ -175,6 +175,9 @@ static const Addr PageOffset = PageBytes - 1;
static StaticInstPtr<AlphaISA> decodeInst(MachInst);
+ // return a no-op instruction... used for instruction fetch faults
+ static const MachInst NoopMachInst;
+
enum annotes {
ANNOTE_NONE = 0,
// An impossible number for instruction annotations
@@ -283,6 +286,43 @@ const int ArgumentReg1 = TheISA::ArgumentReg1;
const int BranchPredAddrShiftAmt = TheISA::BranchPredAddrShiftAmt;
const int MaxAddr = (Addr)-1;
+#ifndef FULL_SYSTEM
+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
+
+
#ifdef FULL_SYSTEM
typedef TheISA::InternalProcReg InternalProcReg;
const int NumInternalProcRegs = TheISA::NumInternalProcRegs;
diff --git a/arch/alpha/pseudo_inst.cc b/arch/alpha/pseudo_inst.cc
index 95c85b45a..22d65638b 100644
--- a/arch/alpha/pseudo_inst.cc
+++ b/arch/alpha/pseudo_inst.cc
@@ -206,7 +206,7 @@ namespace AlphaPseudo
void checkParams();
};
- Context context("PseudoInsts");
+ Context context("pseudo_inst");
Param<bool> __quiesce(&context, "quiesce",
"enable quiesce instructions",
diff --git a/arch/alpha/vptr.hh b/arch/alpha/vptr.hh
index cd4bc547b..e955c67cf 100644
--- a/arch/alpha/vptr.hh
+++ b/arch/alpha/vptr.hh
@@ -26,8 +26,8 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef __VPTR_HH__
-#define __VPTR_HH__
+#ifndef __ARCH_ALPHA_VPTR_HH__
+#define __ARCH_ALPHA_VPTR_HH__
#include "arch/alpha/vtophys.hh"
@@ -69,14 +69,15 @@ class VPtr
const VPtr<T> &operator+=(int offset)
{
ptr += offset;
- assert((ptr & (ALPHA_PGBYTES - 1)) + sizeof(T) < ALPHA_PGBYTES);
+ assert((ptr & (AlphaISA::PageBytes - 1)) + sizeof(T)
+ < AlphaISA::PageBytes);
return *this;
}
const VPtr<T> &operator=(Addr p)
{
- assert((p & (ALPHA_PGBYTES - 1)) + sizeof(T) < ALPHA_PGBYTES);
+ assert((p & (AlphaISA::PageBytes)) + sizeof(T) < AlphaISA::PageBytes);
ptr = p;
return *this;
@@ -110,4 +111,4 @@ class VPtr
}
};
-#endif // __VPTR_HH__
+#endif // __ARCH_ALPHA_VPTR_HH__
diff --git a/arch/isa_parser.py b/arch/isa_parser.py
index c0b5131de..18e4b0a45 100755
--- a/arch/isa_parser.py
+++ b/arch/isa_parser.py
@@ -1210,10 +1210,12 @@ class MemOperandTraits(OperandTraits):
def makeWrite(self, op_desc):
(size, type, is_signed) = operandSizeMap[op_desc.eff_ext]
eff_type = 'uint%d_t' % size
- return 'fault = xc->write((%s&)%s, EA, %s_flags,' \
- ' &%s_write_result);\n' \
+ wb = 'fault = xc->write((%s&)%s, EA, %s_flags, &%s_write_result);\n' \
% (eff_type, op_desc.munged_name, op_desc.base_name,
op_desc.base_name)
+ wb += 'if (traceData) { traceData->setData(%s); }' % \
+ op_desc.munged_name
+ return wb
class NPCOperandTraits(OperandTraits):
def makeConstructor(self, op_desc):
diff --git a/base/inifile.cc b/base/inifile.cc
index 94b17966a..862e4082f 100644
--- a/base/inifile.cc
+++ b/base/inifile.cc
@@ -334,47 +334,6 @@ IniFile::find(const string &sectionName, const string &entryName,
}
bool
-IniFile::findDefault(const string &_section, const string &entry,
- string &value) const
-{
- string section = _section;
- while (!findAppend(section, entry, value)) {
- if (!find(section, "default", section)) {
- return false;
- }
- }
-
- return true;
-}
-
-bool
-IniFile::findAppend(const string &_section, const string &entry,
- string &value) const
-{
- string section = _section;
- bool ret = false;
- bool first = true;
-
- do {
- string val;
- if (find(section, entry, val)) {
- ret = true;
- if (first) {
- value = val;
- first = false;
- } else {
- value += " ";
- value += val;
- }
-
- }
- } while (find(section, "append", section));
-
- return ret;
-}
-
-
-bool
IniFile::sectionExists(const string &sectionName) const
{
return findSection(sectionName) != NULL;
diff --git a/base/inifile.hh b/base/inifile.hh
index 58a657db4..d5d6bab5e 100644
--- a/base/inifile.hh
+++ b/base/inifile.hh
@@ -190,24 +190,6 @@ class IniFile
bool find(const std::string &section, const std::string &entry,
std::string &value) const;
- /// Find value corresponding to given section and entry names,
- /// following "default" links to other sections where possible.
- /// Value is returned by reference in 'value' param.
- /// @return True if found, false if not.
- bool findDefault(const std::string &section, const std::string &entry,
- std::string &value) const;
-
- /**
- * Find a value corresponding to the given section and entry names
- * following "append" links to other sections where possible.
- * @param section The section to start with.
- * @param entry The entry to find.
- * @param value The value found.
- * @return True if the entry was found.
- */
- bool findAppend(const std::string &section, const std::string &entry,
- std::string &value) const;
-
/// Determine whether the named section exists in the .ini file.
/// Note that the 'Section' class is (intentionally) not public,
/// so all clients can do is get a bool that says whether there
diff --git a/base/misc.cc b/base/misc.cc
index 0c459352f..4b7c3632a 100644
--- a/base/misc.cc
+++ b/base/misc.cc
@@ -30,10 +30,11 @@
#include <string>
#include "base/cprintf.hh"
-#include "sim/host.hh"
#include "base/hostinfo.hh"
#include "base/misc.hh"
+#include "base/output.hh"
#include "base/trace.hh"
+#include "sim/host.hh"
#include "sim/universe.hh"
using namespace std;
@@ -116,7 +117,7 @@ __warn(const string &format, cp::ArgList &args, const char *func,
#endif
args.dump(cerr, fmt);
- if (outputStream != &cerr && outputStream != &cout)
+ if (simout.isFile(*outputStream))
args.dump(*outputStream, fmt);
delete &args;
diff --git a/base/output.cc b/base/output.cc
new file mode 100644
index 000000000..2b1733f21
--- /dev/null
+++ b/base/output.cc
@@ -0,0 +1,129 @@
+/*
+ * Copyright (c) 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.
+ */
+
+#include <errno.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <fstream>
+
+#include "base/misc.hh"
+#include "base/output.hh"
+
+using namespace std;
+
+OutputDirectory simout;
+
+/**
+ *
+ */
+OutputDirectory::OutputDirectory()
+{}
+
+OutputDirectory::~OutputDirectory()
+{}
+
+void
+OutputDirectory::setDirectory(const string &d)
+{
+ if (!dir.empty())
+ panic("Output directory already set!\n");
+
+ dir = d;
+
+ if (dir != ".") {
+ if (mkdir(dir.c_str(), 0777) < 0 && errno != EEXIST)
+ panic("couldn't make output dir %s: %s\n",
+ dir, strerror(errno));
+ }
+
+ // guarantee that directory ends with a '/'
+ if (dir[dir.size() - 1] != '/')
+ dir += "/";
+}
+
+const string &
+OutputDirectory::directory()
+{
+ if (dir.empty())
+ panic("Output directory not set!");
+
+ return dir;
+}
+
+string
+OutputDirectory::resolve(const string &name)
+{
+ return (name[0] != '/') ? dir + name : name;
+}
+
+ostream *
+OutputDirectory::create(const string &name)
+{
+ if (name == "cerr" || name == "stderr")
+ return &cerr;
+
+ if (name == "cout" || name == "stdout")
+ return &cout;
+
+ ofstream *file = new ofstream(resolve(name).c_str(), ios::trunc);
+ if (!file->is_open())
+ panic("Cannot open file %s", name);
+
+ return file;
+}
+
+ostream *
+OutputDirectory::find(const string &name)
+{
+ if (name == "cerr" || name == "stderr")
+ return &cerr;
+
+ if (name == "cout" || name == "stdout")
+ return &cout;
+
+ string filename = resolve(name);
+ map_t::iterator i = files.find(filename);
+ if (i != files.end())
+ return (*i).second;
+
+ ofstream *file = new ofstream(filename.c_str(), ios::trunc);
+ if (!file->is_open())
+ panic("Cannot open file %s", filename);
+
+ files[filename] = file;
+ return file;
+}
+
+bool
+OutputDirectory::isFile(const std::ostream *os)
+{
+ return os && os != &cerr && os != &cout;
+}
diff --git a/base/output.hh b/base/output.hh
new file mode 100644
index 000000000..3bbe73e3b
--- /dev/null
+++ b/base/output.hh
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 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.
+ */
+
+#ifndef __BASE_OUTPUT_HH__
+#define __BASE_OUTPUT_HH__
+
+#include <iosfwd>
+#include <map>
+#include <string>
+
+class OutputDirectory
+{
+ private:
+ typedef std::map<std::string, std::ostream *> map_t;
+
+ map_t files;
+ std::string dir;
+
+ public:
+ OutputDirectory();
+ ~OutputDirectory();
+
+ void setDirectory(const std::string &dir);
+ const std::string &directory();
+
+ std::string resolve(const std::string &name);
+ std::ostream *create(const std::string &name);
+ std::ostream *find(const std::string &name);
+
+ static bool isFile(const std::ostream *os);
+ static inline bool isFile(const std::ostream &os) { return isFile(&os); }
+};
+
+extern OutputDirectory simout;
+
+#endif // __BASE_OUTPUT_HH__
diff --git a/base/random.hh b/base/random.hh
index 0bfed100c..fe93a98a6 100644
--- a/base/random.hh
+++ b/base/random.hh
@@ -37,61 +37,61 @@ double getDouble();
template <typename T>
struct Random;
-struct Random<int8_t>
+template<> struct Random<int8_t>
{
static int8_t get()
{ return getLong() & (int8_t)-1; }
};
-struct Random<uint8_t>
+template<> struct Random<uint8_t>
{
static uint8_t get()
{ return getLong() & (uint8_t)-1; }
};
-struct Random<int16_t>
+template<> struct Random<int16_t>
{
static int16_t get()
{ return getLong() & (int16_t)-1; }
};
-struct Random<uint16_t>
+template<> struct Random<uint16_t>
{
static uint16_t get()
{ return getLong() & (uint16_t)-1; }
};
-struct Random<int32_t>
+template<> struct Random<int32_t>
{
static int32_t get()
{ return (int32_t)getLong(); }
};
-struct Random<uint32_t>
+template<> struct Random<uint32_t>
{
static uint32_t get()
{ return (uint32_t)getLong(); }
};
-struct Random<int64_t>
+template<> struct Random<int64_t>
{
static int64_t get()
{ return (int64_t)getLong() << 32 || (uint64_t)getLong(); }
};
-struct Random<uint64_t>
+template<> struct Random<uint64_t>
{
static uint64_t get()
{ return (uint64_t)getLong() << 32 || (uint64_t)getLong(); }
};
-struct Random<float>
+template<> struct Random<float>
{
static float get()
{ return getDouble(); }
};
-struct Random<double>
+template<> struct Random<double>
{
static double get()
{ return getDouble(); }
diff --git a/base/range.hh b/base/range.hh
index 9289792ea..57b6e6a77 100644
--- a/base/range.hh
+++ b/base/range.hh
@@ -30,6 +30,7 @@
#define __BASE_RANGE_HH__
#include <cassert>
+#include <iostream>
#include <string>
/**
diff --git a/base/res_list.hh b/base/res_list.hh
index 7080a3ba7..5dc798fed 100644
--- a/base/res_list.hh
+++ b/base/res_list.hh
@@ -352,7 +352,7 @@ res_list<T>::insert_after(iterator prev, T *d)
iterator p;
if (!allocate_storage)
- panic("Can't copy data... not allocating storage");
+ this->panic("Can't copy data... not allocating storage");
p = insert_after(prev);
if (p.notnull())
diff --git a/base/statistics.cc b/base/statistics.cc
index 6e3dae1ef..6f5caf1fe 100644
--- a/base/statistics.cc
+++ b/base/statistics.cc
@@ -286,6 +286,13 @@ check()
Database::stats().sort(StatData::less);
+#if defined(STATS_BINNING)
+ if (MainBin::curBin() == NULL) {
+ static MainBin mainBin("main bin");
+ mainBin.activate();
+ }
+#endif
+
if (i == end)
return;
diff --git a/base/statistics.hh b/base/statistics.hh
index f3b8a3922..98d50a5bc 100644
--- a/base/statistics.hh
+++ b/base/statistics.hh
@@ -407,7 +407,7 @@ class Wrap : public Child
public:
Wrap()
{
- map(new Data<Child>(*this));
+ map(new Data<Child>(*this));
}
/**
@@ -417,10 +417,10 @@ class Wrap : public Child
*/
Parent &name(const std::string &_name)
{
- Data<Child> *data = statData();
+ Data<Child> *data = this->statData();
data->name = _name;
- setPrint();
- return self();
+ this->setPrint();
+ return this->self();
}
/**
@@ -431,8 +431,8 @@ class Wrap : public Child
*/
Parent &desc(const std::string &_desc)
{
- statData()->desc = _desc;
- return self();
+ this->statData()->desc = _desc;
+ return this->self();
}
/**
@@ -442,8 +442,8 @@ class Wrap : public Child
*/
Parent &precision(int _precision)
{
- statData()->precision = _precision;
- return self();
+ this->statData()->precision = _precision;
+ return this->self();
}
/**
@@ -453,8 +453,8 @@ class Wrap : public Child
*/
Parent &flags(StatFlags _flags)
{
- statData()->flags |= _flags;
- return self();
+ this->statData()->flags |= _flags;
+ return this->self();
}
/**
@@ -466,8 +466,8 @@ class Wrap : public Child
template <class Stat>
Parent &prereq(const Stat &prereq)
{
- statData()->prereq = prereq.statData();
- return self();
+ this->statData()->prereq = prereq.statData();
+ return this->self();
}
};
@@ -487,11 +487,11 @@ class WrapVec : public Wrap<Parent, Child, Data>
*/
Parent &subname(int index, const std::string &name)
{
- std::vector<std::string> &subn = statData()->subnames;
+ std::vector<std::string> &subn = this->statData()->subnames;
if (subn.size() <= index)
subn.resize(index + 1);
subn[index] = name;
- return self();
+ return this->self();
}
/**
@@ -503,12 +503,12 @@ class WrapVec : public Wrap<Parent, Child, Data>
*/
Parent &subdesc(int index, const std::string &desc)
{
- std::vector<std::string> &subd = statData()->subdescs;
+ std::vector<std::string> &subd = this->statData()->subdescs;
if (subd.size() <= index)
subd.resize(index + 1);
subd[index] = desc;
- return self();
+ return this->self();
}
};
@@ -523,19 +523,19 @@ class WrapVec2d : public WrapVec<Parent, Child, Data>
*/
Parent &ysubnames(const char **names)
{
- Data<Child> *data = statData();
- data->y_subnames.resize(y);
- for (int i = 0; i < y; ++i)
+ Data<Child> *data = this->statData();
+ data->y_subnames.resize(this->y);
+ for (int i = 0; i < this->y; ++i)
data->y_subnames[i] = names[i];
- return self();
+ return this->self();
}
Parent &ysubname(int index, const std::string subname)
{
- Data<Child> *data = statData();
- assert(index < y);
- data->y_subnames.resize(y);
+ Data<Child> *data = this->statData();
+ assert(index < this->y);
+ data->y_subnames.resize(this->y);
data->y_subnames[index] = subname.c_str();
- return self();
+ return this->self();
}
};
@@ -711,7 +711,7 @@ class ScalarBase : public DataAccess
/** Define the params of the storage class. */
typedef typename Storage::Params params_t;
/** Define the bin type. */
- typedef typename Bin::Bin<Storage> bin_t;
+ typedef typename Bin::template Bin<Storage> bin_t;
protected:
/** The bin of this stat. */
@@ -914,7 +914,7 @@ class VectorBase : public DataAccess
/** Define the params of the storage class. */
typedef typename Storage::Params params_t;
/** Define the bin type. */
- typedef typename Bin::VectorBin<Storage> bin_t;
+ typedef typename Bin::template VectorBin<Storage> bin_t;
protected:
/** The bin of this stat. */
@@ -1022,7 +1022,7 @@ class ScalarProxy
/** Define the params of the storage class. */
typedef typename Storage::Params params_t;
/** Define the bin type. */
- typedef typename Bin::VectorBin<Storage> bin_t;
+ typedef typename Bin::template VectorBin<Storage> bin_t;
private:
/** Pointer to the bin in the parent VectorBase. */
@@ -1155,7 +1155,7 @@ class ScalarProxy
const StatData *statData() const { return getStatData(stat); }
std::string str() const
{
- return csprintf("%s[%d]", statData()->name, index);
+ return csprintf("%s[%d]", this->statData()->name, index);
}
};
@@ -1176,7 +1176,7 @@ class Vector2dBase : public DataAccess
{
public:
typedef typename Storage::Params params_t;
- typedef typename Bin::VectorBin<Storage> bin_t;
+ typedef typename Bin::template VectorBin<Storage> bin_t;
protected:
size_t x;
@@ -1204,7 +1204,7 @@ class Vector2dBase : public DataAccess
data->cvec[i] = this->data(i)->value(params);
}
- std::string ysubname(int i) const { return (*y_subnames)[i]; }
+ std::string ysubname(int i) const { return (*this->y_subnames)[i]; }
friend class VectorProxy<Storage, Bin>;
VectorProxy<Storage, Bin> operator[](int index);
@@ -1225,7 +1225,7 @@ class VectorProxy
{
public:
typedef typename Storage::Params params_t;
- typedef typename Bin::VectorBin<Storage> bin_t;
+ typedef typename Bin::template VectorBin<Storage> bin_t;
private:
bin_t *bin;
@@ -1622,7 +1622,7 @@ class DistBase : public DataAccess
/** Define the params of the storage class. */
typedef typename Storage::Params params_t;
/** Define the bin type. */
- typedef typename Bin::Bin<Storage> bin_t;
+ typedef typename Bin::template Bin<Storage> bin_t;
protected:
/** The bin of this stat. */
@@ -1698,7 +1698,7 @@ class VectorDistBase : public DataAccess
{
public:
typedef typename Storage::Params params_t;
- typedef typename Bin::VectorBin<Storage> bin_t;
+ typedef typename Bin::template VectorBin<Storage> bin_t;
protected:
bin_t bin;
@@ -1749,7 +1749,7 @@ class DistProxy
{
public:
typedef typename Storage::Params params_t;
- typedef typename Bin::Bin<Storage> bin_t;
+ typedef typename Bin::template Bin<Storage> bin_t;
typedef VectorDistBase<Storage, Bin> base_t;
private:
@@ -2184,7 +2184,7 @@ class SumNode : public Node
* binned. If the typedef is NoBin, nothing is binned. If it is
* MainBin, then all stats are binned under that Bin.
*/
-#if defined(FS_MEASURE) || defined(STATS_BINNING)
+#if defined(STATS_BINNING)
typedef MainBin DefaultBin;
#else
typedef NoBin DefaultBin;
@@ -2206,7 +2206,7 @@ class Scalar
Scalar()
{
- setInit();
+ this->setInit();
}
/**
@@ -2258,7 +2258,7 @@ class Average
Average()
{
- setInit();
+ this->setInit();
}
/**
@@ -2290,8 +2290,8 @@ class Vector
* @return A reference to this stat.
*/
Vector &init(size_t size) {
- bin.init(size, params);
- setInit();
+ this->bin.init(size, this->params);
+ this->setInit();
return *this;
}
@@ -2314,8 +2314,8 @@ class AverageVector
* @return A reference to this stat.
*/
AverageVector &init(size_t size) {
- bin.init(size, params);
- setInit();
+ this->bin.init(size, this->params);
+ this->setInit();
return *this;
}
@@ -2333,10 +2333,10 @@ class Vector2d
{
public:
Vector2d &init(size_t _x, size_t _y) {
- statData()->x = x = _x;
- statData()->y = y = _y;
- bin.init(x * y, params);
- setInit();
+ this->statData()->x = this->x = _x;
+ this->statData()->y = this->y = _y;
+ this->bin.init(this->x * this->y, this->params);
+ this->setInit();
return *this;
}
@@ -2367,12 +2367,12 @@ class Distribution
* @return A reference to this distribution.
*/
Distribution &init(Counter min, Counter max, Counter bkt) {
- params.min = min;
- params.max = max;
- params.bucket_size = bkt;
- params.size = (int)rint((max - min) / bkt + 1.0);
- bin.init(params);
- setInit();
+ this->params.min = min;
+ this->params.max = max;
+ this->params.bucket_size = bkt;
+ this->params.size = (int)rint((max - min) / bkt + 1.0);
+ this->bin.init(this->params);
+ this->setInit();
return *this;
}
@@ -2399,8 +2399,8 @@ class StandardDeviation
* Construct and initialize this distribution.
*/
StandardDeviation() {
- bin.init(params);
- setInit();
+ this->bin.init(this->params);
+ this->setInit();
}
};
@@ -2426,8 +2426,8 @@ class AverageDeviation
*/
AverageDeviation()
{
- bin.init(params);
- setInit();
+ this->bin.init(this->params);
+ this->setInit();
}
};
@@ -2457,12 +2457,12 @@ class VectorDistribution
* @return A reference to this distribution.
*/
VectorDistribution &init(int size, Counter min, Counter max, Counter bkt) {
- params.min = min;
- params.max = max;
- params.bucket_size = bkt;
- params.size = (int)rint((max - min) / bkt + 1.0);
- bin.init(size, params);
- setInit();
+ this->params.min = min;
+ this->params.max = max;
+ this->params.bucket_size = bkt;
+ this->params.size = (int)rint((max - min) / bkt + 1.0);
+ this->bin.init(size, this->params);
+ this->setInit();
return *this;
}
@@ -2491,8 +2491,8 @@ class VectorStandardDeviation
* @return A reference to this distribution.
*/
VectorStandardDeviation &init(int size) {
- bin.init(size, params);
- setInit();
+ this->bin.init(size, this->params);
+ this->setInit();
return *this;
}
@@ -2521,8 +2521,8 @@ class VectorAverageDeviation
* @return A reference to this distribution.
*/
VectorAverageDeviation &init(int size) {
- bin.init(size, params);
- setInit();
+ this->bin.init(size, this->params);
+ this->setInit();
return *this;
}
@@ -2873,12 +2873,6 @@ operator/(Temp l, Temp r)
}
inline Temp
-operator%(Temp l, Temp r)
-{
- return NodePtr(new BinaryNode<std::modulus<Result> >(l, r));
-}
-
-inline Temp
operator-(Temp l)
{
return NodePtr(new UnaryNode<std::negate<Result> >(l));
diff --git a/base/stats/events.cc b/base/stats/events.cc
index e5efceabe..d716fa4d3 100644
--- a/base/stats/events.cc
+++ b/base/stats/events.cc
@@ -134,7 +134,7 @@ InsertEvent::insert(const string &stat)
first = false;
size += sprintf(query + size, "(%u,%u,%llu)",
- event, run, curTick);
+ event, run, (unsigned long long)curTick);
}
void
diff --git a/base/stats/text.cc b/base/stats/text.cc
index f7e82a30f..8cc5ff65e 100644
--- a/base/stats/text.cc
+++ b/base/stats/text.cc
@@ -126,7 +126,7 @@ Text::output()
using namespace Database;
ccprintf(*stream, "\n---------- Begin Simulation Statistics ----------\n");
- if (bins().empty()) {
+ if (bins().empty() || bins().size() == 1) {
stat_list_t::const_iterator i, end = stats().end();
for (i = stats().begin(); i != end; ++i)
(*i)->visit(*this);
diff --git a/base/str.cc b/base/str.cc
index dd8d80043..5357ba79f 100644
--- a/base/str.cc
+++ b/base/str.cc
@@ -39,6 +39,36 @@
using namespace std;
+bool
+split_first(const string &s, string &lhs, string &rhs, char c)
+{
+ string::size_type offset = s.find(c);
+ if (offset == string::npos) {
+ lhs = s;
+ rhs = "";
+ return false;
+ }
+
+ lhs = s.substr(0, offset);
+ rhs = s.substr(offset + 1);
+ return true;
+}
+
+bool
+split_last(const string &s, string &lhs, string &rhs, char c)
+{
+ string::size_type offset = s.rfind(c);
+ if (offset == string::npos) {
+ lhs = s;
+ rhs = "";
+ return false;
+ }
+
+ lhs = s.substr(0, offset);
+ rhs = s.substr(offset + 1);
+ return true;
+}
+
void
tokenize(vector<string>& v, const string &s, char token, bool ignore)
{
diff --git a/base/str.hh b/base/str.hh
index 812f4d41a..41433f2bd 100644
--- a/base/str.hh
+++ b/base/str.hh
@@ -90,6 +90,20 @@ to_lower(const std::string &s)
return lower;
}
+// Split the string s into lhs and rhs on the first occurence of the
+// character c.
+bool
+split_first(const std::string &s, std::string &lhs, std::string &rhs, char c);
+
+// Split the string s into lhs and rhs on the last occurence of the
+// character c.
+bool
+split_last(const std::string &s, std::string &lhs, std::string &rhs, char c);
+
+// Tokenize the string <s> splitting on the character <token>, and
+// place the result in the string vector <vector>. If <ign> is true,
+// then empty result strings (due to trailing tokens, or consecutive
+// tokens) are skipped.
void
tokenize(std::vector<std::string> &vector, const std::string &s,
char token, bool ign = true);
diff --git a/base/trace.cc b/base/trace.cc
index bc6c9aa7a..c9d4a0f78 100644
--- a/base/trace.cc
+++ b/base/trace.cc
@@ -71,7 +71,7 @@ Log::init(int _size)
size = _size;
- buffer = new (Record *)[size];
+ buffer = new Record *[size];
for (int i = 0; i < size; ++i) {
buffer[i] = NULL;
@@ -98,6 +98,8 @@ Log::append(Record *rec)
// dump record to output stream if there's one open
if (dprintf_stream != NULL) {
rec->dump(*dprintf_stream);
+ } else {
+ rec->dump(cout);
}
// no buffering: justget rid of it now
diff --git a/base/trace.hh b/base/trace.hh
index 5e05d6e5e..054b14546 100644
--- a/base/trace.hh
+++ b/base/trace.hh
@@ -26,8 +26,8 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef __TRACE_HH__
-#define __TRACE_HH__
+#ifndef __BASE_TRACE_HH__
+#define __BASE_TRACE_HH__
#include <vector>
@@ -228,4 +228,4 @@ do { \
#endif // TRACING_ON
-#endif // __TRACE_HH__
+#endif // __BASE_TRACE_HH__
diff --git a/base/traceflags.py b/base/traceflags.py
index 8f20a9692..800c47bd3 100644
--- a/base/traceflags.py
+++ b/base/traceflags.py
@@ -110,7 +110,7 @@ baseFlags = [
'IICMore',
'MSHR',
'Chains',
- 'Dispatch',
+ 'Pipeline',
'Stats',
'StatEvents',
'Context',
@@ -139,6 +139,7 @@ compoundFlagMap = {
'ScsiAll' : [ 'ScsiDisk', 'ScsiCtrl', 'ScsiNone' ],
'DiskImageAll' : [ 'DiskImage', 'DiskImageRead', 'DiskImageWrite' ],
'EthernetAll' : [ 'Ethernet', 'EthernetPIO', 'EthernetDMA', 'EthernetData' , 'EthernetDesc', 'EthernetIntr', 'EthernetSM', 'EthernetCksum' ],
+ 'EthernetNoData' : [ 'Ethernet', 'EthernetPIO', 'EthernetDesc', 'EthernetIntr', 'EthernetSM', 'EthernetCksum' ],
'IdeAll' : [ 'IdeCtrl', 'IdeDisk' ]
}
diff --git a/configs/boot/devtime.rcS b/configs/boot/devtime.rcS
new file mode 100644
index 000000000..91fddc20d
--- /dev/null
+++ b/configs/boot/devtime.rcS
@@ -0,0 +1,8 @@
+insmod /modules/devtime.ko dataAddr=0x9000004 count=100
+rmmod devtime
+insmod /modules/devtime.ko dataAddr=0x1a0000300 count=100
+rmmod devtime
+insmod /modules/devtime.ko memTest=1 count=100
+rmmod devtime
+m5 exit
+
diff --git a/configs/boot/micro_memlat.rcS b/configs/boot/micro_memlat.rcS
new file mode 100644
index 000000000..50ee8efb3
--- /dev/null
+++ b/configs/boot/micro_memlat.rcS
@@ -0,0 +1,3 @@
+/benchmarks/micros/lmbench/bin/alphaev6-linux-gnu/lat_mem_rd 512 64
+m5 exit
+
diff --git a/configs/boot/micro_memlat2mb.rcS b/configs/boot/micro_memlat2mb.rcS
new file mode 100644
index 000000000..12643c629
--- /dev/null
+++ b/configs/boot/micro_memlat2mb.rcS
@@ -0,0 +1,3 @@
+/benchmarks/micros/lmbench/bin/alphaev6-linux-gnu/lat_mem_rd_2MB 2 64
+m5 exit
+
diff --git a/configs/boot/micro_memlat8mb.rcS b/configs/boot/micro_memlat8mb.rcS
new file mode 100644
index 000000000..1688a6452
--- /dev/null
+++ b/configs/boot/micro_memlat8mb.rcS
@@ -0,0 +1,3 @@
+/benchmarks/micros/lmbench/bin/alphaev6-linux-gnu/lat_mem_rd_8MB 8 64
+m5 exit
+
diff --git a/configs/boot/micro_syscall.rcS b/configs/boot/micro_syscall.rcS
new file mode 100644
index 000000000..f954becc3
--- /dev/null
+++ b/configs/boot/micro_syscall.rcS
@@ -0,0 +1,3 @@
+/benchmarks/micros/lmbench/bin/alphaev6-linux-gnu/lat_syscall read
+m5 exit
+
diff --git a/configs/boot/micro_tlblat.rcS b/configs/boot/micro_tlblat.rcS
new file mode 100644
index 000000000..ab05fd9ff
--- /dev/null
+++ b/configs/boot/micro_tlblat.rcS
@@ -0,0 +1,3 @@
+/benchmarks/micros/lmbench/bin/alphaev6-linux-gnu/lat_mem_rd_2MB 2 8192
+m5 exit
+
diff --git a/configs/boot/nat-netperf-maerts-client.rcS b/configs/boot/nat-netperf-maerts-client.rcS
index fa3e174e7..ab66b7d4a 100644
--- a/configs/boot/nat-netperf-maerts-client.rcS
+++ b/configs/boot/nat-netperf-maerts-client.rcS
@@ -11,6 +11,7 @@ route add default gw 10.0.0.1
echo "0" > /proc/sys/net/ipv4/tcp_timestamps
echo "0" > /proc/sys/net/ipv4/tcp_sack
+echo "1" > /proc/sys/net/ipv4/tcp_vegas_cong_avoid
echo "5000000 5000000 5000000" > /proc/sys/net/ipv4/tcp_rmem
echo "5000000 5000000 5000000" > /proc/sys/net/ipv4/tcp_wmem
echo "5000000 5000000 5000000" > /proc/sys/net/ipv4/tcp_mem
@@ -21,7 +22,7 @@ echo "262143" > /proc/sys/net/core/wmem_default
echo "262143" > /proc/sys/net/core/optmem_max
echo "100000" > /proc/sys/net/core/netdev_max_backlog
-echo -n "waiting for server..."
+echo -n "waiting for natbox..."
/usr/bin/netcat -c -l -p 8000
BINARY=/benchmarks/netperf/netperf
diff --git a/configs/boot/nat-netperf-server.rcS b/configs/boot/nat-netperf-server.rcS
index c0646b61c..69717b7ce 100644
--- a/configs/boot/nat-netperf-server.rcS
+++ b/configs/boot/nat-netperf-server.rcS
@@ -9,6 +9,7 @@ ifconfig eth0 $SERVER txqueuelen 1000
echo "0" > /proc/sys/net/ipv4/tcp_timestamps
echo "0" > /proc/sys/net/ipv4/tcp_sack
+echo "1" > /proc/sys/net/ipv4/tcp_vegas_cong_avoid
echo "5000000 5000000 5000000" > /proc/sys/net/ipv4/tcp_rmem
echo "5000000 5000000 5000000" > /proc/sys/net/ipv4/tcp_wmem
echo "5000000 5000000 5000000" > /proc/sys/net/ipv4/tcp_mem
@@ -22,7 +23,8 @@ echo "100000" > /proc/sys/net/core/netdev_max_backlog
echo "running netserver..."
/benchmarks/netperf/netserver
-echo -n "signal client to begin..."
+echo -n "signal natbox to begin..."
+sleep 1
echo "server ready" | /usr/bin/netcat -c $NATBOX 8000
echo "done."
diff --git a/configs/boot/nat-netperf-stream-client.rcS b/configs/boot/nat-netperf-stream-client.rcS
index f0f3a23ce..d0213c265 100644
--- a/configs/boot/nat-netperf-stream-client.rcS
+++ b/configs/boot/nat-netperf-stream-client.rcS
@@ -8,6 +8,7 @@ ifconfig eth0 $CLIENT txqueuelen 1000
echo "0" > /proc/sys/net/ipv4/tcp_timestamps
echo "0" > /proc/sys/net/ipv4/tcp_sack
+echo "1" > /proc/sys/net/ipv4/tcp_vegas_cong_avoid
echo "5000000 5000000 5000000" > /proc/sys/net/ipv4/tcp_rmem
echo "5000000 5000000 5000000" > /proc/sys/net/ipv4/tcp_wmem
echo "5000000 5000000 5000000" > /proc/sys/net/ipv4/tcp_mem
diff --git a/configs/boot/nat-spec-surge-client.rcS b/configs/boot/nat-spec-surge-client.rcS
index 2c0b46607..a3bc512db 100644
--- a/configs/boot/nat-spec-surge-client.rcS
+++ b/configs/boot/nat-spec-surge-client.rcS
@@ -20,6 +20,7 @@ echo "0" > /proc/sys/net/ipv4/tcp_timestamps
echo "0" > /proc/sys/net/ipv4/tcp_sack
echo "15" > /proc/sys/net/ipv4/tcp_fin_timeout
echo "16384" > /proc/sys/net/ipv4/tcp_max_syn_backlog
+echo "1" > /proc/sys/net/ipv4/tcp_vegas_cong_avoid
echo "1024 65535" > /proc/sys/net/ipv4/ip_local_port_range
echo "10000000 10000000 10000000" > /proc/sys/net/ipv4/tcp_rmem
diff --git a/configs/boot/nat-spec-surge-server.rcS b/configs/boot/nat-spec-surge-server.rcS
index ed0e96a44..9b5674e63 100755
--- a/configs/boot/nat-spec-surge-server.rcS
+++ b/configs/boot/nat-spec-surge-server.rcS
@@ -23,6 +23,7 @@ echo "0" > /proc/sys/net/ipv4/tcp_timestamps
echo "0" > /proc/sys/net/ipv4/tcp_sack
echo "15" > /proc/sys/net/ipv4/tcp_fin_timeout
echo "16384" > /proc/sys/net/ipv4/tcp_max_syn_backlog
+echo "1" > /proc/sys/net/ipv4/tcp_vegas_cong_avoid
echo "1024 65535" > /proc/sys/net/ipv4/ip_local_port_range
echo "10000000 10000000 10000000" > /proc/sys/net/ipv4/tcp_rmem
diff --git a/configs/boot/natbox-netperf.rcS b/configs/boot/natbox-netperf.rcS
index d665670fe..5ec08c1a2 100644
--- a/configs/boot/natbox-netperf.rcS
+++ b/configs/boot/natbox-netperf.rcS
@@ -10,6 +10,8 @@ ifconfig eth1 $INTIF txqueuelen 1000
echo "0" > /proc/sys/net/ipv4/tcp_timestamps
echo "0" > /proc/sys/net/ipv4/tcp_sack
+echo "1" > /proc/sys/net/ipv4/tcp_vegas_cong_avoid
+
echo "5000000 5000000 5000000" > /proc/sys/net/ipv4/tcp_rmem
echo "5000000 5000000 5000000" > /proc/sys/net/ipv4/tcp_wmem
echo "5000000 5000000 5000000" > /proc/sys/net/ipv4/tcp_mem
diff --git a/configs/boot/natbox-spec-surge.rcS b/configs/boot/natbox-spec-surge.rcS
index ed74b71bd..d612424d2 100644
--- a/configs/boot/natbox-spec-surge.rcS
+++ b/configs/boot/natbox-spec-surge.rcS
@@ -10,6 +10,7 @@ ifconfig eth1 $INTIF txqueuelen 1000
echo "0" > /proc/sys/net/ipv4/tcp_timestamps
echo "0" > /proc/sys/net/ipv4/tcp_sack
+echo "1" > /proc/sys/net/ipv4/tcp_vegas_cong_avoid
echo "5000000 5000000 5000000" > /proc/sys/net/ipv4/tcp_rmem
echo "5000000 5000000 5000000" > /proc/sys/net/ipv4/tcp_wmem
echo "5000000 5000000 5000000" > /proc/sys/net/ipv4/tcp_mem
diff --git a/configs/boot/netperf-server.rcS b/configs/boot/netperf-server.rcS
index f77ff0ce8..c75d918a2 100644
--- a/configs/boot/netperf-server.rcS
+++ b/configs/boot/netperf-server.rcS
@@ -22,6 +22,7 @@ echo "running netserver..."
/benchmarks/netperf/netserver
echo -n "signal client to begin..."
+sleep 1
echo "server ready" | /usr/bin/netcat -c $CLIENT 8000
echo "done."
diff --git a/configs/boot/nfs-client.rcS b/configs/boot/nfs-client.rcS
index a999fb72c..84d15439f 100755
--- a/configs/boot/nfs-client.rcS
+++ b/configs/boot/nfs-client.rcS
@@ -45,6 +45,6 @@ mkdir /nfs
mount 10.0.0.1:/nfs /nfs
echo "done."
-/bin/bonnie++ -u 99 -s 700 -r 0 -n 0 -f -F -d /nfs
+/bin/bonnie++ -u 99 -s 500 -r 0 -n 0 -f -F -d /nfs
/sbin/m5 exit
diff --git a/configs/boot/nfs-server.rcS b/configs/boot/nfs-server.rcS
index 21b7ab83c..0cb489a9d 100755
--- a/configs/boot/nfs-server.rcS
+++ b/configs/boot/nfs-server.rcS
@@ -38,7 +38,7 @@ echo "done."
# mknod /dev/sda1 b 8 1
#fi
-/sbin/insmod /modules/scsi_debug.ko dev_size_mb=768
+/sbin/insmod /modules/scsi_debug.ko dev_size_mb=512
echo -n "creating partition and formatting..."
#echo "1,767,L" > /tmp/sfdisk.run
diff --git a/cpu/base_cpu.cc b/cpu/base_cpu.cc
index 7605ff3c3..181b484e7 100644
--- a/cpu/base_cpu.cc
+++ b/cpu/base_cpu.cc
@@ -26,15 +26,17 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+#include <iostream>
#include <string>
#include <sstream>
-#include <iostream>
#include "base/cprintf.hh"
#include "base/loader/symtab.hh"
#include "base/misc.hh"
+#include "base/output.hh"
#include "cpu/base_cpu.hh"
#include "cpu/exec_context.hh"
+#include "cpu/sampling_cpu/sampling_cpu.hh"
#include "sim/param.hh"
#include "sim/sim_events.hh"
@@ -48,25 +50,12 @@ vector<BaseCPU *> BaseCPU::cpuList;
int maxThreadsPerCPU = 1;
#ifdef FULL_SYSTEM
-BaseCPU::BaseCPU(const string &_name, int _number_of_threads, bool _def_reg,
- Counter max_insts_any_thread,
- Counter max_insts_all_threads,
- Counter max_loads_any_thread,
- Counter max_loads_all_threads,
- System *_system, Tick freq,
- bool _function_trace, Tick _function_trace_start)
- : SimObject(_name), frequency(freq), checkInterrupts(true),
- deferRegistration(_def_reg), number_of_threads(_number_of_threads),
- system(_system)
+BaseCPU::BaseCPU(Params *p)
+ : SimObject(p->name), frequency(p->freq), checkInterrupts(true),
+ params(p), number_of_threads(p->numberOfThreads), system(p->system)
#else
-BaseCPU::BaseCPU(const string &_name, int _number_of_threads, bool _def_reg,
- Counter max_insts_any_thread,
- Counter max_insts_all_threads,
- Counter max_loads_any_thread,
- Counter max_loads_all_threads,
- bool _function_trace, Tick _function_trace_start)
- : SimObject(_name), deferRegistration(_def_reg),
- number_of_threads(_number_of_threads)
+BaseCPU::BaseCPU(Params *p)
+ : SimObject(p->name), params(p), number_of_threads(p->numberOfThreads)
#endif
{
// add self to global list of CPUs
@@ -76,19 +65,19 @@ BaseCPU::BaseCPU(const string &_name, int _number_of_threads, bool _def_reg,
maxThreadsPerCPU = number_of_threads;
// allocate per-thread instruction-based event queues
- comInstEventQueue = new (EventQueue *)[number_of_threads];
+ comInstEventQueue = new EventQueue *[number_of_threads];
for (int i = 0; i < number_of_threads; ++i)
comInstEventQueue[i] = new EventQueue("instruction-based event queue");
//
// set up instruction-count-based termination events, if any
//
- if (max_insts_any_thread != 0)
+ if (p->max_insts_any_thread != 0)
for (int i = 0; i < number_of_threads; ++i)
- new SimExitEvent(comInstEventQueue[i], max_insts_any_thread,
+ new SimExitEvent(comInstEventQueue[i], p->max_insts_any_thread,
"a thread reached the max instruction count");
- if (max_insts_all_threads != 0) {
+ if (p->max_insts_all_threads != 0) {
// allocate & initialize shared downcounter: each event will
// decrement this when triggered; simulation will terminate
// when counter reaches 0
@@ -97,23 +86,23 @@ BaseCPU::BaseCPU(const string &_name, int _number_of_threads, bool _def_reg,
for (int i = 0; i < number_of_threads; ++i)
new CountedExitEvent(comInstEventQueue[i],
"all threads reached the max instruction count",
- max_insts_all_threads, *counter);
+ p->max_insts_all_threads, *counter);
}
// allocate per-thread load-based event queues
- comLoadEventQueue = new (EventQueue *)[number_of_threads];
+ comLoadEventQueue = new EventQueue *[number_of_threads];
for (int i = 0; i < number_of_threads; ++i)
comLoadEventQueue[i] = new EventQueue("load-based event queue");
//
// set up instruction-count-based termination events, if any
//
- if (max_loads_any_thread != 0)
+ if (p->max_loads_any_thread != 0)
for (int i = 0; i < number_of_threads; ++i)
- new SimExitEvent(comLoadEventQueue[i], max_loads_any_thread,
+ new SimExitEvent(comLoadEventQueue[i], p->max_loads_any_thread,
"a thread reached the max load count");
- if (max_loads_all_threads != 0) {
+ if (p->max_loads_all_threads != 0) {
// allocate & initialize shared downcounter: each event will
// decrement this when triggered; simulation will terminate
// when counter reaches 0
@@ -122,7 +111,7 @@ BaseCPU::BaseCPU(const string &_name, int _number_of_threads, bool _def_reg,
for (int i = 0; i < number_of_threads; ++i)
new CountedExitEvent(comLoadEventQueue[i],
"all threads reached the max load count",
- max_loads_all_threads, *counter);
+ p->max_loads_all_threads, *counter);
}
#ifdef FULL_SYSTEM
@@ -131,19 +120,18 @@ BaseCPU::BaseCPU(const string &_name, int _number_of_threads, bool _def_reg,
#endif
functionTracingEnabled = false;
- if (_function_trace) {
- std::string filename = csprintf("ftrace.%s", name());
- functionTraceStream = makeOutputStream(filename);
+ if (p->functionTrace) {
+ functionTraceStream = simout.find(csprintf("ftrace.%s", name()));
currentFunctionStart = currentFunctionEnd = 0;
- functionEntryTick = _function_trace_start;
+ functionEntryTick = p->functionTraceStart;
- if (_function_trace_start == 0) {
+ if (p->functionTraceStart == 0) {
functionTracingEnabled = true;
} else {
Event *e =
new EventWrapper<BaseCPU, &BaseCPU::enableFunctionTrace>(this,
true);
- e->schedule(_function_trace_start);
+ e->schedule(p->functionTraceStart);
}
}
}
@@ -157,15 +145,12 @@ BaseCPU::enableFunctionTrace()
BaseCPU::~BaseCPU()
{
- if (functionTracingEnabled)
- closeOutputStream(functionTraceStream);
}
-
void
BaseCPU::init()
{
- if (!deferRegistration)
+ if (!params->deferRegistration)
registerExecContexts();
}
@@ -210,9 +195,10 @@ BaseCPU::registerExecContexts()
void
-BaseCPU::switchOut()
+BaseCPU::switchOut(SamplingCPU *sampler)
{
- // default: do nothing
+ // default: do nothing, signal done
+ sampler->signalSwitched();
}
void
diff --git a/cpu/base_cpu.hh b/cpu/base_cpu.hh
index baa956aa8..f346f4ec5 100644
--- a/cpu/base_cpu.hh
+++ b/cpu/base_cpu.hh
@@ -32,6 +32,7 @@
#include <vector>
#include "base/statistics.hh"
+#include "cpu/sampling_cpu/sampling_cpu.hh"
#include "sim/eventq.hh"
#include "sim/sim_object.hh"
#include "targetarch/isa_traits.hh"
@@ -90,33 +91,36 @@ class BaseCPU : public SimObject
virtual void haltContext(int thread_num) {}
public:
-
+ struct Params
+ {
+ std::string name;
+ int numberOfThreads;
+ bool deferRegistration;
+ Counter max_insts_any_thread;
+ Counter max_insts_all_threads;
+ Counter max_loads_any_thread;
+ Counter max_loads_all_threads;
+ Tick freq;
+ bool functionTrace;
+ Tick functionTraceStart;
#ifdef FULL_SYSTEM
- BaseCPU(const std::string &_name, int _number_of_threads, bool _def_reg,
- Counter max_insts_any_thread, Counter max_insts_all_threads,
- Counter max_loads_any_thread, Counter max_loads_all_threads,
- System *_system, Tick freq,
- bool _function_trace = false, Tick _function_trace_start = 0);
-#else
- BaseCPU(const std::string &_name, int _number_of_threads, bool _def_reg,
- Counter max_insts_any_thread = 0,
- Counter max_insts_all_threads = 0,
- Counter max_loads_any_thread = 0,
- Counter max_loads_all_threads = 0,
- bool _function_trace = false, Tick _function_trace_start = 0);
+ System *system;
#endif
+ };
+
+ const Params *params;
+ BaseCPU(Params *params);
virtual ~BaseCPU();
virtual void init();
virtual void regStats();
- bool deferRegistration;
void registerExecContexts();
- /// Prepare for another CPU to take over execution. Called by
- /// takeOverFrom() on its argument.
- virtual void switchOut();
+ /// Prepare for another CPU to take over execution. When it is
+ /// is ready (drained pipe) it signals the sampler.
+ virtual void switchOut(SamplingCPU *);
/// Take over execution from the given CPU. Used for warm-up and
/// sampling.
diff --git a/cpu/exec_context.hh b/cpu/exec_context.hh
index 8437a5585..d6140d52f 100644
--- a/cpu/exec_context.hh
+++ b/cpu/exec_context.hh
@@ -435,20 +435,20 @@ class ExecContext
regs.intRegFile[ArgumentReg0 + i] = val;
}
- void setSyscallReturn(int64_t return_value)
+ void setSyscallReturn(SyscallReturn return_value)
{
// check for error condition. Alpha syscall convention is to
// indicate success/failure in reg a3 (r19) and put the
// return value itself in the standard return value reg (v0).
const int RegA3 = 19; // only place this is used
- if (return_value >= 0) {
+ if (return_value.successful()) {
// no error
regs.intRegFile[RegA3] = 0;
- regs.intRegFile[ReturnValueReg] = return_value;
+ regs.intRegFile[ReturnValueReg] = return_value.value();
} else {
// got an error, return details
regs.intRegFile[RegA3] = (IntReg) -1;
- regs.intRegFile[ReturnValueReg] = -return_value;
+ regs.intRegFile[ReturnValueReg] = -return_value.value();
}
}
diff --git a/cpu/exetrace.cc b/cpu/exetrace.cc
index ff7e90c9e..048a7d283 100644
--- a/cpu/exetrace.cc
+++ b/cpu/exetrace.cc
@@ -154,7 +154,7 @@ class ExecutionTraceParamContext : public ParamContext
ExecutionTraceParamContext exeTraceParams("exetrace");
Param<bool> exe_trace_spec(&exeTraceParams, "speculative",
- "capture speculative instructions", false);
+ "capture speculative instructions", true);
Param<bool> exe_trace_print_cycle(&exeTraceParams, "print_cycle",
"print cycle number", true);
diff --git a/cpu/full_cpu/op_class.hh b/cpu/full_cpu/op_class.hh
index a14ccfaed..8e85e8d8a 100644
--- a/cpu/full_cpu/op_class.hh
+++ b/cpu/full_cpu/op_class.hh
@@ -51,6 +51,7 @@ enum OpClass {
FloatSqrtOp, /* floating point square root */
MemReadOp, /* memory read port */
MemWriteOp, /* memory write port */
+ IprAccessOp, /* Internal Processor Register read/write port */
InstPrefetchOp, /* instruction prefetch port (on I-cache) */
Num_OpClasses /* total functional unit classes */
};
diff --git a/cpu/memtest/memtest.cc b/cpu/memtest/memtest.cc
index e967c79da..14b119880 100644
--- a/cpu/memtest/memtest.cc
+++ b/cpu/memtest/memtest.cc
@@ -36,6 +36,7 @@
#include "base/misc.hh"
#include "base/statistics.hh"
+#include "cpu/exec_context.hh"
#include "cpu/memtest/memtest.hh"
#include "mem/cache/base_cache.hh"
#include "mem/functional_mem/main_memory.hh"
@@ -59,10 +60,8 @@ MemTest::MemTest(const string &name,
unsigned _percentSourceUnaligned,
unsigned _percentDestUnaligned,
Addr _traceAddr,
- Counter max_loads_any_thread,
- Counter max_loads_all_threads)
- : BaseCPU(name, 1, true, 0, 0, max_loads_any_thread,
- max_loads_all_threads),
+ Counter _max_loads)
+ : SimObject(name),
tickEvent(this),
cacheInterface(_cache_interface),
mainMem(main_mem),
@@ -74,12 +73,13 @@ MemTest::MemTest(const string &name,
progressInterval(_progressInterval),
nextProgressMessage(_progressInterval),
percentSourceUnaligned(_percentSourceUnaligned),
- percentDestUnaligned(percentDestUnaligned)
+ percentDestUnaligned(percentDestUnaligned),
+ maxLoads(_max_loads)
{
vector<string> cmd;
cmd.push_back("/bin/ls");
vector<string> null_vec;
- xc = new ExecContext(this ,0,mainMem,0);
+ xc = new ExecContext(NULL, 0, mainMem, 0);
blockSize = cacheInterface->getBlockSize();
blockAddrMask = blockSize - 1;
@@ -160,7 +160,8 @@ MemTest::completeRequest(MemReqPtr &req, uint8_t *data)
nextProgressMessage += progressInterval;
}
- comLoadEventQueue[0]->serviceEvents(numReads);
+ if (numReads >= maxLoads)
+ SimExit(curTick, "Maximum number of loads reached!");
break;
case Write:
@@ -402,8 +403,7 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(MemTest)
Param<unsigned> percent_source_unaligned;
Param<unsigned> percent_dest_unaligned;
Param<Addr> trace_addr;
- Param<Counter> max_loads_any_thread;
- Param<Counter> max_loads_all_threads;
+ Param<Counter> max_loads;
END_DECLARE_SIM_OBJECT_PARAMS(MemTest)
@@ -413,23 +413,17 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(MemTest)
INIT_PARAM(cache, "L1 cache"),
INIT_PARAM(main_mem, "hierarchical memory"),
INIT_PARAM(check_mem, "check memory"),
- INIT_PARAM_DFLT(memory_size, "memory size", 65536),
- INIT_PARAM_DFLT(percent_reads, "target read percentage", 65),
- INIT_PARAM_DFLT(percent_copies, "target copy percentage", 0),
- INIT_PARAM_DFLT(percent_uncacheable, "target uncacheable percentage", 10),
- INIT_PARAM_DFLT(progress_interval,
- "progress report interval (in accesses)", 1000000),
- INIT_PARAM_DFLT(percent_source_unaligned, "percent of copy source address "
- "that are unaligned", 50),
- INIT_PARAM_DFLT(percent_dest_unaligned, "percent of copy dest address "
- "that are unaligned", 50),
- INIT_PARAM_DFLT(trace_addr, "address to trace", 0),
- INIT_PARAM_DFLT(max_loads_any_thread,
- "terminate when any thread reaches this load count",
- 0),
- INIT_PARAM_DFLT(max_loads_all_threads,
- "terminate when all threads have reached this load count",
- 0)
+ INIT_PARAM(memory_size, "memory size"),
+ INIT_PARAM(percent_reads, "target read percentage"),
+ INIT_PARAM(percent_copies, "target copy percentage"),
+ INIT_PARAM(percent_uncacheable, "target uncacheable percentage"),
+ INIT_PARAM(progress_interval, "progress report interval (in accesses)"),
+ INIT_PARAM(percent_source_unaligned,
+ "percent of copy source address that are unaligned"),
+ INIT_PARAM(percent_dest_unaligned,
+ "percent of copy dest address that are unaligned"),
+ INIT_PARAM(trace_addr, "address to trace"),
+ INIT_PARAM(max_loads, "terminate when we have reached this load count")
END_INIT_SIM_OBJECT_PARAMS(MemTest)
@@ -440,8 +434,7 @@ CREATE_SIM_OBJECT(MemTest)
check_mem, memory_size, percent_reads, percent_copies,
percent_uncacheable, progress_interval,
percent_source_unaligned, percent_dest_unaligned,
- trace_addr, max_loads_any_thread,
- max_loads_all_threads);
+ trace_addr, max_loads);
}
REGISTER_SIM_OBJECT("MemTest", MemTest)
diff --git a/cpu/memtest/memtest.hh b/cpu/memtest/memtest.hh
index 43b17a713..45b2d24e8 100644
--- a/cpu/memtest/memtest.hh
+++ b/cpu/memtest/memtest.hh
@@ -26,20 +26,21 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef __MEMTEST_HH__
-#define __MEMTEST_HH__
+#ifndef __CPU_MEMTEST_MEMTEST_HH__
+#define __CPU_MEMTEST_MEMTEST_HH__
#include <set>
#include "base/statistics.hh"
-#include "cpu/base_cpu.hh"
-#include "cpu/exec_context.hh"
#include "mem/functional_mem/functional_memory.hh"
#include "mem/mem_interface.hh"
+#include "sim/eventq.hh"
+#include "sim/sim_exit.hh"
#include "sim/sim_object.hh"
#include "sim/stats.hh"
-class MemTest : public BaseCPU
+class ExecContext;
+class MemTest : public SimObject
{
public:
@@ -55,8 +56,7 @@ class MemTest : public BaseCPU
unsigned _percentSourceUnaligned,
unsigned _percentDestUnaligned,
Addr _traceAddr,
- Counter max_loads_any_thread,
- Counter max_loads_all_threads);
+ Counter _max_loads);
// register statistics
virtual void regStats();
@@ -116,6 +116,7 @@ class MemTest : public BaseCPU
Tick noResponseCycles;
uint64_t numReads;
+ uint64_t maxLoads;
Stats::Scalar<> numReadsStat;
Stats::Scalar<> numWritesStat;
Stats::Scalar<> numCopiesStat;
@@ -146,7 +147,7 @@ class MemCompleteEvent : public Event
virtual const char *description();
};
-#endif // __MEMTEST_HH__
+#endif // __CPU_MEMTEST_MEMTEST_HH__
diff --git a/cpu/pc_event.cc b/cpu/pc_event.cc
index 8f046a7a4..21eef677a 100644
--- a/cpu/pc_event.cc
+++ b/cpu/pc_event.cc
@@ -31,10 +31,11 @@
#include <string>
#include <utility>
-#include "sim/debug.hh"
+#include "base/trace.hh"
+#include "cpu/base_cpu.hh"
#include "cpu/exec_context.hh"
#include "cpu/pc_event.hh"
-#include "base/trace.hh"
+#include "sim/debug.hh"
#include "sim/universe.hh"
using namespace std;
@@ -123,6 +124,8 @@ BreakPCEvent::BreakPCEvent(PCEventQueue *q, const std::string &desc, bool del)
void
BreakPCEvent::process(ExecContext *xc)
{
+ StringWrap name(xc->cpu->name() + ".break_event");
+ DPRINTFN("break event %s triggered", descr());
debug_break();
if (remove)
delete this;
diff --git a/cpu/simple_cpu/simple_cpu.cc b/cpu/simple_cpu/simple_cpu.cc
index d48f93663..86aeab7d7 100644
--- a/cpu/simple_cpu/simple_cpu.cc
+++ b/cpu/simple_cpu/simple_cpu.cc
@@ -47,6 +47,7 @@
#include "cpu/exec_context.hh"
#include "cpu/exetrace.hh"
#include "cpu/full_cpu/smt.hh"
+#include "cpu/sampling_cpu/sampling_cpu.hh"
#include "cpu/simple_cpu/simple_cpu.hh"
#include "cpu/static_inst.hh"
#include "mem/base_mem.hh"
@@ -74,15 +75,16 @@
using namespace std;
-SimpleCPU::TickEvent::TickEvent(SimpleCPU *c)
- : Event(&mainEventQueue, CPU_Tick_Pri), cpu(c), multiplier(1)
+
+SimpleCPU::TickEvent::TickEvent(SimpleCPU *c, int w)
+ : Event(&mainEventQueue, CPU_Tick_Pri), cpu(c), width(w)
{
}
void
SimpleCPU::TickEvent::process()
{
- int count = multiplier;
+ int count = width;
do {
cpu->tick();
} while (--count > 0 && cpu->status() == Running);
@@ -96,8 +98,7 @@ SimpleCPU::TickEvent::description()
SimpleCPU::CacheCompletionEvent::CacheCompletionEvent(SimpleCPU *_cpu)
- : Event(&mainEventQueue),
- cpu(_cpu)
+ : Event(&mainEventQueue), cpu(_cpu)
{
}
@@ -112,52 +113,22 @@ SimpleCPU::CacheCompletionEvent::description()
return "SimpleCPU cache completion event";
}
-#ifdef FULL_SYSTEM
-SimpleCPU::SimpleCPU(const string &_name,
- System *_system,
- Counter max_insts_any_thread,
- Counter max_insts_all_threads,
- Counter max_loads_any_thread,
- Counter max_loads_all_threads,
- AlphaITB *itb, AlphaDTB *dtb,
- FunctionalMemory *mem,
- MemInterface *icache_interface,
- MemInterface *dcache_interface,
- bool _def_reg, Tick freq,
- bool _function_trace, Tick _function_trace_start)
- : BaseCPU(_name, /* number_of_threads */ 1, _def_reg,
- max_insts_any_thread, max_insts_all_threads,
- max_loads_any_thread, max_loads_all_threads,
- _system, freq, _function_trace, _function_trace_start),
-#else
-SimpleCPU::SimpleCPU(const string &_name, Process *_process,
- Counter max_insts_any_thread,
- Counter max_insts_all_threads,
- Counter max_loads_any_thread,
- Counter max_loads_all_threads,
- MemInterface *icache_interface,
- MemInterface *dcache_interface,
- bool _def_reg,
- bool _function_trace, Tick _function_trace_start)
- : BaseCPU(_name, /* number_of_threads */ 1, _def_reg,
- max_insts_any_thread, max_insts_all_threads,
- max_loads_any_thread, max_loads_all_threads,
- _function_trace, _function_trace_start),
-#endif
- tickEvent(this), xc(NULL), cacheCompletionEvent(this)
+SimpleCPU::SimpleCPU(Params *p)
+ : BaseCPU(p), tickEvent(this, p->width), xc(NULL),
+ cacheCompletionEvent(this)
{
_status = Idle;
#ifdef FULL_SYSTEM
- xc = new ExecContext(this, 0, system, itb, dtb, mem);
+ xc = new ExecContext(this, 0, p->system, p->itb, p->dtb, p->mem);
// initialize CPU, including PC
TheISA::initCPU(&xc->regs);
#else
- xc = new ExecContext(this, /* thread_num */ 0, _process, /* asid */ 0);
+ xc = new ExecContext(this, /* thread_num */ 0, p->process, /* asid */ 0);
#endif // !FULL_SYSTEM
- icacheInterface = icache_interface;
- dcacheInterface = dcache_interface;
+ icacheInterface = p->icache_interface;
+ dcacheInterface = p->dcache_interface;
memReq = new MemReq();
memReq->xc = xc;
@@ -179,11 +150,21 @@ SimpleCPU::~SimpleCPU()
}
void
-SimpleCPU::switchOut()
+SimpleCPU::switchOut(SamplingCPU *s)
{
- _status = SwitchedOut;
- if (tickEvent.scheduled())
- tickEvent.squash();
+ sampler = s;
+ if (status() == DcacheMissStall) {
+ DPRINTF(Sampler,"Outstanding dcache access, waiting for completion\n");
+ _status = DcacheMissSwitch;
+ }
+ else {
+ _status = SwitchedOut;
+
+ if (tickEvent.scheduled())
+ tickEvent.squash();
+
+ sampler->signalSwitched();
+ }
}
@@ -203,8 +184,6 @@ SimpleCPU::takeOverFrom(BaseCPU *oldCPU)
tickEvent.schedule(curTick);
}
}
-
- oldCPU->switchOut();
}
@@ -414,21 +393,22 @@ template <class T>
Fault
SimpleCPU::read(Addr addr, T &data, unsigned flags)
{
+ if (status() == DcacheMissStall) {
+ Fault fault = xc->read(memReq,data);
+
+ if (traceData) {
+ traceData->setAddr(addr);
+ if (fault == No_Fault)
+ traceData->setData(data);
+ }
+ return fault;
+ }
+
memReq->reset(addr, sizeof(T), flags);
// translate to physical address
Fault fault = xc->translateDataReadReq(memReq);
- // do functional access
- if (fault == No_Fault)
- fault = xc->read(memReq, data);
-
- if (traceData) {
- traceData->setAddr(addr);
- if (fault == No_Fault)
- traceData->setData(data);
- }
-
// if we have a cache, do cache access too
if (fault == No_Fault && dcacheInterface) {
memReq->cmd = Read;
@@ -444,6 +424,24 @@ SimpleCPU::read(Addr addr, T &data, unsigned flags)
lastDcacheStall = curTick;
unscheduleTickEvent();
_status = DcacheMissStall;
+ } else {
+ // do functional access
+ fault = xc->read(memReq, data);
+
+ if (traceData) {
+ traceData->setAddr(addr);
+ if (fault == No_Fault)
+ traceData->setData(data);
+ }
+ }
+ } else if(fault == No_Fault) {
+ // do functional access
+ fault = xc->read(memReq, data);
+
+ if (traceData) {
+ traceData->setAddr(addr);
+ if (fault == No_Fault)
+ traceData->setData(data);
}
}
@@ -605,10 +603,19 @@ SimpleCPU::processCacheCompletion()
scheduleTickEvent(1);
break;
case DcacheMissStall:
+ if (memReq->cmd.isRead()) {
+ curStaticInst->execute(this,traceData);
+ }
dcacheStallCycles += curTick - lastDcacheStall;
_status = Running;
scheduleTickEvent(1);
break;
+ case DcacheMissSwitch:
+ if (memReq->cmd.isRead()) {
+ curStaticInst->execute(this,traceData);
+ }
+ _status = SwitchedOut;
+ sampler->signalSwitched();
case SwitchedOut:
// If this CPU has been switched out due to sampling/warm-up,
// ignore any further status changes (e.g., due to cache
@@ -750,10 +757,10 @@ SimpleCPU::tick()
comInstEventQueue[0]->serviceEvents(numInst);
// decode the instruction
- inst = htoa(inst);
- StaticInstPtr<TheISA> si(inst);
+ inst = htoa(inst);
+ curStaticInst = StaticInst<TheISA>::decode(inst);
- traceData = Trace::getInstRecord(curTick, xc, this, si,
+ traceData = Trace::getInstRecord(curTick, xc, this, curStaticInst,
xc->regs.pc);
#ifdef FULL_SYSTEM
@@ -762,18 +769,18 @@ SimpleCPU::tick()
xc->func_exe_inst++;
- fault = si->execute(this, traceData);
+ fault = curStaticInst->execute(this, traceData);
#ifdef FULL_SYSTEM
if (xc->fnbin)
- xc->execute(si.get());
+ xc->execute(curStaticInst.get());
#endif
- if (si->isMemRef()) {
+ if (curStaticInst->isMemRef()) {
numMemRefs++;
}
- if (si->isLoad()) {
+ if (curStaticInst->isLoad()) {
++numLoad;
comLoadEventQueue[0]->serviceEvents(numLoad);
}
@@ -840,7 +847,7 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(SimpleCPU)
SimObjectParam<BaseMem *> dcache;
Param<bool> defer_registration;
- Param<int> multiplier;
+ Param<int> width;
Param<bool> function_trace;
Param<Tick> function_trace_start;
@@ -848,71 +855,67 @@ END_DECLARE_SIM_OBJECT_PARAMS(SimpleCPU)
BEGIN_INIT_SIM_OBJECT_PARAMS(SimpleCPU)
- INIT_PARAM_DFLT(max_insts_any_thread,
- "terminate when any thread reaches this inst count",
- 0),
- INIT_PARAM_DFLT(max_insts_all_threads,
- "terminate when all threads have reached this inst count",
- 0),
- INIT_PARAM_DFLT(max_loads_any_thread,
- "terminate when any thread reaches this load count",
- 0),
- INIT_PARAM_DFLT(max_loads_all_threads,
- "terminate when all threads have reached this load count",
- 0),
+ INIT_PARAM(max_insts_any_thread,
+ "terminate when any thread reaches this inst count"),
+ INIT_PARAM(max_insts_all_threads,
+ "terminate when all threads have reached this inst count"),
+ INIT_PARAM(max_loads_any_thread,
+ "terminate when any thread reaches this load count"),
+ INIT_PARAM(max_loads_all_threads,
+ "terminate when all threads have reached this load count"),
#ifdef FULL_SYSTEM
INIT_PARAM(itb, "Instruction TLB"),
INIT_PARAM(dtb, "Data TLB"),
INIT_PARAM(mem, "memory"),
INIT_PARAM(system, "system object"),
- INIT_PARAM_DFLT(mult, "system clock multiplier", 1),
+ INIT_PARAM(mult, "system clock multiplier"),
#else
INIT_PARAM(workload, "processes to run"),
#endif // FULL_SYSTEM
- INIT_PARAM_DFLT(icache, "L1 instruction cache object", NULL),
- INIT_PARAM_DFLT(dcache, "L1 data cache object", NULL),
- INIT_PARAM_DFLT(defer_registration, "defer registration with system "
- "(for sampling)", false),
-
- INIT_PARAM_DFLT(multiplier, "clock multiplier", 1),
- INIT_PARAM_DFLT(function_trace, "Enable function trace", false),
- INIT_PARAM_DFLT(function_trace_start, "Cycle to start function trace", 0)
+ INIT_PARAM(icache, "L1 instruction cache object"),
+ INIT_PARAM(dcache, "L1 data cache object"),
+ INIT_PARAM(defer_registration, "defer system registration (for sampling)"),
+ INIT_PARAM(width, "cpu width"),
+ INIT_PARAM(function_trace, "Enable function trace"),
+ INIT_PARAM(function_trace_start, "Cycle to start function trace")
END_INIT_SIM_OBJECT_PARAMS(SimpleCPU)
CREATE_SIM_OBJECT(SimpleCPU)
{
- SimpleCPU *cpu;
#ifdef FULL_SYSTEM
if (mult != 1)
panic("processor clock multiplier must be 1\n");
+#endif
- cpu = new SimpleCPU(getInstanceName(), system,
- max_insts_any_thread, max_insts_all_threads,
- max_loads_any_thread, max_loads_all_threads,
- itb, dtb, mem,
- (icache) ? icache->getInterface() : NULL,
- (dcache) ? dcache->getInterface() : NULL,
- defer_registration,
- ticksPerSecond * mult,
- function_trace, function_trace_start);
-#else
-
- cpu = new SimpleCPU(getInstanceName(), workload,
- max_insts_any_thread, max_insts_all_threads,
- max_loads_any_thread, max_loads_all_threads,
- (icache) ? icache->getInterface() : NULL,
- (dcache) ? dcache->getInterface() : NULL,
- defer_registration,
- function_trace, function_trace_start);
+ SimpleCPU::Params *params = new SimpleCPU::Params();
+ params->name = getInstanceName();
+ params->numberOfThreads = 1;
+ params->max_insts_any_thread = max_insts_any_thread;
+ params->max_insts_all_threads = max_insts_all_threads;
+ params->max_loads_any_thread = max_loads_any_thread;
+ params->max_loads_all_threads = max_loads_all_threads;
+ params->deferRegistration = defer_registration;
+ params->freq = ticksPerSecond;
+ params->functionTrace = function_trace;
+ params->functionTraceStart = function_trace_start;
+ params->icache_interface = (icache) ? icache->getInterface() : NULL;
+ params->dcache_interface = (dcache) ? dcache->getInterface() : NULL;
+ params->width = width;
-#endif // FULL_SYSTEM
-
- cpu->setTickMultiplier(multiplier);
+#ifdef FULL_SYSTEM
+ params->itb = itb;
+ params->dtb = dtb;
+ params->mem = mem;
+ params->system = system;
+#else
+ params->process = workload;
+#endif
+ SimpleCPU *cpu = new SimpleCPU(params);
return cpu;
}
diff --git a/cpu/simple_cpu/simple_cpu.hh b/cpu/simple_cpu/simple_cpu.hh
index 341a0da23..f245a7bba 100644
--- a/cpu/simple_cpu/simple_cpu.hh
+++ b/cpu/simple_cpu/simple_cpu.hh
@@ -26,15 +26,16 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef __SIMPLE_CPU_HH__
-#define __SIMPLE_CPU_HH__
+#ifndef __CPU_SIMPLE_CPU_SIMPLE_CPU_HH__
+#define __CPU_SIMPLE_CPU_SIMPLE_CPU_HH__
-#include "cpu/base_cpu.hh"
-#include "sim/eventq.hh"
-#include "cpu/pc_event.hh"
#include "base/statistics.hh"
+#include "cpu/base_cpu.hh"
#include "cpu/exec_context.hh"
+#include "cpu/pc_event.hh"
+#include "cpu/sampling_cpu/sampling_cpu.hh"
#include "cpu/static_inst.hh"
+#include "sim/eventq.hh"
// forward declarations
#ifdef FULL_SYSTEM
@@ -69,9 +70,9 @@ class SimpleCPU : public BaseCPU
struct TickEvent : public Event
{
SimpleCPU *cpu;
- int multiplier;
+ int width;
- TickEvent(SimpleCPU *c);
+ TickEvent(SimpleCPU *c, int w);
void process();
const char *description();
};
@@ -94,20 +95,8 @@ class SimpleCPU : public BaseCPU
tickEvent.squash();
}
- public:
- void setTickMultiplier(int multiplier)
- {
- tickEvent.multiplier = multiplier;
- }
-
private:
Trace::InstRecord *traceData;
- template<typename T>
- void trace_data(T data) {
- if (traceData) {
- traceData->setData(data);
- }
- };
public:
//
@@ -117,6 +106,7 @@ class SimpleCPU : public BaseCPU
IcacheMissStall,
IcacheMissComplete,
DcacheMissStall,
+ DcacheMissSwitch,
SwitchedOut
};
@@ -134,36 +124,28 @@ class SimpleCPU : public BaseCPU
}
};
+ public:
+ struct Params : public BaseCPU::Params
+ {
+ MemInterface *icache_interface;
+ MemInterface *dcache_interface;
+ int width;
#ifdef FULL_SYSTEM
-
- SimpleCPU(const std::string &_name,
- System *_system,
- Counter max_insts_any_thread, Counter max_insts_all_threads,
- Counter max_loads_any_thread, Counter max_loads_all_threads,
- AlphaITB *itb, AlphaDTB *dtb, FunctionalMemory *mem,
- MemInterface *icache_interface, MemInterface *dcache_interface,
- bool _def_reg, Tick freq,
- bool _function_trace, Tick _function_trace_start);
-
+ AlphaITB *itb;
+ AlphaDTB *dtb;
+ FunctionalMemory *mem;
#else
-
- SimpleCPU(const std::string &_name, Process *_process,
- Counter max_insts_any_thread,
- Counter max_insts_all_threads,
- Counter max_loads_any_thread,
- Counter max_loads_all_threads,
- MemInterface *icache_interface, MemInterface *dcache_interface,
- bool _def_reg,
- bool _function_trace, Tick _function_trace_start);
-
+ Process *process;
#endif
-
+ };
+ SimpleCPU(Params *params);
virtual ~SimpleCPU();
+ public:
// execution context
ExecContext *xc;
- void switchOut();
+ void switchOut(SamplingCPU *s);
void takeOverFrom(BaseCPU *oldCPU);
#ifdef FULL_SYSTEM
@@ -184,6 +166,13 @@ class SimpleCPU : public BaseCPU
// Refcounted pointer to the one memory request.
MemReqPtr memReq;
+ // Pointer to the sampler that is telling us to switchover.
+ // Used to signal the completion of the pipe drain and schedule
+ // the next switchover
+ SamplingCPU *sampler;
+
+ StaticInstPtr<TheISA> curStaticInst;
+
class CacheCompletionEvent : public Event
{
private:
@@ -249,6 +238,11 @@ class SimpleCPU : public BaseCPU
template <class T>
Fault write(T data, Addr addr, unsigned flags, uint64_t *res);
+ // These functions are only used in CPU models that split
+ // effective address computation from the actual memory access.
+ void setEA(Addr EA) { panic("SimpleCPU::setEA() not implemented\n"); }
+ Addr getEA() { panic("SimpleCPU::getEA() not implemented\n"); }
+
void prefetch(Addr addr, unsigned flags)
{
// need to do this...
@@ -274,47 +268,47 @@ class SimpleCPU : public BaseCPU
// storage (which is pretty hard to imagine they would have reason
// to do).
- uint64_t readIntReg(StaticInst<TheISA> *si, int idx)
+ uint64_t readIntReg(const StaticInst<TheISA> *si, int idx)
{
return xc->readIntReg(si->srcRegIdx(idx));
}
- float readFloatRegSingle(StaticInst<TheISA> *si, int idx)
+ float readFloatRegSingle(const StaticInst<TheISA> *si, int idx)
{
int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag;
return xc->readFloatRegSingle(reg_idx);
}
- double readFloatRegDouble(StaticInst<TheISA> *si, int idx)
+ double readFloatRegDouble(const StaticInst<TheISA> *si, int idx)
{
int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag;
return xc->readFloatRegDouble(reg_idx);
}
- uint64_t readFloatRegInt(StaticInst<TheISA> *si, int idx)
+ uint64_t readFloatRegInt(const StaticInst<TheISA> *si, int idx)
{
int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag;
return xc->readFloatRegInt(reg_idx);
}
- void setIntReg(StaticInst<TheISA> *si, int idx, uint64_t val)
+ void setIntReg(const StaticInst<TheISA> *si, int idx, uint64_t val)
{
xc->setIntReg(si->destRegIdx(idx), val);
}
- void setFloatRegSingle(StaticInst<TheISA> *si, int idx, float val)
+ void setFloatRegSingle(const StaticInst<TheISA> *si, int idx, float val)
{
int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag;
xc->setFloatRegSingle(reg_idx, val);
}
- void setFloatRegDouble(StaticInst<TheISA> *si, int idx, double val)
+ void setFloatRegDouble(const StaticInst<TheISA> *si, int idx, double val)
{
int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag;
xc->setFloatRegDouble(reg_idx, val);
}
- void setFloatRegInt(StaticInst<TheISA> *si, int idx, uint64_t val)
+ void setFloatRegInt(const StaticInst<TheISA> *si, int idx, uint64_t val)
{
int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag;
xc->setFloatRegInt(reg_idx, val);
@@ -346,4 +340,4 @@ class SimpleCPU : public BaseCPU
ExecContext *xcBase() { return xc; }
};
-#endif // __SIMPLE_CPU_HH__
+#endif // __CPU_SIMPLE_CPU_SIMPLE_CPU_HH__
diff --git a/cpu/static_inst.cc b/cpu/static_inst.cc
index 4cb45a818..d522dbf5a 100644
--- a/cpu/static_inst.cc
+++ b/cpu/static_inst.cc
@@ -68,7 +68,7 @@ StaticInst<AlphaISA>::nullStaticInstPtr;
template <class ISA>
bool
-StaticInst<ISA>::hasBranchTarget(Addr pc, ExecContext *xc, Addr &tgt)
+StaticInst<ISA>::hasBranchTarget(Addr pc, ExecContext *xc, Addr &tgt) const
{
if (isDirectCtrl()) {
tgt = branchTarget(pc);
@@ -85,4 +85,4 @@ StaticInst<ISA>::hasBranchTarget(Addr pc, ExecContext *xc, Addr &tgt)
// force instantiation of template function(s) above
-template StaticInst<AlphaISA>;
+template class StaticInst<AlphaISA>;
diff --git a/cpu/static_inst.hh b/cpu/static_inst.hh
index 46b2e4b19..75bdcc286 100644
--- a/cpu/static_inst.hh
+++ b/cpu/static_inst.hh
@@ -285,13 +285,13 @@ class StaticInst : public StaticInstBase
* String representation of disassembly (lazily evaluated via
* disassemble()).
*/
- std::string *cachedDisassembly;
+ mutable std::string *cachedDisassembly;
/**
* Internal function to generate disassembly string.
*/
- virtual std::string generateDisassembly(Addr pc,
- const SymbolTable *symtab) = 0;
+ virtual std::string
+ generateDisassembly(Addr pc, const SymbolTable *symtab) const = 0;
/// Constructor.
StaticInst(const char *_mnemonic, MachInst _machInst, OpClass __opClass)
@@ -311,23 +311,27 @@ class StaticInst : public StaticInstBase
/**
* Execute this instruction under SimpleCPU model.
*/
- virtual Fault execute(SimpleCPU *xc, Trace::InstRecord *traceData) = 0;
+ virtual Fault execute(SimpleCPU *xc,
+ Trace::InstRecord *traceData) const = 0;
- /**
+ /**
* Execute this instruction under InorderCPU model.
*/
- virtual Fault execute(InorderCPU *xc, Trace::InstRecord *traceData) = 0;
+ virtual Fault execute(InorderCPU *xc,
+ Trace::InstRecord *traceData) const = 0;
/**
* Execute this instruction under FastCPU model.
*/
- virtual Fault execute(FastCPU *xc, Trace::InstRecord *traceData) = 0;
+ virtual Fault execute(FastCPU *xc,
+ Trace::InstRecord *traceData) const = 0;
/**
* Execute this instruction under detailed FullCPU model.
*/
- virtual Fault execute(DynInst *xc, Trace::InstRecord *traceData) = 0;
+ virtual Fault execute(DynInst *xc,
+ Trace::InstRecord *traceData) const = 0;
/**
* Return the target address for a PC-relative branch.
@@ -357,7 +361,7 @@ class StaticInst : public StaticInstBase
* Return true if the instruction is a control transfer, and if so,
* return the target address as well.
*/
- bool hasBranchTarget(Addr pc, ExecContext *xc, Addr &tgt);
+ bool hasBranchTarget(Addr pc, ExecContext *xc, Addr &tgt) const;
/**
* Return string representation of disassembled instruction.
@@ -367,7 +371,7 @@ class StaticInst : public StaticInstBase
* should not be cached, this function should be overridden directly.
*/
virtual const std::string &disassemble(Addr pc,
- const SymbolTable *symtab = 0)
+ const SymbolTable *symtab = 0) const
{
if (!cachedDisassembly)
cachedDisassembly =
@@ -456,7 +460,7 @@ class StaticInstPtr : public RefCountingPtr<StaticInst<ISA> >
/// Convert to pointer to StaticInstBase class.
operator const StaticInstBasePtr()
{
- return get();
+ return this->get();
}
};
diff --git a/cpu/trace/opt_cpu.cc b/cpu/trace/opt_cpu.cc
index 77211e382..15b53d46e 100644
--- a/cpu/trace/opt_cpu.cc
+++ b/cpu/trace/opt_cpu.cc
@@ -48,7 +48,7 @@ OptCPU::OptCPU(const string &name,
int block_size,
int cache_size,
int _assoc)
- : BaseCPU(name, 1, true), tickEvent(this), trace(_trace),
+ : SimObject(name), tickEvent(this), trace(_trace),
numBlks(cache_size/block_size), assoc(_assoc), numSets(numBlks/assoc),
setMask(numSets - 1)
{
diff --git a/cpu/trace/opt_cpu.hh b/cpu/trace/opt_cpu.hh
index 847147b3c..7f6aa3e18 100644
--- a/cpu/trace/opt_cpu.hh
+++ b/cpu/trace/opt_cpu.hh
@@ -32,14 +32,14 @@
* trace to access a fully associative cache with optimal replacement.
*/
-#ifndef __OPT_CPU_HH__
-#define __OPT_CPU_HH__
+#ifndef __CPU_TRACE_OPT_CPU_HH__
+#define __CPU_TRACE_OPT_CPU_HH__
#include <vector>
-#include "cpu/base_cpu.hh"
#include "mem/mem_req.hh" // for MemReqPtr
#include "sim/eventq.hh" // for Event
+#include "sim/sim_object.hh"
// Forward Declaration
class MemTraceReader;
@@ -47,8 +47,9 @@ class MemTraceReader;
/**
* A CPU object to simulate a fully-associative cache with optimal replacement.
*/
-class OptCPU : public BaseCPU
+class OptCPU : public SimObject
{
+ private:
typedef int RefIndex;
typedef std::vector<RefIndex> L3Table;
@@ -219,4 +220,4 @@ class OptCPU : public BaseCPU
void tick();
};
-#endif
+#endif // __CPU_TRACE_OPT_CPU_HH__
diff --git a/cpu/trace/trace_cpu.cc b/cpu/trace/trace_cpu.cc
index f1160337a..1902d0be4 100644
--- a/cpu/trace/trace_cpu.cc
+++ b/cpu/trace/trace_cpu.cc
@@ -47,7 +47,7 @@ TraceCPU::TraceCPU(const string &name,
MemInterface *icache_interface,
MemInterface *dcache_interface,
MemTraceReader *data_trace)
- : BaseCPU(name, 4, true), icacheInterface(icache_interface),
+ : SimObject(name), icacheInterface(icache_interface),
dcacheInterface(dcache_interface),
dataTrace(data_trace), outstandingRequests(0), tickEvent(this)
{
diff --git a/cpu/trace/trace_cpu.hh b/cpu/trace/trace_cpu.hh
index 1711646a8..cdac4bb4f 100644
--- a/cpu/trace/trace_cpu.hh
+++ b/cpu/trace/trace_cpu.hh
@@ -32,14 +32,14 @@
* provided memory hierarchy.
*/
-#ifndef __TRACE_CPU_HH__
-#define __TRACE_CPU_HH__
+#ifndef __CPU_TRACE_TRACE_CPU_HH__
+#define __CPU_TRACE_TRACE_CPU_HH__
#include <string>
-#include "cpu/base_cpu.hh"
#include "mem/mem_req.hh" // for MemReqPtr
#include "sim/eventq.hh" // for Event
+#include "sim/sim_object.hh"
// Forward declaration.
class MemInterface;
@@ -48,8 +48,9 @@ class MemTraceReader;
/**
* A cpu object for running memory traces through a memory hierarchy.
*/
-class TraceCPU : public BaseCPU
+class TraceCPU : public SimObject
{
+ private:
/** Interface for instruction trace requests, if any. */
MemInterface *icacheInterface;
/** Interface for data trace requests, if any. */
@@ -133,5 +134,5 @@ class TraceCompleteEvent : public Event
virtual const char *description();
};
-#endif //__TRACE_CPU_HH__
+#endif // __CPU_TRACE_TRACE_CPU_HH__
diff --git a/dev/alpha_console.cc b/dev/alpha_console.cc
index 7deabe2fc..8309ea16d 100644
--- a/dev/alpha_console.cc
+++ b/dev/alpha_console.cc
@@ -56,10 +56,10 @@
using namespace std;
AlphaConsole::AlphaConsole(const string &name, SimConsole *cons, SimpleDisk *d,
- System *system, BaseCPU *cpu, Platform *platform,
+ System *system, BaseCPU *cpu, Platform *p,
int num_cpus, MemoryController *mmu, Addr a,
HierParams *hier, Bus *bus)
- : PioDevice(name), disk(d), console(cons), addr(a)
+ : PioDevice(name, p), disk(d), console(cons), addr(a)
{
mmu->add_child(this, RangeSize(addr, size));
@@ -79,7 +79,7 @@ AlphaConsole::AlphaConsole(const string &name, SimConsole *cons, SimpleDisk *d,
alphaAccess->numCPUs = num_cpus;
alphaAccess->mem_size = system->physmem->size();
alphaAccess->cpuClock = cpu->getFreq() / 1000000;
- alphaAccess->intrClockFrequency = platform->intrFrequency();
+ alphaAccess->intrClockFrequency = platform->intrFrequency();
alphaAccess->diskUnit = 1;
alphaAccess->diskCount = 0;
@@ -329,6 +329,7 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(AlphaConsole)
SimObjectParam<BaseCPU *> cpu;
SimObjectParam<Platform *> platform;
SimObjectParam<Bus*> io_bus;
+ Param<Tick> pio_latency;
SimObjectParam<HierParams *> hier;
END_DECLARE_SIM_OBJECT_PARAMS(AlphaConsole)
@@ -344,6 +345,7 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(AlphaConsole)
INIT_PARAM(cpu, "Processor"),
INIT_PARAM(platform, "platform"),
INIT_PARAM_DFLT(io_bus, "The IO Bus to attach to", NULL),
+ INIT_PARAM_DFLT(pio_latency, "Programmed IO latency", 1000),
INIT_PARAM_DFLT(hier, "Hierarchy global variables", &defaultHierParams)
END_INIT_SIM_OBJECT_PARAMS(AlphaConsole)
diff --git a/dev/alpha_console.hh b/dev/alpha_console.hh
index 49c3a9f78..96b0a22c2 100644
--- a/dev/alpha_console.hh
+++ b/dev/alpha_console.hh
@@ -42,7 +42,6 @@
class BaseCPU;
class SimConsole;
class System;
-class Platform;
class SimpleDisk;
/*
@@ -75,7 +74,7 @@ class AlphaConsole : public PioDevice
protected:
union {
AlphaAccess *alphaAccess;
- uint8_t *consoleData;
+ uint8_t *consoleData;
};
/** the disk must be accessed from the console */
diff --git a/dev/baddev.cc b/dev/baddev.cc
index 73b082d47..bb1d289ab 100644
--- a/dev/baddev.cc
+++ b/dev/baddev.cc
@@ -37,6 +37,7 @@
#include "base/trace.hh"
#include "cpu/exec_context.hh"
#include "dev/baddev.hh"
+#include "dev/platform.hh"
#include "mem/bus/bus.hh"
#include "mem/bus/pio_interface.hh"
#include "mem/bus/pio_interface_impl.hh"
@@ -48,7 +49,7 @@ using namespace std;
BadDevice::BadDevice(const string &name, Addr a, MemoryController *mmu,
HierParams *hier, Bus *bus, const string &devicename)
- : PioDevice(name), addr(a), devname(devicename)
+ : PioDevice(name, NULL), addr(a), devname(devicename)
{
mmu->add_child(this, RangeSize(addr, size));
@@ -83,20 +84,24 @@ BadDevice::cacheAccess(MemReqPtr &req)
BEGIN_DECLARE_SIM_OBJECT_PARAMS(BadDevice)
+ SimObjectParam<Platform *> platform;
SimObjectParam<MemoryController *> mmu;
Param<Addr> addr;
SimObjectParam<HierParams *> hier;
SimObjectParam<Bus*> io_bus;
+ Param<Tick> pio_latency;
Param<string> devicename;
END_DECLARE_SIM_OBJECT_PARAMS(BadDevice)
BEGIN_INIT_SIM_OBJECT_PARAMS(BadDevice)
+ INIT_PARAM(platform, "Platform"),
INIT_PARAM(mmu, "Memory Controller"),
INIT_PARAM(addr, "Device Address"),
INIT_PARAM_DFLT(hier, "Hierarchy global variables", &defaultHierParams),
INIT_PARAM_DFLT(io_bus, "The IO Bus to attach to", NULL),
+ INIT_PARAM_DFLT(pio_latency, "Programmed IO latency", 1000),
INIT_PARAM(devicename, "Name of device to error on")
END_INIT_SIM_OBJECT_PARAMS(BadDevice)
diff --git a/dev/baddev.hh b/dev/baddev.hh
index 8680f6b0a..a9e904c62 100644
--- a/dev/baddev.hh
+++ b/dev/baddev.hh
@@ -31,8 +31,8 @@
* kernel that touches the frame buffer which isn't allowed.
*/
-#ifndef __BADDEV_HH__
-#define __BADDEV_HH__
+#ifndef __DEV_BADDEV_HH__
+#define __DEV_BADDEV_HH__
#include "base/range.hh"
#include "dev/io_device.hh"
@@ -90,4 +90,4 @@ class BadDevice : public PioDevice
Tick cacheAccess(MemReqPtr &req);
};
-#endif // __BADDEV_HH__
+#endif // __DEV_BADDEV_HH__
diff --git a/dev/etherdump.cc b/dev/etherdump.cc
index 485d5599c..3de417bdc 100644
--- a/dev/etherdump.cc
+++ b/dev/etherdump.cc
@@ -36,14 +36,15 @@
#include <string>
#include "base/misc.hh"
+#include "base/output.hh"
#include "dev/etherdump.hh"
#include "sim/builder.hh"
#include "sim/universe.hh"
using std::string;
-EtherDump::EtherDump(const string &name, std::ostream *_stream, int max)
- : SimObject(name), stream(_stream), maxlen(max)
+EtherDump::EtherDump(const string &name, const string &file, int max)
+ : SimObject(name), stream(file.c_str()), maxlen(max)
{
}
@@ -86,7 +87,7 @@ EtherDump::init()
hdr.sigfigs = 0;
hdr.linktype = DLT_EN10MB;
- stream->write(reinterpret_cast<char *>(&hdr), sizeof(hdr));
+ stream.write(reinterpret_cast<char *>(&hdr), sizeof(hdr));
/*
* output an empty packet with the current time so that we know
@@ -98,9 +99,9 @@ EtherDump::init()
pkthdr.microseconds = 0;
pkthdr.caplen = 0;
pkthdr.len = 0;
- stream->write(reinterpret_cast<char *>(&pkthdr), sizeof(pkthdr));
+ stream.write(reinterpret_cast<char *>(&pkthdr), sizeof(pkthdr));
- stream->flush();
+ stream.flush();
}
void
@@ -111,9 +112,9 @@ EtherDump::dumpPacket(PacketPtr &packet)
pkthdr.microseconds = (curTick / us_freq) % ULL(1000000);
pkthdr.caplen = std::min(packet->length, maxlen);
pkthdr.len = packet->length;
- stream->write(reinterpret_cast<char *>(&pkthdr), sizeof(pkthdr));
- stream->write(reinterpret_cast<char *>(packet->data), pkthdr.caplen);
- stream->flush();
+ stream.write(reinterpret_cast<char *>(&pkthdr), sizeof(pkthdr));
+ stream.write(reinterpret_cast<char *>(packet->data), pkthdr.caplen);
+ stream.flush();
}
BEGIN_DECLARE_SIM_OBJECT_PARAMS(EtherDump)
@@ -132,7 +133,7 @@ END_INIT_SIM_OBJECT_PARAMS(EtherDump)
CREATE_SIM_OBJECT(EtherDump)
{
- return new EtherDump(getInstanceName(), makeOutputStream(file), maxlen);
+ return new EtherDump(getInstanceName(), simout.resolve(file), maxlen);
}
REGISTER_SIM_OBJECT("EtherDump", EtherDump)
diff --git a/dev/etherdump.hh b/dev/etherdump.hh
index b127d05e2..ba15796c8 100644
--- a/dev/etherdump.hh
+++ b/dev/etherdump.hh
@@ -43,7 +43,7 @@
class EtherDump : public SimObject
{
private:
- std::ostream *stream;
+ std::ofstream stream;
const int maxlen;
void dumpPacket(PacketPtr &packet);
void init();
@@ -53,7 +53,7 @@ class EtherDump : public SimObject
Tick us_freq;
public:
- EtherDump(const std::string &name, std::ostream *_stream, int max);
+ EtherDump(const std::string &name, const std::string &file, int max);
inline void dump(PacketPtr &pkt) { dumpPacket(pkt); }
};
diff --git a/dev/etherlink.cc b/dev/etherlink.cc
index d637e152a..81cdbc20f 100644
--- a/dev/etherlink.cc
+++ b/dev/etherlink.cc
@@ -47,32 +47,32 @@
using namespace std;
-EtherLink::EtherLink(const string &name, EtherInt *i1, EtherInt *i2,
+EtherLink::EtherLink(const string &name, EtherInt *peer0, EtherInt *peer1,
Tick speed, Tick dly, EtherDump *dump)
: SimObject(name)
{
double rate = ((double)ticksPerSecond * 8.0) / (double)speed;
Tick delay = US2Ticks(dly);
- link1 = new Link(name + ".link1", rate, delay, dump);
- link2 = new Link(name + ".link2", rate, delay, dump);
+ link[0] = new Link(name + ".link0", this, 0, rate, delay, dump);
+ link[1] = new Link(name + ".link1", this, 1, rate, delay, dump);
- int1 = new Interface(name + ".int1", link1, link2);
- int2 = new Interface(name + ".int2", link2, link1);
+ interface[0] = new Interface(name + ".int0", link[0], link[1]);
+ interface[1] = new Interface(name + ".int1", link[1], link[0]);
- int1->setPeer(i1);
- i1->setPeer(int1);
- int2->setPeer(i2);
- i2->setPeer(int2);
+ interface[0]->setPeer(peer0);
+ peer0->setPeer(interface[0]);
+ interface[1]->setPeer(peer1);
+ peer1->setPeer(interface[1]);
}
EtherLink::~EtherLink()
{
- delete link1;
- delete link2;
+ delete link[0];
+ delete link[1];
- delete int1;
- delete int2;
+ delete interface[0];
+ delete interface[1];
}
EtherLink::Interface::Interface(const string &name, Link *tx, Link *rx)
@@ -82,26 +82,25 @@ EtherLink::Interface::Interface(const string &name, Link *tx, Link *rx)
rx->setRxInt(this);
}
-EtherLink::Link::Link(const string &name, double rate, Tick delay,
- EtherDump *d)
- : objName(name), txint(NULL), rxint(NULL), ticksPerByte(rate),
- linkDelay(delay), dump(d), doneEvent(this)
-{}
+EtherLink::Link::Link(const string &name, EtherLink *p, int num,
+ double rate, Tick delay, EtherDump *d)
+ : objName(name), parent(p), number(num), txint(NULL), rxint(NULL),
+ ticksPerByte(rate), linkDelay(delay), dump(d),
+ doneEvent(this)
+{ }
void
EtherLink::serialize(ostream &os)
{
- nameOut(os, name() + ".link1");
- link1->serialize(os);
- nameOut(os, name() + ".link2");
- link2->serialize(os);
+ link[0]->serialize("link0", os);
+ link[1]->serialize("link1", os);
}
void
EtherLink::unserialize(Checkpoint *cp, const string &section)
{
- link1->unserialize(cp, section + ".link1");
- link2->unserialize(cp, section + ".link2");
+ link[0]->unserialize("link0", cp, section);
+ link[1]->unserialize("link1", cp, section);
}
void
@@ -118,10 +117,9 @@ class LinkDelayEvent : public Event
EtherLink::Link *link;
PacketPtr packet;
- // non-scheduling version for createForUnserialize()
- LinkDelayEvent(EtherLink::Link *link);
-
public:
+ // non-scheduling version for createForUnserialize()
+ LinkDelayEvent();
LinkDelayEvent(EtherLink::Link *link, PacketPtr pkt, Tick when);
void process();
@@ -132,7 +130,6 @@ class LinkDelayEvent : public Event
const string &section);
};
-
void
EtherLink::Link::txDone()
{
@@ -173,43 +170,44 @@ EtherLink::Link::transmit(PacketPtr pkt)
}
void
-EtherLink::Link::serialize(ostream &os)
+EtherLink::Link::serialize(const string &base, ostream &os)
{
bool packet_exists = packet;
- SERIALIZE_SCALAR(packet_exists);
+ paramOut(os, base + ".packet_exists", packet_exists);
+ if (packet_exists)
+ packet->serialize(base + ".packet", os);
bool event_scheduled = doneEvent.scheduled();
- SERIALIZE_SCALAR(event_scheduled);
+ paramOut(os, base + ".event_scheduled", event_scheduled);
if (event_scheduled) {
Tick event_time = doneEvent.when();
- SERIALIZE_SCALAR(event_time);
+ paramOut(os, base + ".event_time", event_time);
}
- if (packet_exists)
- packet->serialize("packet", os);
}
void
-EtherLink::Link::unserialize(Checkpoint *cp, const string &section)
+EtherLink::Link::unserialize(const string &base, Checkpoint *cp,
+ const string &section)
{
bool packet_exists;
- UNSERIALIZE_SCALAR(packet_exists);
+ paramIn(cp, section, base + ".packet_exists", packet_exists);
if (packet_exists) {
packet = new PacketData(16384);
- packet->unserialize("packet", cp, section);
+ packet->unserialize(base + ".packet", cp, section);
}
bool event_scheduled;
- UNSERIALIZE_SCALAR(event_scheduled);
+ paramIn(cp, section, base + ".event_scheduled", event_scheduled);
if (event_scheduled) {
Tick event_time;
- UNSERIALIZE_SCALAR(event_time);
+ paramIn(cp, section, base + ".event_time", event_time);
doneEvent.schedule(event_time);
}
}
-LinkDelayEvent::LinkDelayEvent(EtherLink::Link *l)
- : Event(&mainEventQueue), link(l)
+LinkDelayEvent::LinkDelayEvent()
+ : Event(&mainEventQueue), link(NULL)
{
setFlags(AutoSerialize);
setFlags(AutoDelete);
@@ -234,7 +232,11 @@ LinkDelayEvent::serialize(ostream &os)
{
paramOut(os, "type", string("LinkDelayEvent"));
Event::serialize(os);
- SERIALIZE_OBJPTR(link);
+
+ EtherLink *parent = link->parent;
+ bool number = link->number;
+ SERIALIZE_OBJPTR(parent);
+ SERIALIZE_SCALAR(number);
packet->serialize("packet", os);
}
@@ -244,6 +246,14 @@ void
LinkDelayEvent::unserialize(Checkpoint *cp, const string &section)
{
Event::unserialize(cp, section);
+
+ EtherLink *parent;
+ bool number;
+ UNSERIALIZE_OBJPTR(parent);
+ UNSERIALIZE_SCALAR(number);
+
+ link = parent->link[number];
+
packet = new PacketData(16384);
packet->unserialize("packet", cp, section);
}
@@ -252,37 +262,34 @@ LinkDelayEvent::unserialize(Checkpoint *cp, const string &section)
Serializable *
LinkDelayEvent::createForUnserialize(Checkpoint *cp, const string &section)
{
- EtherLink::Link *link;
- UNSERIALIZE_OBJPTR(link);
- return new LinkDelayEvent(link);
+ return new LinkDelayEvent();
}
REGISTER_SERIALIZEABLE("LinkDelayEvent", LinkDelayEvent)
BEGIN_DECLARE_SIM_OBJECT_PARAMS(EtherLink)
- SimObjectParam<EtherInt *> interface1;
- SimObjectParam<EtherInt *> interface2;
- Param<Tick> link_speed;
- Param<Tick> link_delay;
- SimObjectParam<EtherDump *> packet_dump;
+ SimObjectParam<EtherInt *> int1;
+ SimObjectParam<EtherInt *> int2;
+ Param<Tick> speed;
+ Param<Tick> delay;
+ SimObjectParam<EtherDump *> dump;
END_DECLARE_SIM_OBJECT_PARAMS(EtherLink)
BEGIN_INIT_SIM_OBJECT_PARAMS(EtherLink)
- INIT_PARAM(interface1, "interface 1"),
- INIT_PARAM(interface2, "interface 2"),
- INIT_PARAM_DFLT(link_speed, "link speed in bits per second", 100000000),
- INIT_PARAM_DFLT(link_delay, "transmit delay of packets in us", 0),
- INIT_PARAM_DFLT(packet_dump, "object to dump network packets to", NULL)
+ INIT_PARAM(int1, "interface 1"),
+ INIT_PARAM(int2, "interface 2"),
+ INIT_PARAM_DFLT(speed, "link speed in bits per second", 100000000),
+ INIT_PARAM_DFLT(delay, "transmit delay of packets in us", 0),
+ INIT_PARAM_DFLT(dump, "object to dump network packets to", NULL)
END_INIT_SIM_OBJECT_PARAMS(EtherLink)
CREATE_SIM_OBJECT(EtherLink)
{
- return new EtherLink(getInstanceName(), interface1, interface2, link_speed,
- link_delay, packet_dump);
+ return new EtherLink(getInstanceName(), int1, int2, speed, delay, dump);
}
REGISTER_SIM_OBJECT("EtherLink", EtherLink)
diff --git a/dev/etherlink.hh b/dev/etherlink.hh
index e998a006f..28ab61301 100644
--- a/dev/etherlink.hh
+++ b/dev/etherlink.hh
@@ -30,17 +30,17 @@
* Device module for modelling a fixed bandwidth full duplex ethernet link
*/
-#ifndef __ETHERLINK_HH__
-#define __ETHERLINK_HH__
+#ifndef __DEV_ETHERLINK_HH__
+#define __DEV_ETHERLINK_HH__
-#include "sim/host.hh"
-#include "sim/eventq.hh"
#include "dev/etherint.hh"
#include "dev/etherpkt.hh"
+#include "sim/eventq.hh"
+#include "sim/host.hh"
#include "sim/sim_object.hh"
class EtherDump;
-
+class Checkpoint;
/*
* Model for a fixed bandwidth full duplex ethernet link
*/
@@ -53,10 +53,14 @@ class EtherLink : public SimObject
/*
* Model for a single uni-directional link
*/
- class Link : public Serializable {
+ class Link
+ {
protected:
std::string objName;
+ EtherLink *parent;
+ int number;
+
Interface *txint;
Interface *rxint;
@@ -71,18 +75,18 @@ class EtherLink : public SimObject
PacketPtr packet;
void txDone();
typedef EventWrapper<Link, &Link::txDone> DoneEvent;
- friend class DoneEvent;
+ friend void DoneEvent::process();
DoneEvent doneEvent;
friend class LinkDelayEvent;
void txComplete(PacketPtr packet);
public:
- Link(const std::string &name, double rate, Tick delay,
- EtherDump *dump);
+ Link(const std::string &name, EtherLink *p, int num,
+ double rate, Tick delay, EtherDump *dump);
~Link() {}
- virtual const std::string name() const { return objName; }
+ const std::string name() const { return objName; }
bool busy() const { return (bool)packet; }
bool transmit(PacketPtr packet);
@@ -90,8 +94,9 @@ class EtherLink : public SimObject
void setTxInt(Interface *i) { assert(!txint); txint = i; }
void setRxInt(Interface *i) { assert(!rxint); rxint = i; }
- virtual void serialize(std::ostream &os);
- virtual void unserialize(Checkpoint *cp, const std::string &section);
+ void serialize(const std::string &base, std::ostream &os);
+ void unserialize(const std::string &base, Checkpoint *cp,
+ const std::string &section);
};
/*
@@ -108,14 +113,11 @@ class EtherLink : public SimObject
void sendDone() { peer->sendDone(); }
};
- Link *link1;
- Link *link2;
-
- EtherInt *int1;
- EtherInt *int2;
+ Link *link[2];
+ EtherInt *interface[2];
public:
- EtherLink(const std::string &name, EtherInt *i1, EtherInt *i2,
+ EtherLink(const std::string &name, EtherInt *peer0, EtherInt *peer1,
Tick speed, Tick delay, EtherDump *dump);
virtual ~EtherLink();
diff --git a/dev/ethertap.cc b/dev/ethertap.cc
index 1603a9bd3..807765d91 100644
--- a/dev/ethertap.cc
+++ b/dev/ethertap.cc
@@ -311,7 +311,7 @@ EtherTap::unserialize(Checkpoint *cp, const std::string &section)
BEGIN_DECLARE_SIM_OBJECT_PARAMS(EtherTap)
SimObjectParam<EtherInt *> peer;
- SimObjectParam<EtherDump *> packet_dump;
+ SimObjectParam<EtherDump *> dump;
Param<unsigned> port;
Param<unsigned> bufsz;
@@ -320,7 +320,7 @@ END_DECLARE_SIM_OBJECT_PARAMS(EtherTap)
BEGIN_INIT_SIM_OBJECT_PARAMS(EtherTap)
INIT_PARAM_DFLT(peer, "peer interface", NULL),
- INIT_PARAM_DFLT(packet_dump, "object to dump network packets to", NULL),
+ INIT_PARAM_DFLT(dump, "object to dump network packets to", NULL),
INIT_PARAM_DFLT(port, "tap port", 3500),
INIT_PARAM_DFLT(bufsz, "tap buffer size", 10000)
@@ -329,7 +329,7 @@ END_INIT_SIM_OBJECT_PARAMS(EtherTap)
CREATE_SIM_OBJECT(EtherTap)
{
- EtherTap *tap = new EtherTap(getInstanceName(), packet_dump, port, bufsz);
+ EtherTap *tap = new EtherTap(getInstanceName(), dump, port, bufsz);
if (peer) {
tap->setPeer(peer);
diff --git a/dev/ide_ctrl.cc b/dev/ide_ctrl.cc
index 109908ead..037de1dea 100644
--- a/dev/ide_ctrl.cc
+++ b/dev/ide_ctrl.cc
@@ -664,6 +664,7 @@ IdeController::unserialize(Checkpoint *cp, const std::string &section)
BEGIN_DECLARE_SIM_OBJECT_PARAMS(IdeController)
+ Param<Addr> addr;
SimObjectVectorParam<IdeDisk *> disks;
SimObjectParam<MemoryController *> mmu;
SimObjectParam<PciConfigAll *> configspace;
@@ -680,6 +681,7 @@ END_DECLARE_SIM_OBJECT_PARAMS(IdeController)
BEGIN_INIT_SIM_OBJECT_PARAMS(IdeController)
+ INIT_PARAM(addr, "Device Address"),
INIT_PARAM(disks, "IDE disks attached to this controller"),
INIT_PARAM(mmu, "Memory controller"),
INIT_PARAM(configspace, "PCI Configspace"),
diff --git a/dev/ide_disk.cc b/dev/ide_disk.cc
index 073c10436..bfaf3d3aa 100644
--- a/dev/ide_disk.cc
+++ b/dev/ide_disk.cc
@@ -1171,12 +1171,14 @@ IdeDisk::unserialize(Checkpoint *cp, const string &section)
#ifndef DOXYGEN_SHOULD_SKIP_THIS
+enum DriveID { master, slave };
+static const char *DriveID_strings[] = { "master", "slave" };
BEGIN_DECLARE_SIM_OBJECT_PARAMS(IdeDisk)
SimObjectParam<DiskImage *> image;
SimObjectParam<PhysicalMemory *> physmem;
- Param<int> driveID;
- Param<int> disk_delay;
+ SimpleEnumParam<DriveID> driveID;
+ Param<int> delay;
END_DECLARE_SIM_OBJECT_PARAMS(IdeDisk)
@@ -1184,16 +1186,15 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(IdeDisk)
INIT_PARAM(image, "Disk image"),
INIT_PARAM(physmem, "Physical memory"),
- INIT_PARAM(driveID, "Drive ID (0=master 1=slave)"),
- INIT_PARAM_DFLT(disk_delay, "Fixed disk delay in microseconds", 1)
+ INIT_ENUM_PARAM(driveID, "Drive ID (0=master 1=slave)", DriveID_strings),
+ INIT_PARAM_DFLT(delay, "Fixed disk delay in microseconds", 1)
END_INIT_SIM_OBJECT_PARAMS(IdeDisk)
CREATE_SIM_OBJECT(IdeDisk)
{
- return new IdeDisk(getInstanceName(), image, physmem, driveID,
- disk_delay);
+ return new IdeDisk(getInstanceName(), image, physmem, driveID, delay);
}
REGISTER_SIM_OBJECT("IdeDisk", IdeDisk)
diff --git a/dev/io_device.cc b/dev/io_device.cc
index 7703ad5e3..ffded5858 100644
--- a/dev/io_device.cc
+++ b/dev/io_device.cc
@@ -31,8 +31,8 @@
#include "mem/bus/dma_interface.hh"
#include "sim/builder.hh"
-PioDevice::PioDevice(const std::string &name)
- : FunctionalMemory(name), pioInterface(NULL), pioLatency(0)
+PioDevice::PioDevice(const std::string &name, Platform *p)
+ : FunctionalMemory(name), platform(p), pioInterface(NULL), pioLatency(0)
{}
PioDevice::~PioDevice()
@@ -43,8 +43,8 @@ PioDevice::~PioDevice()
DEFINE_SIM_OBJECT_CLASS_NAME("PioDevice", PioDevice)
-DmaDevice::DmaDevice(const std::string &name)
- : PioDevice(name), dmaInterface(NULL)
+DmaDevice::DmaDevice(const std::string &name, Platform *p)
+ : PioDevice(name, p), dmaInterface(NULL)
{}
DmaDevice::~DmaDevice()
diff --git a/dev/io_device.hh b/dev/io_device.hh
index 8c9dc4a35..649706956 100644
--- a/dev/io_device.hh
+++ b/dev/io_device.hh
@@ -26,24 +26,26 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef __IO_DEVICE_HH__
-#define __IO_DEVICE_HH__
+#ifndef __DEV_IO_DEVICE_HH__
+#define __DEV_IO_DEVICE_HH__
#include "mem/functional_mem/functional_memory.hh"
class BaseInterface;
class Bus;
class HierParams;
+class Platform;
template <class BusType> class DMAInterface;
class PioDevice : public FunctionalMemory
{
protected:
+ Platform *platform;
BaseInterface *pioInterface;
Tick pioLatency;
public:
- PioDevice(const std::string &name);
+ PioDevice(const std::string &name, Platform *p);
virtual ~PioDevice();
};
@@ -53,8 +55,8 @@ class DmaDevice : public PioDevice
DMAInterface<Bus> *dmaInterface;
public:
- DmaDevice(const std::string &name);
+ DmaDevice(const std::string &name, Platform *p);
virtual ~DmaDevice();
};
-#endif // __IO_DEVICE_HH__
+#endif // __DEV_IO_DEVICE_HH__
diff --git a/dev/ns_gige.cc b/dev/ns_gige.cc
index eee8fbbce..db1474d1c 100644
--- a/dev/ns_gige.cc
+++ b/dev/ns_gige.cc
@@ -36,7 +36,6 @@
#include "base/inet.hh"
#include "cpu/exec_context.hh"
-#include "cpu/intr_control.hh"
#include "dev/dma.hh"
#include "dev/etherlink.hh"
#include "dev/ns_gige.hh"
@@ -245,7 +244,6 @@ NSGigE::regStats()
.precision(0)
;
-
txBandwidth
.name(name() + ".txBandwidth")
.desc("Transmit Bandwidth (bits/s)")
@@ -260,6 +258,34 @@ NSGigE::regStats()
.prereq(rxBytes)
;
+ totBandwidth
+ .name(name() + ".totBandwidth")
+ .desc("Total Bandwidth (bits/s)")
+ .precision(0)
+ .prereq(totBytes)
+ ;
+
+ totPackets
+ .name(name() + ".totPackets")
+ .desc("Total Packets")
+ .precision(0)
+ .prereq(totBytes)
+ ;
+
+ totBytes
+ .name(name() + ".totBytes")
+ .desc("Total Bytes")
+ .precision(0)
+ .prereq(totBytes)
+ ;
+
+ totPacketRate
+ .name(name() + ".totPPS")
+ .desc("Total Tranmission Rate (packets/s)")
+ .precision(0)
+ .prereq(totBytes)
+ ;
+
txPacketRate
.name(name() + ".txPPS")
.desc("Packet Tranmission Rate (packets/s)")
@@ -450,6 +476,10 @@ NSGigE::regStats()
txBandwidth = txBytes * Stats::constant(8) / simSeconds;
rxBandwidth = rxBytes * Stats::constant(8) / simSeconds;
+ totBandwidth = txBandwidth + rxBandwidth;
+ totBytes = txBytes + rxBytes;
+ totPackets = txPackets + rxPackets;
+
txPacketRate = txPackets / simSeconds;
rxPacketRate = rxPackets / simSeconds;
}
@@ -2353,6 +2383,7 @@ NSGigE::serialize(ostream &os)
bool txPacketExists = txPacket;
SERIALIZE_SCALAR(txPacketExists);
if (txPacketExists) {
+ txPacket->length = txPacketBufPtr - txPacket->data;
txPacket->serialize("txPacket", os);
uint32_t txPktBufPtr = (uint32_t) (txPacketBufPtr - txPacket->data);
SERIALIZE_SCALAR(txPktBufPtr);
@@ -2637,6 +2668,7 @@ REGISTER_SIM_OBJECT("NSGigEInt", NSGigEInt)
BEGIN_DECLARE_SIM_OBJECT_PARAMS(NSGigE)
+ Param<Addr> addr;
Param<Tick> tx_delay;
Param<Tick> rx_delay;
Param<Tick> intr_delay;
@@ -2644,7 +2676,7 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(NSGigE)
SimObjectParam<PhysicalMemory *> physmem;
Param<bool> rx_filter;
Param<string> hardware_address;
- SimObjectParam<Bus*> header_bus;
+ SimObjectParam<Bus*> io_bus;
SimObjectParam<Bus*> payload_bus;
SimObjectParam<HierParams *> hier;
Param<Tick> pio_latency;
@@ -2667,6 +2699,7 @@ END_DECLARE_SIM_OBJECT_PARAMS(NSGigE)
BEGIN_INIT_SIM_OBJECT_PARAMS(NSGigE)
+ INIT_PARAM(addr, "Device Address"),
INIT_PARAM_DFLT(tx_delay, "Transmit Delay", 1000),
INIT_PARAM_DFLT(rx_delay, "Receive Delay", 1000),
INIT_PARAM_DFLT(intr_delay, "Interrupt Delay in microseconds", 0),
@@ -2675,7 +2708,7 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(NSGigE)
INIT_PARAM_DFLT(rx_filter, "Enable Receive Filter", true),
INIT_PARAM_DFLT(hardware_address, "Ethernet Hardware Address",
"00:99:00:00:00:01"),
- INIT_PARAM_DFLT(header_bus, "The IO Bus to attach to for headers", NULL),
+ INIT_PARAM_DFLT(io_bus, "The IO Bus to attach to for headers", NULL),
INIT_PARAM_DFLT(payload_bus, "The IO Bus to attach to for payload", NULL),
INIT_PARAM_DFLT(hier, "Hierarchy global variables", &defaultHierParams),
INIT_PARAM_DFLT(pio_latency, "Programmed IO latency in bus cycles", 1),
@@ -2715,7 +2748,7 @@ CREATE_SIM_OBJECT(NSGigE)
params->tx_delay = tx_delay;
params->rx_delay = rx_delay;
params->hier = hier;
- params->header_bus = header_bus;
+ params->header_bus = io_bus;
params->payload_bus = payload_bus;
params->pio_latency = pio_latency;
params->dma_desc_free = dma_desc_free;
diff --git a/dev/ns_gige.hh b/dev/ns_gige.hh
index 8d6016126..58060edac 100644
--- a/dev/ns_gige.hh
+++ b/dev/ns_gige.hh
@@ -91,7 +91,6 @@ struct dp_rom {
uint8_t perfectMatch[ETH_ADDR_LEN];
};
-class IntrControl;
class NSGigEInt;
class PhysicalMemory;
class BaseInterface;
@@ -262,12 +261,12 @@ class NSGigE : public PciDev
void rxKick();
Tick rxKickTick;
typedef EventWrapper<NSGigE, &NSGigE::rxKick> RxKickEvent;
- friend class RxKickEvent;
+ friend void RxKickEvent::process();
void txKick();
Tick txKickTick;
typedef EventWrapper<NSGigE, &NSGigE::txKick> TxKickEvent;
- friend class TxKickEvent;
+ friend void TxKickEvent::process();
/**
* Retransmit event
@@ -280,7 +279,7 @@ class NSGigE : public PciDev
txKick();
}
typedef EventWrapper<NSGigE, &NSGigE::txEventTransmit> TxEvent;
- friend class TxEvent;
+ friend void TxEvent::process();
TxEvent txEvent;
void txDump() const;
@@ -302,7 +301,6 @@ class NSGigE : public PciDev
/**
* Interrupt management
*/
- IntrControl *intctrl;
void devIntrPost(uint32_t interrupts);
void devIntrClear(uint32_t interrupts);
void devIntrChangeMask();
@@ -315,7 +313,7 @@ class NSGigE : public PciDev
void cpuIntrClear();
typedef EventWrapper<NSGigE, &NSGigE::cpuInterrupt> IntrEvent;
- friend class IntrEvent;
+ friend void IntrEvent::process();
IntrEvent *intrEvent;
NSGigEInt *interface;
@@ -381,6 +379,10 @@ class NSGigE : public PciDev
Stats::Scalar<> descDmaWrites;
Stats::Scalar<> descDmaRdBytes;
Stats::Scalar<> descDmaWrBytes;
+ Stats::Formula totBandwidth;
+ Stats::Formula totPackets;
+ Stats::Formula totBytes;
+ Stats::Formula totPacketRate;
Stats::Formula txBandwidth;
Stats::Formula rxBandwidth;
Stats::Formula txPacketRate;
diff --git a/dev/pciconfigall.cc b/dev/pciconfigall.cc
index 609763e92..1a9804f79 100644
--- a/dev/pciconfigall.cc
+++ b/dev/pciconfigall.cc
@@ -48,9 +48,10 @@
using namespace std;
-PciConfigAll::PciConfigAll(const string &name, Addr a, MemoryController *mmu,
+PciConfigAll::PciConfigAll(const string &name,
+ Addr a, MemoryController *mmu,
HierParams *hier, Bus *bus, Tick pio_latency)
- : PioDevice(name), addr(a)
+ : PioDevice(name, NULL), addr(a)
{
mmu->add_child(this, RangeSize(addr, size));
diff --git a/dev/pcidev.cc b/dev/pcidev.cc
index d156b6a02..c45afadd4 100644
--- a/dev/pcidev.cc
+++ b/dev/pcidev.cc
@@ -42,6 +42,7 @@
#include "dev/pciareg.h"
#include "dev/pcidev.hh"
#include "dev/pciconfigall.hh"
+#include "mem/bus/bus.hh"
#include "mem/functional_mem/memory_control.hh"
#include "sim/builder.hh"
#include "sim/param.hh"
@@ -51,7 +52,8 @@
using namespace std;
PciDev::PciDev(Params *p)
- : DmaDevice(p->name), _params(p), plat(p->plat), configData(p->configData)
+ : DmaDevice(p->name, p->plat), _params(p), plat(p->plat),
+ configData(p->configData)
{
// copy the config data from the PciConfigData object
if (configData) {
@@ -283,6 +285,11 @@ PciDev::unserialize(Checkpoint *cp, const std::string &section)
BEGIN_DECLARE_SIM_OBJECT_PARAMS(PciConfigData)
+ SimObjectParam<MemoryController *> mmu;
+ Param<Addr> addr;
+ SimObjectParam<Bus*> io_bus;
+ Param<Tick> pio_latency;
+
Param<uint16_t> VendorID;
Param<uint16_t> DeviceID;
Param<uint16_t> Command;
@@ -320,6 +327,11 @@ END_DECLARE_SIM_OBJECT_PARAMS(PciConfigData)
BEGIN_INIT_SIM_OBJECT_PARAMS(PciConfigData)
+ INIT_PARAM(mmu, "Memory Controller"),
+ INIT_PARAM(addr, "Device Address"),
+ INIT_PARAM_DFLT(io_bus, "The IO Bus to attach to", NULL),
+ INIT_PARAM_DFLT(pio_latency, "Programmed IO latency in bus cycles", 1),
+
INIT_PARAM(VendorID, "Vendor ID"),
INIT_PARAM(DeviceID, "Device ID"),
INIT_PARAM_DFLT(Command, "Command Register", 0x00),
diff --git a/dev/pcidev.hh b/dev/pcidev.hh
index 4b947b560..14f183e28 100644
--- a/dev/pcidev.hh
+++ b/dev/pcidev.hh
@@ -78,10 +78,6 @@ class PciConfigData : public SimObject
*/
class PciDev : public DmaDevice
{
- protected:
- struct Params;
- Params *_params;
-
public:
struct Params
{
@@ -110,6 +106,11 @@ class PciDev : public DmaDevice
/** The function number */
uint32_t functionNum;
};
+
+ protected:
+ Params *_params;
+
+ public:
const Params *params() const { return _params; }
protected:
diff --git a/dev/pktfifo.cc b/dev/pktfifo.cc
index ae82123cf..dcb1c4c03 100644
--- a/dev/pktfifo.cc
+++ b/dev/pktfifo.cc
@@ -54,13 +54,12 @@ PacketFifo::unserialize(const string &base, Checkpoint *cp,
const string &section)
{
paramIn(cp, section, base + ".size", _size);
- paramIn(cp, section, base + ".maxsize", _maxsize);
+// paramIn(cp, section, base + ".maxsize", _maxsize);
paramIn(cp, section, base + ".reserved", _reserved);
int fifosize;
paramIn(cp, section, base + ".packets", fifosize);
fifo.clear();
- fifo.resize(fifosize);
for (int i = 0; i < fifosize; ++i) {
PacketPtr p = new PacketData(16384);
diff --git a/dev/platform.hh b/dev/platform.hh
index 717e49411..47ca6209f 100644
--- a/dev/platform.hh
+++ b/dev/platform.hh
@@ -47,8 +47,6 @@ class Platform : public SimObject
public:
/** Pointer to the interrupt controller */
IntrControl *intrctrl;
- /** Pointer to the simulation console */
- SimConsole *cons;
/** Pointer to the PCI configuration space */
PciConfigAll *pciconfig;
diff --git a/dev/rtcreg.h b/dev/rtcreg.h
new file mode 100644
index 000000000..8e1f51bfa
--- /dev/null
+++ b/dev/rtcreg.h
@@ -0,0 +1,44 @@
+
+/*
+ * Copyright (c) 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.
+ */
+
+#define RTC_SEC 0x00
+#define RTC_SEC_ALRM 0x01
+#define RTC_MIN 0x02
+#define RTC_MIN_ALRM 0x03
+#define RTC_HR 0x04
+#define RTC_HR_ALRM 0x05
+#define RTC_DOW 0x06
+#define RTC_DOM 0x07
+#define RTC_MON 0x08
+#define RTC_YEAR 0x09
+#define RTC_CNTRL_REGA 0x0A
+#define RTC_CNTRL_REGB 0x0B
+#define RTC_CNTRL_REGC 0x0C
+#define RTC_CNTRL_REGD 0x0D
+
diff --git a/dev/simconsole.cc b/dev/simconsole.cc
index d8d890e15..94fd9ec1f 100644
--- a/dev/simconsole.cc
+++ b/dev/simconsole.cc
@@ -43,6 +43,7 @@
#include <string>
#include "base/misc.hh"
+#include "base/output.hh"
#include "base/socket.hh"
#include "base/trace.hh"
#include "dev/platform.hh"
@@ -71,7 +72,7 @@ SimConsole::Event::process(int revent)
cons->detach();
}
-SimConsole::SimConsole(const string &name, std::ostream *os, int num)
+SimConsole::SimConsole(const string &name, ostream *os, int num)
: SimObject(name), event(NULL), number(num), in_fd(-1), out_fd(-1),
listener(NULL), txbuf(16384), rxbuf(16384), outfile(os)
#if TRACING_ON == 1
@@ -85,8 +86,6 @@ SimConsole::SimConsole(const string &name, std::ostream *os, int num)
SimConsole::~SimConsole()
{
close();
- if (outfile)
- closeOutputStream(outfile);
}
void
@@ -313,18 +312,16 @@ END_INIT_SIM_OBJECT_PARAMS(SimConsole)
CREATE_SIM_OBJECT(SimConsole)
{
- string filename;
+ string filename = output;
+ ostream *stream = NULL;
- if (!output.isValid()) {
- filename = getInstanceName();
- } else if (append_name) {
- filename = (string)output + "." + getInstanceName();
- } else {
- filename = output;
+ if (!filename.empty()) {
+ if (append_name)
+ filename += "." + getInstanceName();
+ stream = simout.find(filename);
}
- SimConsole *console = new SimConsole(getInstanceName(),
- makeOutputStream(filename), number);
+ SimConsole *console = new SimConsole(getInstanceName(), stream, number);
((ConsoleListener *)listener)->add(console);
return console;
diff --git a/dev/sinic.cc b/dev/sinic.cc
index 56782b589..fa4cd570f 100644
--- a/dev/sinic.cc
+++ b/dev/sinic.cc
@@ -191,6 +191,34 @@ Device::regStats()
.prereq(rxBytes)
;
+ totBandwidth
+ .name(name() + ".totBandwidth")
+ .desc("Total Bandwidth (bits/s)")
+ .precision(0)
+ .prereq(totBytes)
+ ;
+
+ totPackets
+ .name(name() + ".totPackets")
+ .desc("Total Packets")
+ .precision(0)
+ .prereq(totBytes)
+ ;
+
+ totBytes
+ .name(name() + ".totBytes")
+ .desc("Total Bytes")
+ .precision(0)
+ .prereq(totBytes)
+ ;
+
+ totPacketRate
+ .name(name() + ".totPPS")
+ .desc("Total Tranmission Rate (packets/s)")
+ .precision(0)
+ .prereq(totBytes)
+ ;
+
txBytes
.name(name() + ".txBytes")
.desc("Bytes Transmitted")
@@ -258,6 +286,9 @@ Device::regStats()
txBandwidth = txBytes * Stats::constant(8) / simSeconds;
rxBandwidth = rxBytes * Stats::constant(8) / simSeconds;
+ totBandwidth = txBandwidth + rxBandwidth;
+ totBytes = txBytes + rxBytes;
+ totPackets = txPackets + rxPackets;
txPacketRate = txPackets / simSeconds;
rxPacketRate = rxPackets / simSeconds;
}
diff --git a/dev/sinic.hh b/dev/sinic.hh
index ef515ffad..9b8920f3b 100644
--- a/dev/sinic.hh
+++ b/dev/sinic.hh
@@ -59,7 +59,7 @@ class Base : public PciDev
void cpuIntrClear();
typedef EventWrapper<Base, &Base::cpuInterrupt> IntrEvent;
- friend class IntrEvent;
+ friend void IntrEvent::process();
IntrEvent *intrEvent;
Interface *interface;
@@ -155,12 +155,12 @@ class Device : public Base
void rxKick();
Tick rxKickTick;
typedef EventWrapper<Device, &Device::rxKick> RxKickEvent;
- friend class RxKickEvent;
+ friend void RxKickEvent::process();
void txKick();
Tick txKickTick;
typedef EventWrapper<Device, &Device::txKick> TxKickEvent;
- friend class TxKickEvent;
+ friend void TxKickEvent::process();
/**
* Retransmit event
@@ -173,7 +173,7 @@ class Device : public Base
txKick();
}
typedef EventWrapper<Device, &Device::txEventTransmit> TxEvent;
- friend class TxEvent;
+ friend void TxEvent::process();
TxEvent txEvent;
void txDump() const;
@@ -262,6 +262,10 @@ class Device : public Base
Stats::Scalar<> txBytes;
Stats::Formula txBandwidth;
+ Stats::Formula totBandwidth;
+ Stats::Formula totPackets;
+ Stats::Formula totBytes;
+ Stats::Formula totPacketRate;
Stats::Scalar<> txPackets;
Stats::Formula txPacketRate;
Stats::Scalar<> txIpPackets;
diff --git a/dev/tsunami.cc b/dev/tsunami.cc
index f98254354..a95b7365d 100644
--- a/dev/tsunami.cc
+++ b/dev/tsunami.cc
@@ -107,7 +107,6 @@ Tsunami::unserialize(Checkpoint *cp, const std::string &section)
BEGIN_DECLARE_SIM_OBJECT_PARAMS(Tsunami)
SimObjectParam<System *> system;
- SimObjectParam<SimConsole *> cons;
SimObjectParam<IntrControl *> intrctrl;
SimObjectParam<PciConfigAll *> pciconfig;
Param<int> interrupt_frequency;
@@ -117,7 +116,6 @@ END_DECLARE_SIM_OBJECT_PARAMS(Tsunami)
BEGIN_INIT_SIM_OBJECT_PARAMS(Tsunami)
INIT_PARAM(system, "system"),
- INIT_PARAM(cons, "system console"),
INIT_PARAM(intrctrl, "interrupt controller"),
INIT_PARAM(pciconfig, "PCI configuration"),
INIT_PARAM_DFLT(interrupt_frequency, "frequency of interrupts", 1024)
diff --git a/dev/tsunami.hh b/dev/tsunami.hh
index d7c549e90..7722c8417 100644
--- a/dev/tsunami.hh
+++ b/dev/tsunami.hh
@@ -32,8 +32,8 @@
* retains pointers to all its children so the children can communicate.
*/
-#ifndef __TSUNAMI_HH__
-#define __TSUNAMI_HH__
+#ifndef __DEV_TSUNAMI_HH__
+#define __DEV_TSUNAMI_HH__
#include "dev/platform.hh"
@@ -56,7 +56,6 @@ class System;
class Tsunami : public Platform
{
public:
-
/** Max number of CPUs in a Tsunami */
static const int Max_CPUs = 64;
@@ -67,15 +66,15 @@ class Tsunami : public Platform
TsunamiIO *io;
/** Pointer to the Tsunami CChip.
- * The chip contains some configuration information and
- * all the interrupt mask and status registers
- */
+ * The chip contains some configuration information and
+ * all the interrupt mask and status registers
+ */
TsunamiCChip *cchip;
/** Pointer to the Tsunami PChip.
- * The pchip is the interface to the PCI bus, in our case
- * it does not have to do much.
- */
+ * The pchip is the interface to the PCI bus, in our case
+ * it does not have to do much.
+ */
TsunamiPChip *pchip;
int intr_sum_type[Tsunami::Max_CPUs];
@@ -83,12 +82,12 @@ class Tsunami : public Platform
public:
/**
- * Constructor for the Tsunami Class.
- * @param name name of the object
- * @param con pointer to the console
- * @param intrcontrol pointer to the interrupt controller
- * @param intrFreq frequency that interrupts happen
- */
+ * Constructor for the Tsunami Class.
+ * @param name name of the object
+ * @param con pointer to the console
+ * @param intrcontrol pointer to the interrupt controller
+ * @param intrFreq frequency that interrupts happen
+ */
Tsunami(const std::string &name, System *s, IntrControl *intctrl,
PciConfigAll *pci, int intrFreq);
@@ -96,7 +95,7 @@ class Tsunami : public Platform
* Return the interrupting frequency to AlphaAccess
* @return frequency of RTC interrupts
*/
- virtual Tick intrFrequency();
+ virtual Tick intrFrequency();
/**
* Cause the cpu to post a serial interrupt to the CPU.
@@ -120,7 +119,7 @@ class Tsunami : public Platform
virtual Addr pciToDma(Addr pciAddr) const;
- /**
+ /**
* Serialize this object to the given output stream.
* @param os The stream to serialize to.
*/
@@ -134,4 +133,4 @@ class Tsunami : public Platform
virtual void unserialize(Checkpoint *cp, const std::string &section);
};
-#endif // __TSUNAMI_HH__
+#endif // __DEV_TSUNAMI_HH__
diff --git a/dev/tsunami_cchip.cc b/dev/tsunami_cchip.cc
index a1f900153..2fb293fbf 100644
--- a/dev/tsunami_cchip.cc
+++ b/dev/tsunami_cchip.cc
@@ -51,7 +51,7 @@ using namespace std;
TsunamiCChip::TsunamiCChip(const string &name, Tsunami *t, Addr a,
MemoryController *mmu, HierParams *hier, Bus* bus,
Tick pio_latency)
- : PioDevice(name), addr(a), tsunami(t)
+ : PioDevice(name, t), addr(a), tsunami(t)
{
mmu->add_child(this, RangeSize(addr, size));
@@ -173,6 +173,13 @@ TsunamiCChip::read(MemReqPtr &req, uint8_t *data)
break;
case sizeof(uint32_t):
+ if (regnum == TSDEV_CC_DRIR) {
+ warn("accessing DRIR with 32 bit read, "
+ "hopefully your just reading this for timing");
+ *(uint32_t*)data = drir;
+ } else
+ panic("invalid access size(?) for tsunami register!\n");
+ return No_Fault;
case sizeof(uint16_t):
case sizeof(uint8_t):
default:
diff --git a/dev/tsunami_io.cc b/dev/tsunami_io.cc
index 51ff8b81c..6c9195bff 100644
--- a/dev/tsunami_io.cc
+++ b/dev/tsunami_io.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2004 The Regents of The University of Michigan
+ * 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
@@ -45,6 +45,7 @@
#include "sim/builder.hh"
#include "dev/tsunami_cchip.hh"
#include "dev/tsunamireg.h"
+#include "dev/rtcreg.h"
#include "mem/functional_mem/memory_control.hh"
using namespace std;
@@ -66,7 +67,6 @@ TsunamiIO::RTCEvent::process()
schedule(curTick + ticksPerSecond/RTC_RATE);
//Actually interrupt the processor here
tsunami->cchip->postRTC();
-
}
const char *
@@ -162,7 +162,7 @@ TsunamiIO::ClockEvent::unserialize(Checkpoint *cp, const std::string &section)
TsunamiIO::TsunamiIO(const string &name, Tsunami *t, time_t init_time,
Addr a, MemoryController *mmu, HierParams *hier, Bus *bus,
Tick pio_latency)
- : PioDevice(name), addr(a), tsunami(t), rtc(t)
+ : PioDevice(name, t), addr(a), tsunami(t), rtc(t)
{
mmu->add_child(this, RangeSize(addr, size));
@@ -217,36 +217,36 @@ TsunamiIO::read(MemReqPtr &req, uint8_t *data)
return No_Fault;
case TSDEV_RTC_DATA:
switch(RTCAddress) {
- case RTC_CONTROL_REGISTERA:
+ case RTC_CNTRL_REGA:
*(uint8_t*)data = uip << 7 | 0x26;
uip = !uip;
return No_Fault;
- case RTC_CONTROL_REGISTERB:
+ case RTC_CNTRL_REGB:
// DM and 24/12 and UIE
*(uint8_t*)data = 0x46;
return No_Fault;
- case RTC_CONTROL_REGISTERC:
+ case RTC_CNTRL_REGC:
// If we want to support RTC user access in linux
// This won't work, but for now it's fine
*(uint8_t*)data = 0x00;
return No_Fault;
- case RTC_CONTROL_REGISTERD:
+ case RTC_CNTRL_REGD:
panic("RTC Control Register D not implemented");
- case RTC_SECOND:
+ case RTC_SEC:
*(uint8_t *)data = tm.tm_sec;
return No_Fault;
- case RTC_MINUTE:
+ case RTC_MIN:
*(uint8_t *)data = tm.tm_min;
return No_Fault;
- case RTC_HOUR:
+ case RTC_HR:
*(uint8_t *)data = tm.tm_hour;
return No_Fault;
- case RTC_DAY_OF_WEEK:
+ case RTC_DOW:
*(uint8_t *)data = tm.tm_wday;
return No_Fault;
- case RTC_DAY_OF_MONTH:
+ case RTC_DOM:
*(uint8_t *)data = tm.tm_mday;
- case RTC_MONTH:
+ case RTC_MON:
*(uint8_t *)data = tm.tm_mon + 1;
return No_Fault;
case RTC_YEAR:
diff --git a/dev/tsunami_io.hh b/dev/tsunami_io.hh
index d507355c3..a9f044ec9 100644
--- a/dev/tsunami_io.hh
+++ b/dev/tsunami_io.hh
@@ -30,8 +30,8 @@
* Tsunami Fake I/O Space mapping including RTC/timer interrupts
*/
-#ifndef __TSUNAMI_DMA_HH__
-#define __TSUNAMI_DMA_HH__
+#ifndef __DEV_TSUNAMI_IO_HH__
+#define __DEV_TSUNAMI_IO_HH__
#include "dev/io_device.hh"
#include "base/range.hh"
@@ -56,9 +56,11 @@ class TsunamiIO : public PioDevice
struct tm tm;
- /** In Tsunami RTC only has two i/o ports one for data and one for address,
- * so you write the address and then read/write the data. This store the
- * address you are going to be reading from on a read.
+ /**
+ * In Tsunami RTC only has two i/o ports one for data and one for
+ * address, so you write the address and then read/write the
+ * data. This store the address you are going to be reading from
+ * on a read.
*/
uint8_t RTCAddress;
@@ -132,38 +134,37 @@ class TsunamiIO : public PioDevice
class RTCEvent : public Event
{
protected:
- /** A pointer back to tsunami to create interrupt the processor. */
- Tsunami* tsunami;
+ /** A pointer back to tsunami to create interrupt the processor. */
+ Tsunami* tsunami;
public:
- /** RTC Event initializes the RTC event by scheduling an event
- * RTC_RATE times pre second. */
- RTCEvent(Tsunami* t);
-
- /**
- * Interrupth the processor and reschedule the event.
- * */
- virtual void process();
-
- /**
- * Return a description of this event.
- * @return a description
- */
- virtual const char *description();
-
- /**
- * Serialize this object to the given output stream.
- * @param os The stream to serialize to.
- */
- virtual void serialize(std::ostream &os);
-
-
- /**
- * Reconstruct the state of this object from a checkpoint.
- * @param cp The checkpoint use.
- * @param section The section name of this object
- */
- virtual void unserialize(Checkpoint *cp, const std::string &section);
- };
+ /** RTC Event initializes the RTC event by scheduling an event
+ * RTC_RATE times pre second. */
+ RTCEvent(Tsunami* t);
+
+ /**
+ * Interrupth the processor and reschedule the event.
+ */
+ virtual void process();
+
+ /**
+ * Return a description of this event.
+ * @return a description
+ */
+ virtual const char *description();
+
+ /**
+ * Serialize this object to the given output stream.
+ * @param os The stream to serialize to.
+ */
+ virtual void serialize(std::ostream &os);
+
+ /**
+ * Reconstruct the state of this object from a checkpoint.
+ * @param cp The checkpoint use.
+ * @param section The section name of this object
+ */
+ virtual void unserialize(Checkpoint *cp, const std::string &section);
+ };
/** uip UpdateInProgess says that the rtc is updating, but we just fake it
* by alternating it on every read of the bit since we are going to
@@ -219,7 +220,6 @@ class TsunamiIO : public PioDevice
*/
uint32_t timerData;
-
public:
/**
* Return the freqency of the RTC
@@ -227,7 +227,6 @@ class TsunamiIO : public PioDevice
*/
Tick frequency() const { return RTC_RATE; }
-
/**
* Initialize all the data for devices supported by Tsunami I/O.
* @param name name of this device.
@@ -279,7 +278,6 @@ class TsunamiIO : public PioDevice
*/
virtual void serialize(std::ostream &os);
-
/**
* Reconstruct the state of this object from a checkpoint.
* @param cp The checkpoint use.
@@ -287,8 +285,7 @@ class TsunamiIO : public PioDevice
*/
virtual void unserialize(Checkpoint *cp, const std::string &section);
-
Tick cacheAccess(MemReqPtr &req);
};
-#endif // __TSUNAMI_IO_HH__
+#endif // __DEV_TSUNAMI_IO_HH__
diff --git a/dev/tsunami_pchip.cc b/dev/tsunami_pchip.cc
index 9af19d930..f846725f9 100644
--- a/dev/tsunami_pchip.cc
+++ b/dev/tsunami_pchip.cc
@@ -51,7 +51,7 @@ using namespace std;
TsunamiPChip::TsunamiPChip(const string &name, Tsunami *t, Addr a,
MemoryController *mmu, HierParams *hier,
Bus *bus, Tick pio_latency)
- : PioDevice(name), addr(a), tsunami(t)
+ : PioDevice(name, t), addr(a), tsunami(t)
{
mmu->add_child(this, RangeSize(addr, size));
diff --git a/dev/tsunamireg.h b/dev/tsunamireg.h
index 3304082a5..290f21a5b 100644
--- a/dev/tsunamireg.h
+++ b/dev/tsunamireg.h
@@ -122,23 +122,6 @@
#define TSDEV_RTC_ADDR 0x70
#define TSDEV_RTC_DATA 0x71
-// RTC defines
-#define RTC_SECOND 0 // second of minute [0..59]
-#define RTC_SECOND_ALARM 1 // seconds to alarm
-#define RTC_MINUTE 2 // minute of hour [0..59]
-#define RTC_MINUTE_ALARM 3 // minutes to alarm
-#define RTC_HOUR 4 // hour of day [0..23]
-#define RTC_HOUR_ALARM 5 // hours to alarm
-#define RTC_DAY_OF_WEEK 6 // day of week [1..7]
-#define RTC_DAY_OF_MONTH 7 // day of month [1..31]
-#define RTC_MONTH 8 // month of year [1..12]
-#define RTC_YEAR 9 // year [00..99]
-#define RTC_CONTROL_REGISTERA 10 // control register A
-#define RTC_CONTROL_REGISTERB 11 // control register B
-#define RTC_CONTROL_REGISTERC 12 // control register C
-#define RTC_CONTROL_REGISTERD 13 // control register D
-#define RTC_REGNUMBER_RTC_CR1 0x6A // control register 1
-
#define PCHIP_PCI0_MEMORY ULL(0x00000000000)
#define PCHIP_PCI0_IO ULL(0x001FC000000)
#define TSUNAMI_UNCACHABLE_BIT ULL(0x80000000000)
diff --git a/dev/uart.cc b/dev/uart.cc
index 2ff94dda5..3c4ab6d04 100644
--- a/dev/uart.cc
+++ b/dev/uart.cc
@@ -88,8 +88,8 @@ Uart::IntrEvent::scheduleIntr()
Uart::Uart(const string &name, SimConsole *c, MemoryController *mmu, Addr a,
Addr s, HierParams *hier, Bus *bus, Tick pio_latency, Platform *p)
- : PioDevice(name), addr(a), size(s), cons(c), txIntrEvent(this, TX_INT),
- rxIntrEvent(this, RX_INT), platform(p)
+ : PioDevice(name, p), addr(a), size(s), cons(c),
+ txIntrEvent(this, TX_INT), rxIntrEvent(this, RX_INT)
{
mmu->add_child(this, RangeSize(addr, size));
diff --git a/dev/uart.hh b/dev/uart.hh
index 855915840..d1f167526 100644
--- a/dev/uart.hh
+++ b/dev/uart.hh
@@ -72,7 +72,6 @@ class Uart : public PioDevice
IntrEvent txIntrEvent;
IntrEvent rxIntrEvent;
- Platform *platform;
public:
Uart(const std::string &name, SimConsole *c, MemoryController *mmu,
diff --git a/kern/linux/linux_syscalls.hh b/kern/linux/linux_syscalls.hh
index dee7c5fcd..44a038def 100644
--- a/kern/linux/linux_syscalls.hh
+++ b/kern/linux/linux_syscalls.hh
@@ -26,14 +26,15 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef __LINUX_SYSCALLS_HH__
-#define __LINUX_SYSCALLS_HH__
+#ifndef __KERN_LINUX_LINUX_SYSCALLS_HH__
+#define __KERN_LINUX_LINUX_SYSCALLS_HH__
#include "kern/linux/linux.hh"
template <class OS>
class SystemCalls;
+template <>
class SystemCalls<Linux>
{
public:
@@ -322,4 +323,4 @@ class SystemCalls<Linux>
};
-#endif // __LINUX_SYSCALLS_HH__
+#endif // __KERN_LINUX_LINUX_SYSCALLS_HH__
diff --git a/kern/linux/linux_system.cc b/kern/linux/linux_system.cc
index 4342463c3..4ac03143e 100644
--- a/kern/linux/linux_system.cc
+++ b/kern/linux/linux_system.cc
@@ -102,12 +102,19 @@ LinuxSystem::LinuxSystem(Params *p)
} else
panic("could not find dp264_mv\n");
-#ifdef DEBUG
+#ifndef NDEBUG
kernelPanicEvent = new BreakPCEvent(&pcEventQueue, "kernel panic");
if (kernelSymtab->findAddress("panic", addr))
kernelPanicEvent->schedule(addr);
else
panic("could not find kernel symbol \'panic\'");
+
+ kernelDieEvent = new BreakPCEvent(&pcEventQueue, "die if kernel");
+ if (kernelSymtab->findAddress("die_if_kernel", addr))
+ kernelDieEvent->schedule(addr);
+ else
+ panic("could not find kernel symbol \'die_if_kernel\'");
+
#endif
/**
@@ -174,7 +181,7 @@ LinuxSystem::LinuxSystem(Params *p)
LinuxSystem::~LinuxSystem()
{
-#ifdef DEBUG
+#ifndef NDEBUG
delete kernelPanicEvent;
#endif
delete skipIdeDelay50msEvent;
@@ -208,12 +215,12 @@ LinuxSystem::setDelayLoop(ExecContext *xc)
BEGIN_DECLARE_SIM_OBJECT_PARAMS(LinuxSystem)
- SimObjectParam<MemoryController *> mem_ctl;
+ SimObjectParam<MemoryController *> memctrl;
SimObjectParam<PhysicalMemory *> physmem;
- Param<string> kernel_code;
- Param<string> console_code;
- Param<string> pal_code;
+ Param<string> kernel;
+ Param<string> console;
+ Param<string> pal;
Param<string> boot_osflags;
Param<string> readfile;
@@ -230,11 +237,11 @@ END_DECLARE_SIM_OBJECT_PARAMS(LinuxSystem)
BEGIN_INIT_SIM_OBJECT_PARAMS(LinuxSystem)
- INIT_PARAM(mem_ctl, "memory controller"),
+ INIT_PARAM(memctrl, "memory controller"),
INIT_PARAM(physmem, "phsyical memory"),
- INIT_PARAM(kernel_code, "file that contains the kernel code"),
- INIT_PARAM(console_code, "file that contains the console code"),
- INIT_PARAM(pal_code, "file that contains palcode"),
+ INIT_PARAM(kernel, "file that contains the kernel code"),
+ INIT_PARAM(console, "file that contains the console code"),
+ INIT_PARAM(pal, "file that contains palcode"),
INIT_PARAM_DFLT(boot_osflags, "flags to pass to the kernel during boot",
"a"),
INIT_PARAM_DFLT(readfile, "file to read startup script from", ""),
@@ -251,11 +258,11 @@ CREATE_SIM_OBJECT(LinuxSystem)
{
System::Params *p = new System::Params;
p->name = getInstanceName();
- p->memctrl = mem_ctl;
+ p->memctrl = memctrl;
p->physmem = physmem;
- p->kernel_path = kernel_code;
- p->console_path = console_code;
- p->palcode = pal_code;
+ p->kernel_path = kernel;
+ p->console_path = console;
+ p->palcode = pal;
p->boot_osflags = boot_osflags;
p->init_param = init_param;
p->readfile = readfile;
diff --git a/kern/linux/linux_system.hh b/kern/linux/linux_system.hh
index 5e3cba9b3..905b0ee70 100644
--- a/kern/linux/linux_system.hh
+++ b/kern/linux/linux_system.hh
@@ -57,9 +57,12 @@ class PrintThreadInfo;
class LinuxSystem : public System
{
private:
-#ifdef DEBUG
+#ifndef NDEBUG
/** Event to halt the simulator if the kernel calls panic() */
BreakPCEvent *kernelPanicEvent;
+
+ /** Event to halt the simulator if the kernel calls die_if_kernel */
+ BreakPCEvent *kernelDieEvent;
#endif
/**
diff --git a/kern/tru64/tru64_syscalls.hh b/kern/tru64/tru64_syscalls.hh
index 7ddc699b1..44e5de250 100644
--- a/kern/tru64/tru64_syscalls.hh
+++ b/kern/tru64/tru64_syscalls.hh
@@ -26,14 +26,15 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef __TRU64_SYSCALLS_HH__
-#define __TRU64_SYSCALLS_HH__
+#ifndef __KERN_TRU64_TRU64_SYSCALLS_HH__
+#define __KERN_TRU64_TRU64_SYSCALLS_HH__
#include "kern/tru64/tru64.hh"
template <class OS>
class SystemCalls;
+template <>
class SystemCalls<Tru64>
{
public:
@@ -355,4 +356,4 @@ class SystemCalls<Tru64>
}
};
-#endif // __TRU64_SYSCALLS_HH__
+#endif // __KERN_TRU64_TRU64_SYSCALLS_HH__
diff --git a/kern/tru64/tru64_system.cc b/kern/tru64/tru64_system.cc
index c6435cb18..7a2e033d8 100644
--- a/kern/tru64/tru64_system.cc
+++ b/kern/tru64/tru64_system.cc
@@ -116,12 +116,12 @@ Tru64System::~Tru64System()
BEGIN_DECLARE_SIM_OBJECT_PARAMS(Tru64System)
- SimObjectParam<MemoryController *> mem_ctl;
+ SimObjectParam<MemoryController *> memctrl;
SimObjectParam<PhysicalMemory *> physmem;
- Param<string> kernel_code;
- Param<string> console_code;
- Param<string> pal_code;
+ Param<string> kernel;
+ Param<string> console;
+ Param<string> pal;
Param<string> boot_osflags;
Param<string> readfile;
@@ -137,11 +137,11 @@ END_DECLARE_SIM_OBJECT_PARAMS(Tru64System)
BEGIN_INIT_SIM_OBJECT_PARAMS(Tru64System)
- INIT_PARAM(mem_ctl, "memory controller"),
+ INIT_PARAM(memctrl, "memory controller"),
INIT_PARAM(physmem, "phsyical memory"),
- INIT_PARAM(kernel_code, "file that contains the kernel code"),
- INIT_PARAM(console_code, "file that contains the console code"),
- INIT_PARAM(pal_code, "file that contains palcode"),
+ INIT_PARAM(kernel, "file that contains the kernel code"),
+ INIT_PARAM(console, "file that contains the console code"),
+ INIT_PARAM(pal, "file that contains palcode"),
INIT_PARAM_DFLT(boot_osflags, "flags to pass to the kernel during boot",
"a"),
INIT_PARAM_DFLT(readfile, "file to read startup script from", ""),
@@ -157,11 +157,11 @@ CREATE_SIM_OBJECT(Tru64System)
{
System::Params *p = new System::Params;
p->name = getInstanceName();
- p->memctrl = mem_ctl;
+ p->memctrl = memctrl;
p->physmem = physmem;
- p->kernel_path = kernel_code;
- p->console_path = console_code;
- p->palcode = pal_code;
+ p->kernel_path = kernel;
+ p->console_path = console;
+ p->palcode = pal;
p->boot_osflags = boot_osflags;
p->init_param = init_param;
p->readfile = readfile;
diff --git a/objects/AlphaConsole.mpy b/objects/AlphaConsole.mpy
new file mode 100644
index 000000000..79918a01e
--- /dev/null
+++ b/objects/AlphaConsole.mpy
@@ -0,0 +1,9 @@
+from Device import PioDevice
+
+simobj AlphaConsole(PioDevice):
+ type = 'AlphaConsole'
+ cpu = Param.BaseCPU(Super, "Processor")
+ disk = Param.SimpleDisk("Simple Disk")
+ num_cpus = Param.Int(1, "Number of CPUs")
+ sim_console = Param.SimConsole(Super, "The Simulator Console")
+ system = Param.BaseSystem(Super, "system object")
diff --git a/objects/AlphaTLB.mpy b/objects/AlphaTLB.mpy
new file mode 100644
index 000000000..8e7cd62cc
--- /dev/null
+++ b/objects/AlphaTLB.mpy
@@ -0,0 +1,12 @@
+simobj AlphaTLB(SimObject):
+ type = 'AlphaTLB'
+ abstract = True
+ size = Param.Int("TLB size")
+
+simobj AlphaDTB(AlphaTLB):
+ type = 'AlphaDTB'
+ size = 64
+
+simobj AlphaITB(AlphaTLB):
+ type = 'AlphaITB'
+ size = 48
diff --git a/objects/BadDevice.mpy b/objects/BadDevice.mpy
new file mode 100644
index 000000000..35a12e0bf
--- /dev/null
+++ b/objects/BadDevice.mpy
@@ -0,0 +1,5 @@
+from Device import PioDevice
+
+simobj BadDevice(PioDevice):
+ type = 'BadDevice'
+ devicename = Param.String("Name of device to error on")
diff --git a/objects/BaseCPU.mpy b/objects/BaseCPU.mpy
new file mode 100644
index 000000000..484fcccd6
--- /dev/null
+++ b/objects/BaseCPU.mpy
@@ -0,0 +1,25 @@
+simobj BaseCPU(SimObject):
+ type = 'BaseCPU'
+ abstract = True
+ icache = Param.BaseMem(NULL, "L1 instruction cache object")
+ dcache = Param.BaseMem(NULL, "L1 data cache object")
+
+ if Bool._convert(env.get('FULL_SYSTEM', 'False')):
+ dtb = Param.AlphaDTB("Data TLB")
+ itb = Param.AlphaITB("Instruction TLB")
+ mem = Param.FunctionalMemory("memory")
+ system = Param.BaseSystem(Super, "system object")
+ else:
+ workload = VectorParam.Process("processes to run")
+
+ max_insts_all_threads = Param.Counter(0,
+ "terminate when all threads have reached this inst count")
+ max_insts_any_thread = Param.Counter(0,
+ "terminate when any thread reaches this inst count")
+ max_loads_all_threads = Param.Counter(0,
+ "terminate when all threads have reached this load count")
+ max_loads_any_thread = Param.Counter(0,
+ "terminate when any thread reaches this load count")
+
+ defer_registration = Param.Bool(False,
+ "defer registration with system (for sampling)")
diff --git a/objects/BaseCache.mpy b/objects/BaseCache.mpy
new file mode 100644
index 000000000..98a422e30
--- /dev/null
+++ b/objects/BaseCache.mpy
@@ -0,0 +1,38 @@
+from BaseMem import BaseMem
+
+simobj BaseCache(BaseMem):
+ type = 'BaseCache'
+ adaptive_compression = Param.Bool(False,
+ "Use an adaptive compression scheme")
+ assoc = Param.Int("associativity")
+ block_size = Param.Int("block size in bytes")
+ compressed_bus = Param.Bool(False,
+ "This cache connects to a compressed memory")
+ compression_latency = Param.Int(0,
+ "Latency in cycles of compression algorithm")
+ do_copy = Param.Bool(False, "perform fast copies in the cache")
+ hash_delay = Param.Int(1, "time in cycles of hash access")
+ in_bus = Param.Bus(NULL, "incoming bus object")
+ lifo = Param.Bool(False,
+ "whether this NIC partition should use LIFO repl. policy")
+ max_miss_count = Param.Counter(0,
+ "number of misses to handle before calling exit")
+ mshrs = Param.Int("number of MSHRs (max outstanding requests)")
+ out_bus = Param.Bus("outgoing bus object")
+ prioritizeRequests = Param.Bool(False,
+ "always service demand misses first")
+ protocol = Param.CoherenceProtocol(NULL, "coherence protocol to use")
+ repl = Param.Repl(NULL, "replacement policy")
+ size = Param.Int("capacity in bytes")
+ split = Param.Bool(False, "whether or not this cache is split")
+ split_size = Param.Int(0,
+ "How many ways of the cache belong to CPU/LRU partition")
+ store_compressed = Param.Bool(False,
+ "Store compressed data in the cache")
+ subblock_size = Param.Int(0,
+ "Size of subblock in IIC used for compression")
+ tgts_per_mshr = Param.Int("max number of accesses per MSHR")
+ trace_addr = Param.Addr(0, "address to trace")
+ two_queue = Param.Bool(False,
+ "whether the lifo should have two queue replacement")
+ write_buffers = Param.Int(8, "number of write buffers")
diff --git a/objects/BaseSystem.mpy b/objects/BaseSystem.mpy
new file mode 100644
index 000000000..1cbdf4e99
--- /dev/null
+++ b/objects/BaseSystem.mpy
@@ -0,0 +1,15 @@
+simobj BaseSystem(SimObject):
+ type = 'BaseSystem'
+ abstract = True
+ memctrl = Param.MemoryController(Super, "memory controller")
+ physmem = Param.PhysicalMemory(Super, "phsyical memory")
+ kernel = Param.String("file that contains the kernel code")
+ console = Param.String("file that contains the console code")
+ pal = Param.String("file that contains palcode")
+ readfile = Param.String("", "file to read startup script from")
+ init_param = Param.UInt64(0, "numerical value to pass into simulator")
+ boot_osflags = Param.String("a", "boot flags to pass to the kernel")
+ system_type = Param.UInt64("Type of system we are emulating")
+ system_rev = Param.UInt64("Revision of system we are emulating")
+ bin = Param.Bool(False, "is this system binned")
+ binned_fns = VectorParam.String([], "functions broken down and binned")
diff --git a/objects/Bus.mpy b/objects/Bus.mpy
new file mode 100644
index 000000000..025d69785
--- /dev/null
+++ b/objects/Bus.mpy
@@ -0,0 +1,6 @@
+from BaseHier import BaseHier
+
+simobj Bus(BaseHier):
+ type = 'Bus'
+ clock_ratio = Param.Int("ratio of CPU to bus frequency")
+ width = Param.Int("bus width in bytes")
diff --git a/objects/CoherenceProtocol.mpy b/objects/CoherenceProtocol.mpy
new file mode 100644
index 000000000..f3b0026b7
--- /dev/null
+++ b/objects/CoherenceProtocol.mpy
@@ -0,0 +1,6 @@
+class Coherence(Enum): vals = ['uni', 'msi', 'mesi', 'mosi', 'moesi']
+
+simobj CoherenceProtocol(SimObject):
+ type = 'CoherenceProtocol'
+ do_upgrades = Param.Bool(True, "use upgrade transactions?")
+ protocol = Param.Coherence("name of coherence protocol")
diff --git a/objects/Device.mpy b/objects/Device.mpy
new file mode 100644
index 000000000..47f8db1cb
--- /dev/null
+++ b/objects/Device.mpy
@@ -0,0 +1,33 @@
+from FunctionalMemory import FunctionalMemory
+
+# This device exists only because there are some devices that I don't
+# want to have a Platform parameter because it would cause a cycle in
+# the C++ that cannot be easily solved.
+#
+# The real solution to this problem is to pass the ParamXXX structure
+# to the constructor, but with the express condition that SimObject
+# parameter values are not to be available at construction time. If
+# some further configuration must be done, it must be done during the
+# initialization phase at which point all SimObject pointers will be
+# valid.
+simobj FooPioDevice(FunctionalMemory):
+ type = 'PioDevice'
+ abstract = True
+ addr = Param.Addr("Device Address")
+ mmu = Param.MemoryController(Super, "Memory Controller")
+ io_bus = Param.Bus(NULL, "The IO Bus to attach to")
+ pio_latency = Param.Tick(1, "Programmed IO latency in bus cycles")
+
+simobj FooDmaDevice(FooPioDevice):
+ type = 'DmaDevice'
+ abstract = True
+
+simobj PioDevice(FooPioDevice):
+ type = 'PioDevice'
+ abstract = True
+ platform = Param.Platform(Super, "Platform")
+
+simobj DmaDevice(PioDevice):
+ type = 'DmaDevice'
+ abstract = True
+
diff --git a/objects/DiskImage.mpy b/objects/DiskImage.mpy
new file mode 100644
index 000000000..80ef7b072
--- /dev/null
+++ b/objects/DiskImage.mpy
@@ -0,0 +1,14 @@
+simobj DiskImage(SimObject):
+ type = 'DiskImage'
+ abstract = True
+ image_file = Param.String("disk image file")
+ read_only = Param.Bool(False, "read only image")
+
+simobj RawDiskImage(DiskImage):
+ type = 'RawDiskImage'
+
+simobj CowDiskImage(DiskImage):
+ type = 'CowDiskImage'
+ child = Param.DiskImage("child image")
+ table_size = Param.Int(65536, "initial table size")
+ image_file = ''
diff --git a/objects/Ethernet.mpy b/objects/Ethernet.mpy
new file mode 100644
index 000000000..088df4b93
--- /dev/null
+++ b/objects/Ethernet.mpy
@@ -0,0 +1,86 @@
+from Device import DmaDevice
+from Pci import PciDevice
+
+simobj EtherInt(SimObject):
+ type = 'EtherInt'
+ abstract = True
+ peer = Param.EtherInt(NULL, "peer interface")
+
+simobj EtherLink(SimObject):
+ type = 'EtherLink'
+ int1 = Param.EtherInt("interface 1")
+ int2 = Param.EtherInt("interface 2")
+ delay = Param.Tick(0, "transmit delay of packets in us")
+ speed = Param.Tick(100000000, "link speed in bits per second")
+ dump = Param.EtherDump(NULL, "dump object")
+
+simobj EtherBus(SimObject):
+ type = 'EtherBus'
+ loopback = Param.Bool(True,
+ "send packet back to the interface from which it came")
+ dump = Param.EtherDump(NULL, "dump object")
+ speed = Param.UInt64(100000000, "bus speed in bits per second")
+
+simobj EtherTap(EtherInt):
+ type = 'EtherTap'
+ bufsz = Param.Int(10000, "tap buffer size")
+ dump = Param.EtherDump(NULL, "dump object")
+ port = Param.UInt16(3500, "tap port")
+
+simobj EtherDump(SimObject):
+ type = 'EtherDump'
+ file = Param.String("dump file")
+
+simobj EtherDev(DmaDevice):
+ type = 'EtherDev'
+ hardware_address = Param.EthernetAddr(NextEthernetAddr,
+ "Ethernet Hardware Address")
+
+ dma_data_free = Param.Bool(False, "DMA of Data is free")
+ dma_desc_free = Param.Bool(False, "DMA of Descriptors is free")
+ dma_read_delay = Param.Tick(0, "fixed delay for dma reads")
+ dma_read_factor = Param.Tick(0, "multiplier for dma reads")
+ dma_write_delay = Param.Tick(0, "fixed delay for dma writes")
+ dma_write_factor = Param.Tick(0, "multiplier for dma writes")
+
+ rx_filter = Param.Bool(True, "Enable Receive Filter")
+ rx_delay = Param.Tick(1000, "Receive Delay")
+ tx_delay = Param.Tick(1000, "Transmit Delay")
+
+ intr_delay = Param.Tick(0, "Interrupt Delay in microseconds")
+ payload_bus = Param.Bus(NULL, "The IO Bus to attach to for payload")
+ physmem = Param.PhysicalMemory(Super, "Physical Memory")
+ tlaser = Param.Turbolaser(Super, "Turbolaser")
+
+simobj NSGigE(PciDevice):
+ type = 'NSGigE'
+ hardware_address = Param.EthernetAddr(NextEthernetAddr,
+ "Ethernet Hardware Address")
+
+ dma_data_free = Param.Bool(False, "DMA of Data is free")
+ dma_desc_free = Param.Bool(False, "DMA of Descriptors is free")
+ dma_read_delay = Param.Tick(0, "fixed delay for dma reads")
+ dma_read_factor = Param.Tick(0, "multiplier for dma reads")
+ dma_write_delay = Param.Tick(0, "fixed delay for dma writes")
+ dma_write_factor = Param.Tick(0, "multiplier for dma writes")
+
+ rx_filter = Param.Bool(True, "Enable Receive Filter")
+ rx_delay = Param.Tick(1000, "Receive Delay")
+ tx_delay = Param.Tick(1000, "Transmit Delay")
+
+ rx_fifo_size = Param.Int(131072, "max size in bytes of rxFifo")
+ tx_fifo_size = Param.Int(131072, "max size in bytes of txFifo")
+
+ intr_delay = Param.Tick(0, "Interrupt Delay in microseconds")
+ payload_bus = Param.Bus(NULL, "The IO Bus to attach to for payload")
+ physmem = Param.PhysicalMemory(Super, "Physical Memory")
+
+simobj EtherDevInt(EtherInt):
+ type = 'EtherDevInt'
+ device = Param.EtherDev("Ethernet device of this interface")
+
+simobj NSGigEInt(EtherInt):
+ type = 'NSGigEInt'
+ device = Param.NSGigE("Ethernet device of this interface")
+
+
diff --git a/objects/Ide.mpy b/objects/Ide.mpy
new file mode 100644
index 000000000..ce760ad96
--- /dev/null
+++ b/objects/Ide.mpy
@@ -0,0 +1,14 @@
+from Pci import PciDevice
+
+class IdeID(Enum): vals = ['master', 'slave']
+
+simobj IdeDisk(SimObject):
+ type = 'IdeDisk'
+ delay = Param.Tick(1, "Fixed disk delay in microseconds")
+ driveID = Param.IdeID('master', "Drive ID")
+ image = Param.DiskImage("Disk image")
+ physmem = Param.PhysicalMemory(Super, "Physical memory")
+
+simobj IdeController(PciDevice):
+ type = 'IdeController'
+ disks = VectorParam.IdeDisk("IDE disks attached to this controller")
diff --git a/objects/IntrControl.mpy b/objects/IntrControl.mpy
new file mode 100644
index 000000000..1ef5a17ee
--- /dev/null
+++ b/objects/IntrControl.mpy
@@ -0,0 +1,3 @@
+simobj IntrControl(SimObject):
+ type = 'IntrControl'
+ cpu = Param.BaseCPU(Super, "the cpu")
diff --git a/objects/MemTest.mpy b/objects/MemTest.mpy
new file mode 100644
index 000000000..af14ed9c3
--- /dev/null
+++ b/objects/MemTest.mpy
@@ -0,0 +1,18 @@
+simobj MemTest(SimObject):
+ type = 'MemTest'
+ cache = Param.BaseCache("L1 cache")
+ check_mem = Param.FunctionalMemory("check memory")
+ main_mem = Param.FunctionalMemory("hierarchical memory")
+ max_loads = Param.Counter("number of loads to execute")
+ memory_size = Param.Int(65536, "memory size")
+ percent_copies = Param.Percent(0, "target copy percentage")
+ percent_dest_unaligned = Param.Percent(50,
+ "percent of copy dest address that are unaligned")
+ percent_reads = Param.Percent(65, "target read percentage")
+ percent_source_unaligned = Param.Percent(50,
+ "percent of copy source address that are unaligned")
+ percent_uncacheable = Param.Percent(10,
+ "target uncacheable percentage")
+ progress_interval = Param.Counter(1000000,
+ "progress report interval (in accesses)")
+ trace_addr = Param.Addr(0, "address to trace")
diff --git a/objects/Pci.mpy b/objects/Pci.mpy
new file mode 100644
index 000000000..caa3c52ff
--- /dev/null
+++ b/objects/Pci.mpy
@@ -0,0 +1,52 @@
+from Device import FooPioDevice, DmaDevice
+
+simobj PciConfigData(FooPioDevice):
+ type = 'PciConfigData'
+ addr = 0xffffffffffffffffL
+ VendorID = Param.UInt16("Vendor ID")
+ DeviceID = Param.UInt16("Device ID")
+ Command = Param.UInt16(0, "Command")
+ Status = Param.UInt16(0, "Status")
+ Revision = Param.UInt8(0, "Device")
+ ProgIF = Param.UInt8(0, "Programming Interface")
+ SubClassCode = Param.UInt8(0, "Sub-Class Code")
+ ClassCode = Param.UInt8(0, "Class Code")
+ CacheLineSize = Param.UInt8(0, "System Cacheline Size")
+ LatencyTimer = Param.UInt8(0, "PCI Latency Timer")
+ HeaderType = Param.UInt8(0, "PCI Header Type")
+ BIST = Param.UInt8(0, "Built In Self Test")
+
+ BAR0 = Param.UInt32(0x00, "Base Address Register 0")
+ BAR1 = Param.UInt32(0x00, "Base Address Register 1")
+ BAR2 = Param.UInt32(0x00, "Base Address Register 2")
+ BAR3 = Param.UInt32(0x00, "Base Address Register 3")
+ BAR4 = Param.UInt32(0x00, "Base Address Register 4")
+ BAR5 = Param.UInt32(0x00, "Base Address Register 5")
+ BAR0Size = Param.UInt32(0, "Base Address Register 0 Size")
+ BAR1Size = Param.UInt32(0, "Base Address Register 1 Size")
+ BAR2Size = Param.UInt32(0, "Base Address Register 2 Size")
+ BAR3Size = Param.UInt32(0, "Base Address Register 3 Size")
+ BAR4Size = Param.UInt32(0, "Base Address Register 4 Size")
+ BAR5Size = Param.UInt32(0, "Base Address Register 5 Size")
+
+ CardbusCIS = Param.UInt32(0x00, "Cardbus Card Information Structure")
+ SubsystemID = Param.UInt16(0x00, "Subsystem ID")
+ SubsystemVendorID = Param.UInt16(0x00, "Subsystem Vendor ID")
+ ExpansionROM = Param.UInt32(0x00, "Expansion ROM Base Address")
+ InterruptLine = Param.UInt8(0x00, "Interrupt Line")
+ InterruptPin = Param.UInt8(0x00, "Interrupt Pin")
+ MaximumLatency = Param.UInt8(0x00, "Maximum Latency")
+ MinimumGrant = Param.UInt8(0x00, "Minimum Grant")
+
+simobj PciConfigAll(FooPioDevice):
+ type = 'PciConfigAll'
+
+simobj PciDevice(DmaDevice):
+ type = 'PciDevice'
+ abstract = True
+ pci_bus = Param.Int("PCI bus")
+ pci_dev = Param.Int("PCI device number")
+ pci_func = Param.Int("PCI function code")
+ configdata = Param.PciConfigData(Super, "PCI Config data")
+ configspace = Param.PciConfigAll(Super, "PCI Configspace")
+ addr = 0xffffffffffffffffL
diff --git a/objects/PhysicalMemory.mpy b/objects/PhysicalMemory.mpy
new file mode 100644
index 000000000..d1e4ad4b4
--- /dev/null
+++ b/objects/PhysicalMemory.mpy
@@ -0,0 +1,7 @@
+from FunctionalMemory import FunctionalMemory
+
+simobj PhysicalMemory(FunctionalMemory):
+ type = 'PhysicalMemory'
+ range = Param.AddrRange("Device Address")
+ file = Param.String('', "memory mapped file")
+ mmu = Param.MemoryController(Super, "Memory Controller")
diff --git a/objects/Platform.mpy b/objects/Platform.mpy
new file mode 100644
index 000000000..d0510eaf8
--- /dev/null
+++ b/objects/Platform.mpy
@@ -0,0 +1,5 @@
+simobj Platform(SimObject):
+ type = 'Platform'
+ abstract = True
+ interrupt_frequency = Param.Tick(1200, "frequency of interrupts")
+ intrctrl = Param.IntrControl(Super, "interrupt controller")
diff --git a/objects/Process.mpy b/objects/Process.mpy
new file mode 100644
index 000000000..6a91c09c2
--- /dev/null
+++ b/objects/Process.mpy
@@ -0,0 +1,15 @@
+simobj Process(SimObject):
+ type = 'Process'
+ abstract = True
+ output = Param.String('cout', 'filename for stdout/stderr')
+
+simobj LiveProcess(Process):
+ type = 'LiveProcess'
+ cmd = VectorParam.String("command line (executable plus arguments)")
+ env = VectorParam.String('', "environment settings")
+ input = Param.String('cin', "filename for stdin")
+
+simobj EioProcess(Process):
+ type = 'EioProcess'
+ chkpt = Param.String('', "EIO checkpoint file name (optional)")
+ file = Param.String("EIO trace file name")
diff --git a/objects/Repl.mpy b/objects/Repl.mpy
new file mode 100644
index 000000000..fff5a2a02
--- /dev/null
+++ b/objects/Repl.mpy
@@ -0,0 +1,9 @@
+simobj Repl(SimObject):
+ type = 'Repl'
+ abstract = True
+
+simobj GenRepl(Repl):
+ type = 'GenRepl'
+ fresh_res = Param.Int("associativity")
+ num_pools = Param.Int("capacity in bytes")
+ pool_res = Param.Int("block size in bytes")
diff --git a/objects/Root.mpy b/objects/Root.mpy
new file mode 100644
index 000000000..0e531054b
--- /dev/null
+++ b/objects/Root.mpy
@@ -0,0 +1,15 @@
+from HierParams import HierParams
+from Serialize import Serialize
+from Statistics import Statistics
+from Trace import Trace
+
+simobj Root(SimObject):
+ type = 'Root'
+ frequency = Param.Tick(200000000, "tick frequency")
+ output_file = Param.String('cout', "file to dump simulator output to")
+ full_system = Param.Bool("Full system simulation?")
+ hier = HierParams(do_data = False, do_events = True)
+ checkpoint = Param.String('', "Checkpoint file")
+ stats = Statistics()
+ trace = Trace()
+ serialize = Serialize()
diff --git a/objects/SimConsole.mpy b/objects/SimConsole.mpy
new file mode 100644
index 000000000..fb74f1775
--- /dev/null
+++ b/objects/SimConsole.mpy
@@ -0,0 +1,11 @@
+simobj ConsoleListener(SimObject):
+ type = 'ConsoleListener'
+ port = Param.UInt16(3456, "listen port")
+
+simobj SimConsole(SimObject):
+ type = 'SimConsole'
+ append_name = Param.Bool(True, "append name() to filename")
+ intr_control = Param.IntrControl(Super, "interrupt controller")
+ listener = Param.ConsoleListener("console listener")
+ number = Param.Int(0, "console number")
+ output = Param.String('console', "file to dump output to")
diff --git a/objects/SimpleDisk.mpy b/objects/SimpleDisk.mpy
new file mode 100644
index 000000000..c4dd5435b
--- /dev/null
+++ b/objects/SimpleDisk.mpy
@@ -0,0 +1,4 @@
+simobj SimpleDisk(SimObject):
+ type = 'SimpleDisk'
+ disk = Param.DiskImage("Disk Image")
+ physmem = Param.PhysicalMemory(Super, "Physical Memory")
diff --git a/objects/Tsunami.mpy b/objects/Tsunami.mpy
new file mode 100644
index 000000000..cfe23977e
--- /dev/null
+++ b/objects/Tsunami.mpy
@@ -0,0 +1,25 @@
+from Device import FooPioDevice
+from Platform import Platform
+
+simobj Tsunami(Platform):
+ type = 'Tsunami'
+ pciconfig = Param.PciConfigAll("PCI configuration")
+ system = Param.BaseSystem(Super, "system")
+ interrupt_frequency = Param.Int(1024, "frequency of interrupts")
+
+simobj TsunamiCChip(FooPioDevice):
+ type = 'TsunamiCChip'
+ tsunami = Param.Tsunami(Super, "Tsunami")
+
+simobj TsunamiFake(FooPioDevice):
+ type = 'TsunamiFake'
+
+simobj TsunamiIO(FooPioDevice):
+ type = 'TsunamiIO'
+ time = Param.UInt64(1136073600,
+ "System time to use (0 for actual time, default is 1/1/06)")
+ tsunami = Param.Tsunami(Super, "Tsunami")
+
+simobj TsunamiPChip(FooPioDevice):
+ type = 'TsunamiPChip'
+ tsunami = Param.Tsunami(Super, "Tsunami")
diff --git a/objects/Uart.mpy b/objects/Uart.mpy
new file mode 100644
index 000000000..76ee8805f
--- /dev/null
+++ b/objects/Uart.mpy
@@ -0,0 +1,6 @@
+from Device import PioDevice
+
+simobj Uart(PioDevice):
+ type = 'Uart'
+ console = Param.SimConsole(Super, "The console")
+ size = Param.Addr(0x8, "Device size")
diff --git a/sim/builder.cc b/sim/builder.cc
index fa5c113a7..011694797 100644
--- a/sim/builder.cc
+++ b/sim/builder.cc
@@ -39,14 +39,9 @@
using namespace std;
-SimObjectBuilder::SimObjectBuilder(const string &_configClass,
- const string &_instanceName,
- ConfigNode *_configNode,
- const string &_simObjClassName)
- : ParamContext(_configClass, NoAutoInit),
- instanceName(_instanceName),
- configNode(_configNode),
- simObjClassName(_simObjClassName)
+SimObjectBuilder::SimObjectBuilder(ConfigNode *_configNode)
+ : ParamContext(_configNode->getPath(), NoAutoInit),
+ configNode(_configNode)
{
}
@@ -72,13 +67,8 @@ SimObjectBuilder::parseParams(IniFile &iniFile)
for (i = paramList->begin(); i != paramList->end(); ++i) {
string string_value;
-
- if (iniFile.findDefault(instanceName, (*i)->name, string_value)) {
- (*i)->parse(string_value);
- }
- else if (iniFile.findDefault(iniSection, (*i)->name, string_value)) {
+ if (iniFile.find(iniSection, (*i)->name, string_value))
(*i)->parse(string_value);
- }
}
}
@@ -86,9 +76,8 @@ SimObjectBuilder::parseParams(IniFile &iniFile)
void
SimObjectBuilder::printErrorProlog(ostream &os)
{
- os << "Error creating object '" << getInstanceName()
- << "' of type '" << simObjClassName
- << "', section '" << iniSection << "':" << endl;
+ ccprintf(os, "Error creating object '%s' of type '%s':\n",
+ iniSection, configNode->getType());
}
@@ -111,11 +100,7 @@ SimObjectClass::SimObjectClass(const string &className, CreateFunc createFunc)
classMap = new map<string,SimObjectClass::CreateFunc>();
if ((*classMap)[className])
- {
- cerr << "Error: simulation object class " << className << " redefined"
- << endl;
- fatal("");
- }
+ panic("Error: simulation object class '%s' redefined\n", className);
// add className --> createFunc to class map
(*classMap)[className] = createFunc;
@@ -125,35 +110,20 @@ SimObjectClass::SimObjectClass(const string &className, CreateFunc createFunc)
//
//
SimObject *
-SimObjectClass::createObject(IniFile &configDB,
- const string &configClassName,
- const string &objName,
- ConfigNode *configNode)
+SimObjectClass::createObject(IniFile &configDB, ConfigNode *configNode)
{
- // find simulation object class name from configuration class
- // (specified by 'type=' parameter)
- string simObjClassName;
-
- if (!configNode->find("type", simObjClassName)) {
- cerr << "Configuration class '" << configClassName << "' not found."
- << endl;
- abort();
- }
+ const string &type = configNode->getType();
// look up className to get appropriate createFunc
- if (classMap->find(simObjClassName) == classMap->end()) {
- cerr << "Simulator object class '" << simObjClassName << "' not found."
- << endl;
- abort();
- }
+ if (classMap->find(type) == classMap->end())
+ panic("Simulator object type '%s' not found.\n", type);
+
- CreateFunc createFunc = (*classMap)[simObjClassName];
+ CreateFunc createFunc = (*classMap)[type];
// call createFunc with config hierarchy node to get object
// builder instance (context with parameters for object creation)
- SimObjectBuilder *objectBuilder = (*createFunc)(configClassName,
- objName, configNode,
- simObjClassName);
+ SimObjectBuilder *objectBuilder = (*createFunc)(configNode);
assert(objectBuilder != NULL);
@@ -167,10 +137,10 @@ SimObjectClass::createObject(IniFile &configDB,
// echo object parameters to stats file (for documenting the
// config used to generate the associated stats)
- *configStream << "[" << object->name() << "]" << endl;
- *configStream << "type=" << simObjClassName << endl;
+ ccprintf(*configStream, "[%s]\n", object->name());
+ ccprintf(*configStream, "type=%s\n", type);
objectBuilder->showParams(*configStream);
- *configStream << endl;
+ ccprintf(*configStream, "\n");
// done with the SimObjectBuilder now
delete objectBuilder;
@@ -194,7 +164,7 @@ SimObjectClass::describeAllClasses(ostream &os)
os << "[" << className << "]\n";
// create dummy object builder just to instantiate parameters
- SimObjectBuilder *objectBuilder = (*createFunc)("", "", NULL, "");
+ SimObjectBuilder *objectBuilder = (*createFunc)(NULL);
// now get the object builder to describe ite params
objectBuilder->describeParams(os);
diff --git a/sim/builder.hh b/sim/builder.hh
index 36e40c2a9..f6b7b1a1f 100644
--- a/sim/builder.hh
+++ b/sim/builder.hh
@@ -54,22 +54,13 @@ class SimObject;
class SimObjectBuilder : public ParamContext
{
private:
- // name of the instance we are creating
- std::string instanceName;
-
// The corresponding node in the configuration hierarchy.
// (optional: may be null if the created object is not in the
// hierarchy)
ConfigNode *configNode;
- // The external SimObject class name (for error messages)
- std::string simObjClassName;
-
public:
- SimObjectBuilder(const std::string &_configClass,
- const std::string &_instanceName,
- ConfigNode *_configNode,
- const std::string &_simObjClassName);
+ SimObjectBuilder(ConfigNode *_configNode);
virtual ~SimObjectBuilder();
@@ -82,7 +73,7 @@ class SimObjectBuilder : public ParamContext
// generate the name for this SimObject instance (derived from the
// configuration hierarchy node label and position)
- virtual const std::string &getInstanceName() { return instanceName; }
+ virtual const std::string &getInstanceName() { return iniSection; }
// return the configuration hierarchy node for this context.
virtual ConfigNode *getConfigNode() { return configNode; }
@@ -132,10 +123,7 @@ class SimObjectClass
// 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 SimObjectBuilder is returned.
- typedef SimObjectBuilder *(*CreateFunc)(const std::string &configClassName,
- const std::string &objName,
- ConfigNode *configNode,
- const std::string &simObjClassName);
+ typedef SimObjectBuilder *(*CreateFunc)(ConfigNode *configNode);
static std::map<std::string,CreateFunc> *classMap;
@@ -147,10 +135,7 @@ class SimObjectClass
// create SimObject given name of class and pointer to
// configuration hierarchy node
- static SimObject *createObject(IniFile &configDB,
- const std::string &configClassName,
- const std::string &objName,
- ConfigNode *configNode);
+ static SimObject *createObject(IniFile &configDB, ConfigNode *configNode);
// print descriptions of all parameters registered with all
// SimObject classes
@@ -169,22 +154,15 @@ class OBJ_CLASS##Builder : public SimObjectBuilder \
#define END_DECLARE_SIM_OBJECT_PARAMS(OBJ_CLASS) \
\
- OBJ_CLASS##Builder(const std::string &configClass, \
- const std::string &instanceName, \
- ConfigNode *configNode, \
- const std::string &simObjClassName); \
+ OBJ_CLASS##Builder(ConfigNode *configNode); \
virtual ~OBJ_CLASS##Builder() {} \
\
OBJ_CLASS *create(); \
};
-#define BEGIN_INIT_SIM_OBJECT_PARAMS(OBJ_CLASS) \
-OBJ_CLASS##Builder::OBJ_CLASS##Builder(const std::string &configClass, \
- const std::string &instanceName, \
- ConfigNode *configNode, \
- const std::string &simObjClassName) \
- : SimObjectBuilder(configClass, instanceName, \
- configNode, simObjClassName),
+#define BEGIN_INIT_SIM_OBJECT_PARAMS(OBJ_CLASS) \
+OBJ_CLASS##Builder::OBJ_CLASS##Builder(ConfigNode *configNode) \
+ : SimObjectBuilder(configNode),
#define END_INIT_SIM_OBJECT_PARAMS(OBJ_CLASS) \
@@ -196,13 +174,9 @@ OBJ_CLASS *OBJ_CLASS##Builder::create()
#define REGISTER_SIM_OBJECT(CLASS_NAME, OBJ_CLASS) \
SimObjectBuilder * \
-new##OBJ_CLASS##Builder(const std::string &configClass, \
- const std::string &instanceName, \
- ConfigNode *configNode, \
- const std::string &simObjClassName) \
+new##OBJ_CLASS##Builder(ConfigNode *configNode) \
{ \
- return new OBJ_CLASS##Builder(configClass, instanceName, \
- configNode, simObjClassName); \
+ return new OBJ_CLASS##Builder(configNode); \
} \
\
SimObjectClass the##OBJ_CLASS##Class(CLASS_NAME, \
diff --git a/sim/eventq.hh b/sim/eventq.hh
index 304e4b16a..d62e7df10 100644
--- a/sim/eventq.hh
+++ b/sim/eventq.hh
@@ -30,8 +30,8 @@
* EventQueue interfaces
*/
-#ifndef __EVENTQ_HH__
-#define __EVENTQ_HH__
+#ifndef __SIM_EVENTQ_HH__
+#define __SIM_EVENTQ_HH__
#include <assert.h>
@@ -43,11 +43,24 @@
#include "sim/host.hh" // for Tick
#include "base/fast_alloc.hh"
-#include "sim/serialize.hh"
#include "base/trace.hh"
+#include "sim/serialize.hh"
class EventQueue; // forward declaration
+//////////////////////
+//
+// Main Event Queue
+//
+// Events on this queue are processed at the *beginning* of each
+// cycle, before the pipeline simulation is performed.
+//
+// defined in eventq.cc
+//
+//////////////////////
+extern EventQueue mainEventQueue;
+
+
/*
* An item on an event queue. The action caused by a given
* event is specified by deriving a subclass and overriding the
@@ -228,7 +241,7 @@ DelayFunction(Tick when, T *object)
public:
DelayEvent(Tick when, T *o)
: Event(&mainEventQueue), object(o)
- { setFlags(AutoDestroy); schedule(when); }
+ { setFlags(this->AutoDestroy); schedule(when); }
void process() { (object->*F)(); }
const char *description() { return "delay"; }
};
@@ -386,16 +399,5 @@ EventQueue::reschedule(Event *event)
}
-//////////////////////
-//
-// Main Event Queue
-//
-// Events on this queue are processed at the *beginning* of each
-// cycle, before the pipeline simulation is performed.
-//
-// defined in eventq.cc
-//
-//////////////////////
-extern EventQueue mainEventQueue;
-#endif // __EVENTQ_HH__
+#endif // __SIM_EVENTQ_HH__
diff --git a/sim/main.cc b/sim/main.cc
index e8ac58786..c15d24453 100644
--- a/sim/main.cc
+++ b/sim/main.cc
@@ -31,17 +31,23 @@
///
#include <sys/types.h>
#include <sys/stat.h>
+#include <errno.h>
+#include <libgen.h>
#include <stdlib.h>
#include <signal.h>
+#include <list>
#include <string>
#include <vector>
#include "base/copyright.hh"
+#include "base/embedfile.hh"
#include "base/inifile.hh"
#include "base/misc.hh"
+#include "base/output.hh"
#include "base/pollevent.hh"
#include "base/statistics.hh"
+#include "base/str.hh"
#include "base/time.hh"
#include "cpu/base_cpu.hh"
#include "cpu/full_cpu/smt.hh"
@@ -103,28 +109,35 @@ abortHandler(int sigtype)
}
/// Simulator executable name
-const char *myProgName = "";
+char *myProgName = "";
/// Show brief help message.
-static void
+void
showBriefHelp(ostream &out)
{
- out << "Usage: " << myProgName
- << " [-hnu] [-Dname[=def]] [-Uname] [-I[dir]] "
- << "<config-spec> [<config-spec> ...]\n"
- << "[] [<config file> ...]\n"
- << " -h: print long help (including parameter listing)\n"
- << " -u: don't quit on unreferenced parameters\n"
- << " -D,-U,-I: passed to cpp for preprocessing .ini files\n"
- << " <config-spec>: config file name (.ini or .py) or\n"
- << " single param (--<section>:<param>=<value>)"
- << endl;
+ char *prog = basename(myProgName);
+
+ ccprintf(out, "Usage:\n");
+ ccprintf(out,
+"%s [-d <dir>] [-E <var>[=<val>]] [-I <dir>] [-P <python>]\n"
+" [--<var>=<val>] <config file>\n"
+"\n"
+" -d set the output directory to <dir>\n"
+" -E set the environment variable <var> to <val> (or 'True')\n"
+" -I add the directory <dir> to python's path\n"
+" -P execute <python> directly in the configuration\n"
+" --var=val set the python variable <var> to '<val>'\n"
+" <configfile> config file name (.py or .mpy)\n",
+ prog);
+
+ ccprintf(out, "%s -X\n -X extract embedded files\n", prog);
+ ccprintf(out, "%s -h\n -h print long help\n", prog);
}
/// Show verbose help message. Includes parameter listing from
/// showBriefHelp(), plus an exhaustive list of ini-file parameters
/// and SimObjects (with their parameters).
-static void
+void
showLongHelp(ostream &out)
{
showBriefHelp(out);
@@ -149,7 +162,7 @@ showLongHelp(ostream &out)
}
/// Print welcome message.
-static void
+void
sayHello(ostream &out)
{
extern const char *compileDate; // from date.cc
@@ -173,7 +186,7 @@ sayHello(ostream &out)
/// Echo the command line for posterity in such a way that it can be
/// used to rerun the same simulation (given the same .ini files).
///
-static void
+void
echoCommandLine(int argc, char **argv, ostream &out)
{
out << "command line: " << argv[0];
@@ -205,16 +218,20 @@ echoCommandLine(int argc, char **argv, ostream &out)
out << endl << endl;
}
+char *
+getOptionString(int &index, int argc, char **argv)
+{
+ char *option = argv[index] + 2;
+ if (*option != '\0')
+ return option;
-///
-/// The simulator configuration database. This is the union of all
-/// specified .ini files. This shouldn't need to be visible outside
-/// this file, as it is passed as a parameter to all the param-parsing
-/// routines.
-///
-static IniFile simConfigDB;
+ // We didn't find an argument, it must be in the next variable.
+ if (++index >= argc)
+ panic("option string for option '%s' not found", argv[index - 1]);
+
+ return argv[index];
+}
-/// M5 entry point.
int
main(int argc, char **argv)
{
@@ -230,16 +247,9 @@ main(int argc, char **argv)
sayHello(cerr);
- // Initialize statistics database
- Stats::InitSimStats();
-
- vector<char *> cppArgs;
-
- // Should we quit if there are unreferenced parameters? By
- // default, yes... it's a good way of catching typos in
- // section/parameter names (which otherwise go by silently). Use
- // -u to override.
- bool quitOnUnreferenced = true;
+ bool configfile_found = false;
+ PythonConfig pyconfig;
+ string outdir;
// Parse command-line options.
// Since most of the complex options are handled through the
@@ -248,107 +258,126 @@ main(int argc, char **argv)
for (int i = 1; i < argc; ++i) {
char *arg_str = argv[i];
- // if arg starts with '-', parse as option,
- // else treat it as a configuration file name and load it
- if (arg_str[0] == '-') {
+ // if arg starts with '--', parse as a special python option
+ // of the format --<python var>=<string value>, if the arg
+ // starts with '-', it should be a simulator option with a
+ // format similar to getopt. In any other case, treat the
+ // option as a configuration file name and load it.
+ if (arg_str[0] == '-' && arg_str[1] == '-') {
+ string str = &arg_str[2];
+ string var, val;
+
+ if (!split_first(str, var, val, '='))
+ panic("Could not parse configuration argument '%s'\n"
+ "Expecting --<variable>=<value>\n", arg_str);
+
+ pyconfig.setVariable(var, val);
+ } else if (arg_str[0] == '-') {
+ char *option;
+ string var, val;
// switch on second char
switch (arg_str[1]) {
+ case 'd':
+ outdir = getOptionString(i, argc, argv);
+ break;
+
case 'h':
- // -h: show help
showLongHelp(cerr);
exit(1);
- case 'u':
- // -u: don't quit on unreferenced parameters
- quitOnUnreferenced = false;
+ case 'E':
+ option = getOptionString(i, argc, argv);
+ if (!split_first(option, var, val, '='))
+ val = "True";
+
+ if (setenv(var.c_str(), val.c_str(), true) == -1)
+ panic("setenv: %s\n", strerror(errno));
break;
- case 'D':
- case 'U':
case 'I':
- // cpp options: record & pass to cpp. Note that these
- // cannot have spaces, i.e., '-Dname=val' is OK, but
- // '-D name=val' is not. I don't consider this a
- // problem, since even though gnu cpp accepts the
- // latter, other cpp implementations do not (Tru64,
- // for one).
- cppArgs.push_back(arg_str);
+ option = getOptionString(i, argc, argv);
+ pyconfig.addPath(option);
break;
- case '-':
- // command-line configuration parameter:
- // '--<section>:<parameter>=<value>'
- if (!simConfigDB.add(arg_str + 2)) {
- // parse error
- ccprintf(cerr,
- "Could not parse configuration argument '%s'\n"
- "Expecting --<section>:<parameter>=<value>\n",
- arg_str);
- exit(0);
- }
+ case 'P':
+ option = getOptionString(i, argc, argv);
+ pyconfig.writeLine(option);
break;
+ case 'X': {
+ list<EmbedFile> lst;
+ EmbedMap::all(lst);
+ list<EmbedFile>::iterator i = lst.begin();
+ list<EmbedFile>::iterator end = lst.end();
+
+ while (i != end) {
+ cprintf("Embedded File: %s\n", i->name);
+ cout.write(i->data, i->length);
+ ++i;
+ }
+
+ return 0;
+ }
+
default:
showBriefHelp(cerr);
- ccprintf(cerr, "Fatal: invalid argument '%s'\n", arg_str);
- exit(0);
- }
- }
- else {
- // no '-', treat as config file name
-
- // make STL string out of file name
- string filename(arg_str);
-
- int ext_loc = filename.rfind(".");
-
- string ext =
- (ext_loc != string::npos) ? filename.substr(ext_loc) : "";
-
- if (ext == ".ini") {
- if (!simConfigDB.loadCPP(filename, cppArgs)) {
- cprintf("Error processing file %s\n", filename);
- exit(1);
- }
- } else if (ext == ".py") {
- if (!loadPythonConfig(filename, &simConfigDB)) {
- cprintf("Error processing file %s\n", filename);
- exit(1);
- }
- }
- else {
- cprintf("Config file name '%s' must end in '.py' or '.ini'.\n",
- filename);
- exit(1);
+ panic("invalid argument '%s'\n", arg_str);
}
+ } else {
+ string file(arg_str);
+ string base, ext;
+
+ if (!split_last(file, base, ext, '.') ||
+ ext != "py" && ext != "mpy")
+ panic("Config file '%s' must end in '.py' or '.mpy'\n", file);
+
+ pyconfig.load(file);
+ configfile_found = true;
}
}
+ if (outdir.empty()) {
+ char *env = getenv("OUTPUT_DIR");
+ outdir = env ? env : ".";
+ }
+
+ simout.setDirectory(outdir);
+
+ char *env = getenv("CONFIG_OUTPUT");
+ if (!env)
+ env = "config.out";
+ configStream = simout.find(env);
+
+ if (!configfile_found)
+ panic("no configuration file specified!");
+
// The configuration database is now complete; start processing it.
+ IniFile inifile;
+ if (!pyconfig.output(inifile))
+ panic("Error processing python code");
+
+ // Initialize statistics database
+ Stats::InitSimStats();
+
+ // Now process the configuration hierarchy and create the SimObjects.
+ ConfigHierarchy configHierarchy(inifile);
+ configHierarchy.build();
+ configHierarchy.createSimObjects();
// Parse and check all non-config-hierarchy parameters.
- ParamContext::parseAllContexts(simConfigDB);
+ ParamContext::parseAllContexts(inifile);
ParamContext::checkAllContexts();
- // Print header info into stats file. Can't do this sooner since
- // the stat file name is set via a .ini param... thus it just got
- // opened above during ParamContext::checkAllContexts().
-
// Print hello message to stats file if it's actually a file. If
// it's not (i.e. it's cout or cerr) then we already did it above.
- if (outputStream != &cout && outputStream != &cerr)
+ if (simout.isFile(*outputStream))
sayHello(*outputStream);
// Echo command line and all parameter settings to stats file as well.
echoCommandLine(argc, argv, *outputStream);
ParamContext::showAllContexts(*configStream);
- // Now process the configuration hierarchy and create the SimObjects.
- ConfigHierarchy configHierarchy(simConfigDB);
- configHierarchy.build();
- configHierarchy.createSimObjects();
-
// Do a second pass to finish initializing the sim objects
SimObject::initAll();
@@ -357,13 +386,8 @@ main(int argc, char **argv)
// Done processing the configuration database.
// Check for unreferenced entries.
- if (simConfigDB.printUnreferenced() && quitOnUnreferenced) {
- cerr << "Fatal: unreferenced .ini sections/entries." << endl
- << "If this is not an error, add 'unref_section_ok=y' or "
- << "'unref_entries_ok=y' to the appropriate sections "
- << "to suppress this message." << endl;
- exit(1);
- }
+ if (inifile.printUnreferenced())
+ panic("unreferenced sections/entries in the intermediate ini file");
SimObject::regAllStats();
@@ -378,12 +402,6 @@ main(int argc, char **argv)
// Reset to put the stats in a consistent state.
Stats::reset();
- // Nothing to simulate if we don't have at least one CPU somewhere.
- if (BaseCPU::numSimulatedCPUs() == 0) {
- cerr << "Fatal: no CPUs to simulate." << endl;
- exit(1);
- }
-
warn("Entering event queue. Starting simulation...\n");
SimStartup();
while (!mainEventQueue.empty()) {
diff --git a/sim/param.cc b/sim/param.cc
index d20be8d33..ff023ce85 100644
--- a/sim/param.cc
+++ b/sim/param.cc
@@ -27,21 +27,21 @@
*/
#include <algorithm>
+#include <cassert>
+#include <cstdio>
#include <list>
#include <string>
#include <vector>
-#include <stdio.h> // for sscanf()
-#include <assert.h>
-
-#include "sim/param.hh"
-#include "sim/sim_object.hh"
#include "base/inifile.hh"
-#include "sim/configfile.hh"
-#include "sim/config_node.hh"
#include "base/misc.hh"
+#include "base/range.hh"
#include "base/str.hh"
#include "base/trace.hh"
+#include "sim/config_node.hh"
+#include "sim/configfile.hh"
+#include "sim/param.hh"
+#include "sim/sim_object.hh"
using namespace std;
@@ -180,6 +180,22 @@ parseParam(const string &s, string &value)
return true;
}
+template <>
+bool
+parseParam(const string &s, Range<uint32_t> &value)
+{
+ value = s;
+ return value.valid();
+}
+
+template <>
+bool
+parseParam(const string &s, Range<uint64_t> &value)
+{
+ value = s;
+ return value.valid();
+}
+
//
// End of parseParam/showParam definitions. Now we move on to
// incorporate them into the Param/VectorParam parse() and showValue()
@@ -310,6 +326,9 @@ INSTANTIATE_PARAM_TEMPLATES(double, "double")
INSTANTIATE_PARAM_TEMPLATES(bool, "bool")
INSTANTIATE_PARAM_TEMPLATES(string, "string")
+INSTANTIATE_PARAM_TEMPLATES(Range<uint64_t>, "uint64 range")
+INSTANTIATE_PARAM_TEMPLATES(Range<uint32_t>, "uint32 range")
+
#undef INSTANTIATE_PARAM_TEMPLATES
//
@@ -422,6 +441,11 @@ EnumVectorParam<Map>::parse(const string &s)
{
vector<string> tokens;
+ if (s.empty()) {
+ wasSet = true;
+ return;
+ }
+
tokenize(tokens, s, ' ');
value.resize(tokens.size());
@@ -474,11 +498,11 @@ EnumVectorParam<Map>::showType(ostream &os) const
showEnumType(os, map, num_values);
}
-template EnumParam<const char *>;
-template EnumVectorParam<const char *>;
+template class EnumParam<const char *>;
+template class EnumVectorParam<const char *>;
-template EnumParam<EnumParamMap>;
-template EnumVectorParam<EnumParamMap>;
+template class EnumParam<EnumParamMap>;
+template class EnumVectorParam<EnumParamMap>;
////////////////////////////////////////////////////////////////////////
//
@@ -602,9 +626,8 @@ ParamContext::parseParams(IniFile &iniFile)
for (i = getParamList()->begin(); i != getParamList()->end(); ++i) {
string string_value;
- if (iniFile.findDefault(iniSection, (*i)->name, string_value)) {
+ if (iniFile.find(iniSection, (*i)->name, string_value))
(*i)->parse(string_value);
- }
}
}
@@ -680,18 +703,8 @@ ParamContext::printErrorProlog(ostream &os)
// SimObjectBuilder objects, which return non-NULL for configNode()).
//
SimObject *
-ParamContext::resolveSimObject(const string &_name)
-{
- // look for a colon
- string::size_type i = _name.find(':');
- string name = _name;
- if (i != string::npos) {
- // colon found: local object
- // add as child to current node and create it
- name = _name.substr(0, i);
- string objConfigClassName = _name.substr(i + 1);
- getConfigNode()->addChild(name, objConfigClassName);
- }
+ParamContext::resolveSimObject(const string &name)
+{
ConfigNode *n = getConfigNode();
return n ? n->resolveSimObject(name) : NULL;
}
diff --git a/sim/param.hh b/sim/param.hh
index ac57afa31..f4b9d3450 100644
--- a/sim/param.hh
+++ b/sim/param.hh
@@ -26,9 +26,10 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef __PARAM_HH__
-#define __PARAM_HH__
+#ifndef __SIM_PARAM_HH__
+#define __SIM_PARAM_HH__
+#include <iostream>
#include <list>
#include <string>
#include <vector>
@@ -524,7 +525,7 @@ class MappedEnumParam : public EnumParam<EnumParamMap>
{
if (!isValid())
die("not found");
- return (ENUM)value[n];
+ return (ENUM)value[this->n];
}
};
@@ -782,4 +783,4 @@ SimObjectVectorParam<OBJ_CLASS *>::showType(std::ostream &os) const \
template <class T> bool parseParam(const std::string &str, T &data);
template <class T> void showParam(std::ostream &os, const T &data);
-#endif // _PARAM_HH
+#endif // _SIM_PARAM_HH_
diff --git a/sim/process.cc b/sim/process.cc
index bd1a2d8fd..7111e8733 100644
--- a/sim/process.cc
+++ b/sim/process.cc
@@ -65,14 +65,14 @@ using namespace std;
// current number of allocated processes
int num_processes = 0;
-Process::Process(const string &name,
+Process::Process(const string &nm,
int stdin_fd, // initial I/O descriptors
int stdout_fd,
int stderr_fd)
- : SimObject(name)
+ : SimObject(nm)
{
// allocate memory space
- memory = new MainMemory(name + ".MainMem");
+ memory = new MainMemory(nm + ".MainMem");
// allocate initial register file
init_regs = new RegFile;
@@ -88,8 +88,7 @@ Process::Process(const string &name,
fd_map[i] = -1;
}
- num_syscalls = 0;
-
+ mmap_start = mmap_end = 0;
// other parameters will be initialized when the program is loaded
}
@@ -145,21 +144,28 @@ Process::registerExecContext(ExecContext *xc)
execContexts.push_back(xc);
if (myIndex == 0) {
- // first exec context for this process... initialize & enable
-
// copy process's initial regs struct
xc->regs = *init_regs;
-
- // mark this context as active.
- // activate with zero delay so that we start ticking right
- // away on cycle 0
- xc->activate(0);
}
// return CPU number to caller and increment available CPU count
return myIndex;
}
+void
+Process::startup()
+{
+ if (execContexts.empty())
+ return;
+
+ // first exec context for this process... initialize & enable
+ ExecContext *xc = execContexts[0];
+
+ // mark this context as active.
+ // activate with zero delay so that we start ticking right
+ // away on cycle 0
+ xc->activate(0);
+}
void
Process::replaceExecContext(ExecContext *xc, int xcIndex)
@@ -247,10 +253,10 @@ copyStringArray(vector<string> &strings, Addr array_ptr, Addr data_ptr,
memory->access(Write, array_ptr, &data_ptr, sizeof(Addr));
}
-LiveProcess::LiveProcess(const string &name, ObjectFile *objFile,
+LiveProcess::LiveProcess(const string &nm, ObjectFile *objFile,
int stdin_fd, int stdout_fd, int stderr_fd,
vector<string> &argv, vector<string> &envp)
- : Process(name, stdin_fd, stdout_fd, stderr_fd)
+ : Process(nm, stdin_fd, stdout_fd, stderr_fd)
{
prog_fname = argv[0];
@@ -282,7 +288,7 @@ LiveProcess::LiveProcess(const string &name, ObjectFile *objFile,
// Set up region for mmaps. Tru64 seems to start just above 0 and
// grow up from there.
- mmap_base = 0x10000;
+ mmap_start = mmap_end = 0x10000;
// Set pointer for next thread stack. Reserve 8M for main stack.
next_thread_stack_base = stack_base - (8 * 1024 * 1024);
@@ -334,7 +340,7 @@ LiveProcess::LiveProcess(const string &name, ObjectFile *objFile,
LiveProcess *
-LiveProcess::create(const string &name,
+LiveProcess::create(const string &nm,
int stdin_fd, int stdout_fd, int stderr_fd,
vector<string> &argv, vector<string> &envp)
{
@@ -348,13 +354,13 @@ LiveProcess::create(const string &name,
if (objFile->getArch() == ObjectFile::Alpha) {
switch (objFile->getOpSys()) {
case ObjectFile::Tru64:
- process = new AlphaTru64Process(name, objFile,
+ process = new AlphaTru64Process(nm, objFile,
stdin_fd, stdout_fd, stderr_fd,
argv, envp);
break;
case ObjectFile::Linux:
- process = new AlphaLinuxProcess(name, objFile,
+ process = new AlphaLinuxProcess(nm, objFile,
stdin_fd, stdout_fd, stderr_fd,
argv, envp);
break;
@@ -397,19 +403,29 @@ END_INIT_SIM_OBJECT_PARAMS(LiveProcess)
CREATE_SIM_OBJECT(LiveProcess)
{
+ string in = input;
+ string out = output;
+
// initialize file descriptors to default: same as simulator
- int stdin_fd = input.isValid() ? Process::openInputFile(input) : 0;
- int stdout_fd = output.isValid() ? Process::openOutputFile(output) : 1;
- int stderr_fd = output.isValid() ? stdout_fd : 2;
+ int stdin_fd, stdout_fd, stderr_fd;
- // dummy for default env
- vector<string> null_vec;
+ if (in == "stdin" || in == "cin")
+ stdin_fd = STDIN_FILENO;
+ else
+ stdin_fd = Process::openInputFile(input);
+
+ if (out == "stdout" || out == "cout")
+ stdout_fd = STDOUT_FILENO;
+ else if (out == "stderr" || out == "cerr")
+ stdout_fd = STDERR_FILENO;
+ else
+ stdout_fd = Process::openOutputFile(out);
+
+ stderr_fd = (stdout_fd != STDOUT_FILENO) ? stdout_fd : STDERR_FILENO;
return LiveProcess::create(getInstanceName(),
stdin_fd, stdout_fd, stderr_fd,
- cmd,
- env.isValid() ? env : null_vec);
+ cmd, env);
}
-
REGISTER_SIM_OBJECT("LiveProcess", LiveProcess)
diff --git a/sim/process.hh b/sim/process.hh
index bb4829875..1ab43cd62 100644
--- a/sim/process.hh
+++ b/sim/process.hh
@@ -42,6 +42,7 @@
#include "sim/sim_object.hh"
#include "sim/stats.hh"
#include "base/statistics.hh"
+#include "base/trace.hh"
class ExecContext;
class FunctionalMemory;
@@ -93,7 +94,8 @@ class Process : public SimObject
Addr next_thread_stack_base;
// Base of region for mmaps (when user doesn't specify an address).
- Addr mmap_base;
+ Addr mmap_start;
+ Addr mmap_end;
std::string prog_fname; // file name
Addr prog_entry; // entry point (initial PC)
@@ -103,11 +105,13 @@ class Process : public SimObject
protected:
// constructor
- Process(const std::string &name,
+ Process(const std::string &nm,
int stdin_fd, // initial I/O descriptors
int stdout_fd,
int stderr_fd);
+ // post initialization startup
+ virtual void startup();
protected:
FunctionalMemory *memory;
@@ -156,7 +160,8 @@ class Process : public SimObject
{
return ((data_base <= addr && addr < brk_point) ||
((stack_base - 16*1024*1024) <= addr && addr < stack_base) ||
- (text_base <= addr && addr < (text_base + text_size)));
+ (text_base <= addr && addr < (text_base + text_size)) ||
+ (mmap_start <= addr && addr < mmap_end));
}
virtual void syscall(ExecContext *xc) = 0;
@@ -171,7 +176,7 @@ class ObjectFile;
class LiveProcess : public Process
{
protected:
- LiveProcess(const std::string &name, ObjectFile *objFile,
+ LiveProcess(const std::string &nm, ObjectFile *objFile,
int stdin_fd, int stdout_fd, int stderr_fd,
std::vector<std::string> &argv,
std::vector<std::string> &envp);
@@ -180,7 +185,7 @@ class LiveProcess : public Process
// 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(const std::string &name,
+ static LiveProcess *create(const std::string &nm,
int stdin_fd, int stdout_fd, int stderr_fd,
std::vector<std::string> &argv,
std::vector<std::string> &envp);
diff --git a/sim/pyconfig/SConscript b/sim/pyconfig/SConscript
index 7661e7603..2799ef64f 100644
--- a/sim/pyconfig/SConscript
+++ b/sim/pyconfig/SConscript
@@ -1,6 +1,6 @@
# -*- mode:python -*-
-# Copyright (c) 2004 The Regents of The University of Michigan
+# Copyright (c) 2005 The Regents of The University of Michigan
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
@@ -26,25 +26,190 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-import os
+import os, os.path, re
-Import('env', 'obj_desc_files')
+def WriteEmbeddedPyFile(target, source, path, name, ext, filename):
+ if isinstance(source, str):
+ source = file(source, 'r')
-my_obj_desc_files = map(lambda x: '../../' + x, obj_desc_files)
+ if isinstance(target, str):
+ target = file(target, 'w')
-env.Command('m5odescs.py', my_obj_desc_files,
- '$TARGET.srcdir/load_odescs.py $_CPPDEFFLAGS $SOURCES $TARGET')
+ print >>target, "AddModule(%s, %s, %s, %s, '''\\" % \
+ (`path`, `name`, `ext`, `filename`)
-# Python modules to encapsulate
-string_module_bases = Split('m5config m5configbase m5odescs')
-string_modules = map(lambda x: x + '_as_string.py', string_module_bases)
+ for line in source:
+ line = line
+ # escape existing backslashes
+ line = line.replace('\\', '\\\\')
+ # escape existing triple quotes
+ line = line.replace("'''", r"\'\'\'")
-for m in string_module_bases:
- env.Command(m + '_as_string.py', m + '.py',
- '$TARGET.srcdir/make_string_module.py $SOURCE $TARGET')
+ print >>target, line,
-embedded_py_files = Split('string_importer.py') + string_modules
+ print >>target, "''')"
+ print >>target
-env.Command('code.cc', embedded_py_files,
- '$TARGET.srcdir/make_c_file.py pyconfig_code $SOURCES $TARGET')
+def WriteCFile(target, source, name):
+ if isinstance(source, str):
+ source = file(source, 'r')
+ if isinstance(target, str):
+ target = file(target, 'w')
+
+ print >>target, 'const char %s_string[] = {' % name
+
+ count = 0
+ from array import array
+ try:
+ while True:
+ foo = array('B')
+ foo.fromfile(source, 10000)
+ l = [ str(i) for i in foo.tolist() ]
+ count += len(l)
+ for i in xrange(0,9999,20):
+ print >>target, ','.join(l[i:i+20]) + ','
+ except EOFError:
+ l = [ str(i) for i in foo.tolist() ]
+ count += len(l)
+ for i in xrange(0,len(l),20):
+ print >>target, ','.join(l[i:i+20]) + ','
+ print >>target, ','.join(l[i:]) + ','
+
+ print >>target, '};'
+ print >>target, 'const int %s_length = %d;' % (name, count)
+ print >>target
+
+def splitpath(path):
+ dir,file = os.path.split(path)
+ path = []
+ assert(file)
+ while dir:
+ dir,base = os.path.split(dir)
+ path.insert(0, base)
+ return path, file
+
+Import('env')
+def MakeEmbeddedPyFile(target, source, env):
+ target = file(str(target[0]), 'w')
+
+ tree = {}
+ for src in source:
+ src = str(src)
+ path,pyfile = splitpath(src)
+ node = tree
+ for dir in path:
+ if not node.has_key(dir):
+ node[dir] = { }
+ node = node[dir]
+
+ name,ext = pyfile.split('.')
+ if name == '__init__':
+ node['.hasinit'] = True
+ node[pyfile] = (src,name,ext,src)
+
+ done = False
+ while not done:
+ done = True
+ for name,entry in tree.items():
+ if not isinstance(entry, dict): continue
+ if entry.has_key('.hasinit'): continue
+
+ done = False
+ del tree[name]
+ for key,val in entry.iteritems():
+ if tree.has_key(key):
+ raise NameError, \
+ "dir already has %s can't add it again" % key
+ tree[key] = val
+
+ files = []
+ def populate(node, path = []):
+ names = node.keys()
+ names.sort()
+ for name in names:
+ if name == '.hasinit':
+ continue
+
+ entry = node[name]
+ if isinstance(entry, dict):
+ if not entry.has_key('.hasinit'):
+ raise NameError, 'package directory missing __init__.py'
+ populate(entry, path + [ name ])
+ else:
+ pyfile,name,ext,filename = entry
+ files.append((pyfile, path, name, ext, filename))
+ populate(tree)
+
+ for pyfile, path, name, ext, filename in files:
+ WriteEmbeddedPyFile(target, pyfile, path, name, ext, filename)
+
+def MakeDefinesPyFile(target, source, env):
+ target = file(str(target[0]), 'w')
+
+ print >>target, "import os"
+ defines = env['CPPDEFINES']
+ if isinstance(defines, list):
+ for var in defines:
+ if isinstance(var, tuple):
+ key,val = var
+ else:
+ key,val = var,'True'
+
+ if not isinstance(key, basestring):
+ panic("invalid type for define: %s" % type(key))
+
+ print >>target, "os.environ['%s'] = '%s'" % (key, val)
+
+ elif isinstance(defines, dict):
+ for key,val in defines.iteritems():
+ print >>target, "os.environ['%s'] = '%s'" % (key, val)
+ else:
+ panic("invalid type for defines: %s" % type(defines))
+
+CFileCounter = 0
+def MakePythonCFile(target, source, env):
+ global CFileCounter
+ target = file(str(target[0]), 'w')
+
+ print >>target, '''\
+#include "base/embedfile.hh"
+
+namespace {
+'''
+ for src in source:
+ src = str(src)
+ fname = os.path.basename(src)
+ name = 'embedded_file%d' % CFileCounter
+ CFileCounter += 1
+ WriteCFile(target, src, name)
+ print >>target, '''\
+EmbedMap %(name)s("%(fname)s",
+ %(name)s_string, %(name)s_length);
+
+''' % locals()
+ print >>target, '''\
+
+/* namespace */ }
+'''
+
+embedded_py_files = ['m5config.py', 'importer.py', '../../util/pbs/jobfile.py']
+objpath = os.path.join(env['SRCDIR'], 'objects')
+for root, dirs, files in os.walk(objpath, topdown=True):
+ for i,dir in enumerate(dirs):
+ if dir == 'SCCS':
+ del dirs[i]
+ break
+
+ assert(root.startswith(objpath))
+ for f in files:
+ if f.endswith('.mpy') or f.endswith('.py'):
+ embedded_py_files.append(os.path.join(root, f))
+
+embedfile_hh = os.path.join(env['SRCDIR'], 'base/embedfile.hh')
+env.Command('defines.py', None, MakeDefinesPyFile)
+env.Command('embedded_py.py', embedded_py_files, MakeEmbeddedPyFile)
+env.Depends('embedded_py.cc', embedfile_hh)
+env.Command('embedded_py.cc',
+ ['string_importer.py', 'defines.py', 'embedded_py.py'],
+ MakePythonCFile)
diff --git a/sim/pyconfig/m5config.py b/sim/pyconfig/m5config.py
new file mode 100644
index 000000000..e6201b3ad
--- /dev/null
+++ b/sim/pyconfig/m5config.py
@@ -0,0 +1,1303 @@
+# 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.
+
+from __future__ import generators
+import os, re, sys, types, inspect
+
+from importer import AddToPath, LoadMpyFile
+
+noDot = False
+try:
+ import pydot
+except:
+ noDot = True
+
+env = {}
+env.update(os.environ)
+
+def panic(string):
+ print >>sys.stderr, 'panic:', string
+ sys.exit(1)
+
+def issequence(value):
+ return isinstance(value, tuple) or isinstance(value, list)
+
+class Singleton(type):
+ def __call__(cls, *args, **kwargs):
+ if hasattr(cls, '_instance'):
+ return cls._instance
+
+ cls._instance = super(Singleton, cls).__call__(*args, **kwargs)
+ return cls._instance
+
+#####################################################################
+#
+# M5 Python Configuration Utility
+#
+# The basic idea is to write simple Python programs that build Python
+# objects corresponding to M5 SimObjects for the deisred simulation
+# configuration. For now, the Python emits a .ini file that can be
+# parsed by M5. In the future, some tighter integration between M5
+# and the Python interpreter may allow bypassing the .ini file.
+#
+# Each SimObject class in M5 is represented by a Python class with the
+# same name. The Python inheritance tree mirrors the M5 C++ tree
+# (e.g., SimpleCPU derives from BaseCPU in both cases, and all
+# SimObjects inherit from a single SimObject base class). To specify
+# an instance of an M5 SimObject in a configuration, the user simply
+# instantiates the corresponding Python object. The parameters for
+# that SimObject are given by assigning to attributes of the Python
+# object, either using keyword assignment in the constructor or in
+# separate assignment statements. For example:
+#
+# cache = BaseCache('my_cache', root, size=64*K)
+# cache.hit_latency = 3
+# cache.assoc = 8
+#
+# (The first two constructor arguments specify the name of the created
+# cache and its parent node in the hierarchy.)
+#
+# The magic lies in the mapping of the Python attributes for SimObject
+# classes to the actual SimObject parameter specifications. This
+# allows parameter validity checking in the Python code. Continuing
+# the example above, the statements "cache.blurfl=3" or
+# "cache.assoc='hello'" would both result in runtime errors in Python,
+# since the BaseCache object has no 'blurfl' parameter and the 'assoc'
+# parameter requires an integer, respectively. This magic is done
+# primarily by overriding the special __setattr__ method that controls
+# assignment to object attributes.
+#
+# The Python module provides another class, ConfigNode, which is a
+# superclass of SimObject. ConfigNode implements the parent/child
+# relationship for building the configuration hierarchy tree.
+# Concrete instances of ConfigNode can be used to group objects in the
+# hierarchy, but do not correspond to SimObjects themselves (like a
+# .ini section with "children=" but no "type=".
+#
+# Once a set of Python objects have been instantiated in a hierarchy,
+# calling 'instantiate(obj)' (where obj is the root of the hierarchy)
+# will generate a .ini file. See simple-4cpu.py for an example
+# (corresponding to m5-test/simple-4cpu.ini).
+#
+#####################################################################
+
+#####################################################################
+#
+# ConfigNode/SimObject classes
+#
+# The Python class hierarchy rooted by ConfigNode (which is the base
+# class of SimObject, which in turn is the base class of all other M5
+# SimObject classes) has special attribute behavior. In general, an
+# object in this hierarchy has three categories of attribute-like
+# things:
+#
+# 1. Regular Python methods and variables. These must start with an
+# underscore to be treated normally.
+#
+# 2. SimObject parameters. These values are stored as normal Python
+# attributes, but all assignments to these attributes are checked
+# against the pre-defined set of parameters stored in the class's
+# _params dictionary. Assignments to attributes that do not
+# correspond to predefined parameters, or that are not of the correct
+# type, incur runtime errors.
+#
+# 3. Hierarchy children. The child nodes of a ConfigNode are stored
+# in the node's _children dictionary, but can be accessed using the
+# Python attribute dot-notation (just as they are printed out by the
+# simulator). Children cannot be created using attribute assigment;
+# they must be added by specifying the parent node in the child's
+# constructor or using the '+=' operator.
+
+# The SimObject parameters are the most complex, for a few reasons.
+# First, both parameter descriptions and parameter values are
+# inherited. Thus parameter description lookup must go up the
+# inheritance chain like normal attribute lookup, but this behavior
+# must be explicitly coded since the lookup occurs in each class's
+# _params attribute. Second, because parameter values can be set
+# on SimObject classes (to implement default values), the parameter
+# checking behavior must be enforced on class attribute assignments as
+# well as instance attribute assignments. Finally, because we allow
+# class specialization via inheritance (e.g., see the L1Cache class in
+# the simple-4cpu.py example), we must do parameter checking even on
+# class instantiation. To provide all these features, we use a
+# metaclass to define most of the SimObject parameter behavior for
+# this class hierarchy.
+#
+#####################################################################
+
+class Proxy(object):
+ def __init__(self, path = ()):
+ self._object = None
+ self._path = path
+
+ def __getattr__(self, attr):
+ return Proxy(self._path + (attr, ))
+
+ def __setattr__(self, attr, value):
+ if not attr.startswith('_'):
+ raise AttributeError, 'cannot set attribute %s' % attr
+ super(Proxy, self).__setattr__(attr, value)
+
+ def _convert(self):
+ obj = self._object
+ for attr in self._path:
+ obj = obj.__getattribute__(attr)
+ return obj
+
+Super = Proxy()
+
+def isSubClass(value, cls):
+ try:
+ return issubclass(value, cls)
+ except:
+ return False
+
+def isConfigNode(value):
+ try:
+ return issubclass(value, ConfigNode)
+ except:
+ return False
+
+def isSimObject(value):
+ try:
+ return issubclass(value, SimObject)
+ except:
+ return False
+
+def isSimObjSequence(value):
+ if not issequence(value):
+ return False
+
+ for val in value:
+ if not isNullPointer(val) and not isConfigNode(val):
+ return False
+
+ return True
+
+def isParamContext(value):
+ try:
+ return issubclass(value, ParamContext)
+ except:
+ return False
+
+
+class_decorator = 'M5M5_SIMOBJECT_'
+expr_decorator = 'M5M5_EXPRESSION_'
+dot_decorator = '_M5M5_DOT_'
+
+# The metaclass for ConfigNode (and thus for everything that derives
+# from ConfigNode, including SimObject). This class controls how new
+# classes that derive from ConfigNode are instantiated, and provides
+# inherited class behavior (just like a class controls how instances
+# of that class are instantiated, and provides inherited instance
+# behavior).
+class MetaConfigNode(type):
+ # Attributes that can be set only at initialization time
+ init_keywords = {}
+ # Attributes that can be set any time
+ keywords = { 'check' : types.FunctionType,
+ 'children' : types.ListType }
+
+ # __new__ is called before __init__, and is where the statements
+ # in the body of the class definition get loaded into the class's
+ # __dict__. We intercept this to filter out parameter assignments
+ # and only allow "private" attributes to be passed to the base
+ # __new__ (starting with underscore).
+ def __new__(mcls, name, bases, dict):
+ # Copy "private" attributes (including special methods such as __new__)
+ # to the official dict. Everything else goes in _init_dict to be
+ # filtered in __init__.
+ cls_dict = {}
+ for key,val in dict.items():
+ if key.startswith('_'):
+ cls_dict[key] = val
+ del dict[key]
+ cls_dict['_init_dict'] = dict
+ return super(MetaConfigNode, mcls).__new__(mcls, name, bases, cls_dict)
+
+ # initialization
+ def __init__(cls, name, bases, dict):
+ super(MetaConfigNode, cls).__init__(name, bases, dict)
+
+ # initialize required attributes
+ cls._params = {}
+ cls._values = {}
+ cls._enums = {}
+ cls._bases = [c for c in cls.__mro__ if isConfigNode(c)]
+ cls._anon_subclass_counter = 0
+
+ # If your parent has a value in it that's a config node, clone
+ # it. Do this now so if we update any of the values'
+ # attributes we are updating the clone and not the original.
+ for base in cls._bases:
+ for key,val in base._values.iteritems():
+
+ # don't clone if (1) we're about to overwrite it with
+ # a local setting or (2) we've already cloned a copy
+ # from an earlier (more derived) base
+ if cls._init_dict.has_key(key) or cls._values.has_key(key):
+ continue
+
+ if isConfigNode(val):
+ cls._values[key] = val()
+ elif isSimObjSequence(val):
+ cls._values[key] = [ v() for v in val ]
+ elif isNullPointer(val):
+ cls._values[key] = val
+
+ # now process _init_dict items
+ for key,val in cls._init_dict.items():
+ if isinstance(val, _Param):
+ cls._params[key] = val
+
+ # init-time-only keywords
+ elif cls.init_keywords.has_key(key):
+ cls._set_keyword(key, val, cls.init_keywords[key])
+
+ # enums
+ elif isinstance(val, type) and issubclass(val, Enum):
+ cls._enums[key] = val
+
+ # See description of decorators in the importer.py file.
+ # We just strip off the expr_decorator now since we don't
+ # need from this point on.
+ elif key.startswith(expr_decorator):
+ key = key[len(expr_decorator):]
+ # because it had dots into a list so that we can find the
+ # proper variable to modify.
+ key = key.split(dot_decorator)
+ c = cls
+ for item in key[:-1]:
+ c = getattr(c, item)
+ setattr(c, key[-1], val)
+
+ # default: use normal path (ends up in __setattr__)
+ else:
+ setattr(cls, key, val)
+
+
+ def _isvalue(cls, name):
+ for c in cls._bases:
+ if c._params.has_key(name):
+ return True
+
+ for c in cls._bases:
+ if c._values.has_key(name):
+ return True
+
+ return False
+
+ # generator that iterates across all parameters for this class and
+ # all classes it inherits from
+ def _getparams(cls):
+ params = {}
+ for c in cls._bases:
+ for p,v in c._params.iteritems():
+ if not params.has_key(p):
+ params[p] = v
+ return params
+
+ # Lookup a parameter description by name in the given class.
+ def _getparam(cls, name, default = AttributeError):
+ for c in cls._bases:
+ if c._params.has_key(name):
+ return c._params[name]
+ if isSubClass(default, Exception):
+ raise default, \
+ "object '%s' has no attribute '%s'" % (cls.__name__, name)
+ else:
+ return default
+
+ def _hasvalue(cls, name):
+ for c in cls._bases:
+ if c._values.has_key(name):
+ return True
+
+ return False
+
+ def _getvalues(cls):
+ values = {}
+ for i,c in enumerate(cls._bases):
+ for p,v in c._values.iteritems():
+ if not values.has_key(p):
+ values[p] = v
+ for p,v in c._params.iteritems():
+ if not values.has_key(p) and hasattr(v, 'default'):
+ try:
+ v.valid(v.default)
+ except TypeError:
+ panic("Invalid default %s for param %s in node %s"
+ % (v.default,p,cls.__name__))
+ v = v.default
+ cls._setvalue(p, v)
+ values[p] = v
+
+ return values
+
+ def _getvalue(cls, name, default = AttributeError):
+ value = None
+ for c in cls._bases:
+ if c._values.has_key(name):
+ value = c._values[name]
+ break
+ if value is not None:
+ return value
+
+ param = cls._getparam(name, None)
+ if param is not None and hasattr(param, 'default'):
+ param.valid(param.default)
+ value = param.default
+ cls._setvalue(name, value)
+ return value
+
+ if isSubClass(default, Exception):
+ raise default, 'value for %s not found' % name
+ else:
+ return default
+
+ def _setvalue(cls, name, value):
+ cls._values[name] = value
+
+ def __getattr__(cls, attr):
+ if cls._isvalue(attr):
+ return Value(cls, attr)
+
+ if attr == '_cpp_param_decl' and hasattr(cls, 'type'):
+ return cls.type + '*'
+
+ raise AttributeError, \
+ "object '%s' has no attribute '%s'" % (cls.__name__, attr)
+
+ def _set_keyword(cls, keyword, val, kwtype):
+ if not isinstance(val, kwtype):
+ raise TypeError, 'keyword %s has bad type %s (expecting %s)' % \
+ (keyword, type(val), kwtype)
+ if isinstance(val, types.FunctionType):
+ val = classmethod(val)
+ type.__setattr__(cls, keyword, val)
+
+ # Set attribute (called on foo.attr = value when foo is an
+ # instance of class cls).
+ def __setattr__(cls, attr, value):
+ # normal processing for private attributes
+ if attr.startswith('_'):
+ type.__setattr__(cls, attr, value)
+ return
+
+ if cls.keywords.has_key(attr):
+ cls._set_keyword(attr, value, cls.keywords[attr])
+ return
+
+ # must be SimObject param
+ param = cls._getparam(attr, None)
+ if param:
+ # It's ok: set attribute by delegating to 'object' class.
+ # Note the use of param.make_value() to verify/canonicalize
+ # the assigned value
+ param.valid(value)
+ cls._setvalue(attr, value)
+ elif isConfigNode(value) or isSimObjSequence(value):
+ cls._setvalue(attr, value)
+ else:
+ raise AttributeError, \
+ "Class %s has no parameter %s" % (cls.__name__, attr)
+
+ def add_child(cls, instance, name, child):
+ if isNullPointer(child) or instance.top_child_names.has_key(name):
+ return
+
+ if issequence(child):
+ kid = []
+ for i,c in enumerate(child):
+ n = '%s%d' % (name, i)
+ k = c.instantiate(n, instance)
+
+ instance.children.append(k)
+ instance.child_names[n] = k
+ instance.child_objects[c] = k
+ kid.append(k)
+ else:
+ kid = child.instantiate(name, instance)
+ instance.children.append(kid)
+ instance.child_names[name] = kid
+ instance.child_objects[child] = kid
+
+ instance.top_child_names[name] = kid
+
+ # Print instance info to .ini file.
+ def instantiate(cls, name, parent = None):
+ instance = Node(name, cls, cls.type, parent, isParamContext(cls))
+
+ if hasattr(cls, 'check'):
+ cls.check()
+
+ for key,value in cls._getvalues().iteritems():
+ if isConfigNode(value):
+ cls.add_child(instance, key, value)
+ if issequence(value):
+ list = [ v for v in value if isConfigNode(v) ]
+ if len(list):
+ cls.add_child(instance, key, list)
+
+ for pname,param in cls._getparams().iteritems():
+ try:
+ value = cls._getvalue(pname)
+ except:
+ panic('Error getting %s' % pname)
+
+ try:
+ if isConfigNode(value):
+ value = instance.child_objects[value]
+ elif issequence(value):
+ v = []
+ for val in value:
+ if isConfigNode(val):
+ v.append(instance.child_objects[val])
+ else:
+ v.append(val)
+ value = v
+
+ p = NodeParam(pname, param, value)
+ instance.params.append(p)
+ instance.param_names[pname] = p
+ except:
+ print 'Exception while evaluating %s.%s' % \
+ (instance.path, pname)
+ raise
+
+ return instance
+
+ def _convert(cls, value):
+ realvalue = value
+ if isinstance(value, Node):
+ realvalue = value.realtype
+
+ if isinstance(realvalue, Proxy):
+ return value
+
+ if realvalue == None or isNullPointer(realvalue):
+ return value
+
+ if isSubClass(realvalue, cls):
+ return value
+
+ raise TypeError, 'object %s type %s wrong type, should be %s' % \
+ (repr(realvalue), realvalue, cls)
+
+ def _string(cls, value):
+ if isNullPointer(value):
+ return 'Null'
+ return Node._string(value)
+
+# The ConfigNode class is the root of the special hierarchy. Most of
+# the code in this class deals with the configuration hierarchy itself
+# (parent/child node relationships).
+class ConfigNode(object):
+ # Specify metaclass. Any class inheriting from ConfigNode will
+ # get this metaclass.
+ __metaclass__ = MetaConfigNode
+
+ def __new__(cls, **kwargs):
+ name = cls.__name__ + ("_%d" % cls._anon_subclass_counter)
+ cls._anon_subclass_counter += 1
+ return cls.__metaclass__(name, (cls, ), kwargs)
+
+class ParamContext(ConfigNode):
+ pass
+
+class MetaSimObject(MetaConfigNode):
+ # init_keywords and keywords are inherited from MetaConfigNode,
+ # with overrides/additions
+ init_keywords = MetaConfigNode.init_keywords
+ init_keywords.update({ 'abstract' : types.BooleanType,
+ 'type' : types.StringType })
+
+ keywords = MetaConfigNode.keywords
+ # no additional keywords
+
+ cpp_classes = []
+
+ # initialization
+ def __init__(cls, name, bases, dict):
+ super(MetaSimObject, cls).__init__(name, bases, dict)
+
+ if hasattr(cls, 'type'):
+ if name == 'SimObject':
+ cls._cpp_base = None
+ elif hasattr(cls._bases[1], 'type'):
+ cls._cpp_base = cls._bases[1].type
+ else:
+ panic("SimObject %s derives from a non-C++ SimObject %s "\
+ "(no 'type')" % (cls, cls_bases[1].__name__))
+
+ # This class corresponds to a C++ class: put it on the global
+ # list of C++ objects to generate param structs, etc.
+ MetaSimObject.cpp_classes.append(cls)
+
+ def _cpp_decl(cls):
+ name = cls.__name__
+ code = ""
+ code += "\n".join([e.cpp_declare() for e in cls._enums.values()])
+ code += "\n"
+ param_names = cls._params.keys()
+ param_names.sort()
+ code += "struct Params"
+ if cls._cpp_base:
+ code += " : public %s::Params" % cls._cpp_base
+ code += " {\n "
+ code += "\n ".join([cls._params[pname].cpp_decl(pname) \
+ for pname in param_names])
+ code += "\n};\n"
+ return code
+
+class NodeParam(object):
+ def __init__(self, name, param, value):
+ self.name = name
+ self.param = param
+ self.ptype = param.ptype
+ self.convert = param.convert
+ self.string = param.string
+ self.value = value
+
+class Node(object):
+ all = {}
+ def __init__(self, name, realtype, type, parent, paramcontext):
+ self.name = name
+ self.realtype = realtype
+ self.type = type
+ self.parent = parent
+ self.children = []
+ self.child_names = {}
+ self.child_objects = {}
+ self.top_child_names = {}
+ self.params = []
+ self.param_names = {}
+ self.paramcontext = paramcontext
+
+ path = [ self.name ]
+ node = self.parent
+ while node is not None:
+ if node.name != 'root':
+ path.insert(0, node.name)
+ else:
+ assert(node.parent is None)
+ node = node.parent
+ self.path = '.'.join(path)
+
+ def find(self, realtype, path):
+ if not path:
+ if issubclass(self.realtype, realtype):
+ return self, True
+
+ obj = None
+ for child in self.children:
+ if issubclass(child.realtype, realtype):
+ if obj is not None:
+ raise AttributeError, \
+ 'Super matched more than one: %s %s' % \
+ (obj.path, child.path)
+ obj = child
+ return obj, obj is not None
+
+ try:
+ obj = self
+ for node in path[:-1]:
+ obj = obj.child_names[node]
+
+ last = path[-1]
+ if obj.child_names.has_key(last):
+ value = obj.child_names[last]
+ if issubclass(value.realtype, realtype):
+ return value, True
+ elif obj.param_names.has_key(last):
+ value = obj.param_names[last]
+ realtype._convert(value.value)
+ return value.value, True
+ except KeyError:
+ pass
+
+ return None, False
+
+ def unproxy(self, ptype, value):
+ if not isinstance(value, Proxy):
+ return value
+
+ if value is None:
+ raise AttributeError, 'Error while fixing up %s' % self.path
+
+ obj = self
+ done = False
+ while not done:
+ if obj is None:
+ raise AttributeError, \
+ 'Parent of %s type %s not found at path %s' \
+ % (self.name, ptype, value._path)
+ found, done = obj.find(ptype, value._path)
+ if isinstance(found, Proxy):
+ done = False
+ obj = obj.parent
+
+ return found
+
+ def fixup(self):
+ self.all[self.path] = self
+
+ for param in self.params:
+ ptype = param.ptype
+ pval = param.value
+
+ try:
+ if issequence(pval):
+ param.value = [ self.unproxy(ptype, pv) for pv in pval ]
+ else:
+ param.value = self.unproxy(ptype, pval)
+ except:
+ print 'Error while fixing up %s:%s' % (self.path, param.name)
+ raise
+
+ for child in self.children:
+ assert(child != self)
+ child.fixup()
+
+ # print type and parameter values to .ini file
+ def display(self):
+ print '[' + self.path + ']' # .ini section header
+
+ if isSimObject(self.realtype):
+ print 'type = %s' % self.type
+
+ if self.children:
+ # instantiate children in same order they were added for
+ # backward compatibility (else we can end up with cpu1
+ # before cpu0). Changing ordering can also influence timing
+ # in the current memory system, as caches get added to a bus
+ # in different orders which affects their priority in the
+ # case of simulataneous requests. We should uncomment the
+ # following line once we take care of that issue.
+ # self.children.sort(lambda x,y: cmp(x.name, y.name))
+ children = [ c.name for c in self.children if not c.paramcontext]
+ print 'children =', ' '.join(children)
+
+ self.params.sort(lambda x,y: cmp(x.name, y.name))
+ for param in self.params:
+ try:
+ if param.value is None:
+ raise AttributeError, 'Parameter with no value'
+
+ value = param.convert(param.value)
+ string = param.string(value)
+ except:
+ print 'exception in %s:%s' % (self.path, param.name)
+ raise
+
+ print '%s = %s' % (param.name, string)
+
+ print
+
+ # recursively dump out children
+ for c in self.children:
+ c.display()
+
+ # print type and parameter values to .ini file
+ def outputDot(self, dot):
+
+
+ label = "{%s|" % self.path
+ if isSimObject(self.realtype):
+ label += '%s|' % self.type
+
+ if self.children:
+ # instantiate children in same order they were added for
+ # backward compatibility (else we can end up with cpu1
+ # before cpu0).
+ for c in self.children:
+ dot.add_edge(pydot.Edge(self.path,c.path, style="bold"))
+
+ simobjs = []
+ for param in self.params:
+ try:
+ if param.value is None:
+ raise AttributeError, 'Parameter with no value'
+
+ value = param.convert(param.value)
+ string = param.string(value)
+ except:
+ print 'exception in %s:%s' % (self.name, param.name)
+ raise
+ if isConfigNode(param.ptype) and string != "Null":
+ simobjs.append(string)
+ else:
+ label += '%s = %s\\n' % (param.name, string)
+
+ for so in simobjs:
+ label += "|<%s> %s" % (so, so)
+ dot.add_edge(pydot.Edge("%s:%s" % (self.path, so), so, tailport="w"))
+ label += '}'
+ dot.add_node(pydot.Node(self.path,shape="Mrecord",label=label))
+
+ # recursively dump out children
+ for c in self.children:
+ c.outputDot(dot)
+
+ def _string(cls, value):
+ if not isinstance(value, Node):
+ raise AttributeError, 'expecting %s got %s' % (Node, value)
+ return value.path
+ _string = classmethod(_string)
+
+#####################################################################
+#
+# Parameter description classes
+#
+# The _params dictionary in each class maps parameter names to
+# either a Param or a VectorParam object. These objects contain the
+# parameter description string, the parameter type, and the default
+# value (loaded from the PARAM section of the .odesc files). The
+# _convert() method on these objects is used to force whatever value
+# is assigned to the parameter to the appropriate type.
+#
+# Note that the default values are loaded into the class's attribute
+# space when the parameter dictionary is initialized (in
+# MetaConfigNode._setparams()); after that point they aren't used.
+#
+#####################################################################
+
+def isNullPointer(value):
+ return isinstance(value, NullSimObject)
+
+class Value(object):
+ def __init__(self, obj, attr):
+ super(Value, self).__setattr__('attr', attr)
+ super(Value, self).__setattr__('obj', obj)
+
+ def _getattr(self):
+ return self.obj._getvalue(self.attr)
+
+ def __setattr__(self, attr, value):
+ setattr(self._getattr(), attr, value)
+
+ def __getattr__(self, attr):
+ return getattr(self._getattr(), attr)
+
+ def __getitem__(self, index):
+ return self._getattr().__getitem__(index)
+
+ def __call__(self, *args, **kwargs):
+ return self._getattr().__call__(*args, **kwargs)
+
+ def __nonzero__(self):
+ return bool(self._getattr())
+
+ def __str__(self):
+ return str(self._getattr())
+
+# Regular parameter.
+class _Param(object):
+ def __init__(self, ptype, *args, **kwargs):
+ if isinstance(ptype, types.StringType):
+ self.ptype_string = ptype
+ elif isinstance(ptype, type):
+ self.ptype = ptype
+ else:
+ raise TypeError, "Param type is not a type (%s)" % ptype
+
+ if args:
+ if len(args) == 1:
+ self.desc = args[0]
+ elif len(args) == 2:
+ self.default = args[0]
+ self.desc = args[1]
+ else:
+ raise TypeError, 'too many arguments'
+
+ if kwargs.has_key('desc'):
+ assert(not hasattr(self, 'desc'))
+ self.desc = kwargs['desc']
+ del kwargs['desc']
+
+ if kwargs.has_key('default'):
+ assert(not hasattr(self, 'default'))
+ self.default = kwargs['default']
+ del kwargs['default']
+
+ if kwargs:
+ raise TypeError, 'extra unknown kwargs %s' % kwargs
+
+ if not hasattr(self, 'desc'):
+ raise TypeError, 'desc attribute missing'
+
+ def __getattr__(self, attr):
+ if attr == 'ptype':
+ try:
+ self.ptype = eval(self.ptype_string)
+ return self.ptype
+ except:
+ raise TypeError, 'Param.%s: undefined type' % self.ptype_string
+ else:
+ raise AttributeError, "'%s' object has no attribute '%s'" % \
+ (type(self).__name__, attr)
+
+ def valid(self, value):
+ if not isinstance(value, Proxy):
+ self.ptype._convert(value)
+
+ def convert(self, value):
+ return self.ptype._convert(value)
+
+ def string(self, value):
+ return self.ptype._string(value)
+
+ def set(self, name, instance, value):
+ instance.__dict__[name] = value
+
+ def cpp_decl(self, name):
+ return '%s %s;' % (self.ptype._cpp_param_decl, name)
+
+class _ParamProxy(object):
+ def __init__(self, type):
+ self.ptype = type
+
+ # E.g., Param.Int(5, "number of widgets")
+ def __call__(self, *args, **kwargs):
+ # Param type could be defined only in context of caller (e.g.,
+ # for locally defined Enum subclass). Need to go look up the
+ # type in that enclosing scope.
+ caller_frame = inspect.stack()[1][0]
+ ptype = caller_frame.f_locals.get(self.ptype, None)
+ if not ptype: ptype = caller_frame.f_globals.get(self.ptype, None)
+ if not ptype: ptype = globals().get(self.ptype, None)
+ # ptype could still be None due to circular references... we'll
+ # try one more time to evaluate lazily when ptype is first needed.
+ # In the meantime we'll save the type name as a string.
+ if not ptype: ptype = self.ptype
+ return _Param(ptype, *args, **kwargs)
+
+ def __getattr__(self, attr):
+ if attr == '__bases__':
+ raise AttributeError, ''
+ cls = type(self)
+ return cls(attr)
+
+ def __setattr__(self, attr, value):
+ if attr != 'ptype':
+ raise AttributeError, \
+ 'Attribute %s not available in %s' % (attr, self.__class__)
+ super(_ParamProxy, self).__setattr__(attr, value)
+
+
+Param = _ParamProxy(None)
+
+# Vector-valued parameter description. Just like Param, except that
+# the value is a vector (list) of the specified type instead of a
+# single value.
+class _VectorParam(_Param):
+ def __init__(self, type, *args, **kwargs):
+ _Param.__init__(self, type, *args, **kwargs)
+
+ def valid(self, value):
+ if value == None:
+ return True
+
+ if issequence(value):
+ for val in value:
+ if not isinstance(val, Proxy):
+ self.ptype._convert(val)
+ elif not isinstance(value, Proxy):
+ self.ptype._convert(value)
+
+ # Convert assigned value to appropriate type. If the RHS is not a
+ # list or tuple, it generates a single-element list.
+ def convert(self, value):
+ if value == None:
+ return []
+
+ if issequence(value):
+ # list: coerce each element into new list
+ return [ self.ptype._convert(v) for v in value ]
+ else:
+ # singleton: coerce & wrap in a list
+ return self.ptype._convert(value)
+
+ def string(self, value):
+ if issequence(value):
+ return ' '.join([ self.ptype._string(v) for v in value])
+ else:
+ return self.ptype._string(value)
+
+ def cpp_decl(self, name):
+ return 'std::vector<%s> %s;' % (self.ptype._cpp_param_decl, name)
+
+class _VectorParamProxy(_ParamProxy):
+ # E.g., VectorParam.Int(5, "number of widgets")
+ def __call__(self, *args, **kwargs):
+ return _VectorParam(self.ptype, *args, **kwargs)
+
+VectorParam = _VectorParamProxy(None)
+
+#####################################################################
+#
+# Parameter Types
+#
+# Though native Python types could be used to specify parameter types
+# (the 'ptype' field of the Param and VectorParam classes), it's more
+# flexible to define our own set of types. This gives us more control
+# over how Python expressions are converted to values (via the
+# __init__() constructor) and how these values are printed out (via
+# the __str__() conversion method). Eventually we'll need these types
+# to correspond to distinct C++ types as well.
+#
+#####################################################################
+# Integer parameter type.
+class _CheckedInt(object):
+ def _convert(cls, value):
+ t = type(value)
+ if t == bool:
+ return int(value)
+
+ if t != int and t != long and t != float and t != str:
+ raise TypeError, 'Integer parameter of invalid type %s' % t
+
+ if t == str or t == float:
+ value = long(value)
+
+ if not cls._min <= value <= cls._max:
+ raise TypeError, 'Integer parameter out of bounds %d < %d < %d' % \
+ (cls._min, value, cls._max)
+
+ return value
+ _convert = classmethod(_convert)
+
+ def _string(cls, value):
+ return str(value)
+ _string = classmethod(_string)
+
+class CheckedInt(type):
+ def __new__(cls, cppname, min, max):
+ # New class derives from _CheckedInt base with proper bounding
+ # parameters
+ dict = { '_cpp_param_decl' : cppname, '_min' : min, '_max' : max }
+ return type.__new__(cls, cppname, (_CheckedInt, ), dict)
+
+class CheckedIntType(CheckedInt):
+ def __new__(cls, cppname, size, unsigned):
+ dict = {}
+ if unsigned:
+ min = 0
+ max = 2 ** size - 1
+ else:
+ min = -(2 ** (size - 1))
+ max = (2 ** (size - 1)) - 1
+
+ return super(cls, CheckedIntType).__new__(cls, cppname, min, max)
+
+Int = CheckedIntType('int', 32, False)
+Unsigned = CheckedIntType('unsigned', 32, True)
+
+Int8 = CheckedIntType('int8_t', 8, False)
+UInt8 = CheckedIntType('uint8_t', 8, True)
+Int16 = CheckedIntType('int16_t', 16, False)
+UInt16 = CheckedIntType('uint16_t', 16, True)
+Int32 = CheckedIntType('int32_t', 32, False)
+UInt32 = CheckedIntType('uint32_t', 32, True)
+Int64 = CheckedIntType('int64_t', 64, False)
+UInt64 = CheckedIntType('uint64_t', 64, True)
+
+Counter = CheckedIntType('Counter', 64, True)
+Addr = CheckedIntType('Addr', 64, True)
+Tick = CheckedIntType('Tick', 64, True)
+
+Percent = CheckedInt('int', 0, 100)
+
+class Pair(object):
+ def __init__(self, first, second):
+ self.first = first
+ self.second = second
+
+class _Range(object):
+ def _convert(cls, value):
+ if not isinstance(value, Pair):
+ raise TypeError, 'value %s is not a Pair' % value
+ return Pair(cls._type._convert(value.first),
+ cls._type._convert(value.second))
+ _convert = classmethod(_convert)
+
+ def _string(cls, value):
+ return '%s:%s' % (cls._type._string(value.first),
+ cls._type._string(value.second))
+ _string = classmethod(_string)
+
+def RangeSize(start, size):
+ return Pair(start, start + size - 1)
+
+class Range(type):
+ def __new__(cls, type):
+ dict = { '_cpp_param_decl' : 'Range<%s>' % type._cpp_param_decl,
+ '_type' : type }
+ clsname = 'Range_' + type.__name__
+ return super(cls, Range).__new__(cls, clsname, (_Range, ), dict)
+
+AddrRange = Range(Addr)
+
+# Boolean parameter type.
+class Bool(object):
+ _cpp_param_decl = 'bool'
+ def _convert(value):
+ t = type(value)
+ if t == bool:
+ return value
+
+ if t == int or t == long:
+ return bool(value)
+
+ if t == str:
+ v = value.lower()
+ if v == "true" or v == "t" or v == "yes" or v == "y":
+ return True
+ elif v == "false" or v == "f" or v == "no" or v == "n":
+ return False
+
+ raise TypeError, 'Bool parameter (%s) of invalid type %s' % (v, t)
+ _convert = staticmethod(_convert)
+
+ def _string(value):
+ if value:
+ return "true"
+ else:
+ return "false"
+ _string = staticmethod(_string)
+
+# String-valued parameter.
+class String(object):
+ _cpp_param_decl = 'string'
+
+ # Constructor. Value must be Python string.
+ def _convert(cls,value):
+ if value is None:
+ return ''
+ if isinstance(value, str):
+ return value
+
+ raise TypeError, \
+ "String param got value %s %s" % (repr(value), type(value))
+ _convert = classmethod(_convert)
+
+ # Generate printable string version. Not too tricky.
+ def _string(cls, value):
+ return value
+ _string = classmethod(_string)
+
+
+def IncEthernetAddr(addr, val = 1):
+ bytes = map(lambda x: int(x, 16), addr.split(':'))
+ bytes[5] += val
+ for i in (5, 4, 3, 2, 1):
+ val,rem = divmod(bytes[i], 256)
+ bytes[i] = rem
+ if val == 0:
+ break
+ bytes[i - 1] += val
+ assert(bytes[0] <= 255)
+ return ':'.join(map(lambda x: '%02x' % x, bytes))
+
+class NextEthernetAddr(object):
+ __metaclass__ = Singleton
+ addr = "00:90:00:00:00:01"
+
+ def __init__(self, inc = 1):
+ self.value = self.addr
+ self.addr = IncEthernetAddr(self.addr, inc)
+
+class EthernetAddr(object):
+ _cpp_param_decl = 'EthAddr'
+
+ def _convert(cls, value):
+ if value == NextEthernetAddr:
+ return value
+
+ if not isinstance(value, str):
+ raise TypeError, "expected an ethernet address and didn't get one"
+
+ bytes = value.split(':')
+ if len(bytes) != 6:
+ raise TypeError, 'invalid ethernet address %s' % value
+
+ for byte in bytes:
+ if not 0 <= int(byte) <= 256:
+ raise TypeError, 'invalid ethernet address %s' % value
+
+ return value
+ _convert = classmethod(_convert)
+
+ def _string(cls, value):
+ if value == NextEthernetAddr:
+ value = value().value
+ return value
+ _string = classmethod(_string)
+
+# Special class for NULL pointers. Note the special check in
+# make_param_value() above that lets these be assigned where a
+# SimObject is required.
+# only one copy of a particular node
+class NullSimObject(object):
+ __metaclass__ = Singleton
+
+ def __call__(cls):
+ return cls
+
+ def _instantiate(self, parent = None, path = ''):
+ pass
+
+ def _convert(cls, value):
+ if value == Nxone:
+ return
+
+ if isinstance(value, cls):
+ return value
+
+ raise TypeError, 'object %s %s of the wrong type, should be %s' % \
+ (repr(value), type(value), cls)
+ _convert = classmethod(_convert)
+
+ def _string():
+ return 'NULL'
+ _string = staticmethod(_string)
+
+# The only instance you'll ever need...
+Null = NULL = NullSimObject()
+
+# Enumerated types are a little more complex. The user specifies the
+# type as Enum(foo) where foo is either a list or dictionary of
+# alternatives (typically strings, but not necessarily so). (In the
+# long run, the integer value of the parameter will be the list index
+# or the corresponding dictionary value. For now, since we only check
+# that the alternative is valid and then spit it into a .ini file,
+# there's not much point in using the dictionary.)
+
+# What Enum() must do is generate a new type encapsulating the
+# provided list/dictionary so that specific values of the parameter
+# can be instances of that type. We define two hidden internal
+# classes (_ListEnum and _DictEnum) to serve as base classes, then
+# derive the new type from the appropriate base class on the fly.
+
+
+# Metaclass for Enum types
+class MetaEnum(type):
+
+ def __init__(cls, name, bases, init_dict):
+ if init_dict.has_key('map'):
+ if not isinstance(cls.map, dict):
+ raise TypeError, "Enum-derived class attribute 'map' " \
+ "must be of type dict"
+ # build list of value strings from map
+ cls.vals = cls.map.keys()
+ cls.vals.sort()
+ elif init_dict.has_key('vals'):
+ if not isinstance(cls.vals, list):
+ raise TypeError, "Enum-derived class attribute 'vals' " \
+ "must be of type list"
+ # build string->value map from vals sequence
+ cls.map = {}
+ for idx,val in enumerate(cls.vals):
+ cls.map[val] = idx
+ else:
+ raise TypeError, "Enum-derived class must define "\
+ "attribute 'map' or 'vals'"
+
+ cls._cpp_param_decl = name
+
+ super(MetaEnum, cls).__init__(name, bases, init_dict)
+
+ def cpp_declare(cls):
+ s = 'enum %s {\n ' % cls.__name__
+ s += ',\n '.join(['%s = %d' % (v,cls.map[v]) for v in cls.vals])
+ s += '\n};\n'
+ return s
+
+# Base class for enum types.
+class Enum(object):
+ __metaclass__ = MetaEnum
+ vals = []
+
+ def _convert(self, value):
+ if value not in self.map:
+ raise TypeError, "Enum param got bad value '%s' (not in %s)" \
+ % (value, self.vals)
+ return value
+ _convert = classmethod(_convert)
+
+ # Generate printable string version of value.
+ def _string(self, value):
+ return str(value)
+ _string = classmethod(_string)
+#
+# "Constants"... handy aliases for various values.
+#
+
+# Some memory range specifications use this as a default upper bound.
+MAX_ADDR = Addr._max
+MaxTick = Tick._max
+
+# For power-of-two sizing, e.g. 64*K gives an integer value 65536.
+K = 1024
+M = K*K
+G = K*M
+
+#####################################################################
+
+# The final hook to generate .ini files. Called from configuration
+# script once config is built.
+def instantiate(root):
+ if not issubclass(root, Root):
+ raise AttributeError, 'Can only instantiate the Root of the tree'
+
+ instance = root.instantiate('root')
+ instance.fixup()
+ instance.display()
+ if not noDot:
+ dot = pydot.Dot()
+ instance.outputDot(dot)
+ dot.orientation = "portrait"
+ dot.size = "8.5,11"
+ dot.ranksep="equally"
+ dot.rank="samerank"
+ dot.write("config.dot")
+ dot.write_ps("config.ps")
+
+# SimObject is a minimal extension of ConfigNode, implementing a
+# hierarchy node that corresponds to an M5 SimObject. It prints out a
+# "type=" line to indicate its SimObject class, prints out the
+# assigned parameters corresponding to its class, and allows
+# parameters to be set by keyword in the constructor. Note that most
+# of the heavy lifting for the SimObject param handling is done in the
+# MetaConfigNode metaclass.
+class SimObject(ConfigNode):
+ __metaclass__ = MetaSimObject
+ type = 'SimObject'
+
+from objects import *
+
+cpp_classes = MetaSimObject.cpp_classes
+cpp_classes.sort()
diff --git a/sim/pyconfig/m5configbase.py b/sim/pyconfig/m5configbase.py
deleted file mode 100644
index 66660994e..000000000
--- a/sim/pyconfig/m5configbase.py
+++ /dev/null
@@ -1,723 +0,0 @@
-# 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.
-
-from __future__ import generators
-
-import os
-import re
-import sys
-
-#####################################################################
-#
-# M5 Python Configuration Utility
-#
-# The basic idea is to write simple Python programs that build Python
-# objects corresponding to M5 SimObjects for the deisred simulation
-# configuration. For now, the Python emits a .ini file that can be
-# parsed by M5. In the future, some tighter integration between M5
-# and the Python interpreter may allow bypassing the .ini file.
-#
-# Each SimObject class in M5 is represented by a Python class with the
-# same name. The Python inheritance tree mirrors the M5 C++ tree
-# (e.g., SimpleCPU derives from BaseCPU in both cases, and all
-# SimObjects inherit from a single SimObject base class). To specify
-# an instance of an M5 SimObject in a configuration, the user simply
-# instantiates the corresponding Python object. The parameters for
-# that SimObject are given by assigning to attributes of the Python
-# object, either using keyword assignment in the constructor or in
-# separate assignment statements. For example:
-#
-# cache = BaseCache('my_cache', root, size=64*K)
-# cache.hit_latency = 3
-# cache.assoc = 8
-#
-# (The first two constructor arguments specify the name of the created
-# cache and its parent node in the hierarchy.)
-#
-# The magic lies in the mapping of the Python attributes for SimObject
-# classes to the actual SimObject parameter specifications. This
-# allows parameter validity checking in the Python code. Continuing
-# the example above, the statements "cache.blurfl=3" or
-# "cache.assoc='hello'" would both result in runtime errors in Python,
-# since the BaseCache object has no 'blurfl' parameter and the 'assoc'
-# parameter requires an integer, respectively. This magic is done
-# primarily by overriding the special __setattr__ method that controls
-# assignment to object attributes.
-#
-# The Python module provides another class, ConfigNode, which is a
-# superclass of SimObject. ConfigNode implements the parent/child
-# relationship for building the configuration hierarchy tree.
-# Concrete instances of ConfigNode can be used to group objects in the
-# hierarchy, but do not correspond to SimObjects themselves (like a
-# .ini section with "children=" but no "type=".
-#
-# Once a set of Python objects have been instantiated in a hierarchy,
-# calling 'instantiate(obj)' (where obj is the root of the hierarchy)
-# will generate a .ini file. See simple-4cpu.py for an example
-# (corresponding to m5-test/simple-4cpu.ini).
-#
-#####################################################################
-
-#####################################################################
-#
-# ConfigNode/SimObject classes
-#
-# The Python class hierarchy rooted by ConfigNode (which is the base
-# class of SimObject, which in turn is the base class of all other M5
-# SimObject classes) has special attribute behavior. In general, an
-# object in this hierarchy has three categories of attribute-like
-# things:
-#
-# 1. Regular Python methods and variables. These must start with an
-# underscore to be treated normally.
-#
-# 2. SimObject parameters. These values are stored as normal Python
-# attributes, but all assignments to these attributes are checked
-# against the pre-defined set of parameters stored in the class's
-# _param_dict dictionary. Assignments to attributes that do not
-# correspond to predefined parameters, or that are not of the correct
-# type, incur runtime errors.
-#
-# 3. Hierarchy children. The child nodes of a ConfigNode are stored
-# in the node's _children dictionary, but can be accessed using the
-# Python attribute dot-notation (just as they are printed out by the
-# simulator). Children cannot be created using attribute assigment;
-# they must be added by specifying the parent node in the child's
-# constructor or using the '+=' operator.
-
-# The SimObject parameters are the most complex, for a few reasons.
-# First, both parameter descriptions and parameter values are
-# inherited. Thus parameter description lookup must go up the
-# inheritance chain like normal attribute lookup, but this behavior
-# must be explicitly coded since the lookup occurs in each class's
-# _param_dict attribute. Second, because parameter values can be set
-# on SimObject classes (to implement default values), the parameter
-# checking behavior must be enforced on class attribute assignments as
-# well as instance attribute assignments. Finally, because we allow
-# class specialization via inheritance (e.g., see the L1Cache class in
-# the simple-4cpu.py example), we must do parameter checking even on
-# class instantiation. To provide all these features, we use a
-# metaclass to define most of the SimObject parameter behavior for
-# this class hierarchy.
-#
-#####################################################################
-
-# The metaclass for ConfigNode (and thus for everything that derives
-# from ConfigNode, including SimObject). This class controls how new
-# classes that derive from ConfigNode are instantiated, and provides
-# inherited class behavior (just like a class controls how instances
-# of that class are instantiated, and provides inherited instance
-# behavior).
-class MetaConfigNode(type):
-
- # __new__ is called before __init__, and is where the statements
- # in the body of the class definition get loaded into the class's
- # __dict__. We intercept this to filter out parameter assignments
- # and only allow "private" attributes to be passed to the base
- # __new__ (starting with underscore).
- def __new__(cls, name, bases, dict):
- priv_keys = [k for k in dict.iterkeys() if k.startswith('_')]
- priv_dict = {}
- for k in priv_keys: priv_dict[k] = dict[k]; del dict[k]
- # entries left in dict will get passed to __init__, where we'll
- # deal with them as params.
- return super(MetaConfigNode, cls).__new__(cls, name, bases, priv_dict)
-
- # initialization: start out with an empty param dict (makes life
- # simpler if we can assume _param_dict is always valid). Also
- # build inheritance list to simplify searching for inherited
- # params. Finally set parameters specified in class definition
- # (if any).
- def __init__(cls, name, bases, dict):
- super(MetaConfigNode, cls).__init__(cls, name, bases, {})
- # initialize _param_dict to empty
- cls._param_dict = {}
- # __mro__ is the ordered list of classes Python uses for
- # method resolution. We want to pick out the ones that have a
- # _param_dict attribute for doing parameter lookups.
- cls._param_bases = \
- [c for c in cls.__mro__ if hasattr(c, '_param_dict')]
- # initialize attributes with values from class definition
- for (pname, value) in dict.items():
- try:
- setattr(cls, pname, value)
- except Exception, exc:
- print "Error setting '%s' to '%s' on class '%s'\n" \
- % (pname, value, cls.__name__), exc
-
- # set the class's parameter dictionary (called when loading
- # class descriptions)
- def set_param_dict(cls, param_dict):
- # should only be called once (current one should be empty one
- # from __init__)
- assert not cls._param_dict
- cls._param_dict = param_dict
- # initialize attributes with default values
- for (pname, param) in param_dict.items():
- try:
- setattr(cls, pname, param.default)
- except Exception, exc:
- print "Error setting '%s' default on class '%s'\n" \
- % (pname, cls.__name__), exc
-
- # Set the class's parameter dictionary given a code string of
- # parameter initializers (as from an object description file).
- # Note that the caller must pass in the namespace in which to
- # execute the code (usually the caller's globals()), since if we
- # call globals() from inside this function all we get is this
- # module's internal scope.
- def init_params(cls, init_code, ctx):
- dict = {}
- try:
- exec fixPythonIndentation(init_code) in ctx, dict
- except Exception, exc:
- print "Error in %s.init_params:" % cls.__name__, exc
- raise
- cls.set_param_dict(dict)
-
- # Lookup a parameter description by name in the given class. Use
- # the _param_bases list defined in __init__ to go up the
- # inheritance hierarchy if necessary.
- def lookup_param(cls, param_name):
- for c in cls._param_bases:
- param = c._param_dict.get(param_name)
- if param: return param
- return None
-
- # Set attribute (called on foo.attr_name = value when foo is an
- # instance of class cls).
- def __setattr__(cls, attr_name, value):
- # normal processing for private attributes
- if attr_name.startswith('_'):
- type.__setattr__(cls, attr_name, value)
- return
- # no '_': must be SimObject param
- param = cls.lookup_param(attr_name)
- if not param:
- raise AttributeError, \
- "Class %s has no parameter %s" % (cls.__name__, attr_name)
- # It's ok: set attribute by delegating to 'object' class.
- # Note the use of param.make_value() to verify/canonicalize
- # the assigned value
- type.__setattr__(cls, attr_name, param.make_value(value))
-
- # generator that iterates across all parameters for this class and
- # all classes it inherits from
- def all_param_names(cls):
- for c in cls._param_bases:
- for p in c._param_dict.iterkeys():
- yield p
-
-# The ConfigNode class is the root of the special hierarchy. Most of
-# the code in this class deals with the configuration hierarchy itself
-# (parent/child node relationships).
-class ConfigNode(object):
- # Specify metaclass. Any class inheriting from ConfigNode will
- # get this metaclass.
- __metaclass__ = MetaConfigNode
-
- # Constructor. Since bare ConfigNodes don't have parameters, just
- # worry about the name and the parent/child stuff.
- def __init__(self, _name, _parent=None):
- # Type-check _name
- if type(_name) != str:
- if isinstance(_name, ConfigNode):
- # special case message for common error of trying to
- # coerce a SimObject to the wrong type
- raise TypeError, \
- "Attempt to coerce %s to %s" \
- % (_name.__class__.__name__, self.__class__.__name__)
- else:
- raise TypeError, \
- "%s name must be string (was %s, %s)" \
- % (self.__class__.__name__, _name, type(_name))
- # if specified, parent must be a subclass of ConfigNode
- if _parent != None and not isinstance(_parent, ConfigNode):
- raise TypeError, \
- "%s parent must be ConfigNode subclass (was %s, %s)" \
- % (self.__class__.__name__, _name, type(_name))
- self._name = _name
- self._parent = _parent
- if (_parent):
- _parent._add_child(self)
- self._children = {}
- # keep a list of children in addition to the dictionary keys
- # so we can remember the order they were added and print them
- # out in that order.
- self._child_list = []
-
- # When printing (e.g. to .ini file), just give the name.
- def __str__(self):
- return self._name
-
- # Catch attribute accesses that could be requesting children, and
- # satisfy them. Note that __getattr__ is called only if the
- # regular attribute lookup fails, so private and parameter lookups
- # will already be satisfied before we ever get here.
- def __getattr__(self, name):
- try:
- return self._children[name]
- except KeyError:
- raise AttributeError, \
- "Node '%s' has no attribute or child '%s'" \
- % (self._name, name)
-
- # Set attribute. All attribute assignments go through here. Must
- # be private attribute (starts with '_') or valid parameter entry.
- # Basically identical to MetaConfigClass.__setattr__(), except
- # this sets attributes on specific instances rather than on classes.
- def __setattr__(self, attr_name, value):
- if attr_name.startswith('_'):
- object.__setattr__(self, attr_name, value)
- return
- # not private; look up as param
- param = self.__class__.lookup_param(attr_name)
- if not param:
- raise AttributeError, \
- "Class %s has no parameter %s" \
- % (self.__class__.__name__, attr_name)
- # It's ok: set attribute by delegating to 'object' class.
- # Note the use of param.make_value() to verify/canonicalize
- # the assigned value.
- v = param.make_value(value)
- object.__setattr__(self, attr_name, v)
-
- # A little convenient magic: if the parameter is a ConfigNode
- # (or vector of ConfigNodes, or anything else with a
- # '_set_parent_if_none' function attribute) that does not have
- # a parent (and so is not part of the configuration
- # hierarchy), then make this node its parent.
- if hasattr(v, '_set_parent_if_none'):
- v._set_parent_if_none(self)
-
- def _path(self):
- # Return absolute path from root.
- if not self._parent and self._name != 'Universe':
- print >> sys.stderr, "Warning:", self._name, "has no parent"
- parent_path = self._parent and self._parent._path()
- if parent_path and parent_path != 'Universe':
- return parent_path + '.' + self._name
- else:
- return self._name
-
- # Add a child to this node.
- def _add_child(self, new_child):
- # set child's parent before calling this function
- assert new_child._parent == self
- if not isinstance(new_child, ConfigNode):
- raise TypeError, \
- "ConfigNode child must also be of class ConfigNode"
- if new_child._name in self._children:
- raise AttributeError, \
- "Node '%s' already has a child '%s'" \
- % (self._name, new_child._name)
- self._children[new_child._name] = new_child
- self._child_list += [new_child]
-
- # operator overload for '+='. You can say "node += child" to add
- # a child that was created with parent=None. An early attempt
- # at playing with syntax; turns out not to be that useful.
- def __iadd__(self, new_child):
- if new_child._parent != None:
- raise AttributeError, \
- "Node '%s' already has a parent" % new_child._name
- new_child._parent = self
- self._add_child(new_child)
- return self
-
- # Set this instance's parent to 'parent' if it doesn't already
- # have one. See ConfigNode.__setattr__().
- def _set_parent_if_none(self, parent):
- if self._parent == None:
- parent += self
-
- # Print instance info to .ini file.
- def _instantiate(self):
- print '[' + self._path() + ']' # .ini section header
- if self._child_list:
- # instantiate children in same order they were added for
- # backward compatibility (else we can end up with cpu1
- # before cpu0).
- print 'children =', ' '.join([c._name for c in self._child_list])
- self._instantiateParams()
- print
- # recursively dump out children
- for c in self._child_list:
- c._instantiate()
-
- # ConfigNodes have no parameters. Overridden by SimObject.
- def _instantiateParams(self):
- pass
-
-# SimObject is a minimal extension of ConfigNode, implementing a
-# hierarchy node that corresponds to an M5 SimObject. It prints out a
-# "type=" line to indicate its SimObject class, prints out the
-# assigned parameters corresponding to its class, and allows
-# parameters to be set by keyword in the constructor. Note that most
-# of the heavy lifting for the SimObject param handling is done in the
-# MetaConfigNode metaclass.
-
-class SimObject(ConfigNode):
- # initialization: like ConfigNode, but handle keyword-based
- # parameter initializers.
- def __init__(self, _name, _parent=None, **params):
- ConfigNode.__init__(self, _name, _parent)
- for param, value in params.items():
- setattr(self, param, value)
-
- # print type and parameter values to .ini file
- def _instantiateParams(self):
- print "type =", self.__class__._name
- for pname in self.__class__.all_param_names():
- value = getattr(self, pname)
- if value != None:
- print pname, '=', value
-
- def _sim_code(cls):
- name = cls.__name__
- param_names = cls._param_dict.keys()
- param_names.sort()
- code = "BEGIN_DECLARE_SIM_OBJECT_PARAMS(%s)\n" % name
- decls = [" " + cls._param_dict[pname].sim_decl(pname) \
- for pname in param_names]
- code += "\n".join(decls) + "\n"
- code += "END_DECLARE_SIM_OBJECT_PARAMS(%s)\n\n" % name
- code += "BEGIN_INIT_SIM_OBJECT_PARAMS(%s)\n" % name
- inits = [" " + cls._param_dict[pname].sim_init(pname) \
- for pname in param_names]
- code += ",\n".join(inits) + "\n"
- code += "END_INIT_SIM_OBJECT_PARAMS(%s)\n\n" % name
- return code
- _sim_code = classmethod(_sim_code)
-
-#####################################################################
-#
-# Parameter description classes
-#
-# The _param_dict dictionary in each class maps parameter names to
-# either a Param or a VectorParam object. These objects contain the
-# parameter description string, the parameter type, and the default
-# value (loaded from the PARAM section of the .odesc files). The
-# make_value() method on these objects is used to force whatever value
-# is assigned to the parameter to the appropriate type.
-#
-# Note that the default values are loaded into the class's attribute
-# space when the parameter dictionary is initialized (in
-# MetaConfigNode.set_param_dict()); after that point they aren't
-# used.
-#
-#####################################################################
-
-def isNullPointer(value):
- return isinstance(value, NullSimObject)
-
-# Regular parameter.
-class Param(object):
- # Constructor. E.g., Param(Int, "number of widgets", 5)
- def __init__(self, ptype, desc, default=None):
- self.ptype = ptype
- self.ptype_name = self.ptype.__name__
- self.desc = desc
- self.default = default
-
- # Convert assigned value to appropriate type. Force parameter
- # value (rhs of '=') to ptype (or None, which means not set).
- def make_value(self, value):
- # nothing to do if None or already correct type. Also allow NULL
- # pointer to be assigned where a SimObject is expected.
- if value == None or isinstance(value, self.ptype) or \
- isNullPointer(value) and issubclass(self.ptype, ConfigNode):
- return value
- # this type conversion will raise an exception if it's illegal
- return self.ptype(value)
-
- def sim_decl(self, name):
- return 'Param<%s> %s;' % (self.ptype_name, name)
-
- def sim_init(self, name):
- if self.default == None:
- return 'INIT_PARAM(%s, "%s")' % (name, self.desc)
- else:
- return 'INIT_PARAM_DFLT(%s, "%s", %s)' % \
- (name, self.desc, str(self.default))
-
-# The _VectorParamValue class is a wrapper for vector-valued
-# parameters. The leading underscore indicates that users shouldn't
-# see this class; it's magically generated by VectorParam. The
-# parameter values are stored in the 'value' field as a Python list of
-# whatever type the parameter is supposed to be. The only purpose of
-# storing these instead of a raw Python list is that we can override
-# the __str__() method to not print out '[' and ']' in the .ini file.
-class _VectorParamValue(object):
- def __init__(self, value):
- assert isinstance(value, list) or value == None
- self.value = value
-
- def __str__(self):
- return ' '.join(map(str, self.value))
-
- # Set member instance's parents to 'parent' if they don't already
- # have one. Extends "magic" parenting of ConfigNodes to vectors
- # of ConfigNodes as well. See ConfigNode.__setattr__().
- def _set_parent_if_none(self, parent):
- if self.value and hasattr(self.value[0], '_set_parent_if_none'):
- for v in self.value:
- v._set_parent_if_none(parent)
-
-# Vector-valued parameter description. Just like Param, except that
-# the value is a vector (list) of the specified type instead of a
-# single value.
-class VectorParam(Param):
-
- # Inherit Param constructor. However, the resulting parameter
- # will be a list of ptype rather than a single element of ptype.
- def __init__(self, ptype, desc, default=None):
- Param.__init__(self, ptype, desc, default)
-
- # Convert assigned value to appropriate type. If the RHS is not a
- # list or tuple, it generates a single-element list.
- def make_value(self, value):
- if value == None: return value
- if isinstance(value, list) or isinstance(value, tuple):
- # list: coerce each element into new list
- val_list = [Param.make_value(self, v) for v in iter(value)]
- else:
- # singleton: coerce & wrap in a list
- val_list = [Param.make_value(self, value)]
- # wrap list in _VectorParamValue (see above)
- return _VectorParamValue(val_list)
-
- def sim_decl(self, name):
- return 'VectorParam<%s> %s;' % (self.ptype_name, name)
-
- # sim_init inherited from Param
-
-#####################################################################
-#
-# Parameter Types
-#
-# Though native Python types could be used to specify parameter types
-# (the 'ptype' field of the Param and VectorParam classes), it's more
-# flexible to define our own set of types. This gives us more control
-# over how Python expressions are converted to values (via the
-# __init__() constructor) and how these values are printed out (via
-# the __str__() conversion method). Eventually we'll need these types
-# to correspond to distinct C++ types as well.
-#
-#####################################################################
-
-# Integer parameter type.
-class Int(object):
- # Constructor. Value must be Python int or long (long integer).
- def __init__(self, value):
- t = type(value)
- if t == int or t == long:
- self.value = value
- else:
- raise TypeError, "Int param got value %s %s" % (repr(value), t)
-
- # Use Python string conversion. Note that this puts an 'L' on the
- # end of long integers; we can strip that off here if it gives us
- # trouble.
- def __str__(self):
- return str(self.value)
-
-# Counter, Addr, and Tick are just aliases for Int for now.
-class Counter(Int):
- pass
-
-class Addr(Int):
- pass
-
-class Tick(Int):
- pass
-
-# Boolean parameter type.
-class Bool(object):
-
- # Constructor. Typically the value will be one of the Python bool
- # constants True or False (or the aliases true and false below).
- # Also need to take integer 0 or 1 values since bool was not a
- # distinct type in Python 2.2. Parse a bunch of boolean-sounding
- # strings too just for kicks.
- def __init__(self, value):
- t = type(value)
- if t == bool:
- self.value = value
- elif t == int or t == long:
- if value == 1:
- self.value = True
- elif value == 0:
- self.value = False
- elif t == str:
- v = value.lower()
- if v == "true" or v == "t" or v == "yes" or v == "y":
- self.value = True
- elif v == "false" or v == "f" or v == "no" or v == "n":
- self.value = False
- # if we didn't set it yet, it must not be something we understand
- if not hasattr(self, 'value'):
- raise TypeError, "Bool param got value %s %s" % (repr(value), t)
-
- # Generate printable string version.
- def __str__(self):
- if self.value: return "true"
- else: return "false"
-
-# String-valued parameter.
-class String(object):
- # Constructor. Value must be Python string.
- def __init__(self, value):
- t = type(value)
- if t == str:
- self.value = value
- else:
- raise TypeError, "String param got value %s %s" % (repr(value), t)
-
- # Generate printable string version. Not too tricky.
- def __str__(self):
- return self.value
-
-# Special class for NULL pointers. Note the special check in
-# make_param_value() above that lets these be assigned where a
-# SimObject is required.
-class NullSimObject(object):
- # Constructor. No parameters, nothing to do.
- def __init__(self):
- pass
-
- def __str__(self):
- return "NULL"
-
-# The only instance you'll ever need...
-NULL = NullSimObject()
-
-# Enumerated types are a little more complex. The user specifies the
-# type as Enum(foo) where foo is either a list or dictionary of
-# alternatives (typically strings, but not necessarily so). (In the
-# long run, the integer value of the parameter will be the list index
-# or the corresponding dictionary value. For now, since we only check
-# that the alternative is valid and then spit it into a .ini file,
-# there's not much point in using the dictionary.)
-
-# What Enum() must do is generate a new type encapsulating the
-# provided list/dictionary so that specific values of the parameter
-# can be instances of that type. We define two hidden internal
-# classes (_ListEnum and _DictEnum) to serve as base classes, then
-# derive the new type from the appropriate base class on the fly.
-
-
-# Base class for list-based Enum types.
-class _ListEnum(object):
- # Constructor. Value must be a member of the type's map list.
- def __init__(self, value):
- if value in self.map:
- self.value = value
- self.index = self.map.index(value)
- else:
- raise TypeError, "Enum param got bad value '%s' (not in %s)" \
- % (value, self.map)
-
- # Generate printable string version of value.
- def __str__(self):
- return str(self.value)
-
-class _DictEnum(object):
- # Constructor. Value must be a key in the type's map dictionary.
- def __init__(self, value):
- if value in self.map:
- self.value = value
- self.index = self.map[value]
- else:
- raise TypeError, "Enum param got bad value '%s' (not in %s)" \
- % (value, self.map.keys())
-
- # Generate printable string version of value.
- def __str__(self):
- return str(self.value)
-
-# Enum metaclass... calling Enum(foo) generates a new type (class)
-# that derives from _ListEnum or _DictEnum as appropriate.
-class Enum(type):
- # counter to generate unique names for generated classes
- counter = 1
-
- def __new__(cls, map):
- if isinstance(map, dict):
- base = _DictEnum
- keys = map.keys()
- elif isinstance(map, list):
- base = _ListEnum
- keys = map
- else:
- raise TypeError, "Enum map must be list or dict (got %s)" % map
- classname = "Enum%04d" % Enum.counter
- Enum.counter += 1
- # New class derives from selected base, and gets a 'map'
- # attribute containing the specified list or dict.
- return type.__new__(cls, classname, (base,), { 'map': map })
-
-
-#
-# "Constants"... handy aliases for various values.
-#
-
-# For compatibility with C++ bool constants.
-false = False
-true = True
-
-# Some memory range specifications use this as a default upper bound.
-MAX_ADDR = 2**64 - 1
-
-# For power-of-two sizing, e.g. 64*K gives an integer value 65536.
-K = 1024
-M = K*K
-G = K*M
-
-#####################################################################
-
-# Munge an arbitrary Python code string to get it to execute (mostly
-# dealing with indentation). Stolen from isa_parser.py... see
-# comments there for a more detailed description.
-def fixPythonIndentation(s):
- # get rid of blank lines first
- s = re.sub(r'(?m)^\s*\n', '', s);
- if (s != '' and re.match(r'[ \t]', s[0])):
- s = 'if 1:\n' + s
- return s
-
-# Hook to generate C++ parameter code.
-def gen_sim_code(file):
- for objname in sim_object_list:
- print >> file, eval("%s._sim_code()" % objname)
-
-# The final hook to generate .ini files. Called from configuration
-# script once config is built.
-def instantiate(*objs):
- for obj in objs:
- obj._instantiate()
-
-
diff --git a/sim/serialize.cc b/sim/serialize.cc
index 2a5e3d398..846d191e0 100644
--- a/sim/serialize.cc
+++ b/sim/serialize.cc
@@ -29,6 +29,7 @@
#include <sys/time.h>
#include <sys/types.h>
#include <sys/stat.h>
+#include <errno.h>
#include <fstream>
#include <list>
@@ -37,6 +38,7 @@
#include "base/inifile.hh"
#include "base/misc.hh"
+#include "base/output.hh"
#include "base/str.hh"
#include "base/trace.hh"
#include "sim/config_node.hh"
@@ -332,11 +334,7 @@ SerializeParamContext::~SerializeParamContext()
void
SerializeParamContext::checkParams()
{
- if (serialize_dir.isValid()) {
- checkpointDirBase = serialize_dir;
- } else {
- checkpointDirBase = outputDirectory + "cpt.%012d";
- }
+ checkpointDirBase = simout.resolve(serialize_dir);
// guarantee that directory ends with a '/'
if (checkpointDirBase[checkpointDirBase.size() - 1] != '/')
diff --git a/sim/startup.cc b/sim/startup.cc
index ebb4c0bc0..7cc0ac8fb 100644
--- a/sim/startup.cc
+++ b/sim/startup.cc
@@ -29,20 +29,32 @@
#include <list>
#include "base/misc.hh"
-#include "sim/startup.hh"
#include "sim/debug.hh"
+#include "sim/startup.hh"
typedef std::list<StartupCallback *> startupq_t;
-startupq_t &startupq() { static startupq_t queue; return queue; }
-StartupCallback::StartupCallback() { startupq().push_back(this); }
-StartupCallback::~StartupCallback() { startupq().remove(this); }
+
+startupq_t *startupq = NULL;
+
+StartupCallback::StartupCallback()
+{
+ if (startupq == NULL)
+ startupq = new startupq_t;
+ startupq->push_back(this);
+}
+
+StartupCallback::~StartupCallback()
+{
+ startupq->remove(this);
+}
+
void StartupCallback::startup() { }
void
SimStartup()
{
- startupq_t::iterator i = startupq().begin();
- startupq_t::iterator end = startupq().end();
+ startupq_t::iterator i = startupq->begin();
+ startupq_t::iterator end = startupq->end();
while (i != end) {
(*i)->startup();
diff --git a/sim/syscall_emul.cc b/sim/syscall_emul.cc
index a0cbdf414..22d62e4d1 100644
--- a/sim/syscall_emul.cc
+++ b/sim/syscall_emul.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2004 The Regents of The University of Michigan
+ * 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
@@ -47,17 +47,17 @@ SyscallDesc::doSyscall(int callnum, Process *process, ExecContext *xc)
DPRINTFR(SyscallVerbose, "%s: syscall %s called\n",
xc->cpu->name(), name);
- int retval = (*funcPtr)(this, callnum, process, xc);
+ SyscallReturn retval = (*funcPtr)(this, callnum, process, xc);
DPRINTFR(SyscallVerbose, "%s: syscall %s returns %d\n",
- xc->cpu->name(), name, retval);
+ xc->cpu->name(), name, retval.value());
- if (!((flags & SyscallDesc::SuppressReturnValue) && retval == 0))
+ if (!(flags & SyscallDesc::SuppressReturnValue))
xc->setSyscallReturn(retval);
}
-int
+SyscallReturn
unimplementedFunc(SyscallDesc *desc, int callnum, Process *process,
ExecContext *xc)
{
@@ -70,7 +70,7 @@ unimplementedFunc(SyscallDesc *desc, int callnum, Process *process,
}
-int
+SyscallReturn
ignoreFunc(SyscallDesc *desc, int callnum, Process *process,
ExecContext *xc)
{
@@ -83,7 +83,7 @@ ignoreFunc(SyscallDesc *desc, int callnum, Process *process,
}
-int
+SyscallReturn
exitFunc(SyscallDesc *desc, int callnum, Process *process,
ExecContext *xc)
{
@@ -93,25 +93,28 @@ exitFunc(SyscallDesc *desc, int callnum, Process *process,
}
-int
+SyscallReturn
getpagesizeFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
{
return VMPageSize;
}
-int
+SyscallReturn
obreakFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
{
// change brk addr to first arg
Addr new_brk = xc->getSyscallArg(0);
if (new_brk != 0)
+ {
p->brk_point = xc->getSyscallArg(0);
+ }
+ DPRINTF(SyscallVerbose, "Break Point changed to: %#X\n", p->brk_point);
return p->brk_point;
}
-int
+SyscallReturn
closeFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
{
int fd = p->sim_fd(xc->getSyscallArg(0));
@@ -119,7 +122,7 @@ closeFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
}
-int
+SyscallReturn
readFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
{
int fd = p->sim_fd(xc->getSyscallArg(0));
@@ -134,7 +137,7 @@ readFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
return bytes_read;
}
-int
+SyscallReturn
writeFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
{
int fd = p->sim_fd(xc->getSyscallArg(0));
@@ -151,7 +154,7 @@ writeFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
}
-int
+SyscallReturn
lseekFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
{
int fd = p->sim_fd(xc->getSyscallArg(0));
@@ -164,7 +167,7 @@ lseekFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
}
-int
+SyscallReturn
munmapFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
{
// given that we don't really implement mmap, munmap is really easy
@@ -174,7 +177,7 @@ munmapFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
const char *hostname = "m5.eecs.umich.edu";
-int
+SyscallReturn
gethostnameFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
{
int name_len = xc->getSyscallArg(1);
@@ -187,19 +190,19 @@ gethostnameFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
return 0;
}
-int
+SyscallReturn
unlinkFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
{
std::string path;
if (xc->mem->readString(path, xc->getSyscallArg(0)) != No_Fault)
- return -EFAULT;
+ return (TheISA::IntReg)-EFAULT;
int result = unlink(path.c_str());
return (result == -1) ? -errno : result;
}
-int
+SyscallReturn
renameFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
{
std::string old_name;
@@ -212,7 +215,7 @@ renameFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
if (xc->mem->readString(new_name, xc->getSyscallArg(1)) != No_Fault)
return -EFAULT;
- int result = rename(old_name.c_str(),new_name.c_str());
+ int64_t result = rename(old_name.c_str(),new_name.c_str());
return (result == -1) ? -errno : result;
}
diff --git a/sim/syscall_emul.hh b/sim/syscall_emul.hh
index 77d104449..51a075a28 100644
--- a/sim/syscall_emul.hh
+++ b/sim/syscall_emul.hh
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2004 The Regents of The University of Michigan
+ * 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
@@ -26,8 +26,8 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef __SYSCALL_EMUL_HH__
-#define __SYSCALL_EMUL_HH__
+#ifndef __SIM_SYSCALL_EMUL_HH__
+#define __SIM_SYSCALL_EMUL_HH__
///
/// @file syscall_emul.hh
@@ -35,14 +35,16 @@
/// This file defines objects used to emulate syscalls from the target
/// application on the host machine.
+#include <errno.h>
#include <string>
#include "base/intmath.hh" // for RoundUp
-#include "targetarch/isa_traits.hh" // for Addr
#include "mem/functional_mem/functional_memory.hh"
+#include "targetarch/isa_traits.hh" // for Addr
-class Process;
-class ExecContext;
+#include "base/trace.hh"
+#include "cpu/exec_context.hh"
+#include "sim/process.hh"
///
/// System call descriptor.
@@ -52,7 +54,7 @@ class SyscallDesc {
public:
/// Typedef for target syscall handler functions.
- typedef int (*FuncPtr)(SyscallDesc *, int num,
+ typedef SyscallReturn (*FuncPtr)(SyscallDesc *, int num,
Process *, ExecContext *);
const char *name; //!< Syscall name (e.g., "open").
@@ -156,46 +158,76 @@ class TypedBufferArg : public BaseBufferArg
/// Handler for unimplemented syscalls that we haven't thought about.
-int unimplementedFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc);
+SyscallReturn unimplementedFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc);
/// Handler for unimplemented syscalls that we never intend to
/// implement (signal handling, etc.) and should not affect the correct
/// behavior of the program. Print a warning only if the appropriate
/// trace flag is enabled. Return success to the target program.
-int ignoreFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc);
+SyscallReturn ignoreFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc);
/// Target exit() handler: terminate simulation.
-int exitFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc);
+SyscallReturn exitFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc);
/// Target getpagesize() handler.
-int getpagesizeFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc);
+SyscallReturn getpagesizeFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc);
/// Target obreak() handler: set brk address.
-int obreakFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc);
+SyscallReturn obreakFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc);
/// Target close() handler.
-int closeFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc);
+SyscallReturn closeFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc);
/// Target read() handler.
-int readFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc);
+SyscallReturn readFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc);
/// Target write() handler.
-int writeFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc);
+SyscallReturn writeFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc);
/// Target lseek() handler.
-int lseekFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc);
+SyscallReturn lseekFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc);
/// Target munmap() handler.
-int munmapFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc);
+SyscallReturn munmapFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc);
/// Target gethostname() handler.
-int gethostnameFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc);
+SyscallReturn gethostnameFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc);
/// Target unlink() handler.
-int unlinkFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc);
+SyscallReturn unlinkFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc);
/// Target rename() handler.
-int renameFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc);
+SyscallReturn renameFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc);
+
+/// This struct is used to build an target-OS-dependent table that
+/// maps the target's open() flags to the host open() flags.
+struct OpenFlagTransTable {
+ int tgtFlag; //!< Target system flag value.
+ int hostFlag; //!< Corresponding host system flag value.
+};
+
+
+
+/// A readable name for 1,000,000, for converting microseconds to seconds.
+const int one_million = 1000000;
+
+/// Approximate seconds since the epoch (1/1/1970). About a billion,
+/// by my reckoning. We want to keep this a constant (not use the
+/// real-world time) to keep simulations repeatable.
+const unsigned seconds_since_epoch = 1000000000;
+
+/// Helper function to convert current elapsed time to seconds and
+/// microseconds.
+template <class T1, class T2>
+void
+getElapsedTime(T1 &sec, T2 &usec)
+{
+ int cycles_per_usec = ticksPerSecond / one_million;
+
+ int elapsed_usecs = curTick / cycles_per_usec;
+ sec = elapsed_usecs / one_million;
+ usec = elapsed_usecs % one_million;
+}
//////////////////////////////////////////////////////////////////////
//
@@ -208,7 +240,7 @@ int renameFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc);
/// only to find out if their stdout is a tty, to determine whether to
/// do line or block buffering.
template <class OS>
-int
+SyscallReturn
ioctlFunc(SyscallDesc *desc, int callnum, Process *process,
ExecContext *xc)
{
@@ -238,17 +270,9 @@ ioctlFunc(SyscallDesc *desc, int callnum, Process *process,
}
}
-/// This struct is used to build an target-OS-dependent table that
-/// maps the target's open() flags to the host open() flags.
-struct OpenFlagTransTable {
- int tgtFlag; //!< Target system flag value.
- int hostFlag; //!< Corresponding host system flag value.
-};
-
-
/// Target open() handler.
template <class OS>
-int
+SyscallReturn
openFunc(SyscallDesc *desc, int callnum, Process *process,
ExecContext *xc)
{
@@ -260,7 +284,7 @@ openFunc(SyscallDesc *desc, int callnum, Process *process,
if (path == "/dev/sysdev0") {
// This is a memory-mapped high-resolution timer device on Alpha.
// We don't support it, so just punt.
- DCOUT(SyscallWarnings) << "Ignoring open(" << path << ", ...)" << endl;
+ DCOUT(SyscallWarnings) << "Ignoring open(" << path << ", ...)" << std::endl;
return -ENOENT;
}
@@ -278,7 +302,7 @@ openFunc(SyscallDesc *desc, int callnum, Process *process,
// any target flags left?
if (tgtFlags != 0)
- cerr << "Syscall: open: cannot decode flags: " << tgtFlags << endl;
+ std::cerr << "Syscall: open: cannot decode flags: " << tgtFlags << std::endl;
#ifdef __CYGWIN32__
hostFlags |= O_BINARY;
@@ -293,7 +317,7 @@ openFunc(SyscallDesc *desc, int callnum, Process *process,
/// Target stat() handler.
template <class OS>
-int
+SyscallReturn
statFunc(SyscallDesc *desc, int callnum, Process *process,
ExecContext *xc)
{
@@ -306,7 +330,7 @@ statFunc(SyscallDesc *desc, int callnum, Process *process,
int result = stat(path.c_str(), &hostBuf);
if (result < 0)
- return -errno;
+ return errno;
OS::copyOutStatBuf(xc->mem, xc->getSyscallArg(1), &hostBuf);
@@ -316,7 +340,7 @@ statFunc(SyscallDesc *desc, int callnum, Process *process,
/// Target lstat() handler.
template <class OS>
-int
+SyscallReturn
lstatFunc(SyscallDesc *desc, int callnum, Process *process,
ExecContext *xc)
{
@@ -338,7 +362,7 @@ lstatFunc(SyscallDesc *desc, int callnum, Process *process,
/// Target fstat() handler.
template <class OS>
-int
+SyscallReturn
fstatFunc(SyscallDesc *desc, int callnum, Process *process,
ExecContext *xc)
{
@@ -374,7 +398,7 @@ fstatFunc(SyscallDesc *desc, int callnum, Process *process,
/// file descriptor, and fail (or implement!) a non-anonymous mmap to
/// anything else.
template <class OS>
-int
+SyscallReturn
mmapFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
{
Addr start = xc->getSyscallArg(0);
@@ -386,8 +410,8 @@ mmapFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
if (start == 0) {
// user didn't give an address... pick one from our "mmap region"
- start = p->mmap_base;
- p->mmap_base += RoundUp<Addr>(length, VMPageSize);
+ start = p->mmap_end;
+ p->mmap_end += RoundUp<Addr>(length, VMPageSize);
}
if (!(flags & OS::TGT_MAP_ANONYMOUS)) {
@@ -400,7 +424,7 @@ mmapFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
/// Target getrlimit() handler.
template <class OS>
-int
+SyscallReturn
getrlimitFunc(SyscallDesc *desc, int callnum, Process *process,
ExecContext *xc)
{
@@ -414,7 +438,7 @@ getrlimitFunc(SyscallDesc *desc, int callnum, Process *process,
break;
default:
- cerr << "getrlimitFunc: unimplemented resource " << resource << endl;
+ std::cerr << "getrlimitFunc: unimplemented resource " << resource << std::endl;
abort();
break;
}
@@ -423,31 +447,9 @@ getrlimitFunc(SyscallDesc *desc, int callnum, Process *process,
return 0;
}
-/// A readable name for 1,000,000, for converting microseconds to seconds.
-const int one_million = 1000000;
-
-/// Approximate seconds since the epoch (1/1/1970). About a billion,
-/// by my reckoning. We want to keep this a constant (not use the
-/// real-world time) to keep simulations repeatable.
-const unsigned seconds_since_epoch = 1000000000;
-
-/// Helper function to convert current elapsed time to seconds and
-/// microseconds.
-template <class T1, class T2>
-void
-getElapsedTime(T1 &sec, T2 &usec)
-{
- int cycles_per_usec = ticksPerSecond / one_million;
-
- int elapsed_usecs = curTick / cycles_per_usec;
- sec = elapsed_usecs / one_million;
- usec = elapsed_usecs % one_million;
-}
-
-
/// Target gettimeofday() handler.
template <class OS>
-int
+SyscallReturn
gettimeofdayFunc(SyscallDesc *desc, int callnum, Process *process,
ExecContext *xc)
{
@@ -464,7 +466,7 @@ gettimeofdayFunc(SyscallDesc *desc, int callnum, Process *process,
/// Target getrusage() function.
template <class OS>
-int
+SyscallReturn
getrusageFunc(SyscallDesc *desc, int callnum, Process *process,
ExecContext *xc)
{
@@ -476,7 +478,7 @@ getrusageFunc(SyscallDesc *desc, int callnum, Process *process,
// plow ahead
DCOUT(SyscallWarnings)
<< "Warning: getrusage() only supports RUSAGE_SELF."
- << " Parameter " << who << " ignored." << endl;
+ << " Parameter " << who << " ignored." << std::endl;
}
getElapsedTime(rup->ru_utime.tv_sec, rup->ru_utime.tv_usec);
@@ -502,6 +504,4 @@ getrusageFunc(SyscallDesc *desc, int callnum, Process *process,
return 0;
}
-
-
-#endif // __SYSCALL_EMUL_HH__
+#endif // __SIM_SYSCALL_EMUL_HH__
diff --git a/sim/universe.cc b/sim/universe.cc
index 824b985fa..9137baaf0 100644
--- a/sim/universe.cc
+++ b/sim/universe.cc
@@ -26,9 +26,6 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include <sys/types.h>
-#include <sys/stat.h>
-
#include <cstring>
#include <fstream>
#include <list>
@@ -36,9 +33,11 @@
#include <vector>
#include "base/misc.hh"
-#include "sim/universe.hh"
+#include "base/output.hh"
+#include "sim/builder.hh"
#include "sim/host.hh"
-#include "sim/param.hh"
+#include "sim/sim_object.hh"
+#include "sim/universe.hh"
using namespace std;
@@ -49,101 +48,61 @@ double __ticksPerUS;
double __ticksPerNS;
double __ticksPerPS;
-string outputDirectory;
+bool fullSystem;
ostream *outputStream;
ostream *configStream;
-class UniverseParamContext : public ParamContext
+// Dummy Object
+class Root : public SimObject
{
public:
- UniverseParamContext(const string &is)
- : ParamContext(is, OutputInitPhase) {}
- void checkParams();
+ Root(const std::string &name) : SimObject(name) {}
};
-UniverseParamContext universe("Universe");
+BEGIN_DECLARE_SIM_OBJECT_PARAMS(Root)
+
+ Param<bool> full_system;
+ Param<Tick> frequency;
+ Param<string> output_file;
+
+END_DECLARE_SIM_OBJECT_PARAMS(Root)
-Param<Tick> universe_freq(&universe, "frequency", "tick frequency",
- 200000000);
+BEGIN_INIT_SIM_OBJECT_PARAMS(Root)
-Param<string> universe_output_dir(&universe, "output_dir",
- "directory to output data to",
- ".");
-Param<string> universe_output_file(&universe, "output_file",
- "file to dump simulator output to",
- "cout");
-Param<string> universe_config_output_file(&universe, "config_output_file",
- "file to dump simulator config to",
- "m5config.out");
+ INIT_PARAM(full_system, "full system simulation"),
+ INIT_PARAM(frequency, "tick frequency"),
+ INIT_PARAM(output_file, "file to dump simulator output to")
-void
-UniverseParamContext::checkParams()
+END_INIT_SIM_OBJECT_PARAMS(Root)
+
+CREATE_SIM_OBJECT(Root)
{
- ticksPerSecond = universe_freq;
+ static bool created = false;
+ if (created)
+ panic("only one root object allowed!");
+
+ created = true;
+ fullSystem = full_system;
+
+#ifdef FULL_SYSTEM
+ if (!fullSystem)
+ panic("FULL_SYSTEM compiled and configuration not full_system");
+#else
+ if (fullSystem)
+ panic("FULL_SYSTEM not compiled but configuration is full_system");
+#endif
+
+ ticksPerSecond = frequency;
double freq = double(ticksPerSecond);
__ticksPerMS = freq / 1.0e3;
__ticksPerUS = freq / 1.0e6;
__ticksPerNS = freq / 1.0e9;
__ticksPerPS = freq / 1.0e12;
- if (universe_output_dir.isValid()) {
- outputDirectory = universe_output_dir;
-
- // guarantee that directory ends with a '/'
- if (outputDirectory[outputDirectory.size() - 1] != '/')
- outputDirectory += "/";
-
- if (mkdir(outputDirectory.c_str(), 0777) < 0) {
- if (errno != EEXIST) {
- panic("%s\ncould not make output directory: %s\n",
- strerror(errno), outputDirectory);
- }
- }
- }
-
- outputStream = makeOutputStream(universe_output_file);
- configStream = universe_config_output_file.isValid()
- ? makeOutputStream(universe_config_output_file)
- : outputStream;
-}
-
-
-std::ostream *
-makeOutputStream(std::string &name)
-{
- if (name == "cerr" || name == "stderr")
- return &std::cerr;
+ outputStream = simout.find(output_file);
- if (name == "cout" || name == "stdout")
- return &std::cout;
-
- string path = (name[0] != '/') ? outputDirectory + name : name;
-
- // have to dynamically allocate a stream since we're going to
- // return it... though the caller can't easily free it since it
- // may be cerr or cout. need GC!
- ofstream *s = new ofstream(path.c_str(), ios::trunc);
-
- if (!s->is_open())
- fatal("Cannot open file %s", path);
-
- return s;
+ return new Root(getInstanceName());
}
-
-void
-closeOutputStream(std::ostream *os)
-{
- // can't close cerr or cout
- if (os == &std::cerr || os == &std::cout)
- return;
-
- // can only close ofstreams, not generic ostreams, so try to
- // downcast and close only if the downcast succeeds
- std::ofstream *ofs = dynamic_cast<std::ofstream *>(os);
- if (ofs)
- ofs->close();
-}
-
-
+REGISTER_SIM_OBJECT("Root", Root)
diff --git a/test/genini.py b/test/genini.py
new file mode 100755
index 000000000..f4d1575db
--- /dev/null
+++ b/test/genini.py
@@ -0,0 +1,64 @@
+#!/usr/bin/env python
+# Copyright (c) 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.
+
+import getopt, os, os.path, sys
+from os.path import join as joinpath, realpath
+
+mypath = sys.path[0]
+sys.path.append(joinpath(mypath, '..'))
+sys.path.append(joinpath(mypath, '../util/pbs'))
+sys.path.append(joinpath(mypath, '../sim/pyconfig'))
+
+from importer import AddToPath, LoadMpyFile
+
+AddToPath('.')
+
+try:
+ opts, args = getopt.getopt(sys.argv[1:], '-E:I:')
+ for opt,arg in opts:
+ if opt == '-E':
+ offset = arg.find('=')
+ if offset == -1:
+ name = arg
+ value = True
+ else:
+ name = arg[:offset]
+ value = arg[offset+1:]
+ os.environ[name] = value
+ if opt == '-I':
+ AddToPath(arg)
+except getopt.GetoptError:
+ sys.exit('Improper Usage')
+
+from m5config import *
+
+for arg in args:
+ LoadMpyFile(arg)
+
+if globals().has_key('root') and isinstance(root, type) \
+ and issubclass(root, Root):
+ instantiate(root)
diff --git a/util/pbs/job.py b/util/pbs/job.py
new file mode 100755
index 000000000..5eed0cd75
--- /dev/null
+++ b/util/pbs/job.py
@@ -0,0 +1,183 @@
+#!/usr/bin/env python
+# Copyright (c) 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
+
+import os, os.path, shutil, signal, socket, sys, time
+from os import environ as env
+from os.path import join as joinpath, expanduser
+
+class rsync:
+ def __init__(self):
+ self.sudo = False
+ self.rsync = 'rsync'
+ self.compress = False
+ self.archive = True
+ self.delete = False
+ self.options = ''
+
+ def do(self, src, dst):
+ args = []
+ if self.sudo:
+ args.append('sudo')
+
+ args.append(self.rsync)
+ if (self.archive):
+ args.append('-a')
+ if (self.compress):
+ args.append('-z')
+ if (self.delete):
+ args.append('--delete')
+ if len(self.options):
+ args.append(self.options)
+ args.append(src)
+ args.append(dst)
+
+ return os.spawnvp(os.P_WAIT, args[0], args)
+
+def cleandir(dir):
+ for root, dirs, files in os.walk(dir, False):
+ for name in files:
+ os.remove(joinpath(root, name))
+ for name in dirs:
+ os.rmdir(joinpath(root, name))
+
+def date():
+ return time.strftime('%a %b %e %H:%M:%S %Z %Y', time.localtime())
+
+def remfile(file):
+ if os.path.isfile(file):
+ os.unlink(file)
+
+def readval(filename):
+ file = open(filename, 'r')
+ value = file.readline().strip()
+ file.close()
+ return value
+
+if __name__ == '__main__':
+ rootdir = env.setdefault('ROOTDIR', os.getcwd())
+ jobid = env['PBS_JOBID']
+ jobname = env['PBS_JOBNAME']
+ jobdir = joinpath(rootdir, jobname)
+ basedir = joinpath(rootdir, 'Base')
+ user = env['USER']
+
+ env['POOLJOB'] = 'True'
+ env['OUTPUT_DIR'] = jobdir
+ env['JOBFILE'] = joinpath(basedir, 'test.py')
+ env['JOBNAME'] = jobname
+
+ def echofile(filename, string):
+ try:
+ f = file(joinpath(jobdir, filename), 'w')
+ print >>f, string
+ f.flush()
+ f.close()
+ except IOError,e:
+ sys.exit(e)
+
+ if os.path.isdir("/work"):
+ workbase = "/work"
+ else:
+ workbase = "/tmp/"
+
+ workdir = joinpath(workbase, '%s.%s' % (user, jobid))
+
+ os.umask(0022)
+
+ echofile('.start', date())
+ echofile('.jobid', jobid)
+ echofile('.host', socket.gethostname())
+
+ if os.path.isdir(workdir):
+ cleandir(workdir)
+ else:
+ os.mkdir(workdir)
+
+ if os.path.isdir('/z/dist'):
+ sync = rsync()
+ sync.delete = True
+ sync.sudo = True
+ sync.do('poolfs::dist/m5/', '/z/dist/m5/')
+
+ try:
+ os.chdir(workdir)
+ except OSError,e:
+ sys.exit(e)
+
+ os.symlink(joinpath(jobdir, 'output'), 'status.out')
+
+ args = [ joinpath(basedir, 'm5'), joinpath(basedir, 'run.mpy') ]
+ if not len(args):
+ sys.exit("no arguments")
+
+ print 'starting job... %s' % date()
+ print ' '.join(args)
+ print
+ sys.stdout.flush()
+
+ childpid = os.fork()
+ if not childpid:
+ # Execute command
+ sys.stdin.close()
+ fd = os.open(joinpath(jobdir, "output"),
+ os.O_WRONLY | os.O_CREAT | os.O_TRUNC)
+ os.dup2(fd, sys.stdout.fileno())
+ os.dup2(fd, sys.stderr.fileno())
+ os.execvp(args[0], args)
+
+ def handler(signum, frame):
+ if childpid != 0:
+ os.kill(childpid, signum)
+
+ signal.signal(signal.SIGHUP, handler)
+ signal.signal(signal.SIGINT, handler)
+ signal.signal(signal.SIGQUIT, handler)
+ signal.signal(signal.SIGTERM, handler)
+ signal.signal(signal.SIGSTOP, handler)
+ signal.signal(signal.SIGCONT, handler)
+ signal.signal(signal.SIGUSR1, handler)
+ signal.signal(signal.SIGUSR2, handler)
+
+ done = 0
+ while not done:
+ try:
+ thepid,ec = os.waitpid(childpid, 0)
+ if ec:
+ print 'Exit code ', ec
+ echofile('.failure', date())
+ else:
+ echofile('.success', date())
+ done = 1
+ except OSError:
+ pass
+
+ print '\njob complete... %s' % date()
+ echofile('.stop', date())
diff --git a/util/pbs/jobfile.py b/util/pbs/jobfile.py
new file mode 100644
index 000000000..83eb81358
--- /dev/null
+++ b/util/pbs/jobfile.py
@@ -0,0 +1,92 @@
+# Copyright (c) 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
+
+from os.path import expanduser, isfile, join as joinpath
+import sys
+
+def crossproduct(options):
+ number = len(options)
+ indexes = [ 0 ] * number
+ maxes = [ len(opt) for opt in options ]
+ def next():
+ for i in xrange(number - 1, -1, -1):
+ indexes[i] += 1
+ if indexes[i] < maxes[i]:
+ return False
+
+ indexes[i] = 0
+ return True
+
+ done = False
+ while not done:
+ result = []
+ for i in xrange(number):
+ result.append(options[i][indexes[i]])
+ yield result
+ done = next()
+
+class JobFile(object):
+ def __init__(self, jfile):
+ self.data = {}
+ jfile = expanduser(jfile)
+ if not isfile(jfile):
+ for p in sys.path:
+ if isfile(joinpath(p, jfile)):
+ jfile = joinpath(p, jfile)
+ break
+
+ execfile(jfile, self.data)
+ self.options = self.data['options']
+ self.environment = self.data['environment']
+ self.jobinfo = {}
+ self.jobs = []
+ for job in crossproduct(self.options):
+ jobname = '.'.join([ id[0] for id in job ])
+ self.jobs.append(jobname)
+ list = []
+ for info in job:
+ for item in info[1:]:
+ list.append(item)
+ self.jobinfo[jobname] = list
+
+ def env(self, jobname):
+ env = {}
+ for key,val in self.jobinfo[jobname]:
+ env[key] = val
+
+ for key,val in self.environment:
+ env[key] = val
+ return env
+
+ def printinfo(self, jobname):
+ print '%s:' % jobname
+ for key,val in self.jobinfo[jobname]:
+ print ' %s = %s' % (key, val)
+
+ for key,val in self.environment:
+ print ' %s = %s' % (key, val)
diff --git a/util/pbs/pbs.py b/util/pbs/pbs.py
new file mode 100755
index 000000000..ecacbeba2
--- /dev/null
+++ b/util/pbs/pbs.py
@@ -0,0 +1,176 @@
+# Copyright (c) 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
+
+import os, popen2, re, sys
+
+class MyPOpen(object):
+ def __init__(self, cmd, input = None, output = None, bufsize = -1):
+ self.status = -1
+
+ if input is None:
+ p2c_read, p2c_write = os.pipe()
+ self.tochild = os.fdopen(p2c_write, 'w', bufsize)
+ else:
+ p2c_write = None
+ if isinstance(input, file):
+ p2c_read = input.fileno()
+ elif isinstance(input, str):
+ input = file(input, 'r')
+ p2c_read = input.fileno()
+ elif isinstance(input, int):
+ p2c_read = input
+ else:
+ raise AttributeError
+
+ if output is None:
+ c2p_read, c2p_write = os.pipe()
+ self.fromchild = os.fdopen(c2p_read, 'r', bufsize)
+ else:
+ c2p_read = None
+ if isinstance(output, file):
+ c2p_write = output.fileno()
+ elif isinstance(output, str):
+ output = file(output, 'w')
+ c2p_write = output.fileno()
+ elif isinstance(output, int):
+ c2p_write = output
+ else:
+ raise AttributeError
+
+ self.pid = os.fork()
+ if self.pid == 0:
+ os.dup2(p2c_read, sys.stdin.fileno())
+ os.dup2(c2p_write, sys.stdout.fileno())
+ os.dup2(c2p_write, sys.stderr.fileno())
+ try:
+ os.execvp(cmd[0], cmd)
+ finally:
+ os._exit(1)
+
+ os.close(p2c_read)
+ os.close(c2p_write)
+
+ def poll(self):
+ if self.status < 0:
+ pid, status = os.waitpid(self.pid, os.WNOHANG)
+ if pid == self.pid:
+ self.status = status
+ return self.status
+
+ def wait(self):
+ if self.status < 0:
+ pid, status = os.waitpid(self.pid, 0)
+ if pid == self.pid:
+ self.status = status
+ return self.status
+
+class qsub:
+ def __init__(self):
+ self.hold = False
+ self.join = False
+ self.keep_stdout = False
+ self.keep_stderr = False
+ self.node_type = ''
+ self.mail_abort = False
+ self.mail_begin = False
+ self.mail_end = False
+ self.name = ''
+ self.stdout = ''
+ self.priority = 0
+ self.queue = ''
+ self.pbshost = ''
+ self.qsub = 'qsub'
+ self.env = {}
+
+ def build(self, script, args = []):
+ self.cmd = [ self.qsub ]
+
+ if self.env:
+ arg = '-v'
+ arg += ','.join([ '%s=%s' % i for i in self.env.iteritems() ])
+ self.cmd.append(arg)
+
+ if self.hold:
+ self.cmd.append('-h')
+
+ if len(self.stdout):
+ self.cmd.append('-olocalhost:' + self.stdout)
+
+ if self.keep_stdout and self.keep_stderr:
+ self.cmd.append('-koe')
+ elif self.keep_stdout:
+ self.cmd.append('-ko')
+ elif self.keep_stderr:
+ self.cmd.append('-ke')
+ else:
+ self.cmd.append('-kn')
+
+ if self.join:
+ self.cmd.append('-joe')
+
+ if len(self.node_type):
+ self.cmd.append('-lnodes=' + self.node_type)
+
+ if self.mail_abort or self.mail_begin or self.mail_end:
+ flags = ''
+ if self.mail_abort:
+ flags.append('a')
+ if self.mail_begin:
+ flags.append('b')
+ if self.mail_end:
+ flags.append('e')
+ if len(flags):
+ self.cmd.append('-m ' + flags)
+
+ if len(self.name):
+ self.cmd.append("-N%s" % self.name)
+
+ if self.priority != 0:
+ self.cmd.append('-p' + self.priority)
+
+ if len(self.queue):
+ self.cmd.append('-q' + self.queue)
+
+ self.cmd.extend(args)
+ self.script = script
+ self.command = ' '.join(self.cmd + [ self.script ])
+
+ def do(self):
+ pbs = MyPOpen(self.cmd + [ self.script ])
+ self.result = pbs.fromchild.read()
+ ec = pbs.wait()
+
+ if ec != 0 and self.pbshost:
+ cmd = ' '.join(self.cmd + [ '-' ])
+ cmd = [ 'ssh', '-x', self.pbshost, cmd ]
+ self.command = ' '.join(cmd)
+ ssh = MyPOpen(cmd, input = self.script)
+ self.result = ssh.fromchild.read()
+ ec = ssh.wait()
+
+ return ec
diff --git a/util/pbs/send.py b/util/pbs/send.py
new file mode 100755
index 000000000..b796cadbd
--- /dev/null
+++ b/util/pbs/send.py
@@ -0,0 +1,190 @@
+#!/usr/bin/env python
+# Copyright (c) 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: Ali Saidi
+# Nathan Binkert
+
+import os, os.path, re, socket, sys
+from os import environ as env, listdir
+from os.path import basename, isdir, isfile, islink, join as joinpath
+from filecmp import cmp as filecmp
+from shutil import copyfile
+
+def nfspath(dir):
+ if dir.startswith('/.automount/'):
+ dir = '/n/%s' % dir[12:]
+ elif not dir.startswith('/n/'):
+ dir = '/n/%s%s' % (socket.gethostname().split('.')[0], dir)
+ return dir
+
+progpath = nfspath(sys.path[0])
+progname = basename(sys.argv[0])
+usage = """\
+Usage:
+ %(progname)s [-c] [-e] [-f] [-q queue] [-v] <regexp>
+ -c clean directory if job can be run
+ -e only echo pbs command info, don't actually send the job
+ -f force the job to run regardless of state
+ -q <queue> submit job to the named queue
+ -v be verbose
+
+ %(progname)s -l [-v] <regexp>
+ -l list job names, don't submit
+ -v be verbose (list job parameters)
+
+ %(progname)s -h
+ -h display this help
+""" % locals()
+
+try:
+ import getopt
+ opts, args = getopt.getopt(sys.argv[1:], '-cd:efhlq:v')
+except getopt.GetoptError:
+ sys.exit(usage)
+
+clean = False
+onlyecho = False
+exprs = []
+force = False
+listonly = False
+queue = ''
+verbose = False
+rootdir = nfspath(os.getcwd())
+for opt,arg in opts:
+ if opt == '-c':
+ clean = True
+ if opt == '-d':
+ rootdir = arg
+ if opt == '-e':
+ onlyecho = True
+ if opt == '-f':
+ force = True
+ if opt == '-h':
+ print usage
+ sys.exit(0)
+ if opt == '-l':
+ listonly = True
+ if opt == '-q':
+ queue = arg
+ if opt == '-v':
+ verbose = True
+
+basedir = joinpath(rootdir, 'Base')
+linkdir = joinpath(rootdir, 'Link')
+
+for arg in args:
+ exprs.append(re.compile(arg))
+
+if not listonly and not onlyecho and isdir(linkdir):
+ if verbose:
+ print 'Checking for outdated files in Link directory'
+ entries = listdir(linkdir)
+ for entry in entries:
+ link = joinpath(linkdir, entry)
+ if not islink(link) or not isfile(link):
+ continue
+
+ base = joinpath(basedir, entry)
+ if not isfile(base) or not filecmp(link, base):
+ print 'Base/%s is different than Link/%s: copying' % (entry, entry)
+ copyfile(link, base)
+
+import job, jobfile, pbs
+
+test = jobfile.JobFile(joinpath(basedir, 'test.py'))
+
+joblist = []
+for jobname in test.jobs:
+ if not exprs:
+ joblist.append(jobname)
+ continue
+
+ for expr in exprs:
+ if expr.match(jobname):
+ joblist.append(jobname)
+ break
+
+if listonly:
+ if verbose:
+ for jobname in joblist:
+ test.printinfo(jobname)
+ else:
+ for jobname in joblist:
+ print jobname
+ sys.exit(0)
+
+if not onlyecho:
+ jl = []
+ for jobname in joblist:
+ jobdir = joinpath(rootdir, jobname)
+ if os.path.exists(jobname):
+ if not force:
+ if os.path.isfile(joinpath(jobdir, '.success')):
+ continue
+
+ if os.path.isfile(joinpath(jobdir, '.start')) and \
+ not os.path.isfile(joinpath(jobdir, '.stop')):
+ continue
+
+ if not clean:
+ sys.exit('job directory not clean!')
+
+ job.cleandir(jobdir)
+ else:
+ os.mkdir(jobdir)
+ jl.append(jobname)
+ joblist = jl
+
+for jobname in joblist:
+ jobdir = joinpath(rootdir, jobname)
+
+ if not onlyecho and not os.path.isdir(jobdir):
+ sys.exit('%s is not a directory. Cannot build job' % jobdir)
+
+ print 'Job name: %s' % jobname
+ print 'Job directory: %s' % jobdir
+
+ qsub = pbs.qsub()
+ qsub.pbshost = 'simpool.eecs.umich.edu'
+ qsub.stdout = joinpath(jobdir, 'jobout')
+ qsub.name = jobname
+ qsub.join = True
+ qsub.node_type = 'FAST'
+ qsub.env['ROOTDIR'] = rootdir
+ if len(queue):
+ qsub.queue = queue
+ qsub.build(joinpath(progpath, 'job.py'))
+
+ if verbose:
+ print 'PBS Command: %s' % qsub.command
+
+ if not onlyecho:
+ ec = qsub.do()
+ if ec == 0:
+ print 'PBS Jobid: %s' % qsub.result
+ else:
+ print 'PBS Failed'
diff --git a/util/stats/db.py b/util/stats/db.py
index 495cdb5b5..ed5d10bc2 100644
--- a/util/stats/db.py
+++ b/util/stats/db.py
@@ -207,16 +207,43 @@ class Database(object):
# Name: listTicks
# Desc: Prints all samples for a given run
- def listTicks(self, run=None):
+ def listTicks(self, runs=None):
print "tick"
print "----------------------------------------"
- sql = 'select distinct dt_tick from data where dt_stat=1950'
- #if run != None:
- # sql += ' where dt_run=%d' % run
+ sql = 'select distinct dt_tick from data where dt_stat=1180 and ('
+ if runs != None:
+ first = True
+ for run in runs:
+ if first:
+ # sql += ' where'
+ first = False
+ else:
+ sql += ' or'
+ sql += ' dt_run=%s' % run.run
+ sql += ')'
self.query(sql)
for r in self.cursor.fetchall():
print r[0]
+ # Name: retTicks
+ # Desc: Prints all samples for a given run
+ def retTicks(self, runs=None):
+ sql = 'select distinct dt_tick from data where dt_stat=1180 and ('
+ if runs != None:
+ first = True
+ for run in runs:
+ if first:
+ first = False
+ else:
+ sql += ' or'
+ sql += ' dt_run=%s' % run.run
+ sql += ')'
+ self.query(sql)
+ ret = []
+ for r in self.cursor.fetchall():
+ ret.append(r[0])
+ return ret
+
# Name: liststats
# Desc: Prints all statistics that appear in the database,
# the optional argument is a regular expression that can
diff --git a/util/stats/info.py b/util/stats/info.py
index d11619765..01d7bdb0f 100644
--- a/util/stats/info.py
+++ b/util/stats/info.py
@@ -3,6 +3,8 @@ import operator, re, types
source = None
display_run = 0
+global globalTicks
+globalTicks = None
def issequence(t):
return isinstance(t, types.TupleType) or isinstance(t, types.ListType)
@@ -130,6 +132,7 @@ def cmp(a, b):
return 1
class Statistic(object):
+
def __init__(self, data):
self.__dict__.update(data.__dict__)
if not self.__dict__.has_key('value'):
@@ -138,9 +141,25 @@ class Statistic(object):
self.__dict__['bins'] = None
if not self.__dict__.has_key('ticks'):
self.__dict__['ticks'] = None
+ if 'vc' not in self.__dict__:
+ self.vc = {}
def __getattribute__(self, attr):
+ if attr == 'ticks':
+ if self.__dict__['ticks'] != globalTicks:
+ self.__dict__['value'] = None
+ self.__dict__['ticks'] = globalTicks
+ return self.__dict__['ticks']
if attr == 'value':
+ if self.__dict__['ticks'] != globalTicks:
+ if self.__dict__['ticks'] != None and \
+ len(self.__dict__['ticks']) == 1:
+ self.vc[self.__dict__['ticks'][0]] = self.__dict__['value']
+ self.__dict__['ticks'] = globalTicks
+ if len(globalTicks) == 1 and self.vc.has_key(globalTicks[0]):
+ self.__dict__['value'] = self.vc[globalTicks[0]]
+ else:
+ self.__dict__['value'] = None
if self.__dict__['value'] == None:
self.__dict__['value'] = self.getValue()
return self.__dict__['value']
@@ -152,11 +171,12 @@ class Statistic(object):
if attr == 'bins':
if value is not None:
value = source.getBin(value)
- elif attr == 'ticks' and type(value) is str:
- value = [ int(x) for x in value.split() ]
+ #elif attr == 'ticks' and type(value) is str:
+ # value = [ int(x) for x in value.split() ]
self.__dict__[attr] = value
self.__dict__['value'] = None
+ self.vc = {}
else:
super(Statistic, self).__setattr__(attr, value)
@@ -287,7 +307,7 @@ class Scalar(Statistic,FormulaStat):
class Vector(Statistic,FormulaStat):
def getValue(self):
- return source.data(self, self.bins);
+ return source.data(self, self.bins, self.ticks);
def display(self):
import display
@@ -304,7 +324,7 @@ class Vector(Statistic,FormulaStat):
def __eq__(self, other):
if issequence(self.value) != issequence(other.value):
- return false
+ return False
if issequence(self.value):
if len(self.value) != len(other.value):
diff --git a/util/stats/stats.py b/util/stats/stats.py
index b2b0ff8ad..c9b7ab2ac 100755
--- a/util/stats/stats.py
+++ b/util/stats/stats.py
@@ -1,11 +1,24 @@
#!/usr/bin/env python
from __future__ import division
-import re, sys
+import re, sys, math
+
def usage():
print '''\
Usage: %s [-E] [-F] [-d <db> ] [-g <get> ] [-h <host>] [-p]
- [-s <system>] [-r <runs> ] [-u <username>] <command> [command args]
+ [-s <system>] [-r <runs> ] [-T <samples>] [-u <username>]
+ <command> [command args]
+
+ commands extra parameters description
+ ----------- ------------------ ---------------------------------------
+ bins [regex] List bins (only matching regex)
+ formula <formula> Evaluated formula specified
+ formulas [regex] List formulas (only matching regex)
+ runs none List all runs in database
+ samples none List samples present in database
+ stability <pairnum> <stats> Calculated statistical info about stats
+ stat <regex> Show stat data (only matching regex)
+ stats [regex] List all stats (only matching regex)
''' % sys.argv[0]
sys.exit(1)
@@ -249,6 +262,86 @@ def commands(options, command, args):
info.source.listRuns(user)
return
+ if command == 'stability':
+ if len(args) < 2:
+ raise CommandException
+
+ try:
+ merge = int(args[0])
+ except ValueError:
+ usage()
+ stats = info.source.getStat(args[1])
+ info.source.get = "sum"
+
+
+ #loop through all the stats selected
+ for stat in stats:
+
+ print "%s:" % stat.name
+ print "%-20s %12s %12s %4s %5s %5s %5s %10s" % \
+ ("run name", "average", "stdev", ">10%", ">1SDV", ">2SDV", "SAMP", "CV")
+ print "%-20s %12s %12s %4s %5s %5s %5s %10s" % \
+ ("--------------------", "------------",
+ "------------", "----", "-----", "-----", "-----", "----------")
+ #loop through all the selected runs
+ for run in runs:
+ info.display_run = run.run;
+ runTicks = info.source.retTicks([ run ])
+ #throw away the first one, it's 0
+ runTicks.pop(0)
+ info.globalTicks = runTicks
+ avg = 0
+ stdev = 0
+ numoutsideavg = 0
+ numoutside1std = 0
+ numoutside2std = 0
+ pairRunTicks = []
+ if float(stat) == 1e300*1e300:
+ continue
+ for t in range(0, len(runTicks)-(merge-1), merge):
+ tempPair = []
+ for p in range(0,merge):
+ tempPair.append(runTicks[t+p])
+ pairRunTicks.append(tempPair)
+ #loop through all the various ticks for each run
+ for tick in pairRunTicks:
+ info.globalTicks = tick
+ avg += float(stat)
+ avg /= len(pairRunTicks)
+ for tick in pairRunTicks:
+ info.globalTicks = tick
+ val = float(stat)
+ stdev += pow((val-avg),2)
+ stdev = math.sqrt(stdev / len(pairRunTicks))
+ for tick in pairRunTicks:
+ info.globalTicks = tick
+ val = float(stat)
+ if (val < (avg * .9)) or (val > (avg * 1.1)):
+ numoutsideavg += 1
+ if (val < (avg - stdev)) or (val > (avg + stdev)):
+ numoutside1std += 1
+ if (val < (avg - (2*stdev))) or (val > (avg + (2*stdev))):
+ numoutside2std += 1
+ if avg > 1000:
+ print "%-20s %12s %12s %4s %5s %5s %5s %10s" % \
+ (run.name, "%.1f" % avg, "%.1f" % stdev,
+ "%d" % numoutsideavg, "%d" % numoutside1std,
+ "%d" % numoutside2std, "%d" % len(pairRunTicks),
+ "%.3f" % (stdev/avg*100))
+ elif avg > 100:
+ print "%-20s %12s %12s %4s %5s %5s %5s %10s" % \
+ (run.name, "%.1f" % avg, "%.1f" % stdev,
+ "%d" % numoutsideavg, "%d" % numoutside1std,
+ "%d" % numoutside2std, "%d" % len(pairRunTicks),
+ "%.5f" % (stdev/avg*100))
+ else:
+ print "%-20s %12s %12s %4s %5s %5s %5s %10s" % \
+ (run.name, "%.5f" % avg, "%.5f" % stdev,
+ "%d" % numoutsideavg, "%d" % numoutside1std,
+ "%d" % numoutside2std, "%d" % len(pairRunTicks),
+ "%.7f" % (stdev/avg*100))
+ return
+
if command == 'stats':
if len(args) == 0:
info.source.listStats()
@@ -270,7 +363,7 @@ def commands(options, command, args):
else:
if options.ticks:
print 'only displaying sample %s' % options.ticks
- stat.ticks = options.ticks
+ info.globalTicks = [ int(x) for x in options.ticks.split() ]
if options.binned:
print 'kernel ticks'
diff --git a/util/tracediff b/util/tracediff
index a95ce8b82..87210f1ed 100755
--- a/util/tracediff
+++ b/util/tracediff
@@ -1,5 +1,5 @@
#! /usr/bin/env perl
-# Copyright (c) 2003-2004 The Regents of The University of Michigan
+# 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
@@ -51,12 +51,15 @@ $sim2 = shift;
# be given to both invocations
$simargs = '"' . join('" "', @ARGV) . '"';
-# Redirect config output to cout so that gets diffed too (in case
-# that's the source of the problem).
-$simargs += " --Universe:config_output_file=cout";
+# Run individual invocations in separate dirs so output and intermediate
+# files (particularly config.py and config.ini) don't conflict.
+$dir1 = "tracediff-$$-1";
+$dir2 = "tracediff-$$-2";
+mkdir($dir1) or die "Can't create dir $dir1\n";
+mkdir($dir2) or die "Can't create dir $dir2\n";
-$cmd1 = "$sim1 $simargs --stats:text_file=tracediff-$$-1.stats 2>&1 |";
-$cmd2 = "$sim2 $simargs --stats:text_file=tracediff-$$-2.stats 2>&1 |";
+$cmd1 = "$sim1 $simargs -d $dir1 2>&1 |";
+$cmd2 = "$sim2 $simargs -d $dir2 2>&1 |";
# This only works if you have rundiff in your path. I just edit it
# with an explicit path if necessary.