summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/alpha/ev5.cc27
-rw-r--r--arch/alpha/isa_desc58
-rw-r--r--arch/alpha/osfpal.cc2
-rw-r--r--arch/alpha/osfpal.hh1
-rw-r--r--base/statistics.cc14
-rw-r--r--base/statistics.hh17
-rw-r--r--base/trace.cc66
-rw-r--r--base/trace.hh4
-rw-r--r--cpu/base_cpu.cc6
-rw-r--r--cpu/exec_context.cc63
-rw-r--r--cpu/exec_context.hh18
-rw-r--r--cpu/memtest/memtest.cc32
-rw-r--r--cpu/simple_cpu/simple_cpu.cc97
-rw-r--r--cpu/simple_cpu/simple_cpu.hh15
-rw-r--r--cpu/static_inst.hh2
-rw-r--r--dev/alpha_console.cc37
-rw-r--r--dev/alpha_console.hh15
-rw-r--r--dev/etherdump.cc20
-rw-r--r--dev/etherlink.cc180
-rw-r--r--dev/etherlink.hh38
-rw-r--r--dev/etherpkt.cc50
-rw-r--r--dev/etherpkt.hh2
-rw-r--r--dev/io_device.cc52
-rw-r--r--dev/io_device.hh59
-rw-r--r--kern/tru64/tru64_events.cc21
-rw-r--r--kern/tru64/tru64_events.hh4
-rw-r--r--kern/tru64/tru64_system.cc429
-rw-r--r--kern/tru64/tru64_system.hh99
-rw-r--r--sim/eventq.hh19
-rw-r--r--sim/sim_events.cc24
-rw-r--r--sim/sim_object.cc8
-rw-r--r--sim/system.cc80
-rw-r--r--sim/system.hh54
-rw-r--r--sim/universe.cc2
-rwxr-xr-xutil/tracediff4
35 files changed, 943 insertions, 676 deletions
diff --git a/arch/alpha/ev5.cc b/arch/alpha/ev5.cc
index 8494ee9f6..551cbdabf 100644
--- a/arch/alpha/ev5.cc
+++ b/arch/alpha/ev5.cc
@@ -237,10 +237,17 @@ ExecContext::readIpr(int idx, Fault &fault)
retval = ipr[idx];
break;
+ case AlphaISA::IPR_CC:
+ retval |= ipr[idx] & ULL(0xffffffff00000000);
+ retval |= curTick & ULL(0x00000000ffffffff);
+ break;
+
case AlphaISA::IPR_VA:
// SFX: unlocks interrupt status registers
retval = ipr[idx];
- regs.intrlock = false;
+
+ if (!misspeculating())
+ regs.intrlock = false;
break;
case AlphaISA::IPR_VA_FORM:
@@ -253,7 +260,7 @@ ExecContext::readIpr(int idx, Fault &fault)
case AlphaISA::IPR_DTB_PTE:
{
- AlphaISA::PTE &pte = dtb->index();
+ AlphaISA::PTE &pte = dtb->index(!misspeculating());
retval |= ((u_int64_t)pte.ppn & ULL(0x7ffffff)) << 32;
retval |= ((u_int64_t)pte.xre & ULL(0xf)) << 8;
@@ -327,13 +334,25 @@ ExecContext::setIpr(int idx, uint64_t val)
case AlphaISA::IPR_PAL_BASE:
case AlphaISA::IPR_IC_PERR_STAT:
case AlphaISA::IPR_DC_PERR_STAT:
- case AlphaISA::IPR_CC_CTL:
- case AlphaISA::IPR_CC:
case AlphaISA::IPR_PMCTR:
// write entire quad w/ no side-effect
ipr[idx] = val;
break;
+ case AlphaISA::IPR_CC_CTL:
+ // This IPR resets the cycle counter. We assume this only
+ // happens once... let's verify that.
+ assert(ipr[idx] == 0);
+ ipr[idx] = 1;
+ break;
+
+ case AlphaISA::IPR_CC:
+ // This IPR only writes the upper 64 bits. It's ok to write
+ // all 64 here since we mask out the lower 32 in rpcc (see
+ // isa_desc).
+ ipr[idx] = val;
+ break;
+
case AlphaISA::IPR_PALtemp23:
// write entire quad w/ no side-effect
ipr[idx] = val;
diff --git a/arch/alpha/isa_desc b/arch/alpha/isa_desc
index 75b2f4138..0da087f97 100644
--- a/arch/alpha/isa_desc
+++ b/arch/alpha/isa_desc
@@ -5,7 +5,7 @@
let {{
global rcs_id
- rcs_id = "$Id$"
+ rcs_id = "$Id: s.isa_desc 1.43 04/02/29 22:41:10-05:00 ehallnor@zazzer.eecs.umich.edu $"
}};
@@ -1000,10 +1000,50 @@ def template PrefetchDeclare {{
*/
class %(class_name)s : public %(base_class)s
{
+ protected:
+
+ /**
+ * "Fake" effective address computation class for "%(mnemonic)s".
+ */
+ class EAComp : public EACompBase
+ {
+ public:
+ /// Constructor
+ EAComp(MachInst machInst)
+ : EACompBase(machInst)
+ {
+ %(ea_constructor)s;
+ }
+ };
+
+ /**
+ * "Fake" memory access instruction class for "%(mnemonic)s".
+ */
+ class MemAcc : public MemAccBase
+ {
+ public:
+ /// Constructor
+ MemAcc(MachInst machInst)
+ : MemAccBase(machInst, %(op_class)s)
+ {
+ %(memacc_constructor)s;
+ }
+ };
+
+ /// Pointer to EAComp object.
+ StaticInstPtr<AlphaISA> eaCompPtr;
+ /// Pointer to MemAcc object.
+ StaticInstPtr<AlphaISA> memAccPtr;
+
public:
+
+ StaticInstPtr<AlphaISA> eaCompInst() { return eaCompPtr; }
+ StaticInstPtr<AlphaISA> memAccInst() { return memAccPtr; }
+
/// Constructor
%(class_name)s(MachInst machInst)
- : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s)
+ : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s),
+ eaCompPtr(new EAComp(machInst)), memAccPtr(new MemAcc(machInst))
{
%(constructor)s;
}
@@ -1814,6 +1854,9 @@ decode OPCODE default Unknown::unknown() {
0x23: ldt({{ EA = Rb + disp; }}, {{ Fa = Mem.df; }});
0x2a: ldl_l({{ EA = Rb + disp; }}, {{ Ra.sl = Mem.sl; }}, LOCKED);
0x2b: ldq_l({{ EA = Rb + disp; }}, {{ Ra.uq = Mem.uq; }}, LOCKED);
+ 0x20: copy_load({{EA = Ra;}},
+ {{ fault = memAccessObj->copySrcTranslate(EA);}},
+ IsMemRef, IsLoad, IsCopy);
}
format LoadOrPrefetch {
@@ -1833,6 +1876,9 @@ decode OPCODE default Unknown::unknown() {
0x0f: stq_u({{ EA = (Rb + disp) & ~7; }}, {{ Mem.uq = Ra.uq; }});
0x26: sts({{ EA = Rb + disp; }}, {{ Mem.ul = t_to_s(Fa.uq); }});
0x27: stt({{ EA = Rb + disp; }}, {{ Mem.df = Fa; }});
+ 0x24: copy_store({{EA = Rb;}},
+ {{ fault = memAccessObj->copy(EA);}},
+ IsMemRef, IsStore, IsCopy);
}
format StoreCond {
@@ -2342,7 +2388,13 @@ decode OPCODE default Unknown::unknown() {
}
format BasicOperate {
- 0xc000: rpcc({{ Ra = curTick; }});
+ 0xc000: rpcc({{
+#ifdef FULL_SYSTEM
+ Ra = xc->readIpr(AlphaISA::IPR_CC, fault);
+#else
+ Ra = curTick;
+#endif
+ }});
// All of the barrier instructions below do nothing in
// their execute() methods (hence the empty code blocks).
diff --git a/arch/alpha/osfpal.cc b/arch/alpha/osfpal.cc
index 4c0ace8c0..90d645ef1 100644
--- a/arch/alpha/osfpal.cc
+++ b/arch/alpha/osfpal.cc
@@ -224,8 +224,8 @@ namespace {
0, // 0xbc
0, // 0xbd
"nphalt", // 0xbe
+ "copypal", // 0xbf
#if 0
- 0, // 0xbf
0, // 0xc0
0, // 0xc1
0, // 0xc2
diff --git a/arch/alpha/osfpal.hh b/arch/alpha/osfpal.hh
index 61e545306..419235b4a 100644
--- a/arch/alpha/osfpal.hh
+++ b/arch/alpha/osfpal.hh
@@ -70,6 +70,7 @@ struct PAL
gentrap = 0xaa,
clrfen = 0xae,
nphalt = 0xbe,
+ copypal = 0xbf,
NumCodes
};
diff --git a/base/statistics.cc b/base/statistics.cc
index 49294ad27..dce545f18 100644
--- a/base/statistics.cc
+++ b/base/statistics.cc
@@ -57,7 +57,7 @@ __nan()
}
#endif
-#ifdef STAT_DEBUG
+#ifdef DEBUG
static int total_stats = 0;
#endif
@@ -409,6 +409,14 @@ DataAccess::setPrint()
Database::StatDB().regPrint(this);
}
+StatData::StatData()
+ : flags(none), precision(-1), prereq(0)
+{
+#ifdef DEBUG
+ number = total_stats++;
+#endif
+}
+
StatData::~StatData()
{
}
@@ -443,8 +451,8 @@ bool
StatData::baseCheck() const
{
if (!(flags & init)) {
-#ifdef STAT_DEBUG
- cprintf("this is stat number %d\n",(*i)->number);
+#ifdef DEBUG
+ cprintf("this is stat number %d\n", number);
#endif
panic("Not all stats have been initialized");
return false;
diff --git a/base/statistics.hh b/base/statistics.hh
index d8b78fbff..0dad31a5a 100644
--- a/base/statistics.hh
+++ b/base/statistics.hh
@@ -60,12 +60,6 @@
#include "base/str.hh"
#include "sim/host.hh"
-//
-// Un-comment this to enable weirdo-stat debugging
-//
-// #define STAT_DEBUG
-
-
#ifndef NAN
float __nan();
/** Define Not a number. */
@@ -146,10 +140,7 @@ struct StatData
/** A pointer to a prerequisite Stat. */
const StatData *prereq;
- StatData()
- : flags(none), precision(-1), prereq(0)
- {}
-
+ StatData();
virtual ~StatData();
/**
@@ -193,6 +184,10 @@ struct StatData
* @return stat1's name is alphabetically before stat2's
*/
static bool less(StatData *stat1, StatData *stat2);
+
+#ifdef DEBUG
+ int number;
+#endif
};
struct ScalarDataBase : public StatData
@@ -2503,7 +2498,7 @@ struct NoBin
* binned. If the typedef is NoBin, nothing is binned. If it is
* MainBin, then all stats are binned under that Bin.
*/
-#ifdef FS_MEASURE
+#if defined(FS_MEASURE)
typedef MainBin DefaultBin;
#else
typedef NoBin DefaultBin;
diff --git a/base/trace.cc b/base/trace.cc
index 156110376..e56bdb11b 100644
--- a/base/trace.cc
+++ b/base/trace.cc
@@ -208,8 +208,7 @@ PrintfRecord::dump(ostream &os)
-RawDataRecord::RawDataRecord(Tick _cycle,
- const uint8_t *_data, int _len)
+RawDataRecord::RawDataRecord(Tick _cycle, const void *_data, int _len)
: Record(_cycle), len(_len)
{
data = new uint8_t[len];
@@ -320,3 +319,66 @@ echoTrace(bool on)
}
}
}
+
+extern "C"
+void
+printTraceFlags()
+{
+ using namespace Trace;
+ for (int i = 0; i < numFlagStrings; ++i)
+ if (flags[i])
+ cprintf("%s\n", flagStrings[i]);
+}
+
+void
+tweakTraceFlag(const char *string, bool value)
+{
+ using namespace Trace;
+ std::string str(string);
+
+ for (int i = 0; i < numFlagStrings; ++i) {
+ if (str != flagStrings[i])
+ continue;
+
+ int idx = i;
+
+ if (idx < NumFlags) {
+ flags[idx] = value;
+ } else {
+ idx -= NumFlags;
+ if (idx >= NumCompoundFlags) {
+ ccprintf(cerr, "Invalid compound flag");
+ return;
+ }
+
+ const Flags *flagVec = compoundFlags[idx];
+
+ for (int j = 0; flagVec[j] != -1; ++j) {
+ if (flagVec[j] >= NumFlags) {
+ ccprintf(cerr, "Invalid compound flag");
+ return;
+ }
+ flags[flagVec[j]] = value;
+ }
+ }
+
+ cprintf("flag %s was %s\n", string, value ? "set" : "cleared");
+ return;
+ }
+
+ cprintf("could not find flag %s\n", string);
+}
+
+extern "C"
+void
+setTraceFlag(const char *string)
+{
+ tweakTraceFlag(string, true);
+}
+
+extern "C"
+void
+clearTraceFlag(const char *string)
+{
+ tweakTraceFlag(string, false);
+}
diff --git a/base/trace.hh b/base/trace.hh
index 9e5952765..e49d7aa61 100644
--- a/base/trace.hh
+++ b/base/trace.hh
@@ -108,7 +108,7 @@ namespace Trace {
int len;
public:
- RawDataRecord(Tick cycle, const uint8_t *_data, int _len);
+ RawDataRecord(Tick cycle, const void *_data, int _len);
virtual ~RawDataRecord();
virtual void dump(std::ostream &);
@@ -149,7 +149,7 @@ namespace Trace {
}
inline void
- rawDump(const uint8_t *data, int len)
+ rawDump(const void *data, int len)
{
theLog.append(new Trace::RawDataRecord(curTick, data, len));
}
diff --git a/cpu/base_cpu.cc b/cpu/base_cpu.cc
index bba31303b..73fb3e7fa 100644
--- a/cpu/base_cpu.cc
+++ b/cpu/base_cpu.cc
@@ -184,6 +184,12 @@ BaseCPU::takeOverFrom(BaseCPU *oldCPU)
newXC->process->replaceExecContext(newXC->cpu_id, newXC);
#endif
}
+
+#ifdef FULL_SYSTEM
+ for (int i = 0; i < NumInterruptLevels; ++i)
+ interrupts[i] = oldCPU->interrupts[i];
+ intstatus = oldCPU->intstatus;
+#endif
}
diff --git a/cpu/exec_context.cc b/cpu/exec_context.cc
index 6a5f463cd..eedd8b8a8 100644
--- a/cpu/exec_context.cc
+++ b/cpu/exec_context.cc
@@ -48,10 +48,7 @@ ExecContext::ExecContext(BaseCPU *_cpu, int _thread_num, System *_sys,
kernelStats(this, _cpu), cpu(_cpu), thread_num(_thread_num),
cpu_id(-1), mem(_mem), itb(_itb), dtb(_dtb), system(_sys),
memCtrl(_sys->memCtrl), physmem(_sys->physmem),
-#ifdef FS_MEASURE
- swCtx(NULL),
-#endif
- func_exe_inst(0), storeCondFailures(0)
+ swCtx(NULL), func_exe_inst(0), storeCondFailures(0)
{
memset(&regs, 0, sizeof(RegFile));
}
@@ -107,6 +104,33 @@ ExecContext::serialize(ostream &os)
regs.serialize(os);
// thread_num and cpu_id are deterministic from the config
SERIALIZE_SCALAR(func_exe_inst);
+
+#ifdef FULL_SYSTEM
+ bool ctx = false;
+ if (swCtx) {
+ ctx = true;
+ SERIALIZE_SCALAR(ctx);
+ SERIALIZE_SCALAR(swCtx->calls);
+ std::stack<fnCall *> *stack = &(swCtx->callStack);
+ fnCall *top;
+ int size = stack->size();
+ SERIALIZE_SCALAR(size);
+
+ for (int j=0; j<size; ++j) {
+ top = stack->top();
+ paramOut(os, csprintf("stackpos[%d]",j), top->name);
+ delete top;
+ stack->pop();
+ }
+ } else {
+ SERIALIZE_SCALAR(ctx);
+ }
+ if (system->bin) {
+ Statistics::MainBin *cur = Statistics::MainBin::curBin();
+ string bin_name = cur->name();
+ SERIALIZE_SCALAR(bin_name);
+ }
+#endif //FULL_SYSTEM
}
@@ -117,6 +141,37 @@ ExecContext::unserialize(Checkpoint *cp, const std::string &section)
regs.unserialize(cp, section);
// thread_num and cpu_id are deterministic from the config
UNSERIALIZE_SCALAR(func_exe_inst);
+
+#ifdef FULL_SYSTEM
+ bool ctx;
+ UNSERIALIZE_SCALAR(ctx);
+ if (ctx) {
+ swCtx = new SWContext;
+ UNSERIALIZE_SCALAR(swCtx->calls);
+ int size;
+ UNSERIALIZE_SCALAR(size);
+
+ vector<fnCall *> calls;
+ fnCall *call;
+ for (int i=0; i<size; ++i) {
+ call = new fnCall;
+ paramIn(cp, section, csprintf("stackpos[%d]",i), call->name);
+ call->myBin = system->getBin(call->name);
+ calls.push_back(call);
+ }
+
+ for (int i=size-1; i>=0; --i) {
+ swCtx->callStack.push(calls[i]);
+ }
+
+ }
+
+ if (system->bin) {
+ string bin_name;
+ UNSERIALIZE_SCALAR(bin_name);
+ system->getBin(bin_name)->activate();
+ }
+#endif //FULL_SYSTEM
}
diff --git a/cpu/exec_context.hh b/cpu/exec_context.hh
index e9dc5efec..a72516ac7 100644
--- a/cpu/exec_context.hh
+++ b/cpu/exec_context.hh
@@ -45,10 +45,7 @@ class MemoryController;
#include "kern/tru64/kernel_stats.hh"
#include "sim/system.hh"
-
-#ifdef FS_MEASURE
#include "sim/sw_context.hh"
-#endif
#else // !FULL_SYSTEM
@@ -137,10 +134,7 @@ class ExecContext
MemoryController *memCtrl;
PhysicalMemory *physmem;
-#ifdef FS_MEASURE
SWContext *swCtx;
-#endif
-
#else
Process *process;
@@ -153,6 +147,18 @@ class ExecContext
#endif
+ /**
+ * Temporary storage to pass the source address from copy_load to
+ * copy_store.
+ * @todo Remove this temporary when we have a better way to do it.
+ */
+ Addr copySrcAddr;
+ /**
+ * Temp storage for the physical source address of a copy.
+ * @todo Remove this temporary when we have a better way to do it.
+ */
+ Addr copySrcPhysAddr;
+
/*
* number of executed instructions, for matching with syscall trace
diff --git a/cpu/memtest/memtest.cc b/cpu/memtest/memtest.cc
index 82bec8ac9..051d9623a 100644
--- a/cpu/memtest/memtest.cc
+++ b/cpu/memtest/memtest.cc
@@ -131,7 +131,8 @@ MemTest::completeRequest(MemReqPtr &req, uint8_t *data)
case Read:
if (memcmp(req->data, data, req->size) != 0) {
cerr << name() << ": on read of 0x" << hex << req->paddr
- << " @ cycle " << dec << curTick
+ << " (0x" << hex << blockAddr(req->paddr) << ")"
+ << "@ cycle " << dec << curTick
<< ", cache returns 0x";
printData(cerr, req->data, req->size);
cerr << ", expected 0x";
@@ -163,11 +164,13 @@ MemTest::completeRequest(MemReqPtr &req, uint8_t *data)
}
if (blockAddr(req->paddr) == traceBlockAddr) {
- cerr << hex << traceBlockAddr << ": " << name() << ": completed "
+ cerr << name() << ": completed "
<< (req->cmd.isWrite() ? "write" : "read")
<< " access of "
<< dec << req->size << " bytes at address 0x"
- << hex << req->paddr << ", value = 0x";
+ << hex << req->paddr
+ << " (0x" << hex << blockAddr(req->paddr) << ")"
+ << ", value = 0x";
printData(cerr, req->data, req->size);
cerr << " @ cycle " << dec << curTick;
@@ -249,11 +252,13 @@ MemTest::tick()
uint8_t *result = new uint8_t[8];
checkMem->access(Read, req->paddr, result, req->size);
if (blockAddr(req->paddr) == traceBlockAddr) {
- cerr << hex << traceBlockAddr << ": " << name()
+ cerr << name()
<< ": initiating read "
<< ((probe)?"probe of ":"access of ")
<< dec << req->size << " bytes from addr 0x"
- << hex << req->paddr << " at cycle "
+ << hex << req->paddr
+ << " (0x" << hex << blockAddr(req->paddr) << ")"
+ << " at cycle "
<< dec << curTick << endl;
}
if (probe) {
@@ -269,13 +274,14 @@ MemTest::tick()
memcpy(req->data, &data, req->size);
checkMem->access(Write, req->paddr, req->data, req->size);
if (blockAddr(req->paddr) == traceBlockAddr) {
- cerr << hex << traceBlockAddr << ": "
- << name() << ": initiating write "
+ cerr << name() << ": initiating write "
<< ((probe)?"probe of ":"access of ")
<< dec << req->size << " bytes (value = 0x";
printData(cerr, req->data, req->size);
cerr << ") to addr 0x"
- << hex << req->paddr << " at cycle "
+ << hex << req->paddr
+ << " (0x" << hex << blockAddr(req->paddr) << ")"
+ << " at cycle "
<< dec << curTick << endl;
}
if (probe) {
@@ -303,11 +309,15 @@ MemTest::tick()
req->data = new uint8_t[blockSize];
req->size = blockSize;
if (source == traceBlockAddr || dest == traceBlockAddr) {
- cerr << hex << traceBlockAddr << ": " << name()
+ cerr << name()
<< ": initiating copy of "
<< dec << req->size << " bytes from addr 0x"
- << hex << source << " to addr 0x"
- << hex << dest << " at cycle "
+ << hex << source
+ << " (0x" << hex << blockAddr(source) << ")"
+ << " to addr 0x"
+ << hex << dest
+ << " (0x" << hex << blockAddr(dest) << ")"
+ << " at cycle "
<< dec << curTick << endl;
}
cacheInterface->access(req);
diff --git a/cpu/simple_cpu/simple_cpu.cc b/cpu/simple_cpu/simple_cpu.cc
index efbe66020..c2796efd0 100644
--- a/cpu/simple_cpu/simple_cpu.cc
+++ b/cpu/simple_cpu/simple_cpu.cc
@@ -120,7 +120,7 @@ SimpleCPU::SimpleCPU(const string &_name,
FunctionalMemory *mem,
MemInterface *icache_interface,
MemInterface *dcache_interface,
- Tick freq)
+ bool _def_reg, Tick freq)
: BaseCPU(_name, /* number_of_threads */ 1,
max_insts_any_thread, max_insts_all_threads,
max_loads_any_thread, max_loads_all_threads,
@@ -132,12 +132,14 @@ SimpleCPU::SimpleCPU(const string &_name, Process *_process,
Counter max_loads_any_thread,
Counter max_loads_all_threads,
MemInterface *icache_interface,
- MemInterface *dcache_interface)
+ MemInterface *dcache_interface,
+ bool _def_reg)
: BaseCPU(_name, /* number_of_threads */ 1,
max_insts_any_thread, max_insts_all_threads,
max_loads_any_thread, max_loads_all_threads),
#endif
- tickEvent(this), xc(NULL), cacheCompletionEvent(this)
+ tickEvent(this), xc(NULL), defer_registration(_def_reg),
+ cacheCompletionEvent(this)
{
_status = Idle;
#ifdef FULL_SYSTEM
@@ -171,6 +173,13 @@ SimpleCPU::~SimpleCPU()
{
}
+void SimpleCPU::init()
+{
+ if (!defer_registration) {
+ this->registerExecContexts();
+ }
+}
+
void
SimpleCPU::switchOut()
{
@@ -318,6 +327,46 @@ change_thread_state(int thread_number, int activate, int priority)
{
}
+Fault
+SimpleCPU::copySrcTranslate(Addr src)
+{
+ memReq->reset(src, (dcacheInterface) ?
+ dcacheInterface->getBlockSize()
+ : 64);
+
+ // translate to physical address
+ Fault fault = xc->translateDataReadReq(memReq);
+
+ if (fault == No_Fault) {
+ xc->copySrcAddr = src;
+ xc->copySrcPhysAddr = memReq->paddr;
+ } else {
+ xc->copySrcAddr = 0;
+ xc->copySrcPhysAddr = 0;
+ }
+ return fault;
+}
+
+Fault
+SimpleCPU::copy(Addr dest)
+{
+ int blk_size = (dcacheInterface) ? dcacheInterface->getBlockSize() : 64;
+ uint8_t data[blk_size];
+ assert(xc->copySrcPhysAddr);
+ memReq->reset(dest, blk_size);
+ // translate to physical address
+ Fault fault = xc->translateDataWriteReq(memReq);
+ if (fault == No_Fault) {
+ Addr dest_addr = memReq->paddr;
+ // Need to read straight from memory since we have more than 8 bytes.
+ memReq->paddr = xc->copySrcPhysAddr;
+ xc->mem->read(memReq, data);
+ memReq->paddr = dest_addr;
+ xc->mem->write(memReq, data);
+ }
+ return fault;
+}
+
// precise architected memory state accessor macros
template <class T>
Fault
@@ -343,7 +392,6 @@ SimpleCPU::read(Addr addr, T &data, unsigned flags)
memReq->cmd = Read;
memReq->completionEvent = NULL;
memReq->time = curTick;
- memReq->flags &= ~UNCACHEABLE;
MemAccessResult result = dcacheInterface->access(memReq);
// Ugly hack to get an event scheduled *only* if the access is
@@ -426,7 +474,6 @@ SimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res)
memcpy(memReq->data,(uint8_t *)&data,memReq->size);
memReq->completionEvent = NULL;
memReq->time = curTick;
- memReq->flags &= ~UNCACHEABLE;
MemAccessResult result = dcacheInterface->access(memReq);
// Ugly hack to get an event scheduled *only* if the access is
@@ -629,7 +676,6 @@ SimpleCPU::tick()
memReq->completionEvent = NULL;
memReq->time = curTick;
- memReq->flags &= ~UNCACHEABLE;
MemAccessResult result = icacheInterface->access(memReq);
// Ugly hack to get an event scheduled *only* if the access is
@@ -669,32 +715,13 @@ SimpleCPU::tick()
xc->func_exe_inst++;
fault = si->execute(this, xc, traceData);
-#ifdef FS_MEASURE
- if (!(xc->misspeculating()) && (xc->system->bin)) {
- SWContext *ctx = xc->swCtx;
- if (ctx && !ctx->callStack.empty()) {
- if (si->isCall()) {
- ctx->calls++;
- }
- if (si->isReturn()) {
- if (ctx->calls == 0) {
- fnCall *top = ctx->callStack.top();
- DPRINTF(TCPIP, "Removing %s from callstack.\n", top->name);
- delete top;
- ctx->callStack.pop();
- if (ctx->callStack.empty())
- xc->system->nonPath->activate();
- else
- ctx->callStack.top()->myBin->activate();
-
- xc->system->dumpState(xc);
- } else {
- ctx->calls--;
- }
- }
- }
- }
+
+#ifdef FULL_SYSTEM
+ SWContext *ctx = xc->swCtx;
+ if (ctx)
+ ctx->process(xc, si.get());
#endif
+
if (si->isMemRef()) {
numMemRefs++;
}
@@ -813,6 +840,7 @@ CREATE_SIM_OBJECT(SimpleCPU)
itb, dtb, mem,
(icache) ? icache->getInterface() : NULL,
(dcache) ? dcache->getInterface() : NULL,
+ defer_registration,
ticksPerSecond * mult);
#else
@@ -820,14 +848,15 @@ CREATE_SIM_OBJECT(SimpleCPU)
max_insts_any_thread, max_insts_all_threads,
max_loads_any_thread, max_loads_all_threads,
(icache) ? icache->getInterface() : NULL,
- (dcache) ? dcache->getInterface() : NULL);
+ (dcache) ? dcache->getInterface() : NULL,
+ defer_registration);
#endif // FULL_SYSTEM
-
+#if 0
if (!defer_registration) {
cpu->registerExecContexts();
}
-
+#endif
return cpu;
}
diff --git a/cpu/simple_cpu/simple_cpu.hh b/cpu/simple_cpu/simple_cpu.hh
index 16753fa4f..9edd66ab4 100644
--- a/cpu/simple_cpu/simple_cpu.hh
+++ b/cpu/simple_cpu/simple_cpu.hh
@@ -133,7 +133,7 @@ class SimpleCPU : public BaseCPU
Counter max_loads_any_thread, Counter max_loads_all_threads,
AlphaItb *itb, AlphaDtb *dtb, FunctionalMemory *mem,
MemInterface *icache_interface, MemInterface *dcache_interface,
- Tick freq);
+ bool _def_reg, Tick freq);
#else
@@ -142,11 +142,13 @@ class SimpleCPU : public BaseCPU
Counter max_insts_all_threads,
Counter max_loads_any_thread,
Counter max_loads_all_threads,
- MemInterface *icache_interface, MemInterface *dcache_interface);
+ MemInterface *icache_interface, MemInterface *dcache_interface,
+ bool _def_reg);
#endif
virtual ~SimpleCPU();
+ virtual void init();
// execution context
ExecContext *xc;
@@ -166,6 +168,8 @@ class SimpleCPU : public BaseCPU
// L1 data cache
MemInterface *dcacheInterface;
+ bool defer_registration;
+
// current instruction
MachInst inst;
@@ -233,16 +237,19 @@ class SimpleCPU : public BaseCPU
Fault write(T data, Addr addr, unsigned flags,
uint64_t *res);
- Fault prefetch(Addr addr, unsigned flags)
+ void prefetch(Addr addr, unsigned flags)
{
// need to do this...
- return No_Fault;
}
void writeHint(Addr addr, int size)
{
// need to do this...
}
+
+ Fault copySrcTranslate(Addr src);
+
+ Fault copy(Addr dest);
};
#endif // __SIMPLE_CPU_HH__
diff --git a/cpu/static_inst.hh b/cpu/static_inst.hh
index 5f4bcae3d..cdf9aefa0 100644
--- a/cpu/static_inst.hh
+++ b/cpu/static_inst.hh
@@ -96,6 +96,7 @@ class StaticInstBase : public RefCounted
IsStore, ///< Writes to memory.
IsInstPrefetch, ///< Instruction-cache prefetch.
IsDataPrefetch, ///< Data-cache prefetch.
+ IsCopy, ///< Fast Cache block copy
IsControl, ///< Control transfer instruction.
IsDirectControl, ///< PC relative control transfer.
@@ -176,6 +177,7 @@ class StaticInstBase : public RefCounted
bool isStore() const { return flags[IsStore]; }
bool isInstPrefetch() const { return flags[IsInstPrefetch]; }
bool isDataPrefetch() const { return flags[IsDataPrefetch]; }
+ bool isCopy() const { return flags[IsCopy];}
bool isInteger() const { return flags[IsInteger]; }
bool isFloating() const { return flags[IsFloating]; }
diff --git a/dev/alpha_console.cc b/dev/alpha_console.cc
index ad9d0a239..f592b239d 100644
--- a/dev/alpha_console.cc
+++ b/dev/alpha_console.cc
@@ -43,6 +43,9 @@
#include "dev/console.hh"
#include "dev/simple_disk.hh"
#include "dev/tlaser_clock.hh"
+#include "mem/bus/bus.hh"
+#include "mem/bus/pio_interface.hh"
+#include "mem/bus/pio_interface_impl.hh"
#include "mem/functional_mem/memory_control.hh"
#include "sim/builder.hh"
#include "sim/system.hh"
@@ -50,14 +53,21 @@
using namespace std;
-AlphaConsole::AlphaConsole(const string &name, SimConsole *cons,
- SimpleDisk *d, System *system,
- BaseCPU *cpu, TsunamiIO *clock, int num_cpus,
- Addr a, MemoryController *mmu)
- : FunctionalMemory(name), disk(d), console(cons), addr(a)
+AlphaConsole::AlphaConsole(const string &name, SimConsole *cons, SimpleDisk *d,
+ System *system, BaseCPU *cpu, TsunamiIO *clock,
+ int num_cpus, MemoryController *mmu, Addr a,
+ HierParams *hier, Bus *bus)
+ : PioDevice(name), disk(d), console(cons), addr(a)
+>>>>>>>
{
mmu->add_child(this, Range<Addr>(addr, addr + size));
+ if (bus) {
+ pioInterface = newPioInterface(name, hier, bus, this,
+ &AlphaConsole::cacheAccess);
+ pioInterface->addAddrRange(addr, addr + size);
+ }
+
consoleData = new uint8_t[size];
memset(consoleData, 0, size);
@@ -185,6 +195,12 @@ AlphaConsole::write(MemReqPtr &req, const uint8_t *data)
return No_Fault;
}
+Tick
+AlphaConsole::cacheAccess(MemReqPtr &req)
+{
+ return curTick + 1000;
+}
+
void
AlphaAccess::serialize(ostream &os)
{
@@ -253,6 +269,8 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(AlphaConsole)
SimObjectParam<System *> system;
SimObjectParam<BaseCPU *> cpu;
SimObjectParam<TsunamiIO *> clock;
+ SimObjectParam<Bus*> io_bus;
+ SimObjectParam<HierParams *> hier;
END_DECLARE_SIM_OBJECT_PARAMS(AlphaConsole)
@@ -265,14 +283,17 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(AlphaConsole)
INIT_PARAM(addr, "Device Address"),
INIT_PARAM(system, "system object"),
INIT_PARAM(cpu, "Processor"),
- INIT_PARAM(clock, "Turbolaser Clock")
+ INIT_PARAM(clock, "Turbolaser Clock"),
+ INIT_PARAM_DFLT(io_bus, "The IO Bus to attach to", NULL),
+ INIT_PARAM_DFLT(hier, "Hierarchy global variables", &defaultHierParams)
END_INIT_SIM_OBJECT_PARAMS(AlphaConsole)
CREATE_SIM_OBJECT(AlphaConsole)
{
- return new AlphaConsole(getInstanceName(), sim_console, disk,
- system, cpu, clock, num_cpus, addr, mmu);
+ return new AlphaConsole(getInstanceName(), sim_console, disk,
+ system, cpu, clock, num_cpus, mmu,
+ addr, hier, io_bus);
}
REGISTER_SIM_OBJECT("AlphaConsole", AlphaConsole)
diff --git a/dev/alpha_console.hh b/dev/alpha_console.hh
index d0fa552af..be8538e50 100644
--- a/dev/alpha_console.hh
+++ b/dev/alpha_console.hh
@@ -35,7 +35,7 @@
#include "base/range.hh"
#include "dev/alpha_access.h"
-#include "mem/functional_mem/functional_memory.hh"
+#include "dev/io_device.hh"
#include "sim/host.hh"
#include "dev/tsunami_io.hh"
@@ -70,7 +70,7 @@ class SimpleDisk;
* primarily used doing boot before the kernel has loaded its device
* drivers.
*/
-class AlphaConsole : public FunctionalMemory
+class AlphaConsole : public PioDevice
{
protected:
union {
@@ -89,10 +89,10 @@ class AlphaConsole : public FunctionalMemory
public:
/** Standard Constructor */
- AlphaConsole(const std::string &name, SimConsole *cons,
- SimpleDisk *d, System *system, BaseCPU *cpu,
- TsunamiIO *clock, int num_cpus,
- Addr a, MemoryController *mmu);
+ AlphaConsole(const std::string &name, SimConsole *cons, SimpleDisk *d,
+ System *system, BaseCPU *cpu, TsunamiIO *clock,
+ int num_cpus, MemoryController *mmu, Addr addr,
+ HierParams *hier, Bus *bus);
/**
* memory mapped reads and writes
@@ -105,6 +105,9 @@ class AlphaConsole : public FunctionalMemory
*/
virtual void serialize(std::ostream &os);
virtual void unserialize(Checkpoint *cp, const std::string &section);
+
+ public:
+ Tick cacheAccess(MemReqPtr &req);
};
#endif // __ALPHA_CONSOLE_HH__
diff --git a/dev/etherdump.cc b/dev/etherdump.cc
index 6d86adc32..b6d6bbe30 100644
--- a/dev/etherdump.cc
+++ b/dev/etherdump.cc
@@ -34,6 +34,7 @@
#include <string>
+#include "base/misc.hh"
#include "dev/etherdump.hh"
#include "sim/builder.hh"
#include "sim/universe.hh"
@@ -43,11 +44,8 @@ using std::string;
EtherDump::EtherDump(const string &name, const string &file)
: SimObject(name)
{
- if (!file.empty()) {
+ if (!file.empty())
stream.open(file.c_str());
- if (stream.is_open())
- init();
- }
}
#define DLT_EN10MB 1 // Ethernet (10Mb)
@@ -66,7 +64,8 @@ struct pcap_file_header {
};
struct pcap_pkthdr {
- struct timeval ts; // time stamp
+ uint32_t seconds;
+ uint32_t microseconds;
uint32_t caplen; // length of portion present
uint32_t len; // length this packet (off wire)
};
@@ -74,6 +73,9 @@ struct pcap_pkthdr {
void
EtherDump::init()
{
+ if (!stream.is_open())
+ return;
+
curtime = time(NULL);
s_freq = ticksPerSecond;
us_freq = ticksPerSecond / ULL(1000000);
@@ -96,8 +98,8 @@ EtherDump::init()
* to sim_cycles.
*/
pcap_pkthdr pkthdr;
- pkthdr.ts.tv_sec = curtime;
- pkthdr.ts.tv_usec = 0;
+ pkthdr.seconds = curtime;
+ pkthdr.microseconds = 0;
pkthdr.caplen = 0;
pkthdr.len = 0;
stream.write(reinterpret_cast<char *>(&pkthdr), sizeof(pkthdr));
@@ -109,8 +111,8 @@ void
EtherDump::dumpPacket(PacketPtr &packet)
{
pcap_pkthdr pkthdr;
- pkthdr.ts.tv_sec = curtime + (curTick / s_freq);
- pkthdr.ts.tv_usec = (curTick / us_freq) % ULL(1000000);
+ pkthdr.seconds = curtime + (curTick / s_freq);
+ pkthdr.microseconds = (curTick / us_freq) % ULL(1000000);
pkthdr.caplen = packet->length;
pkthdr.len = packet->length;
stream.write(reinterpret_cast<char *>(&pkthdr), sizeof(pkthdr));
diff --git a/dev/etherlink.cc b/dev/etherlink.cc
index 676b1da1c..25991f1a7 100644
--- a/dev/etherlink.cc
+++ b/dev/etherlink.cc
@@ -42,17 +42,19 @@
#include "dev/etherpkt.hh"
#include "sim/builder.hh"
#include "sim/universe.hh"
+#include "sim/system.hh"
using namespace std;
-EtherLink::EtherLink(const std::string &name, EtherInt *i1, EtherInt *i2,
- Tick speed, EtherDump *dump)
+EtherLink::EtherLink(const string &name, EtherInt *i1, EtherInt *i2,
+ 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, dump);
- link2 = new Link(name + ".link2", rate, dump);
+ link1 = new Link(name + ".link1", rate, delay, dump);
+ link2 = new Link(name + ".link2", rate, delay, dump);
int1 = new Interface(name + ".int1", link1, link2);
int2 = new Interface(name + ".int2", link2, link1);
@@ -72,28 +74,76 @@ EtherLink::~EtherLink()
delete int2;
}
-EtherLink::Interface::Interface(const std::string &name, Link *tx, Link *rx)
+EtherLink::Interface::Interface(const string &name, Link *tx, Link *rx)
: EtherInt(name), txlink(tx)
{
tx->setTxInt(this);
rx->setRxInt(this);
}
-EtherLink::Link::Link(const std::string &name, double rate, EtherDump *d)
- : objName(name), txint(NULL), rxint(NULL), ticks_per_byte(rate),
- dump(d), event(&mainEventQueue, 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)
{}
void
+EtherLink::serialize(ostream &os)
+{
+ nameOut(os, name() + ".link1");
+ link1->serialize(os);
+ nameOut(os, name() + ".link2");
+ link2->serialize(os);
+}
+
+void
+EtherLink::unserialize(Checkpoint *cp, const string &section)
+{
+ link1->unserialize(cp, section + ".link1");
+ link2->unserialize(cp, section + ".link2");
+}
+
+void
+EtherLink::Link::txComplete(PacketPtr &packet)
+{
+ DPRINTF(Ethernet, "packet received: len=%d\n", packet->length);
+ DDUMP(EthernetData, packet->data, packet->length);
+ rxint->sendPacket(packet);
+}
+
+class LinkDelayEvent : public Event
+{
+ protected:
+ EtherLink::Link *link;
+ PacketPtr packet;
+
+ // non-scheduling version for createForUnserialize()
+ LinkDelayEvent(EtherLink::Link *link);
+
+ public:
+ LinkDelayEvent(EtherLink::Link *link, PacketPtr &pkt, Tick when);
+
+ void process();
+
+ virtual void serialize(ostream &os);
+ virtual void unserialize(Checkpoint *cp, const string &section);
+ static Serializable *createForUnserialize(Checkpoint *cp,
+ const string &section);
+};
+
+
+void
EtherLink::Link::txDone()
{
if (dump)
dump->dump(packet);
- DPRINTF(Ethernet, "EtherLink packet received: len=%d\n", packet->length);
- DDUMP(EthernetData, packet->data, packet->length);
-
- rxint->sendPacket(packet);
+ if (linkDelay > 0) {
+ DPRINTF(Ethernet, "packet delayed: delay=%d\n", linkDelay);
+ new LinkDelayEvent(this, packet, curTick + linkDelay);
+ } else {
+ txComplete(packet);
+ }
packet = 0;
assert(!busy());
@@ -105,27 +155,118 @@ bool
EtherLink::Link::transmit(PacketPtr &pkt)
{
if (busy()) {
- DPRINTF(Ethernet, "EtherLink packet not sent, link busy\n");
+ DPRINTF(Ethernet, "packet not sent, link busy\n");
return false;
}
- DPRINTF(Ethernet, "EtherLink packet sent: len=%d\n", pkt->length);
+ DPRINTF(Ethernet, "packet sent: len=%d\n", pkt->length);
DDUMP(EthernetData, pkt->data, pkt->length);
packet = pkt;
- int delay = (int)ceil(((double)pkt->length * ticks_per_byte) + 1.0);
- DPRINTF(Ethernet, "EtherLink scheduling packet: delay=%d, (rate=%f)\n",
- delay, ticks_per_byte);
- event.schedule(curTick + delay);
+ Tick delay = (Tick)ceil(((double)pkt->length * ticksPerByte) + 1.0);
+ DPRINTF(Ethernet, "scheduling packet: delay=%d, (rate=%f)\n",
+ delay, ticksPerByte);
+ doneEvent.schedule(curTick + delay);
return true;
}
+void
+EtherLink::Link::serialize(ostream &os)
+{
+ bool packet_exists = packet;
+ SERIALIZE_SCALAR(packet_exists);
+
+ bool event_scheduled = doneEvent.scheduled();
+ SERIALIZE_SCALAR(event_scheduled);
+ if (event_scheduled) {
+ Tick event_time = doneEvent.when();
+ SERIALIZE_SCALAR(event_time);
+ }
+
+ if (packet_exists) {
+ nameOut(os, csprintf("%s.packet", name()));
+ packet->serialize(os);
+ }
+}
+
+void
+EtherLink::Link::unserialize(Checkpoint *cp, const string &section)
+{
+ bool packet_exists;
+ UNSERIALIZE_SCALAR(packet_exists);
+ if (packet_exists) {
+ packet = new EtherPacket;
+ packet->unserialize(cp, csprintf("%s.packet", section));
+ }
+
+ bool event_scheduled;
+ UNSERIALIZE_SCALAR(event_scheduled);
+ if (event_scheduled) {
+ Tick event_time;
+ UNSERIALIZE_SCALAR(event_time);
+ doneEvent.schedule(event_time);
+ }
+}
+
+LinkDelayEvent::LinkDelayEvent(EtherLink::Link *l)
+ : Event(&mainEventQueue), link(l)
+{
+ setFlags(AutoSerialize);
+ setFlags(AutoDelete);
+}
+
+LinkDelayEvent::LinkDelayEvent(EtherLink::Link *l, PacketPtr &p, Tick when)
+ : Event(&mainEventQueue), link(l), packet(p)
+{
+ setFlags(AutoSerialize);
+ setFlags(AutoDelete);
+ schedule(when);
+}
+
+void
+LinkDelayEvent::process()
+{
+ link->txComplete(packet);
+}
+
+void
+LinkDelayEvent::serialize(ostream &os)
+{
+ paramOut(os, "type", string("LinkDelayEvent"));
+ Event::serialize(os);
+ SERIALIZE_OBJPTR(link);
+
+ nameOut(os, csprintf("%s.packet", name()));
+ packet->serialize(os);
+}
+
+
+void
+LinkDelayEvent::unserialize(Checkpoint *cp, const string &section)
+{
+ Event::unserialize(cp, section);
+ packet = new EtherPacket;
+ packet->unserialize(cp, csprintf("%s.packet", section));
+}
+
+
+Serializable *
+LinkDelayEvent::createForUnserialize(Checkpoint *cp, const string &section)
+{
+ EtherLink::Link *link;
+ UNSERIALIZE_OBJPTR(link);
+ return new LinkDelayEvent(link);
+}
+
+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;
END_DECLARE_SIM_OBJECT_PARAMS(EtherLink)
@@ -135,6 +276,7 @@ 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)
END_INIT_SIM_OBJECT_PARAMS(EtherLink)
@@ -142,7 +284,7 @@ END_INIT_SIM_OBJECT_PARAMS(EtherLink)
CREATE_SIM_OBJECT(EtherLink)
{
return new EtherLink(getInstanceName(), interface1, interface2, link_speed,
- packet_dump);
+ link_delay, packet_dump);
}
REGISTER_SIM_OBJECT("EtherLink", EtherLink)
diff --git a/dev/etherlink.hh b/dev/etherlink.hh
index e1a7957ee..3b1dd21bc 100644
--- a/dev/etherlink.hh
+++ b/dev/etherlink.hh
@@ -49,6 +49,7 @@ class EtherLink : public SimObject
protected:
class Interface;
+ friend class LinkDelayEvent;
/*
* Model for a single uni-directional link
*/
@@ -59,34 +60,26 @@ class EtherLink : public SimObject
Interface *txint;
Interface *rxint;
- double ticks_per_byte;
+ double ticksPerByte;
+ Tick linkDelay;
EtherDump *dump;
protected:
/*
* Transfer is complete
*/
- class DoneEvent : public Event
- {
- protected:
- Link *link;
-
- public:
- DoneEvent(EventQueue *q, Link *l)
- : Event(q), link(l) {}
- virtual void process() { link->txDone(); }
- virtual const char *description()
- { return "ethernet link completion"; }
- };
-
- friend class DoneEvent;
- DoneEvent event;
PacketPtr packet;
-
void txDone();
+ typedef EventWrapper<Link, &Link::txDone> DoneEvent;
+ friend class DoneEvent;
+ DoneEvent doneEvent;
+
+ friend class LinkDelayEvent;
+ void txComplete(PacketPtr &packet);
public:
- Link(const std::string &name, double rate, EtherDump *dump);
+ Link(const std::string &name, double rate, Tick delay,
+ EtherDump *dump);
~Link() {}
virtual const std::string name() const { return objName; }
@@ -96,6 +89,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);
};
/*
@@ -120,8 +116,12 @@ class EtherLink : public SimObject
public:
EtherLink(const std::string &name, EtherInt *i1, EtherInt *i2,
- Tick speed, EtherDump *dump);
+ Tick speed, Tick delay, EtherDump *dump);
virtual ~EtherLink();
+
+ virtual void serialize(std::ostream &os);
+ virtual void unserialize(Checkpoint *cp, const std::string &section);
+
};
#endif // __ETHERLINK_HH__
diff --git a/dev/etherpkt.cc b/dev/etherpkt.cc
new file mode 100644
index 000000000..cb6087c89
--- /dev/null
+++ b/dev/etherpkt.cc
@@ -0,0 +1,50 @@
+/*
+ * 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.
+ */
+
+#include <iostream>
+
+#include "dev/etherpkt.hh"
+#include "sim/serialize.hh"
+
+using namespace std;
+
+void
+EtherPacket::serialize(ostream &os)
+{
+ SERIALIZE_SCALAR(length);
+ SERIALIZE_ARRAY(data, length);
+}
+
+void
+EtherPacket::unserialize(Checkpoint *cp, const std::string &section)
+{
+ UNSERIALIZE_SCALAR(length);
+ data = new uint8_t[length];
+ UNSERIALIZE_ARRAY(data, length);
+}
+
diff --git a/dev/etherpkt.hh b/dev/etherpkt.hh
index c91322526..27ac526d6 100644
--- a/dev/etherpkt.hh
+++ b/dev/etherpkt.hh
@@ -33,10 +33,10 @@
#ifndef __ETHERPKT_HH__
#define __ETHERPKT_HH__
+#include <iosfwd>
#include <memory>
#include "sim/host.hh"
-
#include "base/refcnt.hh"
class Checkpoint;
diff --git a/dev/io_device.cc b/dev/io_device.cc
new file mode 100644
index 000000000..4f53ba48d
--- /dev/null
+++ b/dev/io_device.cc
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2003 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 "dev/io_device.hh"
+#include "mem/bus/base_interface.hh"
+#include "mem/bus/dma_interface.hh"
+
+PioDevice::PioDevice(const std::string &name)
+ : FunctionalMemory(name), pioInterface(NULL)
+{}
+
+PioDevice::~PioDevice()
+{
+ if (pioInterface)
+ delete pioInterface;
+}
+
+DmaDevice::DmaDevice(const std::string &name)
+ : PioDevice(name), dmaInterface(NULL)
+{}
+
+DmaDevice::~DmaDevice()
+{
+ if (dmaInterface)
+ delete dmaInterface;
+}
+
diff --git a/dev/io_device.hh b/dev/io_device.hh
new file mode 100644
index 000000000..9300d87e7
--- /dev/null
+++ b/dev/io_device.hh
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2003 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 __IO_DEVICE_HH__
+#define __IO_DEVICE_HH__
+
+#include "mem/functional_mem/functional_memory.hh"
+
+class BaseInterface;
+class Bus;
+class HierParams;
+template <class Bus> class DMAInterface;
+
+class PioDevice : public FunctionalMemory
+{
+ protected:
+ BaseInterface *pioInterface;
+
+ public:
+ PioDevice(const std::string &name);
+ virtual ~PioDevice();
+};
+
+class DmaDevice : public PioDevice
+{
+ protected:
+ DMAInterface<Bus> *dmaInterface;
+
+ public:
+ DmaDevice(const std::string &name);
+ virtual ~DmaDevice();
+};
+
+#endif // __IO_DEVICE_HH__
diff --git a/kern/tru64/tru64_events.cc b/kern/tru64/tru64_events.cc
index f542256e4..a57c01841 100644
--- a/kern/tru64/tru64_events.cc
+++ b/kern/tru64/tru64_events.cc
@@ -35,11 +35,8 @@
#include "kern/tru64/tru64_events.hh"
#include "mem/functional_mem/memory_control.hh"
#include "targetarch/arguments.hh"
-
-#ifdef FS_MEASURE
#include "sim/system.hh"
#include "sim/sw_context.hh"
-#endif
void
SkipFuncEvent::process(ExecContext *xc)
@@ -110,7 +107,6 @@ DumpMbufEvent::process(ExecContext *xc)
}
}
-#ifdef FS_MEASURE
FnEvent::FnEvent(PCEventQueue *q, const std::string & desc, System *system)
: PCEvent(q, desc), _name(desc)
{
@@ -128,13 +124,25 @@ FnEvent::process(ExecContext *xc)
DPRINTF(TCPIP, "%s: %s Event!!!\n", xc->system->name(), description);
if (ctx && !ctx->callStack.empty()) {
+ DPRINTF(TCPIP, "already a callstack!\n");
fnCall *last = ctx->callStack.top();
- if (!xc->system->findCaller(myname(), last->name)) {
+
+ if (last->name == "idle_thread")
+ ctx->calls++;
+
+ if (!xc->system->findCaller(myname(), "" ) &&
+ !xc->system->findCaller(myname(), last->name)) {
+
+ DPRINTF(TCPIP, "but can't find parent %s\n", last->name);
return;
}
ctx->calls--;
+
+ //assert(!ctx->calls && "on a binned fn, calls should == 0 (but can happen in boot)");
} else {
+ DPRINTF(TCPIP, "no callstack yet\n");
if (!xc->system->findCaller(myname(), "")) {
+ DPRINTF(TCPIP, "not the right function, returning\n");
return;
}
if (!ctx) {
@@ -150,6 +158,7 @@ FnEvent::process(ExecContext *xc)
ctx->callStack.push(call);
myBin->activate();
xc->system->fnCalls++;
+ DPRINTF(TCPIP, "fnCalls for %s is %d\n", description,
+ xc->system->fnCalls.val());
xc->system->dumpState(xc);
}
-#endif //FS_MEASURE
diff --git a/kern/tru64/tru64_events.hh b/kern/tru64/tru64_events.hh
index 2067f2ef3..96e6a8b26 100644
--- a/kern/tru64/tru64_events.hh
+++ b/kern/tru64/tru64_events.hh
@@ -35,9 +35,7 @@
class ExecContext;
-#ifdef FS_MEASURE
class System;
-#endif
class SkipFuncEvent : public PCEvent
{
@@ -82,7 +80,6 @@ class DumpMbufEvent : public PCEvent
virtual void process(ExecContext *xc);
};
-#ifdef FS_MEASURE
class FnEvent : public PCEvent
{
public:
@@ -94,5 +91,4 @@ class FnEvent : public PCEvent
std::string _name;
Statistics::MainBin *myBin;
};
-#endif //FS_MEASURE
#endif // __TRU64_EVENTS_HH__
diff --git a/kern/tru64/tru64_system.cc b/kern/tru64/tru64_system.cc
index 1cd98fdc1..b03d7bf26 100644
--- a/kern/tru64/tru64_system.cc
+++ b/kern/tru64/tru64_system.cc
@@ -41,17 +41,15 @@
#include "targetarch/isa_traits.hh"
#include "targetarch/vtophys.hh"
-//un-comment this to see the state of call stack when it changes.
-//#define SW_DEBUG
-
using namespace std;
Tru64System::Tru64System(const string _name, const uint64_t _init_param,
MemoryController *_memCtrl, PhysicalMemory *_physmem,
const string &kernel_path, const string &console_path,
const string &palcode, const string &boot_osflags,
- const bool _bin)
- : System(_name, _init_param, _memCtrl, _physmem, _bin), bin(_bin)
+ const bool _bin, const vector<string> &binned_fns)
+ : System(_name, _init_param, _memCtrl, _physmem, _bin),
+ bin(_bin), binned_fns(binned_fns)
{
kernelSymtab = new SymbolTable;
consoleSymtab = new SymbolTable;
@@ -92,106 +90,6 @@ Tru64System::Tru64System(const string _name, const uint64_t _init_param,
DPRINTF(Loader, "Kernel loaded...\n");
-#ifdef FS_MEASURE
- //INSTRUMENTATION CODEGEN BEGIN ONE
- if (bin == true) {
- esIntrBin = new Statistics::MainBin(name() + " es_intr");
- fnBins.insert(make_pair("es_intr", esIntrBin));
-
- esRxeofBin = new Statistics::MainBin(name() + " es_rxeof");
- fnBins.insert(make_pair("es_rxeof", esRxeofBin));
-
- esNewbufBin = new Statistics::MainBin(name() + " es_newbuf");
- fnBins.insert(make_pair("es_newbuf", esNewbufBin));
-
- esDmaLoadBin = new Statistics::MainBin(name() + " es_dma_load");
- fnBins.insert(make_pair("es_dma_load", esDmaLoadBin));
-
- dmaMapLoadBin = new Statistics::MainBin(name() + " dma_map_load");
- fnBins.insert(make_pair("dma_map_load", dmaMapLoadBin));
-
- etherInputBin = new Statistics::MainBin(name() + " ether_input");
- fnBins.insert(make_pair("ether_input", etherInputBin));
-
- netisrInputBin = new Statistics::MainBin(name() + " netisr_input");
- fnBins.insert(make_pair("netisr_input", netisrInputBin));
-
- schednetisrIsrBin = new Statistics::MainBin(name() + " schednetisr_isr");
- fnBins.insert(make_pair("schednetisr_isr", schednetisrIsrBin));
-
- ipintrBin = new Statistics::MainBin(name() + " ipintr");
- fnBins.insert(make_pair("ipintr", ipintrBin));
-
- ipDooptionsBin = new Statistics::MainBin(name() + " ip_dooptions");
- fnBins.insert(make_pair("ip_dooptions", ipDooptionsBin));
-
- ipReassBin = new Statistics::MainBin(name() + " ip_reass");
- fnBins.insert(make_pair("ip_reass", ipReassBin));
-
- tcpInputBin = new Statistics::MainBin(name() + " tcp_input");
- fnBins.insert(make_pair("tcp_input", tcpInputBin));
-
- sbappendBin = new Statistics::MainBin(name() + " sbappend");
- fnBins.insert(make_pair("sbappend", sbappendBin));
-
- readBin = new Statistics::MainBin(name() + " read");
- fnBins.insert(make_pair("read", readBin));
-
- sooReadBin = new Statistics::MainBin(name() + " soo_read");
- fnBins.insert(make_pair("soo_read", sooReadBin));
-
- orecvBin = new Statistics::MainBin(name() + " orecv");
- fnBins.insert(make_pair("orecv", orecvBin));
-
- recvitBin = new Statistics::MainBin(name() + " recvit");
- fnBins.insert(make_pair("recvit", recvitBin));
-
- soreceiveBin = new Statistics::MainBin(name() + " soreceive");
- fnBins.insert(make_pair("soreceive", soreceiveBin));
-
- osendBin = new Statistics::MainBin(name() + " osend");
- fnBins.insert(make_pair("osend", osendBin));
-
- writeBin = new Statistics::MainBin(name() + " write");
- fnBins.insert(make_pair("write", writeBin));
-
- sooWriteBin = new Statistics::MainBin(name() + " soo_write");
- fnBins.insert(make_pair("soo_write", sooWriteBin));
-
- senditBin = new Statistics::MainBin(name() + " sendit");
- fnBins.insert(make_pair("sendit", senditBin));
-
- sosendBin = new Statistics::MainBin(name() + " sosend");
- fnBins.insert(make_pair("sosend", sosendBin));
-
- tcpSosendBin = new Statistics::MainBin(name() + " tcp_sosend");
- fnBins.insert(make_pair("tcp_sosend", tcpSosendBin));
-
- tcpOutputBin = new Statistics::MainBin(name() + " tcp_output");
- fnBins.insert(make_pair("tcp_output", tcpOutputBin));
-
- ipOutputBin = new Statistics::MainBin(name() + " ip_output");
- fnBins.insert(make_pair("ip_output", ipOutputBin));
-
- etherOutputBin = new Statistics::MainBin(name() + " ether_output");
- fnBins.insert(make_pair("ether_output", etherOutputBin));
-
- esStartBin = new Statistics::MainBin(name() + " es_start");
- fnBins.insert(make_pair("es_start", esStartBin));
-
- esTransmitBin = new Statistics::MainBin(name() + " es_transmit");
- fnBins.insert(make_pair("es_transmit", esTransmitBin));
-
- esTxeofBin = new Statistics::MainBin(name() + " es_txeof");
- fnBins.insert(make_pair("es_txeof", esTxeofBin));
-
- idleThreadBin = new Statistics::MainBin(name() + " idle_thread");
- fnBins.insert(make_pair("idle_thread", idleThreadBin));
-
- }
- //INSTRUMENTATION CODEGEN END
-#endif //FS_MEASURE
-
#ifdef DEBUG
kernelPanicEvent = new BreakPCEvent(&pcEventQueue, "kernel panic");
consolePanicEvent = new BreakPCEvent(&pcEventQueue, "console panic");
@@ -208,44 +106,6 @@ Tru64System::Tru64System(const string _name, const uint64_t _init_param,
"debug_printfr", true);
dumpMbufEvent = new DumpMbufEvent(&pcEventQueue, "dump_mbuf");
-#ifdef FS_MEASURE
- //INSTRUMENTATION CODEGEN BEGIN TWO
- if (bin == true) {
- esIntrEvent = new FnEvent(&pcEventQueue, "es_intr", this);
- esRxeofEvent = new FnEvent(&pcEventQueue, "es_rxeof", this);
- esNewbufEvent = new FnEvent(&pcEventQueue, "es_newbuf", this);
- esDmaLoadEvent = new FnEvent(&pcEventQueue, "es_dma_load", this);
- dmaMapLoadEvent = new FnEvent(&pcEventQueue, "dma_map_load", this);
- etherInputEvent = new FnEvent(&pcEventQueue, "ether_input", this);
- netisrInputEvent = new FnEvent(&pcEventQueue, "netisr_input", this);
- schednetisrIsrEvent = new FnEvent(&pcEventQueue, "schednetisr_isr", this);
- ipintrEvent = new FnEvent(&pcEventQueue, "ipintr", this);
- ipDooptionsEvent = new FnEvent(&pcEventQueue, "ip_dooptions", this);
- ipReassEvent = new FnEvent(&pcEventQueue, "ip_reass", this);
- tcpInputEvent = new FnEvent(&pcEventQueue, "tcp_input", this);
- sbappendEvent = new FnEvent(&pcEventQueue, "sbappend", this);
- readEvent = new FnEvent(&pcEventQueue, "read", this);
- sooReadEvent = new FnEvent(&pcEventQueue, "soo_read", this);
- orecvEvent = new FnEvent(&pcEventQueue, "orecv", this);
- recvitEvent = new FnEvent(&pcEventQueue, "recvit", this);
- soreceiveEvent = new FnEvent(&pcEventQueue, "soreceive", this);
- osendEvent = new FnEvent(&pcEventQueue, "osend", this);
- writeEvent = new FnEvent(&pcEventQueue, "write", this);
- sooWriteEvent = new FnEvent(&pcEventQueue, "soo_write", this);
- senditEvent = new FnEvent(&pcEventQueue, "sendit", this);
- sosendEvent = new FnEvent(&pcEventQueue, "sosend", this);
- tcpSosendEvent = new FnEvent(&pcEventQueue, "tcp_sosend", this);
- tcpOutputEvent = new FnEvent(&pcEventQueue, "tcp_output", this);
- ipOutputEvent = new FnEvent(&pcEventQueue, "ip_output", this);
- etherOutputEvent = new FnEvent(&pcEventQueue, "ether_output", this);
- esStartEvent = new FnEvent(&pcEventQueue, "es_start", this);
- esTransmitEvent = new FnEvent(&pcEventQueue, "es_transmit", this);
- esTxeofEvent = new FnEvent(&pcEventQueue, "es_txeof", this);
- idleThreadEvent = new FnEvent(&pcEventQueue, "idle_thread", this);
- }
- //INSTRUMENTATION CODEGEN END
-#endif //FS_MEASURE
-
Addr addr = 0;
if (kernelSymtab->findAddress("enable_async_printf", addr)) {
Addr paddr = vtophys(physmem, addr);
@@ -299,212 +159,38 @@ Tru64System::Tru64System(const string _name, const uint64_t _init_param,
dumpMbufEvent->schedule(addr);
#endif
-#ifdef FS_MEASURE
- //INSTRUMENTATION CODEGEN BEGIN THREE
+ // BINNING STUFF
if (bin == true) {
- if (kernelSymtab->findAddress("es_intr", addr))
- esIntrEvent->schedule(addr);
- else
- panic("could not find kernel symbol \'es_intr\'");
-
- if (kernelSymtab->findAddress("es_rxeof", addr))
- esRxeofEvent->schedule(addr);
- else
- panic("could not find kernel symbol \'es_rxeof\'");
-
- if (kernelSymtab->findAddress("es_newbuf", addr))
- esNewbufEvent->schedule(addr);
- else
- panic("could not find kernel symbol \'es_newbuf\'");
-
- if (kernelSymtab->findAddress("es_dma_load", addr))
- esDmaLoadEvent->schedule(addr);
- else
- panic("could not find kernel symbol \'es_dma_load\'");
-
- if (kernelSymtab->findAddress("dma_map_load", addr))
- dmaMapLoadEvent->schedule(addr);
- else
- panic("could not find kernel symbol \'dma_map_load\'");
-
- if (kernelSymtab->findAddress("ether_input", addr))
- etherInputEvent->schedule(addr);
- else
- panic("could not find kernel symbol \'ether_input\'");
-
- if (kernelSymtab->findAddress("netisr_input", addr))
- netisrInputEvent->schedule(addr);
- else
- panic("could not find kernel symbol \'netisr_input\'");
-
- if (kernelSymtab->findAddress("schednetisr_isr", addr))
- schednetisrIsrEvent->schedule(addr);
- else
- panic("could not find kernel symbol \'schednetisr_isr\'");
-
- if (kernelSymtab->findAddress("ipintr", addr))
- ipintrEvent->schedule(addr);
- else
- panic("could not find kernel symbol \'ipintr\'");
-
- if (kernelSymtab->findAddress("ip_dooptions", addr))
- ipDooptionsEvent->schedule(addr);
- else
- panic("could not find kernel symbol \'ip_dooptions\'");
-
- if (kernelSymtab->findAddress("ip_reass", addr))
- ipReassEvent->schedule(addr);
- else
- panic("could not find kernel symbol \'ip_reass\'");
-
- if (kernelSymtab->findAddress("tcp_input", addr))
- tcpInputEvent->schedule(addr);
- else
- panic("could not find kernel symbol \'tcp_input\'");
-
- if (kernelSymtab->findAddress("sbappend", addr))
- sbappendEvent->schedule(addr);
- else
- panic("could not find kernel symbol \'sbappend\'");
-
- if (kernelSymtab->findAddress("read", addr))
- readEvent->schedule(addr);
- else
- panic("could not find kernel symbol \'read\'");
-
- if (kernelSymtab->findAddress("soo_read", addr))
- sooReadEvent->schedule(addr);
- else
- panic("could not find kernel symbol \'soo_read\'");
-
- if (kernelSymtab->findAddress("orecv", addr))
- orecvEvent->schedule(addr);
- else
- panic("could not find kernel symbol \'orecv\'");
-
- if (kernelSymtab->findAddress("recvit", addr))
- recvitEvent->schedule(addr);
- else
- panic("could not find kernel symbol \'recvit\'");
-
- if (kernelSymtab->findAddress("soreceive", addr))
- soreceiveEvent->schedule(addr);
- else
- panic("could not find kernel symbol \'soreceive\'");
-
- if (kernelSymtab->findAddress("osend", addr))
- osendEvent->schedule(addr);
- else
- panic("could not find kernel symbol \'osend\'");
-
- if (kernelSymtab->findAddress("write", addr))
- writeEvent->schedule(addr);
- else
- panic("could not find kernel symbol \'write\'");
-
- if (kernelSymtab->findAddress("soo_write", addr))
- sooWriteEvent->schedule(addr);
- else
- panic("could not find kernel symbol \'soo_write\'");
-
- if (kernelSymtab->findAddress("sendit", addr))
- senditEvent->schedule(addr);
- else
- panic("could not find kernel symbol \'sendit\'");
-
- if (kernelSymtab->findAddress("sosend", addr))
- sosendEvent->schedule(addr);
- else
- panic("could not find kernel symbol \'sosend\'");
-
- if (kernelSymtab->findAddress("tcp_sosend", addr))
- tcpSosendEvent->schedule(addr);
- else
- panic("could not find kernel symbol \'tcp_sosend\'");
-
- if (kernelSymtab->findAddress("tcp_output", addr))
- tcpOutputEvent->schedule(addr);
- else
- panic("could not find kernel symbol \'tcp_output\'");
-
- if (kernelSymtab->findAddress("ip_output", addr))
- ipOutputEvent->schedule(addr);
- else
- panic("could not find kernel symbol \'ip_output\'");
-
- if (kernelSymtab->findAddress("ether_output", addr))
- etherOutputEvent->schedule(addr);
- else
- panic("could not find kernel symbol \'ether_output\'");
-
- if (kernelSymtab->findAddress("es_start", addr))
- esStartEvent->schedule(addr);
- else
- panic("could not find kernel symbol \'es_start\'");
-
- if (kernelSymtab->findAddress("es_transmit", addr))
- esTransmitEvent->schedule(addr);
- else
- panic("could not find kernel symbol \'es_transmit\'");
-
- if (kernelSymtab->findAddress("es_txeof", addr))
- esTxeofEvent->schedule(addr);
- else
- panic("could not find kernel symbol \'es_txeof\'");
-
- if (kernelSymtab->findAddress("idle_thread", addr))
- idleThreadEvent->schedule(addr);
- else
- panic("could not find kernel symbol \'idle_thread\'");
+ int end = binned_fns.size();
+ assert(!(end & 1));
+
+ Statistics::MainBin *Bin;
+ Addr address = 0;
+
+ fnEvents.resize(end>>1);
+
+ for (int i = 0; i < end; i +=2) {
+ Bin = new Statistics::MainBin(binned_fns[i]);
+ fnBins.insert(make_pair(binned_fns[i], Bin));
+
+ fnEvents[(i>>1)] = new FnEvent(&pcEventQueue, binned_fns[i], this);
+ if (kernelSymtab->findAddress(binned_fns[i], address))
+ fnEvents[(i>>1)]->schedule(address);
+ else
+ panic("could not find kernel symbol %s\n", binned_fns[i]);
+
+ if (binned_fns[i+1] == "null")
+ populateMap(binned_fns[i], "");
+ else
+ populateMap(binned_fns[i], binned_fns[i+1]);
+ }
- }
- //INSTRUMENTATION CODEGEN END
- if (bin == true) {
fnCalls
.name(name() + ":fnCalls")
.desc("all fn calls being tracked")
;
-
- populateMap("es_intr", "");
- populateMap("es_rxeof", "es_intr");
- populateMap("es_newbuf", "es_rxeof");
- populateMap("es_dma_load", "es_newbuf");
- populateMap("dma_map_load", "es_dma_load");
- populateMap("ether_input", "es_rxeof");
- populateMap("netisr_input", "ether_input");
- populateMap("schednetisr_isr", "netisr_input");
-
- populateMap("ipintr", "");
- populateMap("ip_dooptions", "ipintr");
- populateMap("ip_reass", "ipintr");
- populateMap("tcp_input", "ipintr");
- populateMap("sbappend", "tcp_input");
-
- populateMap("read", "");
- populateMap("orecv", "");
- populateMap("soo_read", "read");
- populateMap("recvit", "orecv");
- populateMap("soreceive", "recvit");
- populateMap("soreceive", "soo_read");
-
- populateMap("write", "");
- populateMap("osend", "");
- populateMap("soo_write", "write");
- populateMap("sendit", "osend");
- populateMap("sosend", "sendit");
- populateMap("sosend", "soo_write");
- populateMap("tcp_sosend", "sosend");
- populateMap("tcp_output", "tcp_sosend");
- populateMap("ip_output", "tcp_output");
- populateMap("ether_output", "ip_output");
- populateMap("es_start", "ether_output");
- populateMap("es_transmit", "es_start");
-
- populateMap("es_txeof", "es_intr");
-
- populateMap("idle_thread", "");
}
-#endif //FS_MEASURE
+ //
}
Tru64System::~Tru64System()
@@ -527,43 +213,13 @@ Tru64System::~Tru64System()
delete debugPrintfrEvent;
delete dumpMbufEvent;
-#ifdef FS_MEASURE
- //INSTRUMENTATION CODEGEN BEGIN FOUR
if (bin == true) {
- delete esIntrEvent;
- delete esRxeofEvent;
- delete esNewbufEvent;
- delete esDmaLoadEvent;
- delete dmaMapLoadEvent;
- delete etherInputEvent;
- delete netisrInputEvent;
- delete schednetisrIsrEvent;
- delete ipintrEvent;
- delete ipDooptionsEvent;
- delete ipReassEvent;
- delete tcpInputEvent;
- delete sbappendEvent;
- delete readEvent;
- delete sooReadEvent;
- delete orecvEvent;
- delete recvitEvent;
- delete soreceiveEvent;
- delete osendEvent;
- delete writeEvent;
- delete sooWriteEvent;
- delete senditEvent;
- delete sosendEvent;
- delete tcpSosendEvent;
- delete tcpOutputEvent;
- delete ipOutputEvent;
- delete etherOutputEvent;
- delete esStartEvent;
- delete esTransmitEvent;
- delete esTxeofEvent;
- delete idleThreadEvent;
+ int end = fnEvents.size();
+ for (int i = 0; i < end; ++i) {
+ delete fnEvents[i];
+ }
+ fnEvents.clear();
}
- //INSTRUMENTATION CODEGEN END
-#endif //FS_MEASURE
}
int
@@ -604,7 +260,6 @@ Tru64System::breakpoint()
return remoteGDB[0]->trap(ALPHA_KENTRY_INT);
}
-#ifdef FS_MEASURE
void
Tru64System::populateMap(std::string callee, std::string caller)
{
@@ -630,23 +285,19 @@ Tru64System::findCaller(std::string callee, std::string caller) const
void
Tru64System::dumpState(ExecContext *xc) const
{
-#ifndef SW_DEBUG
- return;
-#endif
if (xc->swCtx) {
stack<fnCall *> copy(xc->swCtx->callStack);
if (copy.empty())
return;
- cprintf("xc->swCtx:\n");
+ DPRINTF(TCPIP, "xc->swCtx, size: %d:\n", copy.size());
fnCall *top;
- cprintf("|| call: %d\n",xc->swCtx->calls);
+ DPRINTF(TCPIP, "|| call : %d\n",xc->swCtx->calls);
for (top = copy.top(); !copy.empty(); copy.pop() ) {
top = copy.top();
- cprintf("|| %13s : %s \n", top->name, top->myBin->name());
+ DPRINTF(TCPIP, "|| %13s : %s \n", top->name, top->myBin->name());
}
}
}
-#endif //FS_MEASURE
BEGIN_DECLARE_SIM_OBJECT_PARAMS(Tru64System)
@@ -659,6 +310,7 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(Tru64System)
Param<string> console_code;
Param<string> pal_code;
Param<string> boot_osflags;
+ VectorParam<string> binned_fns;
END_DECLARE_SIM_OBJECT_PARAMS(Tru64System)
@@ -672,8 +324,8 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(Tru64System)
INIT_PARAM(console_code, "file that contains the console code"),
INIT_PARAM(pal_code, "file that contains palcode"),
INIT_PARAM_DFLT(boot_osflags, "flags to pass to the kernel during boot",
- "a")
-
+ "a"),
+ INIT_PARAM(binned_fns, "functions to be broken down and binned")
END_INIT_SIM_OBJECT_PARAMS(Tru64System)
@@ -681,7 +333,8 @@ CREATE_SIM_OBJECT(Tru64System)
{
Tru64System *sys = new Tru64System(getInstanceName(), init_param, mem_ctl,
physmem, kernel_code, console_code,
- pal_code, boot_osflags, bin);
+ pal_code, boot_osflags, bin,
+ binned_fns);
return sys;
}
diff --git a/kern/tru64/tru64_system.hh b/kern/tru64/tru64_system.hh
index 93cc908e3..34569664d 100644
--- a/kern/tru64/tru64_system.hh
+++ b/kern/tru64/tru64_system.hh
@@ -29,15 +29,12 @@
#ifndef __TRU64_SYSTEM_HH__
#define __TRU64_SYSTEM_HH__
+#include <map>
#include <vector>
#include "sim/system.hh"
#include "targetarch/isa_traits.hh"
-#ifdef FS_MEASURE
-#include <map>
-#endif
-
class ExecContext;
class EcoffObject;
class SymbolTable;
@@ -48,9 +45,7 @@ class SkipFuncEvent;
class PrintfEvent;
class DebugPrintfEvent;
class DumpMbufEvent;
-#ifdef FS_MEASURE
class FnEvent;
-#endif
class AlphaArguments;
class Tru64System : public System
@@ -62,42 +57,6 @@ class Tru64System : public System
SymbolTable *kernelSymtab;
SymbolTable *consoleSymtab;
-#ifdef FS_MEASURE
- //INSTRUMENTATION CODEGEN BEGIN ONE
- Statistics::MainBin *esIntrBin;
- Statistics::MainBin *esRxeofBin;
- Statistics::MainBin *esNewbufBin;
- Statistics::MainBin *esDmaLoadBin;
- Statistics::MainBin *dmaMapLoadBin;
- Statistics::MainBin *etherInputBin;
- Statistics::MainBin *netisrInputBin;
- Statistics::MainBin *schednetisrIsrBin;
- Statistics::MainBin *ipintrBin;
- Statistics::MainBin *ipDooptionsBin;
- Statistics::MainBin *ipReassBin;
- Statistics::MainBin *tcpInputBin;
- Statistics::MainBin *sbappendBin;
- Statistics::MainBin *readBin;
- Statistics::MainBin *sooReadBin;
- Statistics::MainBin *orecvBin;
- Statistics::MainBin *recvitBin;
- Statistics::MainBin *soreceiveBin;
- Statistics::MainBin *osendBin;
- Statistics::MainBin *writeBin;
- Statistics::MainBin *sooWriteBin;
- Statistics::MainBin *senditBin;
- Statistics::MainBin *sosendBin;
- Statistics::MainBin *tcpSosendBin;
- Statistics::MainBin *tcpOutputBin;
- Statistics::MainBin *ipOutputBin;
- Statistics::MainBin *etherOutputBin;
- Statistics::MainBin *esStartBin;
- Statistics::MainBin *esTransmitBin;
- Statistics::MainBin *esTxeofBin;
- Statistics::MainBin *idleThreadBin;
- //INSTRUMENTATION CODEGEN END
-#endif //FS_MEASURE
-
BreakPCEvent *kernelPanicEvent;
BreakPCEvent *consolePanicEvent;
BadAddrEvent *badaddrEvent;
@@ -107,41 +66,8 @@ class Tru64System : public System
DebugPrintfEvent *debugPrintfEvent;
DebugPrintfEvent *debugPrintfrEvent;
DumpMbufEvent *dumpMbufEvent;
-#ifdef FS_MEASURE
- //INSTRUMENTATION CODEGEN BEGIN TWO
- FnEvent *esIntrEvent;
- FnEvent *esRxeofEvent;
- FnEvent *esNewbufEvent;
- FnEvent *esDmaLoadEvent;
- FnEvent *dmaMapLoadEvent;
- FnEvent *etherInputEvent;
- FnEvent *netisrInputEvent;
- FnEvent *schednetisrIsrEvent;
- FnEvent *ipintrEvent;
- FnEvent *ipDooptionsEvent;
- FnEvent *ipReassEvent;
- FnEvent *tcpInputEvent;
- FnEvent *sbappendEvent;
- FnEvent *readEvent;
- FnEvent *sooReadEvent;
- FnEvent *orecvEvent;
- FnEvent *recvitEvent;
- FnEvent *soreceiveEvent;
- FnEvent *osendEvent;
- FnEvent *writeEvent;
- FnEvent *sooWriteEvent;
- FnEvent *senditEvent;
- FnEvent *sosendEvent;
- FnEvent *tcpSosendEvent;
- FnEvent *tcpOutputEvent;
- FnEvent *ipOutputEvent;
- FnEvent *etherOutputEvent;
- FnEvent *esStartEvent;
- FnEvent *esTransmitEvent;
- FnEvent *esTxeofEvent;
- FnEvent *idleThreadEvent;
- //INSTRUMENTATION CODEGEN END
-#endif //FS_MEASURE
+
+ std::vector<FnEvent *> fnEvents;
private:
@@ -149,11 +75,7 @@ class Tru64System : public System
Addr kernelEnd;
Addr kernelEntry;
bool bin;
-
-#ifdef FS_MEASURE
- std::multimap<const std::string, std::string> callerMap;
- void populateMap(std::string caller, std::string callee);
-#endif
+ std::vector<string> binned_fns;
public:
std::vector<RemoteGDB *> remoteGDB;
@@ -168,7 +90,8 @@ class Tru64System : public System
const std::string &console_path,
const std::string &palcode,
const std::string &boot_osflags,
- const bool _bin);
+ const bool _bin,
+ const std::vector<string> &binned_fns);
~Tru64System();
int registerExecContext(ExecContext *xc);
@@ -182,10 +105,16 @@ class Tru64System : public System
static void Printf(AlphaArguments args);
static void DumpMbuf(AlphaArguments args);
-#ifdef FS_MEASURE
+
+ // Lisa's binning stuff
+ private:
+ std::multimap<const std::string, std::string> callerMap;
+ void populateMap(std::string caller, std::string callee);
+
+ public:
bool findCaller(std::string callee, std::string caller) const;
void dumpState(ExecContext *xc) const;
-#endif //FS_MEASURE
+ //
};
#endif // __TRU64_SYSTEM_HH__
diff --git a/sim/eventq.hh b/sim/eventq.hh
index 31bf9d652..ed37fd4f4 100644
--- a/sim/eventq.hh
+++ b/sim/eventq.hh
@@ -236,6 +236,23 @@ DelayFunction(Tick when, T *object)
new DelayEvent(when, object);
}
+template <class T, void (T::* F)()>
+class EventWrapper : public Event
+{
+ private:
+ T *object;
+
+ public:
+ EventWrapper(T *obj, bool del = false, EventQueue *q = &mainEventQueue,
+ Priority p = Default_Pri)
+ : Event(q, p), object(obj)
+ {
+ if (del)
+ setFlags(AutoDelete);
+ }
+ void process() { (object->*F)(); }
+};
+
/*
* Queue of events sorted in time order
*/
@@ -310,6 +327,8 @@ inline void
Event::schedule(Tick t)
{
assert(!scheduled());
+ assert(t >= curTick);
+
setFlags(Scheduled);
#if TRACING_ON
when_scheduled = curTick;
diff --git a/sim/sim_events.cc b/sim/sim_events.cc
index a31da18dd..f7b07359c 100644
--- a/sim/sim_events.cc
+++ b/sim/sim_events.cc
@@ -28,11 +28,13 @@
#include <string>
-#include "sim/param.hh"
-#include "sim/eventq.hh"
+#include "base/callback.hh"
#include "base/hostinfo.hh"
+#include "sim/eventq.hh"
+#include "sim/param.hh"
#include "sim/sim_events.hh"
#include "sim/sim_exit.hh"
+#include "sim/sim_init.hh"
#include "sim/sim_stats.hh"
using namespace std;
@@ -178,7 +180,7 @@ class ProgressEvent : public Event
ProgressEvent::ProgressEvent(EventQueue *q, Tick _interval)
: Event(q), interval(_interval)
{
- schedule(interval);
+ schedule(curTick + interval);
}
//
@@ -221,10 +223,24 @@ ProgressParamContext progessMessageParams("progress");
Param<Tick> progress_interval(&progessMessageParams, "cycle",
"cycle interval for progress messages");
+namespace {
+ struct SetupProgress : public Callback
+ {
+ Tick interval;
+ SetupProgress(Tick tick) : interval(tick) {}
+
+ virtual void process()
+ {
+ new ProgressEvent(&mainEventQueue, interval);
+ delete this;
+ }
+ };
+}
+
/* check execute options */
void
ProgressParamContext::checkParams()
{
if (progress_interval.isValid())
- new ProgressEvent(&mainEventQueue, progress_interval);
+ registerInitCallback(new SetupProgress(progress_interval));
}
diff --git a/sim/sim_object.cc b/sim/sim_object.cc
index b3ac2c7a4..c55021e41 100644
--- a/sim/sim_object.cc
+++ b/sim/sim_object.cc
@@ -182,11 +182,11 @@ SimObject::printAllExtraOutput(ostream &os)
void
SimObject::serializeAll(ostream &os)
{
- SimObjectList::iterator i = simObjectList.begin();
- SimObjectList::iterator end = simObjectList.end();
+ SimObjectList::reverse_iterator ri = simObjectList.rbegin();
+ SimObjectList::reverse_iterator rend = simObjectList.rend();
- for (; i != end; ++i) {
- SimObject *obj = *i;
+ for (; ri != rend; ++ri) {
+ SimObject *obj = *ri;
obj->nameOut(os);
obj->serialize(os);
}
diff --git a/sim/system.cc b/sim/system.cc
index db93250ee..43f43baec 100644
--- a/sim/system.cc
+++ b/sim/system.cc
@@ -50,13 +50,12 @@ System::System(const std::string _name,
{
// add self to global system list
systemList.push_back(this);
-#ifdef FS_MEASURE
if (bin == true) {
- nonPath = new Statistics::MainBin("non TCPIP path stats");
- nonPath->activate();
+ Kernel = new Statistics::MainBin("non TCPIP Kernel stats");
+ Kernel->activate();
+ User = new Statistics::MainBin("User stats");
} else
- nonPath = NULL;
-#endif
+ Kernel = NULL;
}
@@ -104,14 +103,13 @@ printSystems()
System::printSystems();
}
-#ifdef FS_MEASURE
Statistics::MainBin *
System::getBin(const std::string &name)
{
std::map<const std::string, Statistics::MainBin *>::const_iterator i;
i = fnBins.find(name);
if (i == fnBins.end())
- panic("trying to getBin that is not on system map!");
+ panic("trying to getBin %s that is not on system map!", name);
return (*i).second;
}
@@ -127,7 +125,73 @@ System::findContext(Addr pcb)
} else
return NULL;
}
-#endif //FS_MEASURE
+
+void
+System::serialize(std::ostream &os)
+{
+ if (bin == true) {
+ map<const Addr, SWContext *>::const_iterator iter, end;
+ iter = swCtxMap.begin();
+ end = swCtxMap.end();
+
+ int numCtxs = swCtxMap.size();
+ SERIALIZE_SCALAR(numCtxs);
+ SWContext *ctx;
+ for (int i = 0; iter != end; ++i, ++iter) {
+ paramOut(os, csprintf("Addr[%d]",i), (*iter).first);
+ ctx = (*iter).second;
+ paramOut(os, csprintf("calls[%d]",i), ctx->calls);
+
+ stack<fnCall *> *stack = &(ctx->callStack);
+ fnCall *top;
+ int size = stack->size();
+ paramOut(os, csprintf("stacksize[%d]",i), size);
+ for (int j=0; j<size; ++j) {
+ top = stack->top();
+ paramOut(os, csprintf("ctx[%d].stackpos[%d]",i,j),
+ top->name);
+ delete top;
+ stack->pop();
+ }
+ }
+ }
+}
+
+void
+System::unserialize(Checkpoint *cp, const std::string &section)
+{
+ if (bin == true) {
+ int numCtxs;
+ UNSERIALIZE_SCALAR(numCtxs);
+
+ SWContext *ctx;
+ Addr addr;
+ int size;
+ for(int i = 0; i < numCtxs; ++i) {
+ ctx = new SWContext;
+ paramIn(cp, section, csprintf("Addr[%d]",i), addr);
+ paramIn(cp, section, csprintf("calls[%d]",i), ctx->calls);
+
+ paramIn(cp, section, csprintf("stacksize[%d]",i), size);
+
+ vector<fnCall *> calls;
+ fnCall *call;
+ for (int j = 0; j < size; ++j) {
+ call = new fnCall;
+ paramIn(cp, section, csprintf("ctx[%d].stackpos[%d]",i,j),
+ call->name);
+ call->myBin = getBin(call->name);
+ calls.push_back(call);
+ }
+
+ for (int j=size-1; j>=0; --j) {
+ ctx->callStack.push(calls[j]);
+ }
+
+ addContext(addr, ctx);
+ }
+ }
+}
DEFINE_SIM_OBJECT_CLASS_NAME("System", System)
diff --git a/sim/system.hh b/sim/system.hh
index e5d990e86..7b011aa8f 100644
--- a/sim/system.hh
+++ b/sim/system.hh
@@ -32,14 +32,11 @@
#include <string>
#include <vector>
-#include "sim/sim_object.hh"
-#include "cpu/pc_event.hh"
#include "base/loader/symtab.hh"
-
-#ifdef FS_MEASURE
#include "base/statistics.hh"
+#include "cpu/pc_event.hh"
+#include "sim/sim_object.hh"
#include "sim/sw_context.hh"
-#endif
class MemoryController;
class PhysicalMemory;
@@ -51,11 +48,33 @@ class ExecContext;
class System : public SimObject
{
-#ifdef FS_MEASURE
+ // lisa's binning stuff
protected:
std::map<const std::string, Statistics::MainBin *> fnBins;
std::map<const Addr, SWContext *> swCtxMap;
-#endif //FS_MEASURE
+
+ public:
+ Statistics::Scalar<Counter> fnCalls;
+ Statistics::MainBin *Kernel;
+ Statistics::MainBin *User;
+
+ Statistics::MainBin * getBin(const std::string &name);
+ virtual bool findCaller(std::string, std::string) const = 0;
+
+ SWContext *findContext(Addr pcb);
+ bool addContext(Addr pcb, SWContext *ctx) {
+ return (swCtxMap.insert(make_pair(pcb, ctx))).second;
+ }
+ void remContext(Addr pcb) {
+ swCtxMap.erase(pcb);
+ return;
+ }
+
+ virtual void dumpState(ExecContext *xc) const = 0;
+
+ virtual void serialize(std::ostream &os);
+ virtual void unserialize(Checkpoint *cp, const std::string &section);
+ //
public:
const uint64_t init_param;
@@ -71,11 +90,6 @@ class System : public SimObject
virtual int registerExecContext(ExecContext *xc);
virtual void replaceExecContext(int xcIndex, ExecContext *xc);
-#ifdef FS_MEASURE
- Statistics::Scalar<Counter, Statistics::MainBin> fnCalls;
- Statistics::MainBin *nonPath;
-#endif //FS_MEASURE
-
public:
System(const std::string _name, const uint64_t _init_param,
MemoryController *, PhysicalMemory *, const bool);
@@ -86,22 +100,6 @@ class System : public SimObject
virtual Addr getKernelEntry() const = 0;
virtual bool breakpoint() = 0;
-#ifdef FS_MEASURE
- Statistics::MainBin * getBin(const std::string &name);
- virtual bool findCaller(std::string, std::string) const = 0;
-
- SWContext *findContext(Addr pcb);
- bool addContext(Addr pcb, SWContext *ctx) {
- return (swCtxMap.insert(make_pair(pcb, ctx))).second;
- }
- void remContext(Addr pcb) {
- swCtxMap.erase(pcb);
- return;
- }
-
- virtual void dumpState(ExecContext *xc) const = 0;
-#endif //FS_MEASURE
-
public:
////////////////////////////////////////////
//
diff --git a/sim/universe.cc b/sim/universe.cc
index feede514e..d6c849ac7 100644
--- a/sim/universe.cc
+++ b/sim/universe.cc
@@ -47,6 +47,7 @@ Tick ticksPerSecond;
double __ticksPerMS;
double __ticksPerUS;
double __ticksPerNS;
+double __ticksPerPS;
string outputDirectory;
ostream *outputStream;
@@ -79,6 +80,7 @@ UniverseParamContext::checkParams()
__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;
diff --git a/util/tracediff b/util/tracediff
index fac4f0ec0..0aa579a7d 100755
--- a/util/tracediff
+++ b/util/tracediff
@@ -1,5 +1,5 @@
#! /usr/bin/env perl
-# Copyright (c) 2003 The Regents of The University of Michigan
+# Copyright (c) 2003-2004 The Regents of The University of Michigan
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
@@ -39,7 +39,7 @@ $sim2 = shift;
# Everything else on the command line is taken to be an m5 argument to
# be given to both invocations
-$simargs = join(' ', @ARGV);
+$simargs = '"' . join('" "', @ARGV) . '"';
$cmd1 = "$sim1 $simargs --stats:file=tracediff-$$-1.stats 2>&1 |";
$cmd2 = "$sim2 $simargs --stats:file=tracediff-$$-2.stats 2>&1 |";