summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/SConscript3
-rw-r--r--src/arch/alpha/vtophys.cc51
-rw-r--r--src/arch/alpha/vtophys.hh5
-rw-r--r--src/arch/sparc/arguments.hh2
-rw-r--r--src/arch/sparc/isa_traits.hh5
-rw-r--r--src/arch/sparc/pagetable.hh21
-rw-r--r--src/arch/sparc/remote_gdb.cc48
-rw-r--r--src/arch/sparc/remote_gdb.hh4
-rw-r--r--src/arch/sparc/tlb.cc153
-rw-r--r--src/arch/sparc/tlb.hh19
-rw-r--r--src/arch/sparc/vtophys.cc94
-rw-r--r--src/arch/sparc/vtophys.hh5
-rw-r--r--src/base/bitfield.hh7
-rw-r--r--src/base/statistics.hh1
-rw-r--r--src/base/stats/events.cc2
-rw-r--r--src/base/stats/events.hh2
-rw-r--r--src/base/stats/mysql.cc70
-rw-r--r--src/base/stats/mysql.hh31
-rw-r--r--src/base/stats/output.cc70
-rw-r--r--src/base/stats/text.cc21
-rw-r--r--src/base/stats/text.hh3
-rw-r--r--src/base/trace.cc2
-rw-r--r--src/base/traceflags.py2
-rw-r--r--src/cpu/base.cc2
-rw-r--r--src/cpu/exetrace.hh3
-rw-r--r--src/mem/vport.cc51
-rw-r--r--src/mem/vport.hh7
-rw-r--r--src/python/SConscript1
-rw-r--r--src/python/m5/SimObject.py18
-rw-r--r--src/python/m5/main.py11
-rw-r--r--src/python/m5/objects/Root.py7
-rw-r--r--src/python/swig/pyevent.cc9
-rw-r--r--src/python/swig/stats.i60
-rw-r--r--src/sim/async.hh1
-rw-r--r--src/sim/builder.cc2
-rw-r--r--src/sim/eventq.hh3
-rw-r--r--src/sim/main.cc29
-rw-r--r--src/sim/param.cc109
-rw-r--r--src/sim/param.hh47
-rw-r--r--src/sim/pseudo_inst.cc10
-rw-r--r--src/sim/serialize.cc33
-rw-r--r--src/sim/sim_object.cc9
-rw-r--r--src/sim/sim_object.hh1
-rw-r--r--src/sim/stat_control.cc96
-rw-r--r--src/sim/stat_control.hh19
45 files changed, 615 insertions, 534 deletions
diff --git a/src/SConscript b/src/SConscript
index d6b4c6c8d..c93605ff7 100644
--- a/src/SConscript
+++ b/src/SConscript
@@ -79,6 +79,7 @@ base_sources = Split('''
base/loader/object_file.cc
base/loader/symtab.cc
base/stats/events.cc
+ base/stats/output.cc
base/stats/statdb.cc
base/stats/visit.cc
base/stats/text.cc
@@ -134,6 +135,7 @@ base_sources = Split('''
python/swig/main_wrap.cc
python/swig/event_wrap.cc
python/swig/random_wrap.cc
+ python/swig/stats_wrap.cc
python/swig/trace_wrap.cc
python/swig/pyevent.cc
@@ -148,7 +150,6 @@ base_sources = Split('''
sim/sim_events.cc
sim/sim_object.cc
sim/startup.cc
- sim/stat_context.cc
sim/stat_control.cc
sim/system.cc
''')
diff --git a/src/arch/alpha/vtophys.cc b/src/arch/alpha/vtophys.cc
index fd8f781e4..1a3147bcc 100644
--- a/src/arch/alpha/vtophys.cc
+++ b/src/arch/alpha/vtophys.cc
@@ -113,54 +113,3 @@ AlphaISA::vtophys(ThreadContext *tc, Addr addr)
return paddr;
}
-
-void
-AlphaISA::CopyOut(ThreadContext *tc, void *dest, Addr src, size_t cplen)
-{
- uint8_t *dst = (uint8_t *)dest;
- VirtualPort *vp = tc->getVirtPort(tc);
-
- vp->readBlob(src, dst, cplen);
-
- tc->delVirtPort(vp);
-
-}
-
-void
-AlphaISA::CopyIn(ThreadContext *tc, Addr dest, void *source, size_t cplen)
-{
- uint8_t *src = (uint8_t *)source;
- VirtualPort *vp = tc->getVirtPort(tc);
-
- vp->writeBlob(dest, src, cplen);
-
- tc->delVirtPort(vp);
-}
-
-void
-AlphaISA::CopyStringOut(ThreadContext *tc, char *dst, Addr vaddr, size_t maxlen)
-{
- int len = 0;
- char *start = dst;
- VirtualPort *vp = tc->getVirtPort(tc);
-
- do {
- vp->readBlob(vaddr++, (uint8_t*)dst++, 1);
- } while (len < maxlen && start[len++] != 0 );
-
- tc->delVirtPort(vp);
- dst[len] = 0;
-}
-
-void
-AlphaISA::CopyStringIn(ThreadContext *tc, char *src, Addr vaddr)
-{
- VirtualPort *vp = tc->getVirtPort(tc);
- for (ChunkGenerator gen(vaddr, strlen(src), AlphaISA::PageBytes); !gen.done();
- gen.next())
- {
- vp->writeBlob(gen.addr(), (uint8_t*)src, gen.size());
- src += gen.size();
- }
- tc->delVirtPort(vp);
-}
diff --git a/src/arch/alpha/vtophys.hh b/src/arch/alpha/vtophys.hh
index 32b999c37..bd2ee8468 100644
--- a/src/arch/alpha/vtophys.hh
+++ b/src/arch/alpha/vtophys.hh
@@ -47,11 +47,6 @@ namespace AlphaISA {
Addr vtophys(Addr vaddr);
Addr vtophys(ThreadContext *tc, Addr vaddr);
- void CopyOut(ThreadContext *tc, void *dst, Addr src, size_t len);
- void CopyIn(ThreadContext *tc, Addr dst, void *src, size_t len);
- void CopyStringOut(ThreadContext *tc, char *dst, Addr vaddr, size_t maxlen);
- void CopyStringIn(ThreadContext *tc, char *src, Addr vaddr);
-
};
#endif // __ARCH_ALPHA_VTOPHYS_H__
diff --git a/src/arch/sparc/arguments.hh b/src/arch/sparc/arguments.hh
index 8f925dd25..5596f7408 100644
--- a/src/arch/sparc/arguments.hh
+++ b/src/arch/sparc/arguments.hh
@@ -33,9 +33,9 @@
#include <assert.h>
-#include "arch/sparc/vtophys.hh"
#include "base/refcnt.hh"
#include "sim/host.hh"
+#include "mem/vport.hh"
class ThreadContext;
diff --git a/src/arch/sparc/isa_traits.hh b/src/arch/sparc/isa_traits.hh
index 64ae6abd8..1fbdd160d 100644
--- a/src/arch/sparc/isa_traits.hh
+++ b/src/arch/sparc/isa_traits.hh
@@ -87,6 +87,11 @@ namespace SparcISA
const int LogVMPageSize = 13;
const int VMPageSize = (1 << LogVMPageSize);
+ // real address virtual mapping
+ // sort of like alpha super page, but less frequently used
+ const Addr SegKPMEnd = ULL(0xfffffffc00000000);
+ const Addr SegKPMBase = ULL(0xfffffac000000000);
+
//Why does both the previous set of constants and this one exist?
const int PageShift = 13;
const int PageBytes = 1ULL << PageShift;
diff --git a/src/arch/sparc/pagetable.hh b/src/arch/sparc/pagetable.hh
index fc01e82da..980225052 100644
--- a/src/arch/sparc/pagetable.hh
+++ b/src/arch/sparc/pagetable.hh
@@ -45,6 +45,22 @@ struct VAddr
VAddr(Addr a) { panic("not implemented yet."); }
};
+class TteTag
+{
+ private:
+ uint64_t entry;
+ bool populated;
+
+ public:
+ TteTag() : entry(0), populated(false) {}
+ TteTag(uint64_t e) : entry(e), populated(true) {}
+ const TteTag &operator=(uint64_t e) { populated = true;
+ entry = e; return *this; }
+ bool valid() const {assert(populated); return !bits(entry,62,62); }
+ Addr va() const {assert(populated); return bits(entry,41,0); }
+};
+
+
class PageTableEntry
{
public:
@@ -110,13 +126,14 @@ class PageTableEntry
entry4u = e; return *this; }
const PageTableEntry &operator=(const PageTableEntry &e)
- { populated = true; entry4u = e.entry4u; return *this; }
+ { populated = true; entry4u = e.entry4u; type = e.type; return *this; }
bool valid() const { return bits(entry4u,63,63) && populated; }
uint8_t _size() const { assert(populated);
return bits(entry4u, 62,61) |
bits(entry4u, 48,48) << 2; }
Addr size() const { assert(_size() < 6); return pageSizes[_size()]; }
+ Addr sizeMask() const { assert(_size() < 6); return pageSizes[_size()]-1;}
bool ie() const { return bits(entry4u, 59,59); }
Addr pfn() const { assert(populated); return bits(entry4u,39,13); }
Addr paddr() const { assert(populated); return mbits(entry4u, 39,13);}
@@ -127,6 +144,8 @@ class PageTableEntry
bool writable() const { assert(populated); return bits(entry4u,1,1); }
bool nofault() const { assert(populated); return bits(entry4u,60,60); }
bool sideffect() const { assert(populated); return bits(entry4u,3,3); }
+ Addr paddrMask() const { assert(populated);
+ return mbits(entry4u, 39,13) & ~sizeMask(); }
};
struct TlbRange {
diff --git a/src/arch/sparc/remote_gdb.cc b/src/arch/sparc/remote_gdb.cc
index 2221576a3..e2ea7a84d 100644
--- a/src/arch/sparc/remote_gdb.cc
+++ b/src/arch/sparc/remote_gdb.cc
@@ -152,7 +152,9 @@ RemoteGDB::acc(Addr va, size_t len)
//@Todo In NetBSD, this function checks if all addresses
//from va to va + len have valid page mape entries. Not
//sure how this will work for other OSes or in general.
- return true;
+ if (va)
+ return true;
+ return false;
}
///////////////////////////////////////////////////////////
@@ -166,23 +168,33 @@ RemoteGDB::getregs()
memset(gdbregs.regs, 0, gdbregs.size);
if (context->readMiscRegWithEffect(MISCREG_PSTATE) &
- PSTATE::am)
- panic("In 32bit mode\n");
-
- gdbregs.regs[RegPc] = htobe(context->readPC());
- gdbregs.regs[RegNpc] = htobe(context->readNextPC());
- for(int x = RegG0; x <= RegI0 + 7; x++)
- gdbregs.regs[x] = htobe(context->readIntReg(x - RegG0));
-
- gdbregs.regs[RegFsr] = htobe(context->readMiscRegWithEffect(MISCREG_FSR));
- gdbregs.regs[RegFprs] = htobe(context->readMiscRegWithEffect(MISCREG_FPRS));
- gdbregs.regs[RegY] = htobe(context->readIntReg(NumIntArchRegs + 1));
- gdbregs.regs[RegState] = htobe(
- context->readMiscRegWithEffect(MISCREG_CWP) |
- context->readMiscRegWithEffect(MISCREG_PSTATE) << 8 |
- context->readMiscRegWithEffect(MISCREG_ASI) << 24 |
- context->readIntReg(NumIntArchRegs + 2) << 32);
-
+ PSTATE::am) {
+ uint32_t *regs;
+ regs = (uint32_t*)gdbregs.regs;
+ regs[Reg32Pc] = htobe((uint32_t)context->readPC());
+ regs[Reg32Npc] = htobe((uint32_t)context->readNextPC());
+ for(int x = RegG0; x <= RegI0 + 7; x++)
+ regs[x] = htobe((uint32_t)context->readIntReg(x - RegG0));
+
+ regs[Reg32Y] = htobe((uint32_t)context->readIntReg(NumIntArchRegs + 1));
+ regs[Reg32Psr] = htobe((uint32_t)context->readMiscRegWithEffect(MISCREG_PSTATE));
+ regs[Reg32Fsr] = htobe((uint32_t)context->readMiscRegWithEffect(MISCREG_FSR));
+ regs[Reg32Csr] = htobe((uint32_t)context->readIntReg(NumIntArchRegs + 2));
+ } else {
+ gdbregs.regs[RegPc] = htobe(context->readPC());
+ gdbregs.regs[RegNpc] = htobe(context->readNextPC());
+ for(int x = RegG0; x <= RegI0 + 7; x++)
+ gdbregs.regs[x] = htobe(context->readIntReg(x - RegG0));
+
+ gdbregs.regs[RegFsr] = htobe(context->readMiscRegWithEffect(MISCREG_FSR));
+ gdbregs.regs[RegFprs] = htobe(context->readMiscRegWithEffect(MISCREG_FPRS));
+ gdbregs.regs[RegY] = htobe(context->readIntReg(NumIntArchRegs + 1));
+ gdbregs.regs[RegState] = htobe(
+ context->readMiscRegWithEffect(MISCREG_CWP) |
+ context->readMiscRegWithEffect(MISCREG_PSTATE) << 8 |
+ context->readMiscRegWithEffect(MISCREG_ASI) << 24 |
+ context->readIntReg(NumIntArchRegs + 2) << 32);
+ }
DPRINTF(GDBRead, "PC=%#x\n", gdbregs.regs[RegPc]);
diff --git a/src/arch/sparc/remote_gdb.hh b/src/arch/sparc/remote_gdb.hh
index 17ad7a8e6..b97961a34 100644
--- a/src/arch/sparc/remote_gdb.hh
+++ b/src/arch/sparc/remote_gdb.hh
@@ -53,7 +53,9 @@ namespace SparcISA
RegF0 = 32,
RegPc = 64, RegNpc, RegState, RegFsr, RegFprs, RegY,
/*RegState contains data in same format as tstate */
- NumGDBRegs
+ Reg32Y = 64, Reg32Psr = 65, Reg32Tbr = 66, Reg32Pc = 67,
+ Reg32Npc = 68, Reg32Fsr = 69, Reg32Csr = 70,
+ NumGDBRegs = RegY
};
public:
diff --git a/src/arch/sparc/tlb.cc b/src/arch/sparc/tlb.cc
index 293f667d6..82b1ed175 100644
--- a/src/arch/sparc/tlb.cc
+++ b/src/arch/sparc/tlb.cc
@@ -204,7 +204,8 @@ insertAllLocked:
TlbEntry*
-TLB::lookup(Addr va, int partition_id, bool real, int context_id)
+TLB::lookup(Addr va, int partition_id, bool real, int context_id, bool
+ update_used)
{
MapIter i;
TlbRange tr;
@@ -230,7 +231,10 @@ TLB::lookup(Addr va, int partition_id, bool real, int context_id)
t = i->second;
DPRINTF(TLB, "TLB: Valid entry found pa: %#x size: %#x\n", t->pte.paddr(),
t->pte.size());
- if (!t->used) {
+
+ // Update the used bits only if this is a real access (not a fake one from
+ // virttophys()
+ if (!t->used && update_used) {
t->used = true;
usedEntries++;
if (usedEntries == size) {
@@ -797,13 +801,11 @@ handleQueueRegAccess:
handleSparcErrorRegAccess:
if (!hpriv) {
- if (priv) {
- writeSfr(tc, vaddr, write, Primary, true, IllegalAsi, asi);
+ writeSfr(tc, vaddr, write, Primary, true, IllegalAsi, asi);
+ if (priv)
return new DataAccessException;
- } else {
- writeSfr(tc, vaddr, write, Primary, true, IllegalAsi, asi);
+ else
return new PrivilegedAction;
- }
}
goto regAccessOk;
@@ -821,8 +823,7 @@ DTB::doMmuRegRead(ThreadContext *tc, Packet *pkt)
{
Addr va = pkt->getAddr();
ASI asi = (ASI)pkt->req->getAsi();
- uint64_t temp, data;
- uint64_t tsbtemp, cnftemp;
+ uint64_t temp;
DPRINTF(IPR, "Memory Mapped IPR Read: asi=%#X a=%#x\n",
(uint32_t)pkt->req->getAsi(), pkt->getAddr());
@@ -942,64 +943,36 @@ DTB::doMmuRegRead(ThreadContext *tc, Packet *pkt)
}
break;
case ASI_DMMU_TSB_PS0_PTR_REG:
- temp = tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_TAG_ACCESS);
- if (bits(temp,12,0) == 0) {
- tsbtemp = tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_C0_TSB_PS0);
- cnftemp = tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_C0_CONFIG);
- } else {
- tsbtemp = tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_CX_TSB_PS0);
- cnftemp = tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_CX_CONFIG);
- }
- data = mbits(tsbtemp,63,13);
- data |= temp >> (9 + bits(cnftemp,2,0) * 3) &
- mbits((uint64_t)-1ll,12+bits(tsbtemp,3,0), 4);
- pkt->set(data);
+ pkt->set(MakeTsbPtr(Ps0,
+ tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_TAG_ACCESS),
+ tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_C0_TSB_PS0),
+ tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_C0_CONFIG),
+ tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_CX_TSB_PS0),
+ tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_CX_CONFIG)));
break;
case ASI_DMMU_TSB_PS1_PTR_REG:
- temp = tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_TAG_ACCESS);
- if (bits(temp,12,0) == 0) {
- tsbtemp = tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_C0_TSB_PS1);
- cnftemp = tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_C0_CONFIG);
- } else {
- tsbtemp = tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_CX_TSB_PS1);
- cnftemp = tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_CX_CONFIG);
- }
- data = mbits(tsbtemp,63,13);
- if (bits(tsbtemp,12,12))
- data |= ULL(1) << (13+bits(tsbtemp,3,0));
- data |= temp >> (9 + bits(cnftemp,10,8) * 3) &
- mbits((uint64_t)-1ll,12+bits(tsbtemp,3,0), 4);
- pkt->set(data);
+ pkt->set(MakeTsbPtr(Ps1,
+ tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_TAG_ACCESS),
+ tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_C0_TSB_PS1),
+ tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_C0_CONFIG),
+ tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_CX_TSB_PS1),
+ tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_CX_CONFIG)));
break;
case ASI_IMMU_TSB_PS0_PTR_REG:
- temp = tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_TAG_ACCESS);
- if (bits(temp,12,0) == 0) {
- tsbtemp = tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_C0_TSB_PS0);
- cnftemp = tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_C0_CONFIG);
- } else {
- tsbtemp = tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_CX_TSB_PS0);
- cnftemp = tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_CX_CONFIG);
- }
- data = mbits(tsbtemp,63,13);
- data |= temp >> (9 + bits(cnftemp,2,0) * 3) &
- mbits((uint64_t)-1ll,12+bits(tsbtemp,3,0), 4);
- pkt->set(data);
+ pkt->set(MakeTsbPtr(Ps0,
+ tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_TAG_ACCESS),
+ tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_C0_TSB_PS0),
+ tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_C0_CONFIG),
+ tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_CX_TSB_PS0),
+ tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_CX_CONFIG)));
break;
case ASI_IMMU_TSB_PS1_PTR_REG:
- temp = tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_TAG_ACCESS);
- if (bits(temp,12,0) == 0) {
- tsbtemp = tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_C0_TSB_PS1);
- cnftemp = tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_C0_CONFIG);
- } else {
- tsbtemp = tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_CX_TSB_PS1);
- cnftemp = tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_CX_CONFIG);
- }
- data = mbits(tsbtemp,63,13);
- if (bits(tsbtemp,12,12))
- data |= ULL(1) << (13+bits(tsbtemp,3,0));
- data |= temp >> (9 + bits(cnftemp,10,8) * 3) &
- mbits((uint64_t)-1ll,12+bits(tsbtemp,3,0), 4);
- pkt->set(data);
+ pkt->set(MakeTsbPtr(Ps1,
+ tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_TAG_ACCESS),
+ tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_C0_TSB_PS1),
+ tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_C0_CONFIG),
+ tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_CX_TSB_PS1),
+ tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_CX_CONFIG)));
break;
default:
@@ -1245,6 +1218,64 @@ doMmuWriteError:
}
void
+DTB::GetTsbPtr(ThreadContext *tc, Addr addr, int ctx, Addr *ptrs)
+{
+ uint64_t tag_access = mbits(addr,63,13) | mbits(ctx,12,0);
+ ptrs[0] = MakeTsbPtr(Ps0, tag_access,
+ tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_C0_TSB_PS0),
+ tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_C0_CONFIG),
+ tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_CX_TSB_PS0),
+ tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_CX_CONFIG));
+ ptrs[1] = MakeTsbPtr(Ps1, tag_access,
+ tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_C0_TSB_PS1),
+ tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_C0_CONFIG),
+ tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_CX_TSB_PS1),
+ tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_CX_CONFIG));
+ ptrs[2] = MakeTsbPtr(Ps0, tag_access,
+ tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_C0_TSB_PS0),
+ tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_C0_CONFIG),
+ tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_CX_TSB_PS0),
+ tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_CX_CONFIG));
+ ptrs[3] = MakeTsbPtr(Ps1, tag_access,
+ tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_C0_TSB_PS1),
+ tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_C0_CONFIG),
+ tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_CX_TSB_PS1),
+ tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_CX_CONFIG));
+}
+
+
+
+
+
+uint64_t
+DTB::MakeTsbPtr(TsbPageSize ps, uint64_t tag_access, uint64_t c0_tsb,
+ uint64_t c0_config, uint64_t cX_tsb, uint64_t cX_config)
+{
+ uint64_t tsb;
+ uint64_t config;
+
+ if (bits(tag_access, 12,0) == 0) {
+ tsb = c0_tsb;
+ config = c0_config;
+ } else {
+ tsb = cX_tsb;
+ config = cX_config;
+ }
+
+ uint64_t ptr = mbits(tsb,63,13);
+ bool split = bits(tsb,12,12);
+ int tsb_size = bits(tsb,3,0);
+ int page_size = (ps == Ps0) ? bits(config, 2,0) : bits(config,10,8);
+
+ if (ps == Ps1 && split)
+ ptr |= ULL(1) << (13 + tsb_size);
+ ptr |= (tag_access >> (9 + page_size * 3)) & mask(12+tsb_size, 4);
+
+ return ptr;
+}
+
+
+void
TLB::serialize(std::ostream &os)
{
SERIALIZE_SCALAR(size);
diff --git a/src/arch/sparc/tlb.hh b/src/arch/sparc/tlb.hh
index 34e5f5feb..b5f02c62e 100644
--- a/src/arch/sparc/tlb.hh
+++ b/src/arch/sparc/tlb.hh
@@ -78,17 +78,25 @@ class TLB : public SimObject
Nucleus = 2
};
-
+ enum TsbPageSize {
+ Ps0,
+ Ps1
+ };
+ public:
/** lookup an entry in the TLB based on the partition id, and real bit if
* real is true or the partition id, and context id if real is false.
* @param va the virtual address not shifted (e.g. bottom 13 bits are 0)
* @param paritition_id partition this entry is for
* @param real is this a real->phys or virt->phys translation
* @param context_id if this is virt->phys what context
+ * @param update_used should ew update the used bits in the entries on not
+ * useful if we are trying to do a va->pa without mucking with any state for
+ * a debug read for example.
* @return A pointer to a tlb entry
*/
- TlbEntry *lookup(Addr va, int partition_id, bool real, int context_id = 0);
-
+ TlbEntry *lookup(Addr va, int partition_id, bool real, int context_id = 0,
+ bool update_used = true);
+ protected:
/** Insert a PTE into the TLB. */
void insert(Addr vpn, int partition_id, int context_id, bool real,
const PageTableEntry& PTE, int entry = -1);
@@ -163,12 +171,17 @@ class DTB : public TLB
Fault translate(RequestPtr &req, ThreadContext *tc, bool write);
Tick doMmuRegRead(ThreadContext *tc, Packet *pkt);
Tick doMmuRegWrite(ThreadContext *tc, Packet *pkt);
+ void GetTsbPtr(ThreadContext *tc, Addr addr, int ctx, Addr *ptrs);
private:
void writeSfr(ThreadContext *tc, Addr a, bool write, ContextType ct,
bool se, FaultTypes ft, int asi);
void writeTagAccess(ThreadContext *tc, Addr va, int context);
+ uint64_t MakeTsbPtr(TsbPageSize ps, uint64_t tag_access, uint64_t c0_tsb,
+ uint64_t c0_config, uint64_t cX_tsb, uint64_t cX_config);
+
+
TlbEntry *cacheEntry[2];
ASI cacheAsi[2];
};
diff --git a/src/arch/sparc/vtophys.cc b/src/arch/sparc/vtophys.cc
index 429126b70..cb545185a 100644
--- a/src/arch/sparc/vtophys.cc
+++ b/src/arch/sparc/vtophys.cc
@@ -25,14 +25,14 @@
* (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
+ * Authors: Ali Saidi
*/
#include <string>
#include "arch/sparc/vtophys.hh"
+#include "arch/sparc/tlb.hh"
+#include "base/compiler.hh"
#include "base/chunk_generator.hh"
#include "base/trace.hh"
#include "cpu/thread_context.hh"
@@ -42,37 +42,83 @@ using namespace std;
namespace SparcISA
{
- PageTableEntry kernel_pte_lookup(FunctionalPort *mem,
- Addr ptbr, VAddr vaddr)
- {
- PageTableEntry pte(4);
- return pte;
- }
-
Addr vtophys(Addr vaddr)
{
- return vaddr;
+ // In SPARC it's almost always impossible to turn a VA->PA w/o a context
+ // The only times we can kinda do it are if we have a SegKPM mapping
+ // and can find the real address in the tlb or we have a physical
+ // adddress already (beacuse we are looking at the hypervisor)
+ // Either case is rare, so we'll just panic.
+
+ panic("vtophys() without context on SPARC largly worthless\n");
+ M5_DUMMY_RETURN
}
Addr vtophys(ThreadContext *tc, Addr addr)
{
- return addr;
- }
+ // Here we have many options and are really implementing something like
+ // a fill handler to find the address since there isn't a multilevel
+ // table for us to walk around.
+ //
+ // 1. We are currently hyperpriv, return the address unmodified
+ // 2. The mmu is off return(ra->pa)
+ // 3. We are currently priv, use ctx0* tsbs to find the page
+ // 4. We are not priv, use ctxN0* tsbs to find the page
+ // For all accesses we check the tlbs first since it's possible that
+ // long standing pages (e.g. locked kernel mappings) won't be in the tsb
+ uint64_t tlbdata = tc->readMiscReg(MISCREG_TLB_DATA);
+ bool hpriv = bits(tlbdata,0,0);
+ //bool priv = bits(tlbdata,2,2);
+ bool addr_mask = bits(tlbdata,3,3);
+ bool data_real = !bits(tlbdata,5,5);
+ bool inst_real = !bits(tlbdata,4,4);
+ bool ctx_zero = bits(tlbdata,18,16) > 0;
+ int part_id = bits(tlbdata,15,8);
+ int pri_context = bits(tlbdata,47,32);
+ //int sec_context = bits(tlbdata,63,48);
- void CopyOut(ThreadContext *tc, void *dest, Addr src, size_t cplen)
- {
- }
+ FunctionalPort *mem = tc->getPhysPort();
+ ITB* itb = tc->getITBPtr();
+ DTB* dtb = tc->getDTBPtr();
+ TlbEntry* tbe;
+ PageTableEntry pte;
+ Addr tsbs[4];
+ Addr va_tag;
+ TteTag ttetag;
- void CopyIn(ThreadContext *tc, Addr dest, void *source, size_t cplen)
- {
- }
+ if (hpriv)
+ return addr;
- void CopyStringOut(ThreadContext *tc, char *dst, Addr vaddr, size_t maxlen)
- {
- }
+ if (addr_mask)
+ addr = addr & VAddrAMask;
- void CopyStringIn(ThreadContext *tc, char *src, Addr vaddr)
- {
+ tbe = dtb->lookup(addr, part_id, data_real, ctx_zero ? 0 : pri_context , false);
+ if (tbe) goto foundtbe;
+
+ tbe = itb->lookup(addr, part_id, inst_real, ctx_zero ? 0 : pri_context, false);
+ if (tbe) goto foundtbe;
+
+ // We didn't find it in the tlbs, so lets look at the TSBs
+ dtb->GetTsbPtr(tc, addr, ctx_zero ? 0 : pri_context, tsbs);
+ va_tag = bits(addr, 63, 22);
+ for (int x = 0; x < 4; x++) {
+ ttetag = betoh(mem->read<uint64_t>(tsbs[x]));
+ if (ttetag.valid() && ttetag.va() == va_tag) {
+ pte.populate(betoh(mem->read<uint64_t>(tsbs[x]) + sizeof(uint64_t)),
+ PageTableEntry::sun4v); // I think it's sun4v at least!
+ DPRINTF(VtoPhys, "Virtual(%#x)->Physical(%#x) found in TTE\n", addr,
+ pte.paddrMask() | addr & pte.sizeMask());
+ goto foundpte;
+ }
+ }
+ panic("couldn't translate %#x\n", addr);
+
+foundtbe:
+ pte = tbe->pte;
+ DPRINTF(VtoPhys, "Virtual(%#x)->Physical(%#x) found in TLB\n", addr,
+ pte.paddrMask() | addr & pte.sizeMask());
+foundpte:
+ return pte.paddrMask() | addr & pte.sizeMask();
}
}
diff --git a/src/arch/sparc/vtophys.hh b/src/arch/sparc/vtophys.hh
index 66679a565..f55967b53 100644
--- a/src/arch/sparc/vtophys.hh
+++ b/src/arch/sparc/vtophys.hh
@@ -46,11 +46,6 @@ kernel_pte_lookup(FunctionalPort *mem, Addr ptbr, SparcISA::VAddr vaddr);
Addr vtophys(Addr vaddr);
Addr vtophys(ThreadContext *tc, Addr vaddr);
-void CopyOut(ThreadContext *tc, void *dst, Addr src, size_t len);
-void CopyIn(ThreadContext *tc, Addr dst, void *src, size_t len);
-void CopyStringOut(ThreadContext *tc, char *dst, Addr vaddr, size_t maxlen);
-void CopyStringIn(ThreadContext *tc, char *src, Addr vaddr);
-
};
#endif // __ARCH_SPARC_VTOPHYS_H__
diff --git a/src/base/bitfield.hh b/src/base/bitfield.hh
index 1fc0bad5d..0f1233677 100644
--- a/src/base/bitfield.hh
+++ b/src/base/bitfield.hh
@@ -44,6 +44,7 @@ mask(int nbits)
}
+
/**
* Extract the bitfield from position 'first' to 'last' (inclusive)
* from 'val' and right justify it. MSB is numbered 63, LSB is 0.
@@ -69,6 +70,12 @@ mbits(T val, int first, int last)
return val & (mask(first+1) & ~mask(last));
}
+inline uint64_t
+mask(int first, int last)
+{
+ return mbits((uint64_t)-1LL, first, last);
+}
+
/**
* Sign-extend an N-bit value to 64 bits.
*/
diff --git a/src/base/statistics.hh b/src/base/statistics.hh
index 2b1b327e5..8168473a1 100644
--- a/src/base/statistics.hh
+++ b/src/base/statistics.hh
@@ -2839,6 +2839,7 @@ class Temp
*/
void check();
+void dump();
void reset();
void registerResetCallback(Callback *cb);
diff --git a/src/base/stats/events.cc b/src/base/stats/events.cc
index 6ecc5434c..fa746eab8 100644
--- a/src/base/stats/events.cc
+++ b/src/base/stats/events.cc
@@ -52,8 +52,6 @@ namespace Stats {
Tick EventStart = ULL(0x7fffffffffffffff);
-ObjectMatch event_ignore;
-
#if USE_MYSQL
class InsertEvent
{
diff --git a/src/base/stats/events.hh b/src/base/stats/events.hh
index b09b91c7c..dc1408f5b 100644
--- a/src/base/stats/events.hh
+++ b/src/base/stats/events.hh
@@ -45,8 +45,6 @@ void __event(const std::string &stat);
bool MySqlConnected();
#endif
-bool ignoreEvent(const std::string &name);
-
inline void
recordEvent(const std::string &stat)
{
diff --git a/src/base/stats/mysql.cc b/src/base/stats/mysql.cc
index 0fb31f4ce..01a82c4bf 100644
--- a/src/base/stats/mysql.cc
+++ b/src/base/stats/mysql.cc
@@ -49,14 +49,6 @@ using namespace std;
namespace Stats {
-MySqlRun MySqlDB;
-
-bool
-MySqlConnected()
-{
- return MySqlDB.connected();
-}
-
void
MySqlRun::connect(const string &host, const string &user, const string &passwd,
const string &db, const string &name, const string &sample,
@@ -198,7 +190,7 @@ SetupStat::init()
unsigned
SetupStat::setup()
{
- MySQL::Connection &mysql = MySqlDB.conn();
+ MySQL::Connection &mysql = run->conn();
stringstream insert;
ccprintf(insert,
@@ -317,7 +309,7 @@ void
InsertData::flush()
{
if (size) {
- MySQL::Connection &mysql = MySqlDB.conn();
+ MySQL::Connection &mysql = run->conn();
assert(mysql.connected());
mysql.query(query);
if (mysql.error)
@@ -349,7 +341,7 @@ InsertData::insert()
first = false;
size += sprintf(query + size, "(%u,%d,%d,%u,%llu,\"%f\")",
- stat, x, y, MySqlDB.run(), (unsigned long long)tick,
+ stat, x, y, run->run(), (unsigned long long)tick,
data);
}
@@ -367,7 +359,7 @@ struct InsertSubData
void
InsertSubData::setup()
{
- MySQL::Connection &mysql = MySqlDB.conn();
+ MySQL::Connection &mysql = run->conn();
assert(mysql.connected());
stringstream insert;
ccprintf(insert,
@@ -386,7 +378,7 @@ InsertSubData::setup()
void
InsertFormula(uint16_t stat, const string &formula)
{
- MySQL::Connection &mysql = MySqlDB.conn();
+ MySQL::Connection &mysql = run->conn();
assert(mysql.connected());
stringstream insert_formula;
ccprintf(insert_formula,
@@ -400,7 +392,7 @@ InsertFormula(uint16_t stat, const string &formula)
stringstream insert_ref;
ccprintf(insert_ref,
"INSERT INTO formula_ref(fr_stat,fr_run) values(%d, %d)",
- stat, MySqlDB.run());
+ stat, run->run());
mysql.query(insert_ref);
// if (mysql.error)
@@ -413,7 +405,7 @@ InsertFormula(uint16_t stat, const string &formula)
void
UpdatePrereq(uint16_t stat, uint16_t prereq)
{
- MySQL::Connection &mysql = MySqlDB.conn();
+ MySQL::Connection &mysql = run->conn();
assert(mysql.connected());
stringstream update;
ccprintf(update, "UPDATE stats SET st_prereq=%d WHERE st_id=%d",
@@ -426,6 +418,29 @@ UpdatePrereq(uint16_t stat, uint16_t prereq)
panic("could not commit transaction\n%s\n", mysql.error);
}
+MySql::MySql()
+ : run(new MySqlRun)
+{}
+
+MySql::~MySql()
+{
+ delete run;
+}
+
+void
+MySql::connect(const string &host, const string &user, const string &passwd,
+ const string &db, const string &name, const string &sample,
+ const string &project)
+{
+ run->connect(host, user, passwd, db, name, sample, project);
+}
+
+bool
+MySql::connected() const
+{
+ run->connected();
+}
+
void
MySql::configure()
{
@@ -434,7 +449,7 @@ MySql::configure()
*/
using namespace Database;
- MySQL::Connection &mysql = MySqlDB.conn();
+ MySQL::Connection &mysql = run->conn();
stat_list_t::const_iterator i, end = stats().end();
for (i = stats().begin(); i != end; ++i) {
@@ -605,7 +620,7 @@ MySql::configure(const FormulaData &data)
bool
MySql::valid() const
{
- return MySqlDB.connected();
+ return run->connected();
}
void
@@ -620,7 +635,7 @@ MySql::output()
// store sample #
newdata.tick = curTick;
- MySQL::Connection &mysql = MySqlDB.conn();
+ MySQL::Connection &mysql = run->conn();
Database::stat_list_t::const_iterator i, end = Database::stats().end();
for (i = Database::stats().begin(); i != end; ++i) {
@@ -825,4 +840,21 @@ MySql::visit(const FormulaData &data)
output(data);
}
-/* namespace Stats */ }
+bool
+initMySQL(string host, string user, string password, string database,
+ string name, string sample, string project)
+{
+ extern list<Output *> OutputList;
+ static MySql mysql;
+
+ if (mysql.connected())
+ return false;
+
+ if (user.empty())
+ user = username();
+
+ mysql.connect(host, user, password, database, name, sample, project);
+ OutputList.push_back(&mysql);
+
+ return true;
+}
diff --git a/src/base/stats/mysql.hh b/src/base/stats/mysql.hh
index 50f7d9e97..a43c74ecc 100644
--- a/src/base/stats/mysql.hh
+++ b/src/base/stats/mysql.hh
@@ -35,14 +35,13 @@
#include <string>
#include "base/stats/output.hh"
+#include "config/use_mysql.hh"
namespace MySQL { class Connection; }
namespace Stats {
class DistDataData;
class MySqlRun;
-bool MySqlConnected();
-extern MySqlRun MySqlDB;
struct SetupStat
{
@@ -95,6 +94,9 @@ class InsertData
class MySql : public Output
{
protected:
+ MySqlRun *run; /* Hide the implementation so we don't have a
+ #include mess */
+
SetupStat stat;
InsertData newdata;
std::list<FormulaData *> formulas;
@@ -116,6 +118,17 @@ class MySql : public Output
assert(i != idmap.end());
return (*i).second;
}
+
+ public:
+ MySql(MySqlRun &_run){}
+ ~MySql();
+
+ void connect(const std::string &host, const std::string &user,
+ const std::string &passwd, const std::string &db,
+ const std::string &name, const std::string &sample,
+ const std::string &project);
+ bool connected() const;
+
public:
// Implement Visit
virtual void visit(const ScalarData &data);
@@ -149,6 +162,20 @@ class MySql : public Output
void configure(const FormulaData &data);
};
+bool initMySQL(std::string host, std::string database, std::string user = "",
+ std::string passwd = "", std::string name = "test",
+ std::string sample = "0", std::string project = "test");
+
+#if !USE_MYSQL
+inline bool
+initMySQL(std::string host, std::string user, std::string password,
+ std::string database, std::string name, std::string sample,
+ std::string project)
+{
+ return false;
+}
+#endif
+
/* namespace Stats */ }
#endif // __BASE_STATS_MYSQL_HH__
diff --git a/src/base/stats/output.cc b/src/base/stats/output.cc
new file mode 100644
index 000000000..9f2b91c77
--- /dev/null
+++ b/src/base/stats/output.cc
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2004-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Nathan Binkert
+ */
+
+#include <list>
+
+#include "base/stats/output.hh"
+#include "sim/eventq.hh"
+#include "sim/host.hh"
+
+using namespace std;
+
+namespace Stats {
+
+Tick lastDump(0);
+list<Output *> OutputList;
+
+void
+dump()
+{
+ assert(lastDump <= curTick);
+ if (lastDump == curTick)
+ return;
+ lastDump = curTick;
+
+ list<Output *>::iterator i = OutputList.begin();
+ list<Output *>::iterator end = OutputList.end();
+ for (; i != end; ++i) {
+ Output *output = *i;
+ if (!output->valid())
+ continue;
+
+ output->output();
+ }
+}
+
+/* namespace Stats */ }
+
+void
+debugDumpStats()
+{
+ Stats::dump();
+}
+
diff --git a/src/base/stats/text.cc b/src/base/stats/text.cc
index ae0d65537..66c5955d7 100644
--- a/src/base/stats/text.cc
+++ b/src/base/stats/text.cc
@@ -725,4 +725,25 @@ Text::visit(const FormulaData &data)
visit((const VectorData &)data);
}
+bool
+initText(const string &filename, bool desc, bool compat)
+{
+ static Text text;
+ static bool connected = false;
+
+ if (connected)
+ return false;
+
+ extern list<Output *> OutputList;
+
+ text.open(*simout.find(filename));
+ text.descriptions = desc;
+ text.compat = compat;
+ OutputList.push_back(&text);
+ connected = true;
+
+ return true;
+}
+
+
/* namespace Stats */ }
diff --git a/src/base/stats/text.hh b/src/base/stats/text.hh
index b3faf5ad5..0516bc60d 100644
--- a/src/base/stats/text.hh
+++ b/src/base/stats/text.hh
@@ -34,6 +34,7 @@
#include <iosfwd>
#include <string>
+#include "base/output.hh"
#include "base/stats/output.hh"
namespace Stats {
@@ -73,6 +74,8 @@ class Text : public Output
virtual void output();
};
+bool initText(const std::string &filename, bool desc=true, bool compat=true);
+
/* namespace Stats */ }
#endif // __BASE_STATS_TEXT_HH__
diff --git a/src/base/trace.cc b/src/base/trace.cc
index 7afb038be..2dde1f688 100644
--- a/src/base/trace.cc
+++ b/src/base/trace.cc
@@ -47,7 +47,7 @@ using namespace std;
namespace Trace {
const string DefaultName("global");
FlagVec flags(NumFlags, false);
-bool enabled = true;
+bool enabled = false;
//
// This variable holds the output stream for debug information. Other
diff --git a/src/base/traceflags.py b/src/base/traceflags.py
index 897bf0023..ba6aa6af8 100644
--- a/src/base/traceflags.py
+++ b/src/base/traceflags.py
@@ -253,7 +253,7 @@ def gen_hh(filename):
print >>hhfile, '''
// The remaining enum values are *not* valid indices for Trace::flags.
// They are "compound" flags, which correspond to sets of base
- // flags, and are used only by TraceParamContext::setFlags().
+ // flags, and are used by changeFlag.
''',
for flag in compoundFlags:
diff --git a/src/cpu/base.cc b/src/cpu/base.cc
index 8440d2320..d5a023c59 100644
--- a/src/cpu/base.cc
+++ b/src/cpu/base.cc
@@ -63,7 +63,7 @@ int maxThreadsPerCPU = 1;
CPUProgressEvent::CPUProgressEvent(EventQueue *q, Tick ival,
BaseCPU *_cpu)
- : Event(q, Event::Stat_Event_Pri), interval(ival),
+ : Event(q, Event::Progress_Event_Pri), interval(ival),
lastNumInst(0), cpu(_cpu)
{
if (interval)
diff --git a/src/cpu/exetrace.hh b/src/cpu/exetrace.hh
index be10b4a6a..0f642c08e 100644
--- a/src/cpu/exetrace.hh
+++ b/src/cpu/exetrace.hh
@@ -157,6 +157,9 @@ getInstRecord(Tick when, ThreadContext *tc, const StaticInstPtr staticInst,
if (!IsOn(ExecEnable))
return NULL;
+ if (!Trace::enabled)
+ return NULL;
+
if (!IsOn(ExecSpeculative) && tc->misspeculating())
return NULL;
diff --git a/src/mem/vport.cc b/src/mem/vport.cc
index 8030c5a15..6cc4d9ca9 100644
--- a/src/mem/vport.cc
+++ b/src/mem/vport.cc
@@ -34,6 +34,7 @@
*/
#include "base/chunk_generator.hh"
+#include "cpu/thread_context.hh"
#include "mem/vport.hh"
void
@@ -70,3 +71,53 @@ VirtualPort::writeBlob(Addr addr, uint8_t *p, int size)
}
}
+void
+CopyOut(ThreadContext *tc, void *dest, Addr src, size_t cplen)
+{
+ uint8_t *dst = (uint8_t *)dest;
+ VirtualPort *vp = tc->getVirtPort(tc);
+
+ vp->readBlob(src, dst, cplen);
+
+ tc->delVirtPort(vp);
+
+}
+
+void
+CopyIn(ThreadContext *tc, Addr dest, void *source, size_t cplen)
+{
+ uint8_t *src = (uint8_t *)source;
+ VirtualPort *vp = tc->getVirtPort(tc);
+
+ vp->writeBlob(dest, src, cplen);
+
+ tc->delVirtPort(vp);
+}
+
+void
+CopyStringOut(ThreadContext *tc, char *dst, Addr vaddr, size_t maxlen)
+{
+ int len = 0;
+ char *start = dst;
+ VirtualPort *vp = tc->getVirtPort(tc);
+
+ do {
+ vp->readBlob(vaddr++, (uint8_t*)dst++, 1);
+ } while (len < maxlen && start[len++] != 0 );
+
+ tc->delVirtPort(vp);
+ dst[len] = 0;
+}
+
+void
+CopyStringIn(ThreadContext *tc, char *src, Addr vaddr)
+{
+ VirtualPort *vp = tc->getVirtPort(tc);
+ for (ChunkGenerator gen(vaddr, strlen(src), TheISA::PageBytes); !gen.done();
+ gen.next())
+ {
+ vp->writeBlob(gen.addr(), (uint8_t*)src, gen.size());
+ src += gen.size();
+ }
+ tc->delVirtPort(vp);
+}
diff --git a/src/mem/vport.hh b/src/mem/vport.hh
index c83836258..a8ceaa9fc 100644
--- a/src/mem/vport.hh
+++ b/src/mem/vport.hh
@@ -49,6 +49,7 @@
* simple address masking operation (such as alpha super page accesses).
*/
+
class VirtualPort : public FunctionalPort
{
private:
@@ -75,5 +76,11 @@ class VirtualPort : public FunctionalPort
virtual void writeBlob(Addr addr, uint8_t *p, int size);
};
+
+void CopyOut(ThreadContext *tc, void *dest, Addr src, size_t cplen);
+void CopyIn(ThreadContext *tc, Addr dest, void *source, size_t cplen);
+void CopyStringOut(ThreadContext *tc, char *dst, Addr vaddr, size_t maxlen);
+void CopyStringIn(ThreadContext *tc, char *src, Addr vaddr);
+
#endif //__MEM_VPORT_HH__
diff --git a/src/python/SConscript b/src/python/SConscript
index 51271650f..4dd614cfb 100644
--- a/src/python/SConscript
+++ b/src/python/SConscript
@@ -110,6 +110,7 @@ swig_it('main')
swig_it('debug')
swig_it('event')
swig_it('random')
+swig_it('stats')
swig_it('trace')
# Action function to build the zip archive. Uses the PyZipFile module
diff --git a/src/python/m5/SimObject.py b/src/python/m5/SimObject.py
index 934358298..ba79d3729 100644
--- a/src/python/m5/SimObject.py
+++ b/src/python/m5/SimObject.py
@@ -653,15 +653,13 @@ class SimObject(object):
instanceDict[self.path()] = self
- if hasattr(self, 'type') and not isinstance(self, ParamContext):
+ if hasattr(self, 'type'):
print 'type=%s' % self.type
child_names = self._children.keys()
child_names.sort()
- np_child_names = [c for c in child_names \
- if not isinstance(self._children[c], ParamContext)]
- if len(np_child_names):
- print 'children=%s' % ' '.join(np_child_names)
+ if len(child_names):
+ print 'children=%s' % ' '.join(child_names)
param_names = self._params.keys()
param_names.sort()
@@ -711,8 +709,7 @@ class SimObject(object):
def startDrain(self, drain_event, recursive):
count = 0
- # ParamContexts don't serialize
- if isinstance(self, SimObject) and not isinstance(self, ParamContext):
+ if isinstance(self, SimObject):
count += self._ccObject.drain(drain_event)
if recursive:
for child in self._children.itervalues():
@@ -720,7 +717,7 @@ class SimObject(object):
return count
def resume(self):
- if isinstance(self, SimObject) and not isinstance(self, ParamContext):
+ if isinstance(self, SimObject):
self._ccObject.resume()
for child in self._children.itervalues():
child.resume()
@@ -782,9 +779,6 @@ class SimObject(object):
for c in self.children:
c.outputDot(dot)
-class ParamContext(SimObject):
- pass
-
# Function to provide to C++ so it can look up instances based on paths
def resolveSimObject(name):
obj = instanceDict[name]
@@ -793,7 +787,7 @@ def resolveSimObject(name):
# __all__ defines the list of symbols that get exported when
# 'from config import *' is invoked. Try to keep this reasonably
# short to avoid polluting other namespaces.
-__all__ = ['SimObject', 'ParamContext']
+__all__ = ['SimObject']
# see comment on imports at end of __init__.py.
import proxy
diff --git a/src/python/m5/main.py b/src/python/m5/main.py
index 25b52e830..48c75434f 100644
--- a/src/python/m5/main.py
+++ b/src/python/m5/main.py
@@ -264,7 +264,7 @@ def main():
import objects
# set stats options
- objects.Statistics.text_file = options.stats_file
+ internal.stats.initText(options.stats_file)
# set debugging options
for when in options.debug_break:
@@ -292,11 +292,12 @@ def main():
for flag in off_flags:
internal.trace.clear(flag)
- if options.trace_start is not None:
- internal.trace.enabled = False
+ if options.trace_start:
def enable_trace():
- internal.event.enabled = True
- internal.event.create(enable_trace, options.trace_start)
+ internal.trace.cvar.enabled = True
+ internal.event.create(enable_trace, int(options.trace_start))
+ else:
+ internal.trace.enabled = True
internal.trace.output(options.trace_file)
diff --git a/src/python/m5/objects/Root.py b/src/python/m5/objects/Root.py
index c78ae6ccb..8db4fa5a2 100644
--- a/src/python/m5/objects/Root.py
+++ b/src/python/m5/objects/Root.py
@@ -1,8 +1,5 @@
from m5.SimObject import SimObject
from m5.params import *
-from Serialize import Serialize
-from Serialize import Statreset
-from Statistics import Statistics
class Root(SimObject):
type = 'Root'
@@ -12,7 +9,3 @@ class Root(SimObject):
"print a progress message every n ticks (0 = never)")
output_file = Param.String('cout', "file to dump simulator output to")
checkpoint = Param.String('', "checkpoint file to load")
-# stats = Param.Statistics(Statistics(), "statistics object")
-# serialize = Param.Serialize(Serialize(), "checkpoint generation options")
- stats = Statistics()
- serialize = Serialize()
diff --git a/src/python/swig/pyevent.cc b/src/python/swig/pyevent.cc
index 6fb7d3f17..7f23b8874 100644
--- a/src/python/swig/pyevent.cc
+++ b/src/python/swig/pyevent.cc
@@ -31,6 +31,7 @@
#include <Python.h>
#include "python/swig/pyevent.hh"
+#include "sim/async.hh"
PythonEvent::PythonEvent(PyObject *obj, Tick when, Priority priority)
: Event(&mainEventQueue, priority), object(obj)
@@ -52,9 +53,9 @@ PythonEvent::~PythonEvent()
void
PythonEvent::process()
{
- PyObject *result;
-
- result = PyObject_CallMethod(object, "process", "");
+ PyObject *args = PyTuple_New(0);
+ PyObject *result = PyObject_Call(object, args, NULL);
+ Py_DECREF(args);
if (result) {
// Nothing to do just decrement the reference count
@@ -62,5 +63,7 @@ PythonEvent::process()
} else {
// Somethign should be done to signal back to the main interpreter
// that there's been an exception.
+ async_event = true;
+ async_exception = true;
}
}
diff --git a/src/python/swig/stats.i b/src/python/swig/stats.i
new file mode 100644
index 000000000..d6b39c2cb
--- /dev/null
+++ b/src/python/swig/stats.i
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2006 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Nathan Binkert
+ */
+
+%module stats
+
+%include "std_string.i"
+
+%{
+#include "base/statistics.hh"
+#include "base/stats/mysql.hh"
+#include "base/stats/text.hh"
+#include "sim/stat_control.hh"
+%}
+
+namespace Stats {
+void initSimStats();
+void initText(const std::string &filename, bool desc=true, bool compat=true);
+void initMySQL(std::string host, std::string database, std::string user = "",
+ std::string passwd = "", std::string name = "test",
+ std::string sample = "0", std::string project = "test");
+
+void StatEvent(bool dump, bool reset, Tick when = curTick, Tick repeat = 0);
+
+void dump();
+void reset();
+
+/* namespace Stat */ }
+
+%wrapper %{
+// fix up module name to reflect the fact that it's inside the m5 package
+#undef SWIG_name
+#define SWIG_name "m5.internal._stats"
+%}
diff --git a/src/sim/async.hh b/src/sim/async.hh
index 50ae73040..6ee5eb46a 100644
--- a/src/sim/async.hh
+++ b/src/sim/async.hh
@@ -47,6 +47,7 @@ extern volatile bool async_dump; ///< Async request to dump stats.
extern volatile bool async_exit; ///< Async request to exit simulator.
extern volatile bool async_io; ///< Async I/O request (SIGIO).
extern volatile bool async_alarm; ///< Async alarm event (SIGALRM).
+extern volatile bool async_exception; ///< Python exception.
//@}
#endif // __ASYNC_HH__
diff --git a/src/sim/builder.cc b/src/sim/builder.cc
index 9074cc899..8ef54ce52 100644
--- a/src/sim/builder.cc
+++ b/src/sim/builder.cc
@@ -40,7 +40,7 @@
using namespace std;
SimObjectBuilder::SimObjectBuilder(const std::string &_iniSection)
- : ParamContext(_iniSection, NoAutoInit)
+ : ParamContext(_iniSection)
{
}
diff --git a/src/sim/eventq.hh b/src/sim/eventq.hh
index 1aeb26e25..a57e9077e 100644
--- a/src/sim/eventq.hh
+++ b/src/sim/eventq.hh
@@ -169,6 +169,9 @@ class Event : public Serializable, public FastAlloc
/// everything else, but before exit.
Stat_Event_Pri = 90,
+ /// Progress events come at the end.
+ Progress_Event_Pri = 95,
+
/// If we want to exit on this cycle, it's the very last thing
/// we do.
Sim_Exit_Pri = 100
diff --git a/src/sim/main.cc b/src/sim/main.cc
index 9f9a56450..8e47ac6a0 100644
--- a/src/sim/main.cc
+++ b/src/sim/main.cc
@@ -53,6 +53,7 @@
#include "base/output.hh"
#include "base/pollevent.hh"
#include "base/statistics.hh"
+#include "base/stats/output.hh"
#include "base/str.hh"
#include "base/time.hh"
#include "config/pythonhome.hh"
@@ -82,6 +83,7 @@ volatile bool async_dumpreset = false;
volatile bool async_exit = false;
volatile bool async_io = false;
volatile bool async_alarm = false;
+volatile bool async_exception = false;
/// Stats signal handler.
void
@@ -219,7 +221,7 @@ loadIniFile(PyObject *_resolveFunc)
inifile.load(simout.resolve("config.ini"));
// Initialize statistics database
- Stats::InitSimStats();
+ Stats::initSimStats();
}
@@ -270,13 +272,6 @@ connectPorts(SimObject *o1, const std::string &name1, int i1,
void
finalInit()
{
- // Parse and check all non-config-hierarchy parameters.
- ParamContext::parseAllContexts(inifile);
- ParamContext::checkAllContexts();
-
- // Echo all parameter settings to stats file as well.
- ParamContext::showAllContexts(*configStream);
-
// Do a second pass to finish initializing the sim objects
SimObject::initAll();
@@ -296,7 +291,6 @@ finalInit()
SimStartup();
}
-
/** Simulate for num_cycles additional cycles. If num_cycles is -1
* (the default), do not limit simulation; some other event must
* terminate the loop. Exported to Python via SWIG.
@@ -349,16 +343,12 @@ simulate(Tick num_cycles = MaxTick)
async_event = false;
if (async_dump) {
async_dump = false;
-
- using namespace Stats;
- SetupEvent(Dump, curTick);
+ Stats::StatEvent(true, false);
}
if (async_dumpreset) {
async_dumpreset = false;
-
- using namespace Stats;
- SetupEvent(Dump | Reset, curTick);
+ Stats::StatEvent(true, true);
}
if (async_exit) {
@@ -371,6 +361,11 @@ simulate(Tick num_cycles = MaxTick)
async_alarm = false;
pollQueue.service();
}
+
+ if (async_exception) {
+ async_exception = false;
+ return NULL;
+ }
}
}
@@ -460,8 +455,6 @@ doExitCleanup()
cout.flush();
- ParamContext::cleanupAllContexts();
-
// print simulation stats
- Stats::DumpNow();
+ Stats::dump();
}
diff --git a/src/sim/param.cc b/src/sim/param.cc
index 5cc69b161..51d389f5a 100644
--- a/src/sim/param.cc
+++ b/src/sim/param.cc
@@ -583,30 +583,10 @@ SimObjectBaseParam::parse(const string &s, vector<SimObject *>&value)
//
////////////////////////////////////////////////////////////////////////
-list<ParamContext *> *ParamContext::ctxList = NULL;
-
-ParamContext::ParamContext(const string &_iniSection, InitPhase _initPhase)
+ParamContext::ParamContext(const string &_iniSection)
: iniFilePtr(NULL), // initialized on call to parseParams()
- iniSection(_iniSection), paramList(NULL),
- initPhase(_initPhase)
-{
- // Put this context on global list for initialization
- if (initPhase != NoAutoInit) {
- if (ctxList == NULL)
- ctxList = new list<ParamContext *>();
-
- // keep list sorted by ascending initPhase values
- list<ParamContext *>::iterator i = ctxList->begin();
- list<ParamContext *>::iterator end = ctxList->end();
- for (; i != end; ++i) {
- if (initPhase <= (*i)->initPhase) {
- // found where we want to insert
- break;
- }
- }
- // (fall through case: insert at end)
- ctxList->insert(i, this);
- }
+ iniSection(_iniSection), paramList(NULL)
+{
}
@@ -695,89 +675,6 @@ ParamContext::printErrorProlog(ostream &os)
os << "Parameter error in section [" << iniSection << "]: " << endl;
}
-//
-// static method: call parseParams() on all registered contexts
-//
-void
-ParamContext::parseAllContexts(IniFile &iniFile)
-{
- list<ParamContext *>::iterator iter;
-
- for (iter = ctxList->begin(); iter != ctxList->end(); ++iter) {
- ParamContext *pc = *iter;
-
- pc->parseParams(iniFile);
- }
-}
-
-
-//
-// static method: call checkParams() on all registered contexts
-//
-void
-ParamContext::checkAllContexts()
-{
- list<ParamContext *>::iterator iter;
-
- for (iter = ctxList->begin(); iter != ctxList->end(); ++iter) {
- ParamContext *pc = *iter;
-
- pc->checkParams();
- }
-}
-
-
-//
-// static method: call showParams() on all registered contexts
-//
-void
-ParamContext::showAllContexts(ostream &os)
-{
- list<ParamContext *>::iterator iter;
-
- for (iter = ctxList->begin(); iter != ctxList->end(); ++iter) {
- ParamContext *pc = *iter;
-
- os << "[" << pc->iniSection << "]" << endl;
- pc->showParams(os);
- os << endl;
- }
-}
-
-
-//
-// static method: call cleanup() on all registered contexts
-//
-void
-ParamContext::cleanupAllContexts()
-{
- list<ParamContext *>::iterator iter;
-
- for (iter = ctxList->begin(); iter != ctxList->end(); ++iter) {
- ParamContext *pc = *iter;
-
- pc->cleanup();
- }
-}
-
-
-//
-// static method: call describeParams() on all registered contexts
-//
-void
-ParamContext::describeAllContexts(ostream &os)
-{
- list<ParamContext *>::iterator iter;
-
- for (iter = ctxList->begin(); iter != ctxList->end(); ++iter) {
- ParamContext *pc = *iter;
-
- os << "[" << pc->iniSection << "]\n";
- pc->describeParams(os);
- os << endl;
- }
-}
-
void
parseTime(const std::vector<int> &time, struct tm *tm)
{
diff --git a/src/sim/param.hh b/src/sim/param.hh
index 8a4670e27..dff0fa72d 100644
--- a/src/sim/param.hh
+++ b/src/sim/param.hh
@@ -50,12 +50,6 @@ class SimObject;
//
class ParamContext : protected StartupCallback
{
- private:
-
- // static list of all ParamContext objects, built as a side effect
- // of the ParamContext constructor
- static std::list<ParamContext *> *ctxList;
-
protected:
// .ini file (database) for parameter lookup... initialized on call
@@ -78,31 +72,10 @@ class ParamContext : protected StartupCallback
public:
- /// Initialization phases for ParamContext objects.
- enum InitPhase {
- NoAutoInit = -1, ///< Don't initialize at all... params
- /// will be parsed later (used by
- /// SimObjectBuilder, which parses
- /// params in SimObject::create().
- OutputInitPhase = 0, ///< Output stream initialization
- TraceInitPhase = 1, ///< Trace context initialization:
- /// depends on output streams, but
- /// needs to come before others so we
- /// can use tracing in other
- /// ParamContext init code
- StatsInitPhase = 2, ///< Stats output initialization
- DefaultInitPhase = 3 ///< Everything else
- };
-
- /// Records the initialization phase for this ParamContext.
- InitPhase initPhase;
-
/// Constructor.
/// @param _iniSection Name of .ini section corresponding to this context.
/// @param _initPhase Initialization phase (see InitPhase).
- ParamContext(const std::string &_iniSection,
- InitPhase _initPhase = DefaultInitPhase);
-
+ ParamContext(const std::string &_iniSection);
virtual ~ParamContext() {}
// add a parameter to the context... called from the parameter
@@ -135,24 +108,6 @@ class ParamContext : protected StartupCallback
// generate the name for this instance of this context (used as a
// prefix to create unique names in resolveSimObject()
virtual const std::string &getInstanceName() { return iniSection; }
-
- // Parse all parameters registered with all ParamContext objects.
- static void parseAllContexts(IniFile &iniFile);
-
- // Check all parameters registered with all ParamContext objects.
- // (calls checkParams() on each)
- static void checkAllContexts();
-
- // Print all parameter values on indicated ostream.
- static void showAllContexts(std::ostream &os);
-
- // Clean up all registered ParamContext objects. (calls cleanup()
- // on each)
- static void cleanupAllContexts();
-
- // print descriptions of all parameters registered with all
- // ParamContext objects
- static void describeAllContexts(std::ostream &os);
};
diff --git a/src/sim/pseudo_inst.cc b/src/sim/pseudo_inst.cc
index 4a8c0eb66..66ebc10e1 100644
--- a/src/sim/pseudo_inst.cc
+++ b/src/sim/pseudo_inst.cc
@@ -32,6 +32,7 @@
#include <fcntl.h>
#include <unistd.h>
+#include <fstream>
#include <string>
#include "arch/vtophys.hh"
@@ -199,8 +200,7 @@ namespace AlphaPseudo
Tick when = curTick + delay * Clock::Int::ns;
Tick repeat = period * Clock::Int::ns;
- using namespace Stats;
- SetupEvent(Reset, when, repeat);
+ Stats::StatEvent(false, true, when, repeat);
}
void
@@ -213,8 +213,7 @@ namespace AlphaPseudo
Tick when = curTick + delay * Clock::Int::ns;
Tick repeat = period * Clock::Int::ns;
- using namespace Stats;
- SetupEvent(Dump, when, repeat);
+ Stats::StatEvent(true, false, when, repeat);
}
void
@@ -254,8 +253,7 @@ namespace AlphaPseudo
Tick when = curTick + delay * Clock::Int::ns;
Tick repeat = period * Clock::Int::ns;
- using namespace Stats;
- SetupEvent(Dump|Reset, when, repeat);
+ Stats::StatEvent(true, true, when, repeat);
}
void
diff --git a/src/sim/serialize.cc b/src/sim/serialize.cc
index 1ff16976d..d32bb1142 100644
--- a/src/sim/serialize.cc
+++ b/src/sim/serialize.cc
@@ -407,36 +407,3 @@ Checkpoint::sectionExists(const std::string &section)
{
return db->sectionExists(section);
}
-
-/** Hacked stat reset event */
-
-class StatresetParamContext : public ParamContext
-{
- public:
- StatresetParamContext(const string &section);
- ~StatresetParamContext();
- void startup();
-};
-
-StatresetParamContext statParams("statsreset");
-
-Param<Tick> reset_cycle(&statParams, "reset_cycle",
- "Cycle to reset stats on", 0);
-
-StatresetParamContext::StatresetParamContext(const string &section)
- : ParamContext(section)
-{ }
-
-StatresetParamContext::~StatresetParamContext()
-{
-}
-
-void
-StatresetParamContext::startup()
-{
- if (reset_cycle > 0) {
- Stats::SetupEvent(Stats::Reset, curTick + reset_cycle, 0);
- cprintf("Stats reset event scheduled for %lli\n",
- curTick + reset_cycle);
- }
-}
diff --git a/src/sim/sim_object.cc b/src/sim/sim_object.cc
index 8fc8fe58f..434fcffe6 100644
--- a/src/sim/sim_object.cc
+++ b/src/sim/sim_object.cc
@@ -56,10 +56,6 @@ using namespace std;
//
SimObject::SimObjectList SimObject::simObjectList;
-namespace Stats {
- extern ObjectMatch event_ignore;
-}
-
//
// SimObject constructor: used to maintain static simObjectList
//
@@ -70,7 +66,6 @@ SimObject::SimObject(Params *p)
doDebugBreak = false;
#endif
- doRecordEvent = !Stats::event_ignore.match(name());
simObjectList.push_back(this);
state = Running;
}
@@ -86,7 +81,6 @@ SimObject::SimObject(const string &_name)
doDebugBreak = false;
#endif
- doRecordEvent = !Stats::event_ignore.match(name());
simObjectList.push_back(this);
state = Running;
}
@@ -245,8 +239,7 @@ debugObjectBreak(const char *objs)
void
SimObject::recordEvent(const std::string &stat)
{
- if (doRecordEvent)
- Stats::recordEvent(stat);
+ Stats::recordEvent(stat);
}
unsigned int
diff --git a/src/sim/sim_object.hh b/src/sim/sim_object.hh
index 93802e247..536e761e5 100644
--- a/src/sim/sim_object.hh
+++ b/src/sim/sim_object.hh
@@ -136,7 +136,6 @@ class SimObject : public Serializable, protected StartupCallback
#endif
public:
- bool doRecordEvent;
void recordEvent(const std::string &stat);
};
diff --git a/src/sim/stat_control.cc b/src/sim/stat_control.cc
index 3fad8beb5..228c83898 100644
--- a/src/sim/stat_control.cc
+++ b/src/sim/stat_control.cc
@@ -38,14 +38,9 @@
#include "base/callback.hh"
#include "base/hostinfo.hh"
#include "base/statistics.hh"
-#include "base/str.hh"
#include "base/time.hh"
-#include "base/stats/output.hh"
#include "cpu/base.hh"
#include "sim/eventq.hh"
-#include "sim/sim_object.hh"
-#include "sim/stat_control.hh"
-#include "sim/root.hh"
using namespace std;
@@ -63,11 +58,9 @@ namespace Stats {
Time statTime(true);
Tick startTick;
-Tick lastDump(0);
-class SimTicksReset : public Callback
+struct SimTicksReset : public Callback
{
- public:
void process()
{
statTime.set();
@@ -92,7 +85,7 @@ statElapsedTicks()
SimTicksReset simTicksReset;
void
-InitSimStats()
+initSimStats()
{
simInsts
.functor(BaseCPU::numSimulatedInstructions)
@@ -153,81 +146,40 @@ InitSimStats()
registerResetCallback(&simTicksReset);
}
-class StatEvent : public Event
+class _StatEvent : public Event
{
- protected:
- int flags;
+ private:
+ bool dump;
+ bool reset;
Tick repeat;
public:
- StatEvent(EventQueue *queue, int _flags, Tick _when, Tick _repeat);
- virtual void process();
- virtual const char *description();
-};
-
-StatEvent::StatEvent(EventQueue *queue, int _flags, Tick _when, Tick _repeat)
- : Event(queue, Stat_Event_Pri),
- flags(_flags), repeat(_repeat)
-{
- setFlags(AutoDelete);
- schedule(_when);
-}
-
-const char *
-StatEvent::description()
-{
- return "Statistics dump and/or reset";
-}
-
-void
-StatEvent::process()
-{
- if (flags & Stats::Dump)
- DumpNow();
-
- if (flags & Stats::Reset) {
- cprintf("Resetting stats at cycle %d!\n", curTick);
- reset();
+ _StatEvent(bool _dump, bool _reset, Tick _when, Tick _repeat)
+ : Event(&mainEventQueue, Stat_Event_Pri), dump(_dump), reset(_reset),
+ repeat(_repeat)
+ {
+ setFlags(AutoDelete);
+ schedule(_when);
}
- if (repeat)
- schedule(curTick + repeat);
-}
+ virtual void
+ process()
+ {
+ if (dump)
+ Stats::dump();
-list<Output *> OutputList;
+ if (reset)
+ Stats::reset();
-void
-DumpNow()
-{
- assert(lastDump <= curTick);
- if (lastDump == curTick)
- return;
- lastDump = curTick;
-
- list<Output *>::iterator i = OutputList.begin();
- list<Output *>::iterator end = OutputList.end();
- for (; i != end; ++i) {
- Output *output = *i;
- if (!output->valid())
- continue;
-
- output->output();
+ if (repeat)
+ new _StatEvent(dump, reset, curTick + repeat, repeat);
}
-}
+};
void
-SetupEvent(int flags, Tick when, Tick repeat, EventQueue *queue)
+StatEvent(bool dump, bool reset, Tick when, Tick repeat)
{
- if (queue == NULL)
- queue = &mainEventQueue;
-
- new StatEvent(queue, flags, when, repeat);
+ new _StatEvent(dump, reset, when, repeat);
}
/* namespace Stats */ }
-
-void debugDumpStats()
-{
- Stats::DumpNow();
-}
-
diff --git a/src/sim/stat_control.hh b/src/sim/stat_control.hh
index 67f7cc491..1efa2554e 100644
--- a/src/sim/stat_control.hh
+++ b/src/sim/stat_control.hh
@@ -31,25 +31,10 @@
#ifndef __SIM_STAT_CONTROL_HH__
#define __SIM_STAT_CONTROL_HH__
-#include <fstream>
-#include <list>
-
-class EventQueue;
-
namespace Stats {
-enum {
- Reset = 0x1,
- Dump = 0x2
-};
-
-class Output;
-extern std::list<Output *> OutputList;
-
-void DumpNow();
-void SetupEvent(int flags, Tick when, Tick repeat = 0, EventQueue *queue = NULL);
-
-void InitSimStats();
+void initSimStats();
+void StatEvent(bool dump, bool reset, Tick when = curTick, Tick repeat = 0);
/* namespace Stats */ }