summaryrefslogtreecommitdiff
path: root/src/base
diff options
context:
space:
mode:
authorGabe Black <gblack@eecs.umich.edu>2009-04-06 10:19:36 -0700
committerGabe Black <gblack@eecs.umich.edu>2009-04-06 10:19:36 -0700
commitd080581db1f9ee4e1e6d07d2b01c13c67908a391 (patch)
treecc484b289fa5a30c4631f9faa1d8b456bffeebfc /src/base
parent7a7c4c5fca83a8d47c7e71c9c080a882ebe204a9 (diff)
parent639cb0a42d953ee32bc7e96b0cdfa96cd40e9fc1 (diff)
downloadgem5-d080581db1f9ee4e1e6d07d2b01c13c67908a391.tar.xz
Merge ARM into the head. ARM will compile but may not actually work.
Diffstat (limited to 'src/base')
-rw-r--r--src/base/CPA.py8
-rw-r--r--src/base/SConscript38
-rw-r--r--src/base/annotate.cc122
-rw-r--r--src/base/atomicio.cc92
-rw-r--r--src/base/atomicio.hh (renamed from src/base/annotate.hh)53
-rw-r--r--src/base/bitunion.hh14
-rw-r--r--src/base/cast.hh (renamed from src/base/stats/statdb.hh)58
-rw-r--r--src/base/chunk_generator.hh1
-rw-r--r--src/base/circlebuf.cc33
-rw-r--r--src/base/cp_annotate.cc1404
-rw-r--r--src/base/cp_annotate.hh522
-rw-r--r--src/base/cprintf.cc17
-rw-r--r--src/base/cprintf.hh35
-rw-r--r--src/base/cprintf_formats.hh7
-rw-r--r--src/base/crc.cc6
-rw-r--r--src/base/debug.cc (renamed from src/base/stats/statdb.cc)56
-rw-r--r--src/base/debug.hh36
-rw-r--r--src/base/fast_alloc.cc38
-rw-r--r--src/base/fast_alloc.hh73
-rw-r--r--src/base/flags.hh79
-rw-r--r--src/base/hashmap.hh10
-rw-r--r--src/base/hybrid_pred.hh12
-rw-r--r--src/base/inet.cc21
-rw-r--r--src/base/inet.hh112
-rw-r--r--src/base/inifile.cc111
-rw-r--r--src/base/inifile.hh16
-rw-r--r--src/base/intmath.hh6
-rw-r--r--src/base/loader/aout_object.cc2
-rw-r--r--src/base/loader/coff_sym.h354
-rw-r--r--src/base/loader/coff_symconst.h220
-rw-r--r--src/base/loader/ecoff_object.cc2
-rw-r--r--src/base/loader/elf_object.cc21
-rwxr-xr-xsrc/base/loader/hex_file.cc163
-rwxr-xr-xsrc/base/loader/hex_file.hh37
-rw-r--r--src/base/loader/object_file.hh5
-rw-r--r--src/base/loader/symtab.hh3
-rw-r--r--src/base/misc.cc96
-rw-r--r--src/base/misc.hh147
-rw-r--r--src/base/output.cc83
-rw-r--r--src/base/output.hh12
-rw-r--r--src/base/random_mt.cc6
-rw-r--r--src/base/range_map.hh70
-rw-r--r--src/base/remote_gdb.cc38
-rw-r--r--src/base/res_list.hh2
-rw-r--r--src/base/sat_counter.hh12
-rw-r--r--src/base/socket.cc18
-rw-r--r--src/base/socket.hh8
-rw-r--r--src/base/statistics.cc257
-rw-r--r--src/base/statistics.hh1838
-rw-r--r--src/base/stats/events.cc2
-rw-r--r--src/base/stats/flags.hh23
-rw-r--r--src/base/stats/mysql.cc250
-rw-r--r--src/base/stats/mysql.hh73
-rw-r--r--src/base/stats/mysql_run.hh8
-rw-r--r--src/base/stats/output.cc3
-rw-r--r--src/base/stats/text.cc314
-rw-r--r--src/base/stats/text.hh14
-rw-r--r--src/base/stats/types.hh7
-rw-r--r--src/base/stats/visit.hh28
-rw-r--r--src/base/str.cc15
-rw-r--r--src/base/time.cc6
-rw-r--r--src/base/time.hh4
-rw-r--r--src/base/timebuf.hh13
-rw-r--r--src/base/trace.hh9
-rw-r--r--src/base/varargs.hh20
65 files changed, 4613 insertions, 2550 deletions
diff --git a/src/base/CPA.py b/src/base/CPA.py
new file mode 100644
index 000000000..c0beaedef
--- /dev/null
+++ b/src/base/CPA.py
@@ -0,0 +1,8 @@
+from m5.SimObject import SimObject
+from m5.params import *
+
+class CPA(SimObject):
+ type = 'CPA'
+
+ enabled = Param.Bool(False, "Is Annotation enabled?")
+ user_apps = VectorParam.String([], "List of apps to get symbols for")
diff --git a/src/base/SConscript b/src/base/SConscript
index f9d936d84..58c453184 100644
--- a/src/base/SConscript
+++ b/src/base/SConscript
@@ -30,11 +30,15 @@
Import('*')
-Source('annotate.cc')
+if env['CP_ANNOTATE']:
+ SimObject('CPA.py')
+ Source('cp_annotate.cc')
+Source('atomicio.cc')
Source('bigint.cc')
Source('circlebuf.cc')
Source('cprintf.cc')
Source('crc.cc')
+Source('debug.cc')
Source('fast_alloc.cc')
if env['USE_FENV']:
Source('fenv.c')
@@ -72,7 +76,6 @@ Source('loader/symtab.cc')
Source('stats/events.cc')
Source('stats/output.cc')
-Source('stats/statdb.cc')
Source('stats/text.cc')
Source('stats/visit.cc')
@@ -80,16 +83,23 @@ if env['USE_MYSQL']:
Source('mysql.cc')
Source('stats/mysql.cc')
-TraceFlag('Annotate')
-TraceFlag('GDBAcc')
-TraceFlag('GDBExtra')
-TraceFlag('GDBMisc')
-TraceFlag('GDBRead')
-TraceFlag('GDBRecv')
-TraceFlag('GDBSend')
-TraceFlag('GDBWrite')
-TraceFlag('SQL')
-TraceFlag('StatEvents')
+TraceFlag('Annotate', "State machine annotation debugging")
+TraceFlag('AnnotateQ', "State machine annotation queue debugging")
+TraceFlag('AnnotateVerbose', "Dump all state machine annotation details")
+TraceFlag('GDBAcc', "Remote debugger accesses")
+TraceFlag('GDBExtra', "Dump extra information on reads and writes")
+TraceFlag('GDBMisc', "Breakpoints, traps, watchpoints, etc.")
+TraceFlag('GDBRead', "Reads to the remote address space")
+TraceFlag('GDBRecv', "Messages received from the remote application")
+TraceFlag('GDBSend', "Messages sent to the remote application")
+TraceFlag('GDBWrite', "Writes to the remote address space")
+TraceFlag('SQL', "SQL queries sent to the server")
+TraceFlag('StatEvents', "Statistics event tracking")
+
+CompoundFlag('GDBAll',
+ [ 'GDBMisc', 'GDBAcc', 'GDBRead', 'GDBWrite', 'GDBSend', 'GDBRecv',
+ 'GDBExtra' ],
+ desc="All Remote debugging flags")
+CompoundFlag('AnnotateAll', ['Annotate', 'AnnotateQ', 'AnnotateVerbose'],
+ desc="All Annotation flags")
-CompoundFlag('GDBAll', [ 'GDBMisc', 'GDBAcc', 'GDBRead', 'GDBWrite', 'GDBSend',
- 'GDBRecv', 'GDBExtra' ])
diff --git a/src/base/annotate.cc b/src/base/annotate.cc
deleted file mode 100644
index de7eeed51..000000000
--- a/src/base/annotate.cc
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * 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: Ali Saidi
- */
-
-#include "base/annotate.hh"
-#include "base/callback.hh"
-#include "base/output.hh"
-#include "base/trace.hh"
-#include "sim/core.hh"
-#include "sim/sim_exit.hh"
-#include "sim/system.hh"
-
-
-
-class AnnotateDumpCallback : public Callback
-{
- public:
- virtual void process();
-};
-
-void
-AnnotateDumpCallback::process()
-{
- Annotate::annotations.dump();
-}
-
-namespace Annotate {
-
-
-Annotate annotations;
-
-Annotate::Annotate()
-{
- registerExitCallback(new AnnotateDumpCallback);
-}
-
-void
-Annotate::add(System *sys, Addr stack, uint32_t sm, uint32_t st,
- uint32_t wm, uint32_t ws)
-{
- AnnotateData *an;
-
- an = new AnnotateData;
- an->time = curTick;
-
- std::map<System*, std::string>::iterator i = nameCache.find(sys);
- if (i == nameCache.end()) {
- nameCache[sys] = sys->name();
- }
-
- an->system = nameCache[sys];
- an->stack = stack;
- an->stateMachine = sm;
- an->curState = st;
- an->waitMachine = wm;
- an->waitState = ws;
-
- data.push_back(an);
- if (an->waitMachine)
- DPRINTF(Annotate, "Annotating: %s(%#llX) %d:%d waiting on %d:%d\n",
- an->system, an->stack, an->stateMachine, an->curState,
- an->waitMachine, an->waitState);
- else
- DPRINTF(Annotate, "Annotating: %s(%#llX) %d:%d beginning\n", an->system,
- an->stack, an->stateMachine, an->curState);
-
- DPRINTF(Annotate, "Now %d events on list\n", data.size());
-
-}
-
-void
-Annotate::dump()
-{
-
- std::list<AnnotateData*>::iterator i;
-
- i = data.begin();
-
- if (i == data.end())
- return;
-
- std::ostream *os = simout.create("annotate.dat");
-
- AnnotateData *an;
-
- while (i != data.end()) {
- DPRINTF(Annotate, "Writing\n", data.size());
- an = *i;
- ccprintf(*os, "%d %s(%#llX) %d %d %d %d\n", an->time, an->system,
- an->stack, an->stateMachine, an->curState, an->waitMachine,
- an->waitState);
- i++;
- }
-}
-
-} //namespace Annotate
diff --git a/src/base/atomicio.cc b/src/base/atomicio.cc
new file mode 100644
index 000000000..3f3e6d6f0
--- /dev/null
+++ b/src/base/atomicio.cc
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2008 The Hewlett-Packard Development Company
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Nathan Binkert
+ */
+
+#include <cerrno>
+#include <cstdio>
+
+#include "base/atomicio.hh"
+
+ssize_t
+atomic_read(int fd, void *s, size_t n)
+{
+ char *p = reinterpret_cast<char *>(s);
+ ssize_t pos = 0;
+
+ // Keep reading until we've gotten all of the data.
+ while (n > pos) {
+ ssize_t result = read(fd, p + pos, n - pos);
+
+ // We didn't get any more data, so we should probably punt,
+ // otherwise we'd just keep spinning
+ if (result == 0)
+ break;
+
+ // If there was an error, try again on EINTR/EAGAIN, pass the
+ // error up otherwise.
+ if (result == -1) {
+ if (errno == EINTR || errno == EAGAIN)
+ continue;
+ return result;
+ }
+
+ pos += result;
+ }
+
+ return pos;
+}
+
+ssize_t
+atomic_write(int fd, const void *s, size_t n)
+{
+ const char *p = reinterpret_cast<const char *>(s);
+ ssize_t pos = 0;
+
+ // Keep writing until we've written all of the data
+ while (n > pos) {
+ ssize_t result = write(fd, p + pos, n - pos);
+
+ // We didn't manage to write anything this time, so we should
+ // probably punt, otherwise we'd just keep spinning
+ if (result == 0)
+ break;
+
+ // If there was an error, try again on EINTR/EAGAIN, pass the
+ // error up otherwise.
+ if (result == -1) {
+ if (errno == EINTR || errno == EAGAIN)
+ continue;
+ return result;
+ }
+
+ pos += result;
+ }
+
+ return pos;
+}
diff --git a/src/base/annotate.hh b/src/base/atomicio.hh
index 36607bf90..5e703f315 100644
--- a/src/base/annotate.hh
+++ b/src/base/atomicio.hh
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006 The Regents of The University of Michigan
+ * Copyright (c) 2008 The Hewlett-Packard Development Company
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -25,49 +25,20 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
- * Authors: Ali Saidi
+ * Authors: Nathan Binkert
*/
-#ifndef __BASE__ANNOTATE_HH__
-#define __BASE__ANNOTATE_HH__
+#ifndef __BASE_ATOMICIO_HH__
+#define __BASE_ATOMICIO_HH__
-#include "sim/host.hh"
+#include <unistd.h>
-#include <string>
-#include <list>
-#include <map>
+// These functions keep reading/writing, if possible, until all data
+// has been transferred. Basically, try again when there's no error,
+// but there is data left also retry on EINTR.
+// This function blocks until it is done.
+ssize_t atomic_read(int fd, void *s, size_t n);
+ssize_t atomic_write(int fd, const void *s, size_t n);
-class System;
-
-namespace Annotate {
-
-
-class Annotate {
-
- protected:
- struct AnnotateData {
- Tick time;
- std::string system;
- Addr stack;
- uint32_t stateMachine;
- uint32_t curState;
- uint32_t waitMachine;
- uint32_t waitState;
- };
-
- std::list<AnnotateData*> data;
- std::map<System*, std::string> nameCache;
-
- public:
- Annotate();
- void add(System *sys, Addr stack, uint32_t sm, uint32_t st, uint32_t
- wm, uint32_t ws);
- void dump();
-};
-
-extern Annotate annotations;
-} //namespace Annotate
-
-#endif //__BASE__ANNOTATE_HH__
-
+#endif // __BASE_ATOMICIO_HH__
diff --git a/src/base/bitunion.hh b/src/base/bitunion.hh
index 7f7b06966..8ba28f3ba 100644
--- a/src/base/bitunion.hh
+++ b/src/base/bitunion.hh
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2005 The Regents of The University of Michigan
+ * Copyright (c) 2007-2008 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -34,7 +34,7 @@
#include <inttypes.h>
#include "base/bitfield.hh"
-// The following implements the BitUnion system of defining bitfields
+// The following implements the BitUnion system of defining bitfields
//on top of an underlying class. This is done through the pervasive use of
//both named and unnamed unions which all contain the same actual storage.
//Since they're unioned with each other, all of these storage locations
@@ -242,11 +242,7 @@ namespace BitfieldBackend
//bitfields which are defined in the union, creating shared storage with no
//overhead.
#define __BitUnion(type, name) \
- namespace BitfieldUnderlyingClasses \
- { \
- class name; \
- } \
- class BitfieldUnderlyingClasses::name : \
+ class BitfieldUnderlyingClasses##name : \
public BitfieldBackend::BitfieldTypes<type> \
{ \
public: \
@@ -262,8 +258,8 @@ namespace BitfieldBackend
}; \
}; \
typedef BitfieldBackend::BitUnionOperators< \
- BitfieldUnderlyingClasses::name::__DataType, \
- BitfieldUnderlyingClasses::name> name;
+ BitfieldUnderlyingClasses##name::__DataType, \
+ BitfieldUnderlyingClasses##name> name;
//This sets up a bitfield which has other bitfields nested inside of it. The
//__data member functions like the "underlying storage" of the top level
diff --git a/src/base/stats/statdb.hh b/src/base/cast.hh
index a5b9be7eb..30a065cd2 100644
--- a/src/base/stats/statdb.hh
+++ b/src/base/cast.hh
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2004-2005 The Regents of The University of Michigan
+ * Copyright (c) 2008 The Hewlett-Packard Development Company
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -28,43 +28,41 @@
* Authors: Nathan Binkert
*/
-#ifndef __BASE_STATS_STATDB_HH__
-#define __BASE_STATS_STATDB_HH__
+#ifndef __BASE_CAST_HH__
+#define __BASE_CAST_HH__
-#include <iosfwd>
-#include <list>
-#include <map>
-#include <string>
+#include <cassert>
-class Python;
+// This is designed for situations where we have a pointer to a base
+// type, but in all cases when we cast it to a derived type, we know
+// by construction that it should work correctly.
-namespace Stats {
+#if defined(DEBUG)
-class StatData;
+// In debug builds, do the dynamic cast and assert the result is good
-namespace Database {
-
-typedef std::map<void *, StatData *> stat_map_t;
-typedef std::list<StatData *> stat_list_t;
-
-// We wrap the database in a struct to make sure it is built in time.
-struct TheDatabase
+template <class T, class U>
+inline T
+safe_cast(U ptr)
{
- stat_map_t map;
- stat_list_t stats;
-};
+ T ret = dynamic_cast<T>(ptr);
+ assert(ret);
+ return ret;
+}
-TheDatabase &db();
-inline stat_map_t &map() { return db().map; }
-inline stat_list_t &stats() { return db().stats; }
+#else
-StatData *find(void *stat);
-void regStat(void *stat, StatData *data);
-void regPrint(void *stat);
+// In non debug builds statically cast the result to the pointer we
+// want to use. This is technically unsafe, but this is only for
+// cases where we know that this should work by construction.
-inline std::string name() { return "Statistics Database"; }
+template <class T, class U>
+inline T
+safe_cast(U ptr)
+{
+ return static_cast<T>(ptr);
+}
-/* namespace Database */ }
-/* namespace Stats */ }
+#endif
-#endif // __BASE_STATS_STATDB_HH__
+#endif // __BASE_CAST_HH__
diff --git a/src/base/chunk_generator.hh b/src/base/chunk_generator.hh
index e8238464b..d2ae45d1e 100644
--- a/src/base/chunk_generator.hh
+++ b/src/base/chunk_generator.hh
@@ -82,6 +82,7 @@ class ChunkGenerator
{
// chunkSize must be a power of two
assert(chunkSize == 0 || isPowerOf2(chunkSize));
+ assert(totalSize >= 0);
// set up initial chunk.
curAddr = startAddr;
diff --git a/src/base/circlebuf.cc b/src/base/circlebuf.cc
index a0c015671..06d0075b2 100644
--- a/src/base/circlebuf.cc
+++ b/src/base/circlebuf.cc
@@ -29,12 +29,11 @@
*/
#include <algorithm>
+#include <cstdio>
+#include <cstring>
#include <string>
-#include <stdio.h>
-#include <string.h>
-#include <unistd.h>
-
+#include "base/atomicio.hh"
#include "base/circlebuf.hh"
#include "base/cprintf.hh"
#include "base/intmath.hh"
@@ -59,8 +58,8 @@ CircleBuf::dump()
cprintf("start = %10d, stop = %10d, buflen = %10d\n",
_start, _stop, _buflen);
fflush(stdout);
- ::write(STDOUT_FILENO, _buf, _buflen);
- ::write(STDOUT_FILENO, "<\n", 2);
+ atomic_write(STDOUT_FILENO, _buf, _buflen);
+ atomic_write(STDOUT_FILENO, "<\n", 2);
}
void
@@ -106,19 +105,19 @@ CircleBuf::read(int fd, int len)
if (_stop > _start) {
len = min(len, _stop - _start);
- ::write(fd, _buf + _start, len);
+ atomic_write(fd, _buf + _start, len);
_start += len;
}
else {
int endlen = _buflen - _start;
if (endlen > len) {
- ::write(fd, _buf + _start, len);
+ atomic_write(fd, _buf + _start, len);
_start += len;
}
else {
- ::write(fd, _buf + _start, endlen);
+ atomic_write(fd, _buf + _start, endlen);
_start = min(len - endlen, _stop);
- ::write(fd, _buf, _start);
+ atomic_write(fd, _buf, _start);
}
}
}
@@ -129,11 +128,11 @@ CircleBuf::read(int fd)
_size = 0;
if (_stop > _start) {
- ::write(fd, _buf + _start, _stop - _start);
+ atomic_write(fd, _buf + _start, _stop - _start);
}
else {
- ::write(fd, _buf + _start, _buflen - _start);
- ::write(fd, _buf, _stop);
+ atomic_write(fd, _buf + _start, _buflen - _start);
+ atomic_write(fd, _buf, _stop);
}
_start = _stop;
@@ -159,9 +158,9 @@ void
CircleBuf::readall(int fd)
{
if (_rollover)
- ::write(fd, _buf + _stop, _buflen - _stop);
+ atomic_write(fd, _buf + _stop, _buflen - _stop);
- ::write(fd, _buf, _stop);
+ atomic_write(fd, _buf, _stop);
_start = _stop;
}
@@ -209,7 +208,7 @@ CircleBuf::write(const char *b, int len)
_rollover = true;
}
- if (old_start > old_stop && old_start < _stop ||
- old_start < old_stop && _stop < old_stop)
+ if ((old_start > old_stop && old_start < _stop) ||
+ (old_start < old_stop && _stop < old_stop))
_start = _stop + 1;
}
diff --git a/src/base/cp_annotate.cc b/src/base/cp_annotate.cc
new file mode 100644
index 000000000..0aba2d999
--- /dev/null
+++ b/src/base/cp_annotate.cc
@@ -0,0 +1,1404 @@
+/*
+ * Copyright (c) 2006-2009 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Ali Saidi
+ */
+
+#include "arch/utility.hh"
+#include "arch/alpha/linux/threadinfo.hh"
+#include "base/cp_annotate.hh"
+#include "base/callback.hh"
+#include "base/loader/object_file.hh"
+#include "base/output.hh"
+#include "base/trace.hh"
+#include "cpu/thread_context.hh"
+#include "sim/arguments.hh"
+#include "sim/core.hh"
+#include "sim/sim_exit.hh"
+#include "sim/system.hh"
+
+struct CPAIgnoreSymbol
+{
+ const char *symbol;
+ size_t len;
+};
+#define CPA_IGNORE_SYMBOL(sym) { #sym, sizeof(#sym) }
+
+CPAIgnoreSymbol ignoreSymbols[] = {
+ CPA_IGNORE_SYMBOL("m5a_"),
+ CPA_IGNORE_SYMBOL("ret_from_sys_call"),
+ CPA_IGNORE_SYMBOL("ret_from_reschedule"),
+ CPA_IGNORE_SYMBOL("_spin_"),
+ CPA_IGNORE_SYMBOL("local_bh_"),
+ CPA_IGNORE_SYMBOL("restore_all"),
+ CPA_IGNORE_SYMBOL("Call_Pal_"),
+ CPA_IGNORE_SYMBOL("pal_post_interrupt"),
+ CPA_IGNORE_SYMBOL("rti_to_"),
+ CPA_IGNORE_SYMBOL("sys_int_2"),
+ CPA_IGNORE_SYMBOL("sys_interrupt"),
+ CPA_IGNORE_SYMBOL("normal_int"),
+ CPA_IGNORE_SYMBOL("TRAP_INTERRUPT_10_"),
+ CPA_IGNORE_SYMBOL("Trap_Interrupt"),
+ CPA_IGNORE_SYMBOL("do_entInt"),
+ CPA_IGNORE_SYMBOL("__do_softirq"),
+ CPA_IGNORE_SYMBOL("_end"),
+ CPA_IGNORE_SYMBOL("entInt"),
+ CPA_IGNORE_SYMBOL("entSys"),
+ {0,0}
+};
+#undef CPA_IGNORE_SYMBOL
+
+using namespace std;
+using namespace TheISA;
+
+bool CPA::exists;
+CPA *CPA::_cpa;
+
+class AnnotateDumpCallback : public Callback
+{
+
+ private:
+ CPA *cpa;
+ public:
+ virtual void process();
+ AnnotateDumpCallback(CPA *_cpa)
+ : cpa(_cpa)
+ {}
+};
+
+void
+AnnotateDumpCallback::process()
+{
+ cpa->dump(true);
+ cpa->dumpKey();
+}
+
+
+CPA::CPA(Params *p)
+ : SimObject(p), numSm(0), numSmt(0), numSys(0), numQs(0), conId(0)
+{
+ if (exists)
+ fatal("Multiple annotation objects found in system");
+ exists = true;
+
+ _enabled = p->enabled;
+ _cpa = this;
+
+ vector<string>::iterator i;
+ i = p->user_apps.begin();
+
+ while (i != p->user_apps.end()) {
+ ObjectFile *of = createObjectFile(*i);
+ string sf;
+ if (!of)
+ fatal("Couldn't load symbols from file: %s\n", *i);
+ sf = *i;
+ sf.erase(0, sf.rfind('/') + 1);;
+ DPRINTFN("file %s short: %s\n", *i, sf);
+ userApp[sf] = new SymbolTable;
+ bool result1 = of->loadGlobalSymbols(userApp[sf]);
+ bool result2 = of->loadLocalSymbols(userApp[sf]);
+ if (!result1 || !result2)
+ panic("blah");
+ assert(result1 && result2);
+ i++;
+ }
+}
+
+void
+CPA::startup()
+{
+ osbin = simout.create("annotate.bin", true);
+ // MAGIC version number 'M''5''A'N' + version/capabilities
+ ah.version = 0x4D35414E00000101ULL;
+ ah.num_recs = 0;
+ ah.key_off = 0;
+ osbin->write((char*)&ah, sizeof(AnnotateHeader));
+
+ registerExitCallback(new AnnotateDumpCallback(this));
+}
+void
+CPA::swSmBegin(ThreadContext *tc)
+{
+ if (!enabled())
+ return;
+
+ Arguments args(tc);
+ std::string st;
+ Addr junk;
+ char sm[50];
+ if (!TheISA::inUserMode(tc))
+ debugSymbolTable->findNearestSymbol(
+ tc->readIntReg(ReturnAddressReg), st, junk);
+
+ CopyStringOut(tc, sm, args[0], 50);
+ System *sys = tc->getSystemPtr();
+ StringWrap name(sys->name());
+
+ if (!sm[0])
+ warn("Got null SM at tick %d\n", curTick);
+
+ int sysi = getSys(sys);
+ int smi = getSm(sysi, sm, args[1]);
+ DPRINTF(Annotate, "Starting machine: %s(%d) sysi: %d id: %#x\n", sm,
+ smi, sysi, args[1]);
+ DPRINTF(Annotate, "smMap[%d] = %d, %s, %#x\n", smi,
+ smMap[smi-1].first, smMap[smi-1].second.first,
+ smMap[smi-1].second.second);
+
+ uint64_t frame = getFrame(tc);
+ StackId sid = StackId(sysi, frame);
+
+ // check if we need to link to the previous state machine
+ int flags = args[2];
+ if (flags & FL_LINK) {
+ if (smStack[sid].size()) {
+ int prev_smi = smStack[sid].back();
+ DPRINTF(Annotate, "Linking from %d to state machine %s(%d) [%#x]\n",
+ prev_smi, sm, smi, args[1]);
+
+ if (lnMap[smi])
+ DPRINTF(Annotate, "LnMap already contains entry for %d of %d\n",
+ smi, lnMap[smi]);
+ assert(lnMap[smi] == 0);
+ lnMap[smi] = prev_smi;
+
+ add(OP_LINK, FL_NONE, tc->contextId(), prev_smi, smi);
+ } else {
+ DPRINTF(Annotate, "Not Linking to state machine %s(%d) [%#x]\n",
+ sm, smi, args[1]);
+ }
+ }
+
+
+ smStack[sid].push_back(smi);
+
+ DPRINTF(Annotate, "Stack Now (%#X):\n", frame);
+ for (int x = smStack[sid].size()-1; x >= 0; x--)
+ DPRINTF(Annotate, "-- %d\n", smStack[sid][x]);
+
+ // reset the sw state exculsion to false
+ if (swExpl[sid])
+ swExpl[sid] = false;
+
+
+ Id id = Id(sm, frame);
+ if (scLinks[sysi-1][id]) {
+ AnnDataPtr an = scLinks[sysi-1][id];
+ scLinks[sysi-1].erase(id);
+ an->stq = smi;
+ an->dump = true;
+ DPRINTF(Annotate,
+ "Found prev unknown linking from %d to state machine %s(%d)\n",
+ an->sm, sm, smi);
+
+ if (lnMap[smi])
+ DPRINTF(Annotate, "LnMap already contains entry for %d of %d\n",
+ smi, lnMap[smi]);
+ assert(lnMap[smi] == 0);
+ lnMap[smi] = an->sm;
+ }
+
+ // add a new begin ifwe have that info
+ if (st != "") {
+ DPRINTF(Annotate, "st: %s smi: %d stCache.size %d\n", st,
+ smi, stCache.size());
+ int sti = getSt(sm, st);
+ lastState[smi] = sti;
+ add(OP_BEGIN, FL_NONE, tc->contextId(), smi, sti);
+ }
+}
+
+void
+CPA::swSmEnd(ThreadContext *tc)
+{
+ if (!enabled())
+ return;
+
+ Arguments args(tc);
+ char sm[50];
+ CopyStringOut(tc, sm, args[0], 50);
+ System *sys = tc->getSystemPtr();
+ doSwSmEnd(sys, tc->contextId(), sm, getFrame(tc));
+}
+
+void
+CPA::doSwSmEnd(System *sys, int cpuid, string sm, uint64_t frame)
+{
+ int sysi = getSys(sys);
+ StackId sid = StackId(sysi, frame);
+
+
+ // reset the sw state exculsion to false
+ if (swExpl[sid])
+ swExpl[sid] = false;
+
+
+ int smib = smStack[sid].back();
+ StringWrap name(sys->name());
+ DPRINTF(Annotate, "Ending machine: %s[%d, %#x] (%d?)\n", sm, sysi,
+ frame, smib);
+
+ if (!smStack[sid].size() || smMap[smib-1].second.first != sm) {
+ DPRINTF(Annotate, "State Machine not unwinding correctly. sid: %d, %#x"
+ " top of stack: %s Current Stack:\n",
+ sysi, frame, smMap[smib-1].second.first);
+ for (int x = smStack[sid].size()-1; x >= 0; x--)
+ DPRINTF(Annotate, "-- %d\n", smStack[sid][x]);
+ DPRINTF(Annotate, "Ending machine: %s; end stack: %s\n", sm,
+ smMap[smib-1].second.first);
+
+ warn("State machine stack not unwinding correctly at %d\n", curTick);
+ } else {
+ DPRINTF(Annotate,
+ "State machine ending:%s sysi:%d id:%#x back:%d getSm:%d\n",
+ sm, sysi, smMap[smib-1].second.second, smStack[sid].back(),
+ getSm(sysi, sm, smMap[smib-1].second.second));
+ assert(getSm(sysi, sm, smMap[smib-1].second.second) ==
+ smStack[sid].back());
+
+ int smi = smStack[sid].back();
+ smStack[sid].pop_back();
+
+ if (lnMap[smi]) {
+ DPRINTF(Annotate, "Linking %d back to %d\n", smi, lnMap[smi]);
+ add(OP_LINK, FL_NONE, cpuid, smi, lnMap[smi]);
+ lnMap.erase(smi);
+ }
+
+ if (smStack[sid].size()) {
+ add(OP_BEGIN, FL_NONE, cpuid, smi, lastState[smi]);
+ }
+
+ DPRINTF(Annotate, "Stack Now:\n");
+ for (int x = smStack[sid].size()-1; x >= 0; x--)
+ DPRINTF(Annotate, "-- %d\n", smStack[sid][x]);
+ }
+}
+
+
+void
+CPA::swExplictBegin(ThreadContext *tc)
+{
+ if (!enabled())
+ return;
+
+ Arguments args(tc);
+ char st[50];
+ CopyStringOut(tc, st, args[1], 50);
+
+ StringWrap name(tc->getSystemPtr()->name());
+ DPRINTF(Annotate, "Explict begin of state %s\n", st);
+ uint32_t flags = args[0];
+ if (flags & FL_BAD)
+ warn("BAD state encountered: at cycle %d: %s\n", curTick, st);
+ swBegin(tc->getSystemPtr(), tc->contextId(), st, getFrame(tc), true, args[0]);
+}
+
+void
+CPA::swAutoBegin(ThreadContext *tc, Addr next_pc)
+{
+ if (!enabled())
+ return;
+
+ string sym;
+ Addr sym_addr = 0;
+ SymbolTable *symtab = NULL;
+
+
+ if (!TheISA::inUserMode(tc)) {
+ debugSymbolTable->findNearestSymbol(next_pc, sym, sym_addr);
+ symtab = debugSymbolTable;
+ } else {
+ Linux::ThreadInfo ti(tc);
+ string app = ti.curTaskName();
+ if (userApp.count(app))
+ userApp[app]->findNearestSymbol(next_pc, sym, sym_addr);
+ }
+
+ if (sym_addr)
+ swBegin(tc->getSystemPtr(), tc->contextId(), sym, getFrame(tc));
+}
+
+void
+CPA::swBegin(System *sys, int cpuid, std::string st, uint64_t frame, bool expl,
+ int flags)
+{
+ int x = 0;
+ int len;
+ while (ignoreSymbols[x].len)
+ {
+ len = ignoreSymbols[x].len;
+ if (!st.compare(0,len, ignoreSymbols[x].symbol, len))
+ return;
+ x++;
+ }
+
+ int sysi = getSys(sys);
+ StackId sid = StackId(sysi, frame);
+ // if expl is true suspend symbol table based states
+ if (!smStack[sid].size())
+ return;
+ if (!expl && swExpl[sid])
+ return;
+ if (expl)
+ swExpl[sid] = true;
+ DPRINTFS(AnnotateVerbose, sys, "SwBegin: %s sysi: %d\n", st, sysi);
+ int smi = smStack[sid].back();
+ int sti = getSt(smMap[smi-1].second.first, st);
+ if (lastState[smi] != sti) {
+ lastState[smi] = sti;
+ add(OP_BEGIN, flags, cpuid, smi, sti);
+ }
+}
+
+void
+CPA::swEnd(ThreadContext *tc)
+{
+ if (!enabled())
+ return;
+
+ std::string st;
+ Addr junk;
+ if (!TheISA::inUserMode(tc))
+ debugSymbolTable->findNearestSymbol(
+ tc->readIntReg(ReturnAddressReg), st, junk);
+ System *sys = tc->getSystemPtr();
+ StringWrap name(sys->name());
+
+ int sysi = getSys(sys);
+ StackId sid = StackId(sysi, getFrame(tc));
+ if (!smStack[sid].size()) {
+ DPRINTF(Annotate, "Explict end of State: %s IGNORED\n", st);
+ return;
+ }
+ DPRINTF(Annotate, "Explict end of State: %s\n", st);
+ // return back to symbol table based states
+ swExpl[sid] = false;
+ int smi = smStack[sid].back();
+ if (st != "") {
+ int sti = getSt(smMap[smi-1].second.first, st);
+ lastState[smi] = sti;
+ add(OP_BEGIN, FL_NONE, tc->contextId(), smi, sti);
+ }
+}
+
+void
+CPA::swQ(ThreadContext *tc)
+{
+ if (!enabled())
+ return;
+
+ char q[50];
+ Arguments args(tc);
+ uint64_t id = args[0];
+ CopyStringOut(tc, q, args[1], 50);
+ int32_t count = args[2];
+ System *sys = tc->getSystemPtr();
+
+ int sysi = getSys(sys);
+ StackId sid = StackId(sysi, getFrame(tc));
+ if (!smStack[sid].size())
+ return;
+ int smi = smStack[sid].back();
+ if (swExpl[sid])
+ swExpl[sid] = false;
+ int qi = getQ(sysi, q, id);
+ if (count == 0) {
+ //warn("Tried to queue 0 bytes in %s, ignoring\n", q);
+ return;
+ }
+ DPRINTFS(AnnotateQ, sys,
+ "swQ: %s[%#x] cur size %d %d bytes: %d adding: %d\n",
+ q, id, qSize[qi-1], qData[qi-1].size(), qBytes[qi-1], count);
+ doQ(sys, FL_NONE, tc->contextId(), smi, q, qi, count);
+}
+
+void
+CPA::swDq(ThreadContext *tc)
+{
+ if (!enabled())
+ return;
+
+ char q[50];
+ Arguments args(tc);
+ uint64_t id = args[0];
+ CopyStringOut(tc, q, args[1], 50);
+ int32_t count = args[2];
+ System *sys = tc->getSystemPtr();
+
+ int sysi = getSys(sys);
+ StackId sid = StackId(sysi, getFrame(tc));
+ if (!smStack[sid].size())
+ return;
+ int smi = smStack[sid].back();
+ int qi = getQ(sysi, q, id);
+ if (swExpl[sid])
+ swExpl[sid] = false;
+ DPRINTFS(AnnotateQ, sys,
+ "swDq: %s[%#x] cur size %d %d bytes: %d removing: %d\n",
+ q, id, qSize[qi-1], qData[qi-1].size(), qBytes[qi-1], count);
+ assert(count != 0);
+
+ doDq(sys, FL_NONE, tc->contextId(), smi, q, qi, count);
+}
+
+void
+CPA::swPq(ThreadContext *tc)
+{
+ if (!enabled())
+ return;
+
+ char q[50];
+ Arguments args(tc);
+ uint64_t id = args[0];
+ CopyStringOut(tc, q, args[1], 50);
+ System *sys = tc->getSystemPtr();
+ int32_t count = args[2];
+
+ int sysi = getSys(sys);
+ StackId sid = StackId(sysi, getFrame(tc));
+ if (!smStack[sid].size())
+ return;
+ int smi = smStack[sid].back();
+ int qi = getQ(sysi, q, id);
+ if (swExpl[sid])
+ swExpl[sid] = false;
+ DPRINTFS(AnnotateQ, sys,
+ "swPq: %s [%#x] cur size %d %d bytes: %d peeking: %d\n",
+ q, id, qSize[qi-1], qData[qi-1].size(), qBytes[qi-1], count);
+
+ assert(count != 0);
+ if (qBytes[qi-1] < count) {
+ dump(true);
+ dumpKey();
+ fatal("Queue %s peeking with not enough bytes available in queue!\n", q);
+ }
+
+ add(OP_PEEK, FL_NONE, tc->contextId(), smi, qi, count);
+}
+
+void
+CPA::swRq(ThreadContext *tc)
+{
+ if (!enabled())
+ return;
+
+ char q[50];
+ Arguments args(tc);
+ uint64_t id = args[0];
+ CopyStringOut(tc, q, args[1], 50);
+ System *sys = tc->getSystemPtr();
+ int32_t count = args[2];
+
+ int sysi = getSys(sys);
+ StackId sid = StackId(sysi, getFrame(tc));
+ if (!smStack[sid].size())
+ return;
+ int smi = smStack[sid].back();
+ int qi = getQ(sysi, q, id);
+ if (swExpl[sid])
+ swExpl[sid] = false;
+ DPRINTFS(AnnotateQ, sys,
+ "swRq: %s [%#x] cur size %d %d bytes: %d reserve: %d\n",
+ q, id, qSize[qi-1], qData[qi-1].size(), qBytes[qi-1], count);
+
+ assert(count != 0);
+
+ add(OP_RESERVE, FL_NONE, tc->contextId(), smi, qi, count);
+}
+
+
+void
+CPA::swWf(ThreadContext *tc)
+{
+ if (!enabled())
+ return;
+
+ char q[50];
+ Arguments args(tc);
+ uint64_t id = args[0];
+ CopyStringOut(tc, q, args[1], 50);
+ System *sys = tc->getSystemPtr();
+ int32_t count = args[3];
+
+ int sysi = getSys(sys);
+ StackId sid = StackId(sysi, getFrame(tc));
+ if (!smStack[sid].size())
+ return;
+ int smi = smStack[sid].back();
+ int qi = getQ(sysi, q, id);
+ add(OP_WAIT_FULL, FL_NONE, tc->contextId(), smi, qi, count);
+
+ if (!!args[2]) {
+ char sm[50];
+ CopyStringOut(tc, sm, args[2], 50);
+ doSwSmEnd(tc->getSystemPtr(), tc->contextId(), sm, getFrame(tc));
+ }
+}
+
+void
+CPA::swWe(ThreadContext *tc)
+{
+ if (!enabled())
+ return;
+
+ char q[50];
+ Arguments args(tc);
+ uint64_t id = args[0];
+ CopyStringOut(tc, q, args[1], 50);
+ System *sys = tc->getSystemPtr();
+ int32_t count = args[3];
+
+ int sysi = getSys(sys);
+ StackId sid = StackId(sysi, getFrame(tc));
+ if (!smStack[sid].size())
+ return;
+ int smi = smStack[sid].back();
+ int qi = getQ(sysi, q, id);
+ add(OP_WAIT_EMPTY, FL_NONE, tc->contextId(), smi, qi, count);
+
+ if (!!args[2]) {
+ char sm[50];
+ CopyStringOut(tc, sm, args[2], 50);
+ doSwSmEnd(tc->getSystemPtr(), tc->contextId(), sm, getFrame(tc));
+ }
+}
+
+void
+CPA::swSq(ThreadContext *tc)
+{
+ if (!enabled())
+ return;
+
+ char q[50];
+ Arguments args(tc);
+ uint64_t id = args[0];
+ CopyStringOut(tc, q, args[1], 50);
+ System *sys = tc->getSystemPtr();
+ StringWrap name(sys->name());
+ int32_t size = args[2];
+ int flags = args[3];
+
+ int sysi = getSys(sys);
+ StackId sid = StackId(sysi, getFrame(tc));
+ if (!smStack[sid].size())
+ return;
+ int smi = smStack[sid].back();
+ int qi = getQ(sysi, q, id);
+ DPRINTF(AnnotateQ, "swSq: %s [%#x] cur size: %d bytes: %d, new size: %d\n",
+ q, id, qSize[qi-1], qBytes[qi-1], size);
+
+ if (FL_RESET & flags) {
+ DPRINTF(AnnotateQ, "Resetting Queue %s\n", q);
+ add(OP_SIZE_QUEUE, FL_NONE, tc->contextId(), smi, qi, 0);
+ qData[qi-1].clear();
+ qSize[qi-1] = 0;
+ qBytes[qi-1] = 0;
+ }
+
+ if (qBytes[qi-1] < size)
+ doQ(sys, FL_NONE, tc->contextId(), smi, q, qi, size - qBytes[qi-1]);
+ else if (qBytes[qi-1] > size) {
+ DPRINTF(AnnotateQ, "removing for resize of queue %s\n", q);
+ add(OP_SIZE_QUEUE, FL_NONE, tc->contextId(), smi, qi, size);
+ if (size <= 0) {
+ qData[qi-1].clear();
+ qSize[qi-1] = 0;
+ qBytes[qi-1] = 0;
+ return;
+ }
+ int need = qBytes[qi-1] - size;
+ qBytes[qi-1] = size;
+ while (need > 0) {
+ int32_t tail_bytes = qData[qi-1].back()->data;
+ if (qSize[qi-1] <= 0 || qBytes[qi-1] < 0) {
+ dump(true);
+ dumpKey();
+ fatal("Queue %s had inconsistancy when doing size queue!\n", q);
+ }
+ if (tail_bytes > need) {
+ qData[qi-1].back()->data -= need;
+ need = 0;
+ } else if (tail_bytes == need) {
+ qData[qi-1].pop_back();
+ qSize[qi-1]--;
+ need = 0;
+ } else {
+ qData[qi-1].pop_back();
+ qSize[qi-1]--;
+ need -= tail_bytes;
+ }
+ }
+ }
+}
+
+void
+CPA::swAq(ThreadContext *tc)
+{
+ if (!enabled())
+ return;
+
+ char q[50];
+ Arguments args(tc);
+ uint64_t id = args[0];
+ CopyStringOut(tc, q, args[1], 50);
+ System *sys = tc->getSystemPtr();
+ StringWrap name(sys->name());
+ int32_t size = args[2];
+
+ int sysi = getSys(sys);
+ int qi = getQ(sysi, q, id);
+ if (qBytes[qi-1] != size) {
+ DPRINTF(AnnotateQ, "Queue %s [%#x] has inconsintant size\n", q, id);
+ //dump(true);
+ //dumpKey();
+ std::list<AnnDataPtr>::iterator ai = qData[qi-1].begin();
+ int x = 0;
+ while (ai != qData[qi-1].end()) {
+ DPRINTF(AnnotateQ, "--Element %d size %d\n", x, (*ai)->data);
+ ai++;
+ x++;
+ }
+
+ warn("%d: Queue Assert: SW said there should be %d byte(s) in %s,"
+ "however there are %d byte(s)\n",
+ curTick, size, q, qBytes[qi-1]);
+ DPRINTF(AnnotateQ, "%d: Queue Assert: SW said there should be %d"
+ " byte(s) in %s, however there are %d byte(s)\n",
+ curTick, size, q, qBytes[qi-1]);
+ }
+}
+
+void
+CPA::swLink(ThreadContext *tc)
+{
+ if (!enabled())
+ return;
+
+ char lsm[50];
+ Arguments args(tc);
+ CopyStringOut(tc, lsm, args[0], 50);
+ System *sys = tc->getSystemPtr();
+ StringWrap name(sys->name());
+
+ int sysi = getSys(sys);
+ StackId sid = StackId(sysi, getFrame(tc));
+ if (!smStack[sid].size())
+ return;
+ int smi = smStack[sid].back();
+ int lsmi = getSm(sysi, lsm, args[1]);
+
+ DPRINTF(Annotate, "Linking from %d to state machine %s(%d) [%#x]\n",
+ smi, lsm, lsmi, args[1]);
+
+ if (lnMap[lsmi])
+ DPRINTF(Annotate, "LnMap already contains entry for %d of %d\n",
+ lsmi, lnMap[lsmi]);
+ assert(lnMap[lsmi] == 0);
+ lnMap[lsmi] = smi;
+
+ add(OP_LINK, FL_NONE, tc->contextId(), smi, lsmi);
+
+ if (!!args[2]) {
+ char sm[50];
+ CopyStringOut(tc, sm, args[2], 50);
+ doSwSmEnd(tc->getSystemPtr(), tc->contextId(), sm, getFrame(tc));
+ }
+}
+
+void
+CPA::swIdentify(ThreadContext *tc)
+{
+ if (!enabled())
+ return;
+
+ Arguments args(tc);
+ int sysi = getSys(tc->getSystemPtr());
+ StackId sid = StackId(sysi, getFrame(tc));
+ if (!smStack[sid].size())
+ return;
+ int smi = smStack[sid].back();
+
+ DPRINTFS(Annotate, tc->getSystemPtr(), "swIdentify: id %#X\n", args[0]);
+
+ add(OP_IDENT, FL_NONE, tc->contextId(), smi, 0, args[0]);
+}
+
+uint64_t
+CPA::swGetId(ThreadContext *tc)
+{
+ if (!enabled())
+ return 0;
+
+ uint64_t id = ++conId;
+ int sysi = getSys(tc->getSystemPtr());
+ StackId sid = StackId(sysi, getFrame(tc));
+ if (!smStack[sid].size())
+ panic("swGetId called without a state machine stack!");
+ int smi = smStack[sid].back();
+
+ DPRINTFS(Annotate, tc->getSystemPtr(), "swGetId: id %#X\n", id);
+
+ add(OP_IDENT, FL_NONE, tc->contextId(), smi, 0, id);
+ return id;
+}
+
+
+void
+CPA::swSyscallLink(ThreadContext *tc)
+{
+ if (!enabled())
+ return;
+
+ char lsm[50];
+ Arguments args(tc);
+ CopyStringOut(tc, lsm, args[0], 50);
+ System *sys = tc->getSystemPtr();
+ StringWrap name(sys->name());
+ int sysi = getSys(sys);
+
+ Id id = Id(lsm, getFrame(tc));
+ StackId sid = StackId(sysi, getFrame(tc));
+
+ if (!smStack[sid].size())
+ return;
+
+ int smi = smStack[sid].back();
+
+ DPRINTF(Annotate, "Linking from %d to state machine %s(UNKNOWN)\n",
+ smi, lsm);
+
+ if (scLinks[sysi-1][id])
+ DPRINTF(Annotate,
+ "scLinks already contains entry for system %d %s[%x] of %d\n",
+ sysi, lsm, getFrame(tc), scLinks[sysi-1][id]);
+ assert(scLinks[sysi-1][id] == 0);
+ scLinks[sysi-1][id] = add(OP_LINK, FL_NONE, tc->contextId(), smi, 0xFFFF);
+ scLinks[sysi-1][id]->dump = false;
+
+ if (!!args[1]) {
+ char sm[50];
+ CopyStringOut(tc, sm, args[1], 50);
+ doSwSmEnd(tc->getSystemPtr(), tc->contextId(), sm, getFrame(tc));
+ }
+}
+
+CPA::AnnDataPtr
+CPA::add(int t, int f, int c, int sm, int stq, int32_t d)
+{
+ AnnDataPtr an = new AnnotateData;
+ an->time = curTick;
+ an->data = d;
+ an->orig_data = d;
+ an->op = t;
+ an->flag = f;
+ an->sm = sm;
+ an->stq = stq;
+ an->cpu = c;
+ an->dump = true;
+
+ data.push_back(an);
+
+ DPRINTF(AnnotateVerbose, "Annotate: op: %d flags: 0x%x sm: %d state: %d time: %d, data: %d\n",
+ an->op, an->flag, an->sm, an->stq, an->time, an->data);
+
+ // Don't dump Links because we might be setting no-dump on it
+ if (an->op != OP_LINK)
+ dump(false);
+
+ return an;
+}
+
+void
+CPA::dumpKey()
+{
+ std::streampos curpos = osbin->tellp();
+ ah.key_off = curpos;
+
+ // Output the various state machines and their corresponding states
+ *osbin << "# Automatically generated state machine descriptor file" << endl;
+
+ *osbin << "sms = {}" << endl << endl;
+ vector<string> state_machines;
+ state_machines.resize(numSmt+1);
+
+ // State machines, id -> states
+ SCache::iterator i = smtCache.begin();
+ while (i != smtCache.end()) {
+ state_machines[i->second] = i->first;
+ i++;
+ }
+
+ for (int x = 1; x < state_machines.size(); x++) {
+ vector<string> states;
+ states.resize(numSt[x-1]+1);
+ assert(x-1 < stCache.size());
+ SCache::iterator i = stCache[x-1].begin();
+ while (i != stCache[x-1].end()) {
+ states[i->second] = i->first;
+ i++;
+ }
+ *osbin << "sms[\"" << state_machines[x] << "\"] = [\"NULL\"";
+ for (int y = 1; y < states.size(); y++)
+ *osbin << ", \"" << states[y] << "\"";
+ *osbin << "]" << endl;
+ }
+
+ *osbin << endl << endl << endl;
+
+ // state machine number -> system, name, id
+ *osbin << "smNum = [\"NULL\"";
+ for (int x = 0; x < smMap.size(); x++)
+ *osbin << ", (" << smMap[x].first << ", \"" << smMap[x].second.first <<
+ "\", " << smMap[x].second.second << ")";
+ *osbin << "]" << endl;
+
+ *osbin << endl << endl << endl;
+
+ // Output the systems
+ vector<string> systems;
+ systems.resize(numSys+1);
+ NameCache::iterator i2 = nameCache.begin();
+ while (i2 != nameCache.end()) {
+ systems[i2->second.second] = i2->second.first;
+ i2++;
+ }
+
+ *osbin << "sysNum = [\"NULL\"";
+ for (int x = 1; x < systems.size(); x++) {
+ *osbin << ", \"" << systems[x] << "\"";
+ }
+ *osbin << "]" << endl;
+
+ // queue number -> system, qname, qid
+ *osbin << "queues = [\"NULL\"";
+ for (int x = 0; x < qMap.size(); x++)
+ *osbin << ", (" << qMap[x].first << ", \"" << qMap[x].second.first <<
+ "\", " << qMap[x].second.second << ")";
+ *osbin << "]" << endl;
+
+ *osbin << "smComb = [s for s in [(i,r) for i in xrange(1,len(sysNum)) "
+ << "for r in xrange (1,len(smNum))]]" << endl;
+ ah.key_len = osbin->tellp() - curpos;
+
+ // output index
+ curpos = osbin->tellp();
+ ah.idx_off = curpos;
+
+ for (int x = 0; x < annotateIdx.size(); x++)
+ osbin->write((char*)&annotateIdx[x], sizeof(uint64_t));
+ ah.idx_len = osbin->tellp() - curpos;
+
+ osbin->seekp(0);
+ osbin->write((char*)&ah, sizeof(AnnotateHeader));
+ osbin->flush();
+
+}
+
+void
+CPA::dump(bool all)
+{
+
+ list<AnnDataPtr>::iterator i;
+
+ i = data.begin();
+
+ if (i == data.end())
+ return;
+
+ // Dump the data every
+ if (!all && data.size() < 10000)
+ return;
+
+ DPRINTF(Annotate, "Writing %d\n", data.size());
+ while (i != data.end()) {
+ AnnDataPtr an = *i;
+
+ // If we can't dump this record, hold here
+ if (!an->dump && !all)
+ break;
+
+ ah.num_recs++;
+ if (ah.num_recs % 100000 == 0)
+ annotateIdx.push_back(osbin->tellp());
+
+
+ osbin->write((char*)&(an->time), sizeof(an->time));
+ osbin->write((char*)&(an->orig_data), sizeof(an->orig_data));
+ osbin->write((char*)&(an->sm), sizeof(an->sm));
+ osbin->write((char*)&(an->stq), sizeof(an->stq));
+ osbin->write((char*)&(an->op), sizeof(an->op));
+ osbin->write((char*)&(an->flag), sizeof(an->flag));
+ osbin->write((char*)&(an->cpu), sizeof(an->cpu));
+ i++;
+ }
+ if (data.begin() != i)
+ data.erase(data.begin(), i);
+
+ if (all)
+ osbin->flush();
+}
+
+void
+CPA::doQ(System *sys, int flags, int cpuid, int sm,
+ string q, int qi, int count)
+{
+ qSize[qi-1]++;
+ qBytes[qi-1] += count;
+ if (qSize[qi-1] > 2501 || qBytes[qi-1] > 2000000000)
+ warn("Queue %s is %d elements/%d bytes, "
+ "maybe things aren't being removed?\n",
+ q, qSize[qi-1], qBytes[qi-1]);
+ if (flags & FL_QOPP)
+ qData[qi-1].push_front(add(OP_QUEUE, flags, cpuid, sm, qi, count));
+ else
+ qData[qi-1].push_back(add(OP_QUEUE, flags, cpuid, sm, qi, count));
+ DPRINTFS(AnnotateQ, sys, "Queing in queue %s size now %d/%d\n",
+ q, qSize[qi-1], qBytes[qi-1]);
+ assert(qSize[qi-1] >= 0);
+ assert(qBytes[qi-1] >= 0);
+}
+
+
+void
+CPA::doDq(System *sys, int flags, int cpuid, int sm,
+ string q, int qi, int count)
+{
+
+ StringWrap name(sys->name());
+ if (count == -1) {
+ add(OP_DEQUEUE, flags, cpuid, sm, qi, count);
+ qData[qi-1].clear();
+ qSize[qi-1] = 0;
+ qBytes[qi-1] = 0;
+ DPRINTF(AnnotateQ, "Dequeing all data in queue %s size now %d/%d\n",
+ q, qSize[qi-1], qBytes[qi-1]);
+ return;
+ }
+
+ assert(count > 0);
+ if (qSize[qi-1] <= 0 || qBytes[qi-1] <= 0 || !qData[qi-1].size()) {
+ dump(true);
+ dumpKey();
+ fatal("Queue %s dequing with no data available in queue!\n",
+ q);
+ }
+ assert(qSize[qi-1] >= 0);
+ assert(qBytes[qi-1] >= 0);
+ assert(qData[qi-1].size());
+
+ int32_t need = count;
+ qBytes[qi-1] -= count;
+ if (qBytes[qi-1] < 0) {
+ dump(true);
+ dumpKey();
+ fatal("Queue %s dequing with no bytes available in queue!\n",
+ q);
+ }
+
+ while (need > 0) {
+ int32_t head_bytes = qData[qi-1].front()->data;
+ if (qSize[qi-1] <= 0 || qBytes[qi-1] < 0) {
+ dump(true);
+ dumpKey();
+ fatal("Queue %s dequing with nothing in queue!\n",
+ q);
+ }
+
+ if (head_bytes > need) {
+ qData[qi-1].front()->data -= need;
+ need = 0;
+ } else if (head_bytes == need) {
+ qData[qi-1].pop_front();
+ qSize[qi-1]--;
+ need = 0;
+ } else {
+ qData[qi-1].pop_front();
+ qSize[qi-1]--;
+ need -= head_bytes;
+ }
+ }
+
+ add(OP_DEQUEUE, flags, cpuid, sm, qi, count);
+ DPRINTF(AnnotateQ, "Dequeing in queue %s size now %d/%d\n",
+ q, qSize[qi-1], qBytes[qi-1]);
+}
+
+
+
+void
+CPA::serialize(std::ostream &os)
+{
+
+ SERIALIZE_SCALAR(numSm);
+ SERIALIZE_SCALAR(numSmt);
+ arrayParamOut(os, "numSt", numSt);
+ arrayParamOut(os, "numQ", numQ);
+ SERIALIZE_SCALAR(numSys);
+ SERIALIZE_SCALAR(numQs);
+ SERIALIZE_SCALAR(conId);
+ arrayParamOut(os, "qSize", qSize);
+ arrayParamOut(os, "qSize", qSize);
+ arrayParamOut(os, "qBytes", qBytes);
+
+ std::list<AnnDataPtr>::iterator ai;
+
+ SCache::iterator i;
+ int x = 0, y = 0;
+
+ // smtCache (SCache)
+ x = 0;
+ y = 0;
+ i = smtCache.begin();
+ while (i != smtCache.end()) {
+ paramOut(os, csprintf("smtCache%d.str", x), i->first);
+ paramOut(os, csprintf("smtCache%d.int", x), i->second);
+ x++; i++;
+ }
+
+ // stCache (StCache)
+ for (x = 0; x < stCache.size(); x++) {
+ i = stCache[x].begin();
+ y = 0;
+ while (i != stCache[x].end()) {
+ paramOut(os, csprintf("stCache%d_%d.str", x, y), i->first);
+ paramOut(os, csprintf("stCache%d_%d.int", x, y), i->second);
+ y++; i++;
+ }
+ }
+
+ // qCache (IdCache)
+ IdHCache::iterator idi;
+ for (x = 0; x < qCache.size(); x++) {
+ idi = qCache[x].begin();
+ y = 0;
+ while (idi != qCache[x].end()) {
+ paramOut(os, csprintf("qCache%d_%d.str", x, y), idi->first.first);
+ paramOut(os, csprintf("qCache%d_%d.id", x, y), idi->first.second);
+ paramOut(os, csprintf("qCache%d_%d.int", x, y), idi->second);
+ y++; idi++;
+ }
+ }
+
+ // smCache (IdCache)
+ for (x = 0; x < smCache.size(); x++) {
+ idi = smCache[x].begin();
+ y = 0;
+ paramOut(os, csprintf("smCache%d", x), smCache[x].size());
+ while (idi != smCache[x].end()) {
+ paramOut(os, csprintf("smCache%d_%d.str", x, y), idi->first.first);
+ paramOut(os, csprintf("smCache%d_%d.id", x, y), idi->first.second);
+ paramOut(os, csprintf("smCache%d_%d.int", x, y), idi->second);
+ y++; idi++;
+ }
+ }
+
+ // scLinks (ScCache) -- data not serialize
+
+
+ // namecache (NameCache)
+ NameCache::iterator ni;
+
+ ni = nameCache.begin();
+ x = 0;
+ while (ni != nameCache.end()) {
+ paramOut(os, csprintf("nameCache%d.name", x), ni->first->name());
+ paramOut(os, csprintf("nameCache%d.str", x), ni->second.first);
+ paramOut(os, csprintf("nameCache%d.int", x), ni->second.second);
+ x++; ni++;
+ }
+
+ // smStack (SmStack)
+ SmStack::iterator si;
+ si = smStack.begin();
+ x = 0;
+ paramOut(os, "smStackIdCount", smStack.size());
+ while (si != smStack.end()) {
+ paramOut(os, csprintf("smStackId%d.sys", x), si->first.first);
+ paramOut(os, csprintf("smStackId%d.frame", x), si->first.second);
+ paramOut(os, csprintf("smStackId%d.count", x), si->second.size());
+ for (y = 0; y < si->second.size(); y++)
+ paramOut(os, csprintf("smStackId%d_%d", x, y), si->second[y]);
+ x++; si++;
+ }
+
+ // lnMap (LinkMap)
+ x = 0;
+ LinkMap::iterator li;
+ li = lnMap.begin();
+ paramOut(os, "lnMapSize", lnMap.size());
+ while (li != lnMap.end()) {
+ paramOut(os, csprintf("lnMap%d.smi", x), li->first);
+ paramOut(os, csprintf("lnMap%d.lsmi", x), li->second);
+ x++; li++;
+ }
+
+ // swExpl (vector)
+ SwExpl::iterator swexpli;
+ swexpli = swExpl.begin();
+ x = 0;
+ paramOut(os, "swExplCount", swExpl.size());
+ while (swexpli != swExpl.end()) {
+ paramOut(os, csprintf("swExpl%d.sys", x), swexpli->first.first);
+ paramOut(os, csprintf("swExpl%d.frame", x), swexpli->first.second);
+ paramOut(os, csprintf("swExpl%d.swexpl", x), swexpli->second);
+ x++; swexpli++;
+ }
+
+ // lastState (IMap)
+ x = 0;
+ IMap::iterator ii;
+ ii = lastState.begin();
+ paramOut(os, "lastStateSize", lastState.size());
+ while (ii != lastState.end()) {
+ paramOut(os, csprintf("lastState%d.smi", x), ii->first);
+ paramOut(os, csprintf("lastState%d.sti", x), ii->second);
+ x++; ii++;
+ }
+
+ // smMap (IdMap)
+ for (x = 0; x < smMap.size(); x++) {
+ paramOut(os, csprintf("smMap%d.sys", x), smMap[x].first);
+ paramOut(os, csprintf("smMap%d.smname", x), smMap[x].second.first);
+ paramOut(os, csprintf("smMap%d.id", x), smMap[x].second.second);
+ }
+
+ // qMap (IdMap)
+ for (x = 0; x < qMap.size(); x++) {
+ paramOut(os, csprintf("qMap%d.sys", x), qMap[x].first);
+ paramOut(os, csprintf("qMap%d.qname", x), qMap[x].second.first);
+ paramOut(os, csprintf("qMap%d.id", x), qMap[x].second.second);
+ }
+
+ // qData (vector<AnnotateList>)
+ for(x = 0; x < qData.size(); x++) {
+ if (!qData[x].size())
+ continue;
+ y = 0;
+ ai = qData[x].begin();
+ while (ai != qData[x].end()) {
+ nameOut(os, csprintf("%s.Q%d_%d", name(), x, y));
+ (*ai)->serialize(os);
+ ai++;
+ y++;
+ }
+ }
+}
+
+void
+CPA::unserialize(Checkpoint *cp, const std::string &section)
+{
+ UNSERIALIZE_SCALAR(numSm);
+ UNSERIALIZE_SCALAR(numSmt);
+ arrayParamIn(cp, section, "numSt", numSt);
+ arrayParamIn(cp, section, "numQ", numQ);
+ UNSERIALIZE_SCALAR(numSys);
+ UNSERIALIZE_SCALAR(numQs);
+ UNSERIALIZE_SCALAR(conId);
+ arrayParamIn(cp, section, "qSize", qSize);
+ arrayParamIn(cp, section, "qBytes", qBytes);
+
+
+ // smtCache (SCache
+ string str;
+ int smi;
+ for (int x = 0; x < numSmt; x++) {
+ paramIn(cp, section, csprintf("smtCache%d.str", x), str);
+ paramIn(cp, section, csprintf("smtCache%d.int", x), smi);
+ smtCache[str] = smi;
+ }
+
+ // stCache (StCache)
+ stCache.resize(numSmt);
+ for (int x = 0; x < numSmt; x++) {
+ for (int y = 0; y < numSt[x]; y++) {
+ paramIn(cp, section, csprintf("stCache%d_%d.str", x,y), str);
+ paramIn(cp, section, csprintf("stCache%d_%d.int", x,y), smi);
+ stCache[x][str] = smi;
+ }
+ }
+
+ // qCache (IdCache)
+ uint64_t id;
+ qCache.resize(numSys);
+ for (int x = 0; x < numSys; x++) {
+ for (int y = 0; y < numQ[x]; y++) {
+ paramIn(cp, section, csprintf("qCache%d_%d.str", x,y), str);
+ paramIn(cp, section, csprintf("qCache%d_%d.id", x,y), id);
+ paramIn(cp, section, csprintf("qCache%d_%d.int", x,y), smi);
+ qCache[x][Id(str,id)] = smi;
+ }
+ }
+
+ // smCache (IdCache)
+ smCache.resize(numSys);
+ for (int x = 0; x < numSys; x++) {
+ int size;
+ paramIn(cp, section, csprintf("smCache%d", x), size);
+ for (int y = 0; y < size; y++) {
+ paramIn(cp, section, csprintf("smCache%d_%d.str", x,y), str);
+ paramIn(cp, section, csprintf("smCache%d_%d.id", x,y), id);
+ paramIn(cp, section, csprintf("smCache%d_%d.int", x,y), smi);
+ smCache[x][Id(str,id)] = smi;
+ }
+ }
+
+ // scLinks (ScCache) -- data not serialized, just creating one per sys
+ for (int x = 0; x < numSys; x++)
+ scLinks.push_back(ScHCache());
+
+ // nameCache (NameCache)
+ for (int x = 0; x < numSys; x++) {
+ System *sys;
+ SimObject *sptr;
+ string str;
+ int sysi;
+
+ objParamIn(cp, section, csprintf("nameCache%d.name", x), sptr);
+ sys = dynamic_cast<System*>(sptr);
+
+ paramIn(cp, section, csprintf("nameCache%d.str", x), str);
+ paramIn(cp, section, csprintf("nameCache%d.int", x), sysi);
+ nameCache[sys] = std::make_pair<std::string,int>(str, sysi);
+ }
+
+ //smStack (SmStack)
+ int smStack_size;
+ paramIn(cp, section, "smStackIdCount", smStack_size);
+ for (int x = 0; x < smStack_size; x++) {
+ int sysi;
+ uint64_t frame;
+ int count;
+ paramIn(cp, section, csprintf("smStackId%d.sys", x), sysi);
+ paramIn(cp, section, csprintf("smStackId%d.frame", x), frame);
+ paramIn(cp, section, csprintf("smStackId%d.count", x), count);
+ StackId sid = StackId(sysi, frame);
+ for (int y = 0; y < count; y++) {
+ paramIn(cp, section, csprintf("smStackId%d_%d", x, y), smi);
+ smStack[sid].push_back(smi);
+ }
+ }
+
+ // lnMap (LinkMap)
+ int lsmi;
+ int lnMap_size;
+ paramIn(cp, section, "lnMapSize", lnMap_size);
+ for (int x = 0; x < lnMap_size; x++) {
+ paramIn(cp, section, csprintf("lnMap%d.smi", x), smi);
+ paramIn(cp, section, csprintf("lnMap%d.lsmi", x), lsmi);
+ lnMap[smi] = lsmi;
+ }
+
+ // swExpl (vector)
+ int swExpl_size;
+ paramIn(cp, section, "swExplCount", swExpl_size);
+ for (int x = 0; x < swExpl_size; x++) {
+ int sysi;
+ uint64_t frame;
+ bool b;
+ paramIn(cp, section, csprintf("swExpl%d.sys", x), sysi);
+ paramIn(cp, section, csprintf("swExpl%d.frame", x), frame);
+ paramIn(cp, section, csprintf("swExpl%d.swexpl", x), b);
+ StackId sid = StackId(sysi, frame);
+ swExpl[sid] = b;
+ }
+
+ // lastState (IMap)
+ int sti;
+ int lastState_size;
+ paramIn(cp, section, "lastStateSize", lastState_size);
+ for (int x = 0; x < lastState_size; x++) {
+ paramIn(cp, section, csprintf("lastState%d.smi", x), smi);
+ paramIn(cp, section, csprintf("lastState%d.sti", x), sti);
+ lastState[smi] = sti;
+ }
+
+
+ //smMap (IdMap)
+ smMap.resize(numSm);
+ for (int x = 0; x < smMap.size(); x++) {
+ paramIn(cp, section, csprintf("smMap%d.sys", x), smMap[x].first);
+ paramIn(cp, section, csprintf("smMap%d.smname", x), smMap[x].second.first);
+ paramIn(cp, section, csprintf("smMap%d.id", x), smMap[x].second.second);
+ }
+
+ //qMap (IdMap)
+ qMap.resize(numQs);
+ for (int x = 0; x < qMap.size(); x++) {
+ paramIn(cp, section, csprintf("qMap%d.sys", x), qMap[x].first);
+ paramIn(cp, section, csprintf("qMap%d.qname", x), qMap[x].second.first);
+ paramIn(cp, section, csprintf("qMap%d.id", x), qMap[x].second.second);
+ }
+
+
+ // qData (vector<AnnotateList>)
+ qData.resize(qSize.size());
+ for (int x = 0; x < qSize.size(); x++) {
+ if (!qSize[x])
+ continue;
+ for (int y = 0; y < qSize[x]; y++) {
+ AnnDataPtr a = new AnnotateData;
+ a->unserialize(cp, csprintf("%s.Q%d_%d", section, x, y));
+ data.push_back(a);
+ qData[x].push_back(a);
+ }
+ }
+}
+
+void
+CPA::AnnotateData::serialize(std::ostream &os)
+{
+ SERIALIZE_SCALAR(time);
+ SERIALIZE_SCALAR(data);
+ SERIALIZE_SCALAR(sm);
+ SERIALIZE_SCALAR(stq);
+ SERIALIZE_SCALAR(op);
+ SERIALIZE_SCALAR(flag);
+ SERIALIZE_SCALAR(cpu);
+}
+
+void
+CPA::AnnotateData::unserialize(Checkpoint *cp, const std::string &section)
+{
+ UNSERIALIZE_SCALAR(time);
+ UNSERIALIZE_SCALAR(data);
+ orig_data = data;
+ UNSERIALIZE_SCALAR(sm);
+ UNSERIALIZE_SCALAR(stq);
+ UNSERIALIZE_SCALAR(op);
+ UNSERIALIZE_SCALAR(flag);
+ UNSERIALIZE_SCALAR(cpu);
+ dump = true;
+}
+
+CPA*
+CPAParams::create()
+{
+ return new CPA(this);
+}
+
diff --git a/src/base/cp_annotate.hh b/src/base/cp_annotate.hh
new file mode 100644
index 000000000..13ced82de
--- /dev/null
+++ b/src/base/cp_annotate.hh
@@ -0,0 +1,522 @@
+/*
+ * Copyright (c) 2006-2009 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Ali Saidi
+ */
+
+#ifndef __BASE__CP_ANNOTATE_HH__
+#define __BASE__CP_ANNOTATE_HH__
+
+#include "base/loader/symtab.hh"
+#include "config/cp_annotate.hh"
+#include "sim/host.hh"
+#include "sim/serialize.hh"
+#include "sim/startup.hh"
+#include "sim/system.hh"
+
+#include <string>
+#include <list>
+#include <vector>
+#include <map>
+#include "base/hashmap.hh"
+#include "base/trace.hh"
+#if CP_ANNOTATE
+#include "params/CPA.hh"
+#endif
+
+class System;
+class ThreadContext;
+
+
+#if !CP_ANNOTATE
+class CPA
+{
+ public:
+ enum flags {
+ FL_NONE = 0x00,
+ FL_HW = 0x01,
+ FL_BAD = 0x02,
+ FL_QOPP = 0x04,
+ FL_WAIT = 0x08,
+ FL_LINK = 0x10,
+ FL_RESET = 0x20
+ };
+
+ static CPA *cpa() { return NULL; }
+ static bool available() { return false; }
+ bool enabled() { return false; }
+ void swSmBegin(ThreadContext *tc) { return; }
+ void swSmEnd(ThreadContext *tc) { return; }
+ void swExplictBegin(ThreadContext *tc) { return; }
+ void swAutoBegin(ThreadContext *tc, Addr next_pc) { return; }
+ void swEnd(ThreadContext *tc) { return; }
+ void swQ(ThreadContext *tc) { return; }
+ void swDq(ThreadContext *tc) { return; }
+ void swPq(ThreadContext *tc) { return; }
+ void swRq(ThreadContext *tc) { return; }
+ void swWf(ThreadContext *tc) { return; }
+ void swWe(ThreadContext *tc) { return; }
+ void swSq(ThreadContext *tc) { return; }
+ void swAq(ThreadContext *tc) { return; }
+ void swLink(ThreadContext *tc) { return; }
+ void swIdentify(ThreadContext *tc) { return; }
+ uint64_t swGetId(ThreadContext *tc) { return 0; }
+ void swSyscallLink(ThreadContext *tc) { return; }
+ void hwBegin(flags f, System *sys, uint64_t frame, std::string sm,
+ std::string st) { return; }
+ void hwQ(flags f, System *sys, uint64_t frame, std::string sm,
+ std::string q, uint64_t qid, System *q_sys = NULL,
+ int32_t count = 1) { return; }
+ void hwDq(flags f, System *sys, uint64_t frame, std::string sm,
+ std::string q, uint64_t qid, System *q_sys = NULL,
+ int32_t count = 1) { return; }
+ void hwPq(flags f, System *sys, uint64_t frame, std::string sm,
+ std::string q, uint64_t qid, System *q_sys = NULL,
+ int32_t count = 1) { return; }
+ void hwRq(flags f, System *sys, uint64_t frame, std::string sm,
+ std::string q, uint64_t qid, System *q_sys = NULL,
+ int32_t count = 1) { return; }
+ void hwWf(flags f, System *sys, uint64_t frame, std::string sm,
+ std::string q, uint64_t qid, System *q_sys = NULL,
+ int32_t count = 1) { return; }
+ void hwWe(flags f, System *sys, uint64_t frame, std::string sm,
+ std::string q, uint64_t qid, System *q_sys = NULL,
+ int32_t count = 1) { return; }
+};
+#else
+class CPA : SimObject
+{
+ public:
+ typedef CPAParams Params;
+
+ /** The known operations that are written to the annotation output file. */
+ enum ops {
+ OP_BEGIN = 0x01,
+ OP_WAIT_EMPTY = 0x02,
+ OP_WAIT_FULL = 0x03,
+ OP_QUEUE = 0x04,
+ OP_DEQUEUE = 0x05,
+ OP_SIZE_QUEUE = 0x08,
+ OP_PEEK = 0x09,
+ OP_LINK = 0x0A,
+ OP_IDENT = 0x0B,
+ OP_RESERVE = 0x0C
+ };
+
+ /** Flags for the various options.*/
+ enum flags {
+ /* no flags */
+ FL_NONE = 0x00,
+ /* operation was done on hardware */
+ FL_HW = 0x01,
+ /* operation should cause a warning when encountered */
+ FL_BAD = 0x02,
+ /* Queue like a stack, not a queue */
+ FL_QOPP = 0x04,
+ /* Mark HW state as waiting for some non-resource constraint
+ * (e.g. wait because SM only starts after 10 items are queued) */
+ FL_WAIT = 0x08,
+ /* operation is linking to another state machine */
+ FL_LINK = 0x10,
+ /* queue should be completely cleared/reset before executing this
+ * operation */
+ FL_RESET = 0x20
+ };
+
+
+
+ protected:
+ const Params *
+ params() const
+ {
+ return dynamic_cast<const Params *>(_params);
+ }
+
+ /* struct that is written to the annotation output file */
+ struct AnnotateData : public RefCounted {
+
+ Tick time;
+ uint32_t data;
+ uint32_t orig_data;
+ uint16_t sm;
+ uint16_t stq;
+ uint8_t op;
+ uint8_t flag;
+ uint8_t cpu;
+ bool dump;
+
+ void serialize(std::ostream &os);
+ void unserialize(Checkpoint *cp, const std::string &section);
+
+ };
+
+ typedef RefCountingPtr<AnnotateData> AnnDataPtr;
+
+ /* header for the annotation file */
+ struct AnnotateHeader {
+ uint64_t version;
+ uint64_t num_recs;
+ uint64_t key_off;
+ uint64_t idx_off;
+ uint32_t key_len;
+ uint32_t idx_len;
+ };
+
+ AnnotateHeader ah;
+
+ std::vector<uint64_t> annotateIdx;
+
+ // number of state machines encountered in the simulation
+ int numSm;
+ // number of states encountered in the simulation
+ int numSmt;
+ // number of states/queues for a given state machine/system respectively
+ std::vector<int> numSt, numQ;
+ // number of systems in the simulation
+ int numSys;
+ // number of queues in the state machine
+ int numQs;
+ // maximum connection id assigned so far
+ uint64_t conId;
+
+ // Convert state strings into state ids
+ typedef m5::hash_map<std::string, int> SCache;
+ typedef std::vector<SCache> StCache;
+
+ // Convert sm and queue name,id into queue id
+ typedef std::pair<std::string, uint64_t> Id;
+ typedef m5::hash_map<Id, int> IdHCache;
+ typedef std::vector<IdHCache> IdCache;
+
+ // Hold mapping of sm and queues to output python
+ typedef std::vector<std::pair<int, Id> > IdMap;
+
+ // System pointer to name,id
+ typedef std::map<System*, std::pair<std::string, int> > NameCache;
+
+ // array of systems each of which is a stack of running sm
+ typedef std::pair<int, uint64_t> StackId;
+ typedef std::map<StackId, std::vector<int> > SmStack;
+
+ // map of each context and if it's currently in explict state mode
+ // states are not automatically updated until it leaves
+ typedef std::map<StackId, bool> SwExpl;
+
+ typedef std::map<int,int> IMap;
+ // List of annotate records have not been written/completed yet
+ typedef std::list<AnnDataPtr> AnnotateList;
+
+ // Maintain link state information
+ typedef std::map<int, int> LinkMap;
+
+ // SC Links
+ typedef m5::hash_map<Id, AnnDataPtr> ScHCache;
+ typedef std::vector<ScHCache> ScCache;
+
+
+ AnnotateList data;
+
+ // vector indexed by queueid to find current number of elements and bytes
+ std::vector<int> qSize;
+ std::vector<int32_t> qBytes;
+
+
+ // Turn state machine string into state machine id (small int)
+ // Used for outputting key to convert id back into string
+ SCache smtCache;
+ // Turn state machine id, state name into state id (small int)
+ StCache stCache;
+ // turn system, queue, and queue identify into qid (small int)
+ // turn system, state, and context into state machine id (small int)
+ IdCache qCache, smCache;
+ //Link state machines accross system calls
+ ScCache scLinks;
+ // System pointer to name,id
+ NameCache nameCache;
+ // Stack of state machines currently nested (should unwind correctly)
+ SmStack smStack;
+ // Map of currently outstanding links
+ LinkMap lnMap;
+ // If the state machine is currently exculding automatic changes
+ SwExpl swExpl;
+ // Last state that a given state machine was in
+ IMap lastState;
+ // Hold mapping of sm and queues to output python
+ IdMap smMap, qMap;
+ // Items still in queue, used for sanity checking
+ std::vector<AnnotateList> qData;
+
+ void doDq(System *sys, int flags, int cpu, int sm, std::string q, int qi,
+ int count);
+ void doQ(System *sys, int flags, int cpu, int sm, std::string q, int qi,
+ int count);
+
+ void doSwSmEnd(System *sys, int cpuid, std::string sm, uint64_t frame);
+
+ // Turn a system id, state machine string, state machine id into a small int
+ // for annotation output
+ int
+ getSm(int sysi, std::string si, uint64_t id)
+ {
+ int smi;
+ Id smid = Id(si, id);
+
+ smi = smCache[sysi-1][smid];
+ if (smi == 0) {
+ smCache[sysi-1][smid] = smi = ++numSm;
+ assert(smi < 65535);
+ smMap.push_back(std::make_pair<int, Id>(sysi, smid));
+ }
+ return smi;
+ }
+
+ // Turn a state machine string, state string into a small int
+ // for annotation output
+ int
+ getSt(std::string sm, std::string s)
+ {
+ int sti, smi;
+
+ smi = smtCache[sm];
+ if (smi == 0)
+ smi = smtCache[sm] = ++numSmt;
+
+ while (stCache.size() < smi) {
+ //stCache.resize(sm);
+ stCache.push_back(SCache());
+ numSt.push_back(0);
+ }
+ //assert(stCache.size() == sm);
+ //assert(numSt.size() == sm);
+ sti = stCache[smi-1][s];
+ if (sti == 0)
+ stCache[smi-1][s] = sti = ++numSt[smi-1];
+ return sti;
+ }
+
+ // Turn state machine pointer into a smal int for annotation output
+ int
+ getSys(System *s)
+ {
+ NameCache::iterator i = nameCache.find(s);
+ if (i == nameCache.end()) {
+ nameCache[s] = std::make_pair<std::string,int>(s->name(), ++numSys);
+ i = nameCache.find(s);
+ // might need to put smstackid into map here, but perhaps not
+ //smStack.push_back(std::vector<int>());
+ //swExpl.push_back(false);
+ numQ.push_back(0);
+ qCache.push_back(IdHCache());
+ smCache.push_back(IdHCache());
+ scLinks.push_back(ScHCache());
+ }
+ return i->second.second;
+ }
+
+ // Turn queue name, and queue context into small int for
+ // annotation output
+ int
+ getQ(int sys, std::string q, uint64_t id)
+ {
+ int qi;
+ Id qid = Id(q, id);
+
+ qi = qCache[sys-1][qid];
+ if (qi == 0) {
+ qi = qCache[sys-1][qid] = ++numQs;
+ assert(qi < 65535);
+ qSize.push_back(0);
+ qBytes.push_back(0);
+ qData.push_back(AnnotateList());
+ numQ[sys-1]++;
+ qMap.push_back(std::make_pair<int, Id>(sys, qid));
+ }
+ return qi;
+ }
+
+ void swBegin(System *sys, int cpuid, std::string st, uint64_t frame,
+ bool expl = false, int flags = FL_NONE);
+
+ AnnDataPtr add(int t, int f, int c, int sm, int stq, int32_t data=0);
+
+ std::ostream *osbin;
+
+ bool _enabled;
+
+ /** Only allow one CPA object in a system. It doesn't make sense to have
+ * more that one per simulation because if a part of the system was
+ * important it would have annotations and queues, and with more than one
+ * object none of the sanity checking for queues will work. */
+ static bool exists;
+ static CPA *_cpa;
+
+
+ std::map<std::string, SymbolTable*> userApp;
+
+ public:
+ static CPA *cpa() { return _cpa; }
+ void swSmBegin(ThreadContext *tc);
+ void swSmEnd(ThreadContext *tc);
+ void swExplictBegin(ThreadContext *tc);
+ void swAutoBegin(ThreadContext *tc, Addr next_pc);
+ void swEnd(ThreadContext *tc);
+ void swQ(ThreadContext *tc);
+ void swDq(ThreadContext *tc);
+ void swPq(ThreadContext *tc);
+ void swRq(ThreadContext *tc);
+ void swWf(ThreadContext *tc);
+ void swWe(ThreadContext *tc);
+ void swSq(ThreadContext *tc);
+ void swAq(ThreadContext *tc);
+ void swLink(ThreadContext *tc);
+ void swIdentify(ThreadContext *tc);
+ uint64_t swGetId(ThreadContext *tc);
+ void swSyscallLink(ThreadContext *tc);
+
+ inline void hwBegin(flags f, System *sys, uint64_t frame, std::string sm,
+ std::string st)
+ {
+ if (!enabled())
+ return;
+
+ int sysi = getSys(sys);
+ int smi = getSm(sysi, sm, frame);
+ add(OP_BEGIN, FL_HW | f, 0, smi, getSt(sm, st));
+ if (f & FL_BAD)
+ warn("BAD state encountered: at cycle %d: %s\n", curTick, st);
+ }
+
+ inline void hwQ(flags f, System *sys, uint64_t frame, std::string sm,
+ std::string q, uint64_t qid, System *q_sys = NULL, int32_t count = 1)
+ {
+ if (!enabled())
+ return;
+
+ int sysi = getSys(sys);
+ int qi = getQ(q_sys ? getSys(q_sys) : sysi, q, qid);
+ DPRINTFS(AnnotateQ, sys,
+ "hwQ: %s[%#x] cur size %d %d bytes: %d adding: %d\n",
+ q, qid, qSize[qi-1], qData[qi-1].size(), qBytes[qi-1], count);
+ doQ(sys, FL_HW | f, 0, getSm(sysi, sm, frame), q, qi, count);
+
+ }
+
+ inline void hwDq(flags f, System *sys, uint64_t frame, std::string sm,
+ std::string q, uint64_t qid, System *q_sys = NULL, int32_t count = 1)
+ {
+ if (!enabled())
+ return;
+
+ int sysi = getSys(sys);
+ int qi = getQ(q_sys ? getSys(q_sys) : sysi, q, qid);
+ DPRINTFS(AnnotateQ, sys,
+ "hwDQ: %s[%#x] cur size %d %d bytes: %d removing: %d\n",
+ q, qid, qSize[qi-1], qData[qi-1].size(), qBytes[qi-1], count);
+ doDq(sys, FL_HW | f, 0, getSm(sysi,sm, frame), q, qi, count);
+ }
+
+ inline void hwPq(flags f, System *sys, uint64_t frame, std::string sm,
+ std::string q, uint64_t qid, System *q_sys = NULL, int32_t count = 1)
+ {
+ if (!enabled())
+ return;
+
+ int sysi = getSys(sys);
+ int qi = getQ(q_sys ? getSys(q_sys) : sysi, q, qid);
+ DPRINTFS(AnnotateQ, sys,
+ "hwPQ: %s[%#x] cur size %d %d bytes: %d peeking: %d\n",
+ q, qid, qSize[qi-1], qData[qi-1].size(), qBytes[qi-1], count);
+ add(OP_PEEK, FL_HW | f, 0, getSm(sysi, sm, frame), qi, count);
+ }
+
+ inline void hwRq(flags f, System *sys, uint64_t frame, std::string sm,
+ std::string q, uint64_t qid, System *q_sys = NULL, int32_t count = 1)
+ {
+ if (!enabled())
+ return;
+
+ int sysi = getSys(sys);
+ int qi = getQ(q_sys ? getSys(q_sys) : sysi, q, qid);
+ DPRINTFS(AnnotateQ, sys,
+ "hwRQ: %s[%#x] cur size %d %d bytes: %d reserving: %d\n",
+ q, qid, qSize[qi-1], qData[qi-1].size(), qBytes[qi-1], count);
+ add(OP_RESERVE, FL_HW | f, 0, getSm(sysi, sm, frame), qi, count);
+ }
+
+ inline void hwWf(flags f, System *sys, uint64_t frame, std::string sm,
+ std::string q, uint64_t qid, System *q_sys = NULL, int32_t count = 1)
+ {
+ if (!enabled())
+ return;
+
+ int sysi = getSys(sys);
+ int qi = getQ(q_sys ? getSys(q_sys) : sysi, q, qid);
+ add(OP_WAIT_FULL, FL_HW | f, 0, getSm(sysi, sm, frame), qi, count);
+ }
+
+ inline void hwWe(flags f, System *sys, uint64_t frame, std::string sm,
+ std::string q, uint64_t qid, System *q_sys = NULL, int32_t count = 1)
+ {
+ if (!enabled())
+ return;
+
+ int sysi = getSys(sys);
+ int qi = getQ(q_sys ? getSys(q_sys) : sysi, q, qid);
+ add(OP_WAIT_EMPTY, FL_HW | f, 0, getSm(sysi, sm, frame), qi, count);
+ }
+
+ public:
+ CPA(Params *p);
+ void startup();
+
+ // This code is ISA specific and will need to be changed
+ // if the annotation code is used for something other than Alpha
+ inline uint64_t getFrame(ThreadContext *tc)
+ { return (tc->readMiscRegNoEffect(TheISA::IPR_PALtemp23) &
+ ~ULL(0x3FFF)); }
+
+ static bool available() { return true; }
+
+ bool
+ enabled()
+ {
+ if (!this)
+ return false;
+ return _enabled;
+ }
+
+ void dump(bool all);
+ void dumpKey();
+
+ void serialize(std::ostream &os);
+ void unserialize(Checkpoint *cp, const std::string &section);
+
+};
+#endif // !CP_ANNOTATE
+
+#endif //__BASE__CP_ANNOTATE_HH__
+
diff --git a/src/base/cprintf.cc b/src/base/cprintf.cc
index d4ba9ca21..5c11e501c 100644
--- a/src/base/cprintf.cc
+++ b/src/base/cprintf.cc
@@ -40,7 +40,7 @@ using namespace std;
namespace cp {
Print::Print(std::ostream &stream, const std::string &format)
- : stream(stream), format(format.c_str()), ptr(format.c_str())
+ : stream(stream), format(format.c_str()), ptr(format.c_str()), cont(false)
{
saved_flags = stream.flags();
saved_fill = stream.fill();
@@ -48,7 +48,7 @@ Print::Print(std::ostream &stream, const std::string &format)
}
Print::Print(std::ostream &stream, const char *format)
- : stream(stream), format(format), ptr(format)
+ : stream(stream), format(format), ptr(format), cont(false)
{
saved_flags = stream.flags();
saved_fill = stream.fill();
@@ -60,8 +60,10 @@ Print::~Print()
}
void
-Print::process(Format &fmt)
+Print::process()
{
+ fmt.clear();
+
size_t len;
while (*ptr) {
@@ -221,8 +223,15 @@ Print::process(Format &fmt)
number = number * 10 + (*ptr - '0');
break;
+ case '*':
+ if (have_precision)
+ fmt.get_precision = true;
+ else
+ fmt.get_width = true;
+ break;
+
case '%':
- assert("we shouldn't get here");
+ assert(false && "we shouldn't get here");
break;
default:
diff --git a/src/base/cprintf.hh b/src/base/cprintf.hh
index cff73a228..2920e210d 100644
--- a/src/base/cprintf.hh
+++ b/src/base/cprintf.hh
@@ -51,24 +51,53 @@ struct Print
std::ostream &stream;
const char *format;
const char *ptr;
+ bool cont;
std::ios::fmtflags saved_flags;
char saved_fill;
int saved_precision;
- void process(Format &fmt);
+ Format fmt;
+ void process();
public:
Print(std::ostream &stream, const std::string &format);
Print(std::ostream &stream, const char *format);
~Print();
+ int
+ get_number(int data)
+ {
+ return data;
+ }
+
+ template <typename T>
+ int
+ get_number(const T& data)
+ {
+ return 0;
+ }
+
template <typename T>
void
add_arg(const T &data)
{
- Format fmt;
- process(fmt);
+ if (!cont)
+ process();
+
+ if (fmt.get_width) {
+ fmt.get_width = false;
+ cont = true;
+ fmt.width = get_number(data);
+ return;
+ }
+
+ if (fmt.get_precision) {
+ fmt.get_precision = false;
+ cont = true;
+ fmt.precision = get_number(data);
+ return;
+ }
switch (fmt.format) {
case Format::character:
diff --git a/src/base/cprintf_formats.hh b/src/base/cprintf_formats.hh
index 4e8b2b09e..6bf6b2b66 100644
--- a/src/base/cprintf_formats.hh
+++ b/src/base/cprintf_formats.hh
@@ -31,8 +31,9 @@
#ifndef __BASE_CPRINTF_FORMATS_HH__
#define __BASE_CPRINTF_FORMATS_HH__
-#include <sstream>
+#include <cstring>
#include <ostream>
+#include <sstream>
namespace cp {
@@ -49,6 +50,8 @@ struct Format
enum { best, fixed, scientific } float_format;
int precision;
int width;
+ bool get_precision;
+ bool get_width;
Format() { clear(); }
@@ -64,6 +67,8 @@ struct Format
format = none;
precision = -1;
width = 0;
+ get_precision = false;
+ get_width = false;
}
};
diff --git a/src/base/crc.cc b/src/base/crc.cc
index 08f039577..ce837a408 100644
--- a/src/base/crc.cc
+++ b/src/base/crc.cc
@@ -1,6 +1,6 @@
/*
* Copyright (c) 1988, 1992, 1993
- * The Regents of the University of California. All rights reserved.
+ * The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -12,8 +12,8 @@
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
diff --git a/src/base/stats/statdb.cc b/src/base/debug.cc
index f9136807a..de201af18 100644
--- a/src/base/stats/statdb.cc
+++ b/src/base/debug.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2004-2005 The Regents of The University of Michigan
+ * Copyright (c) 2003-2005 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -28,56 +28,18 @@
* Authors: Nathan Binkert
*/
-#include "base/misc.hh"
-#include "base/trace.hh"
-#include "base/statistics.hh"
-#include "base/stats/statdb.hh"
+#include <sys/types.h>
+#include <signal.h>
+#include <unistd.h>
-using namespace std;
-
-namespace Stats {
-namespace Database {
-
-StatData *
-find(void *stat)
-{
- stat_map_t::const_iterator i = map().find(stat);
-
- if (i == map().end())
- return NULL;
-
- return (*i).second;
-}
+#include "base/cprintf.hh"
void
-regStat(void *stat, StatData *data)
+debug_break()
{
- if (map().find(stat) != map().end())
- panic("shouldn't register stat twice!");
-
- stats().push_back(data);
-
#ifndef NDEBUG
- pair<stat_map_t::iterator, bool> result =
+ kill(getpid(), SIGTRAP);
+#else
+ cprintf("debug_break suppressed, compiled with NDEBUG\n");
#endif
- map().insert(make_pair(stat, data));
- assert(result.second && "this should never fail");
- assert(map().find(stat) != map().end());
}
-
-void
-regPrint(void *stat)
-{
- StatData *data = find(stat);
- assert(data);
- data->flags |= print;
-}
-
-TheDatabase &db()
-{
- static TheDatabase db;
- return db;
-}
-
-/* namespace Database */ }
-/* namespace Stats */ }
diff --git a/src/base/debug.hh b/src/base/debug.hh
new file mode 100644
index 000000000..b1577f782
--- /dev/null
+++ b/src/base/debug.hh
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2003-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Nathan Binkert
+ */
+
+#ifndef __BASE_DEBUG_HH__
+#define __BASE_DEBUG_HH__
+
+void debug_break();
+
+#endif // __BASE_DEBUG_HH__
diff --git a/src/base/fast_alloc.cc b/src/base/fast_alloc.cc
index e1298a8bd..a91a99d20 100644
--- a/src/base/fast_alloc.cc
+++ b/src/base/fast_alloc.cc
@@ -34,7 +34,8 @@
* by permission.
*/
-#include <assert.h>
+#include <cassert>
+
#include "base/fast_alloc.hh"
#if !NO_FAST_ALLOC
@@ -45,21 +46,22 @@
void *FastAlloc::freeLists[Num_Buckets];
-#ifdef FAST_ALLOC_STATS
+#if FAST_ALLOC_STATS
unsigned FastAlloc::newCount[Num_Buckets];
unsigned FastAlloc::deleteCount[Num_Buckets];
unsigned FastAlloc::allocCount[Num_Buckets];
#endif
-void *FastAlloc::moreStructs(int bucket)
+void *
+FastAlloc::moreStructs(int bucket)
{
assert(bucket > 0 && bucket < Num_Buckets);
int sz = bucket * Alloc_Quantum;
- const int nstructs = Num_Structs_Per_New; // how many to allocate?
+ const int nstructs = Num_Structs_Per_New; // how many to allocate?
char *p = ::new char[nstructs * sz];
-#ifdef FAST_ALLOC_STATS
+#if FAST_ALLOC_STATS
++allocCount[bucket];
#endif
@@ -71,14 +73,13 @@ void *FastAlloc::moreStructs(int bucket)
return (p + sz);
}
+#if FAST_ALLOC_DEBUG
-#ifdef FAST_ALLOC_DEBUG
-
-#include <typeinfo>
-#include <iostream>
#include <iomanip>
+#include <iostream>
#include <map>
#include <string>
+#include <typeinfo>
using namespace std;
@@ -97,7 +98,6 @@ FastAlloc::FastAlloc(FastAlloc *prev, FastAlloc *next)
inUseNext = next;
}
-
// constructor: marks as in use, add to in-use list
FastAlloc::FastAlloc()
{
@@ -131,7 +131,6 @@ FastAlloc::~FastAlloc()
inUseNext->inUsePrev = inUsePrev;
}
-
// summarize in-use list
void
FastAlloc::dump_summary()
@@ -148,48 +147,43 @@ FastAlloc::dump_summary()
cout << " count type\n"
<< " ----- ----\n";
for (mapiter = typemap.begin(); mapiter != typemap.end(); ++mapiter)
- {
cout << setw(6) << mapiter->second << " " << mapiter->first << endl;
- }
}
-
// show oldest n items on in-use list
void
FastAlloc::dump_oldest(int n)
{
// sanity check: don't want to crash the debugger if you forget to
// pass in a parameter
- if (n < 0 || n > numInUse)
- {
+ if (n < 0 || n > numInUse) {
cout << "FastAlloc::dump_oldest: bad arg " << n
<< " (" << numInUse << " objects in use" << endl;
return;
}
- for (FastAlloc *p = inUseHead.inUsePrev;
+ for (FastAlloc *p = inUseHead.inUseNext;
p != &inUseHead && n > 0;
- p = p->inUsePrev, --n)
- {
+ p = p->inUseNext, --n)
cout << p << " " << typeid(*p).name() << endl;
- }
}
-
//
// C interfaces to FastAlloc::dump_summary() and FastAlloc::dump_oldest().
// gdb seems to have trouble with calling C++ functions directly.
//
+void
fast_alloc_summary()
{
FastAlloc::dump_summary();
}
+void
fast_alloc_oldest(int n)
{
FastAlloc::dump_oldest(n);
}
-#endif
+#endif // FAST_ALLOC_DEBUG
#endif // NO_FAST_ALLOC
diff --git a/src/base/fast_alloc.hh b/src/base/fast_alloc.hh
index 3e22e59c1..775c93d50 100644
--- a/src/base/fast_alloc.hh
+++ b/src/base/fast_alloc.hh
@@ -34,10 +34,10 @@
* by permission.
*/
-#ifndef __FAST_ALLOC_H__
-#define __FAST_ALLOC_H__
+#ifndef __BASE_FAST_ALLOC_HH__
+#define __BASE_FAST_ALLOC_HH__
-#include <stddef.h>
+#include <cstddef>
// Fast structure allocator. Designed for small objects that are
// frequently allocated and deallocated. This code is derived from the
@@ -62,35 +62,30 @@
// collapse the destructor call chain back up the inheritance
// hierarchy.
-// Uncomment this #define to track in-use objects
-// (for debugging memory leaks).
-//#define FAST_ALLOC_DEBUG
-
-// Uncomment this #define to count news, deletes, and chunk allocations
-// (by bucket).
-// #define FAST_ALLOC_STATS
-
#include "config/no_fast_alloc.hh"
+#include "config/fast_alloc_debug.hh"
+#include "config/fast_alloc_stats.hh"
#if NO_FAST_ALLOC
-class FastAlloc {
+class FastAlloc
+{
};
#else
-class FastAlloc {
+class FastAlloc
+{
public:
-
static void *allocate(size_t);
static void deallocate(void *, size_t);
void *operator new(size_t);
void operator delete(void *, size_t);
-#ifdef FAST_ALLOC_DEBUG
+#if FAST_ALLOC_DEBUG
FastAlloc();
- FastAlloc(FastAlloc*,FastAlloc*); // for inUseHead, see below
+ FastAlloc(FastAlloc *, FastAlloc *); // for inUseHead, see below
virtual ~FastAlloc();
#else
virtual ~FastAlloc() {}
@@ -121,21 +116,21 @@ class FastAlloc {
static void *freeLists[Num_Buckets];
-#ifdef FAST_ALLOC_STATS
+#if FAST_ALLOC_STATS
static unsigned newCount[Num_Buckets];
static unsigned deleteCount[Num_Buckets];
static unsigned allocCount[Num_Buckets];
#endif
-#ifdef FAST_ALLOC_DEBUG
+#if FAST_ALLOC_DEBUG
// per-object debugging fields
- bool inUse; // in-use flag
- FastAlloc *inUsePrev; // ptrs to build list of in-use objects
+ bool inUse; // in-use flag
+ FastAlloc *inUsePrev; // ptrs to build list of in-use objects
FastAlloc *inUseNext;
// static (global) debugging vars
- static int numInUse; // count in-use objects
- static FastAlloc inUseHead; // dummy head for list of in-use objects
+ static int numInUse; // count in-use objects
+ static FastAlloc inUseHead; // dummy head for list of in-use objects
public:
// functions to dump debugging info (see fast_alloc.cc for C
@@ -145,16 +140,14 @@ class FastAlloc {
#endif
};
-
-inline
-int FastAlloc::bucketFor(size_t sz)
+inline int
+FastAlloc::bucketFor(size_t sz)
{
return (sz + Alloc_Quantum - 1) >> Log2_Alloc_Quantum;
}
-
-inline
-void *FastAlloc::allocate(size_t sz)
+inline void *
+FastAlloc::allocate(size_t sz)
{
int b;
void *p;
@@ -170,21 +163,19 @@ void *FastAlloc::allocate(size_t sz)
else
p = moreStructs(b);
-#ifdef FAST_ALLOC_STATS
+#if FAST_ALLOC_STATS
++newCount[b];
#endif
return p;
}
-
-inline
-void FastAlloc::deallocate(void *p, size_t sz)
+inline void
+FastAlloc::deallocate(void *p, size_t sz)
{
int b;
- if (sz > Max_Alloc_Size)
- {
+ if (sz > Max_Alloc_Size) {
::delete [] (char *)p;
return;
}
@@ -192,25 +183,23 @@ void FastAlloc::deallocate(void *p, size_t sz)
b = bucketFor(sz);
*(void **)p = freeLists[b];
freeLists[b] = p;
-#ifdef FAST_ALLOC_STATS
+#if FAST_ALLOC_STATS
++deleteCount[b];
#endif
}
-
-inline
-void *FastAlloc::operator new(size_t sz)
+inline void *
+FastAlloc::operator new(size_t sz)
{
return allocate(sz);
}
-
-inline
-void FastAlloc::operator delete(void *p, size_t sz)
+inline void
+FastAlloc::operator delete(void *p, size_t sz)
{
deallocate(p, sz);
}
#endif // NO_FAST_ALLOC
-#endif // __FAST_ALLOC_H__
+#endif // __BASE_FAST_ALLOC_HH__
diff --git a/src/base/flags.hh b/src/base/flags.hh
new file mode 100644
index 000000000..2e0506391
--- /dev/null
+++ b/src/base/flags.hh
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2008 The Hewlett-Packard Development Company
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Nathan Binkert
+ */
+
+#ifndef __BASE_FLAGS_HH__
+#define __BASE_FLAGS_HH__
+
+template <typename T>
+class Flags
+{
+ private:
+ T _flags;
+
+ public:
+ typedef T Type;
+ Flags() : _flags(0) {}
+ Flags(Type flags) : _flags(flags) {}
+
+ operator const Type() const { return _flags; }
+
+ template <typename U>
+ const Flags<T> &
+ operator=(const Flags<U> &flags)
+ {
+ _flags = flags._flags;
+ return *this;
+ }
+
+ const Flags<T> &
+ operator=(T flags)
+ {
+ _flags = flags;
+ return *this;
+ }
+
+ bool isSet() const { return _flags; }
+ bool isSet(Type flags) const { return (_flags & flags); }
+ bool allSet() const { return !(~_flags); }
+ bool allSet(Type flags) const { return (_flags & flags) == flags; }
+ bool noneSet() const { return _flags == 0; }
+ bool noneSet(Type flags) const { return (_flags & flags) == 0; }
+ void clear() { _flags = 0; }
+ void clear(Type flags) { _flags &= ~flags; }
+ void set(Type flags) { _flags |= flags; }
+ void set(Type f, bool val) { _flags = (_flags & ~f) | (val ? f : 0); }
+ void
+ update(Type flags, Type mask)
+ {
+ _flags = (_flags & ~mask) | (flags & mask);
+ }
+};
+
+#endif // __BASE_FLAGS_HH__
diff --git a/src/base/hashmap.hh b/src/base/hashmap.hh
index f8d799780..ff2aa151f 100644
--- a/src/base/hashmap.hh
+++ b/src/base/hashmap.hh
@@ -81,6 +81,16 @@ namespace __hash_namespace {
return(__stl_hash_string(s.c_str()));
}
};
+
+ template <>
+ struct hash<std::pair<std::string, uint64_t> > {
+ size_t operator() (std::pair<std::string, uint64_t> r) const {
+ return (__stl_hash_string(r.first.c_str())) ^ r.second;
+ }
+ };
+
+
+
}
diff --git a/src/base/hybrid_pred.hh b/src/base/hybrid_pred.hh
index cb1d6003b..5e478553b 100644
--- a/src/base/hybrid_pred.hh
+++ b/src/base/hybrid_pred.hh
@@ -62,12 +62,12 @@ class HybridPredictor : public GenericPredictor
//
// Stats
//
- Stats::Scalar<> pred_one; //num_one_preds
- Stats::Scalar<> pred_zero; //num_zero_preds
- Stats::Scalar<> correct_pred_one; //num_one_correct
- Stats::Scalar<> correct_pred_zero; //num_zero_correct
- Stats::Scalar<> record_one; //num_one_updates
- Stats::Scalar<> record_zero; //num_zero_updates
+ Stats::Scalar pred_one; //num_one_preds
+ Stats::Scalar pred_zero; //num_zero_preds
+ Stats::Scalar correct_pred_one; //num_one_correct
+ Stats::Scalar correct_pred_zero; //num_zero_correct
+ Stats::Scalar record_one; //num_one_updates
+ Stats::Scalar record_zero; //num_zero_updates
Stats::Formula total_preds;
Stats::Formula frac_preds_zero;
diff --git a/src/base/inet.cc b/src/base/inet.cc
index b8da12a99..8c3240fa6 100644
--- a/src/base/inet.cc
+++ b/src/base/inet.cc
@@ -206,4 +206,25 @@ TcpOpt::sack(vector<SackRange> &vec) const
return false;
}
+int
+hsplit(const EthPacketPtr &ptr)
+{
+ int split_point = 0;
+
+ IpPtr ip(ptr);
+ if (ip) {
+ split_point = ip.pstart();
+
+ TcpPtr tcp(ip);
+ if (tcp)
+ split_point = tcp.pstart();
+
+ UdpPtr udp(ip);
+ if (udp)
+ split_point = udp.pstart();
+ }
+ return split_point;
+}
+
+
/* namespace Net */ }
diff --git a/src/base/inet.hh b/src/base/inet.hh
index 1bf7c585f..59b05291d 100644
--- a/src/base/inet.hh
+++ b/src/base/inet.hh
@@ -140,6 +140,8 @@ class EthPtr
EthPacketPtr packet() { return p; }
bool operator!() const { return !p; }
operator bool() const { return p; }
+ int off() const { return 0; }
+ int pstart() const { return off() + ((const EthHdr*)p->data)->size(); }
};
/*
@@ -162,6 +164,9 @@ struct IpHdr : public ip_hdr
uint32_t dst() const { return ntohl(ip_dst); }
void sum(uint16_t sum) { ip_sum = sum; }
+ void id(uint16_t _id) { ip_id = htons(_id); }
+ void len(uint16_t _len) { ip_len = htons(_len); }
+
bool options(std::vector<const IpOpt *> &vec) const;
@@ -179,32 +184,31 @@ class IpPtr
friend class UdpPtr;
EthPacketPtr p;
- const IpHdr *h() const
- { return (const IpHdr *)(p->data + sizeof(eth_hdr)); }
- IpHdr *h() { return (IpHdr *)(p->data + sizeof(eth_hdr)); }
-
void set(const EthPacketPtr &ptr)
{
- EthHdr *eth = (EthHdr *)ptr->data;
- if (eth->type() == ETH_TYPE_IP)
- p = ptr;
- else
- p = 0;
+ p = 0;
+
+ if (ptr) {
+ EthHdr *eth = (EthHdr *)ptr->data;
+ if (eth->type() == ETH_TYPE_IP)
+ p = ptr;
+ }
}
public:
- IpPtr() {}
- IpPtr(const EthPacketPtr &ptr) { set(ptr); }
- IpPtr(const EthPtr &ptr) { set(ptr.p); }
+ IpPtr() : p(0) {}
+ IpPtr(const EthPacketPtr &ptr) : p(0) { set(ptr); }
+ IpPtr(const EthPtr &ptr) : p(0) { set(ptr.p); }
IpPtr(const IpPtr &ptr) : p(ptr.p) { }
- IpHdr *operator->() { return h(); }
- IpHdr &operator*() { return *h(); }
- operator IpHdr *() { return h(); }
+ IpHdr *get() { return (IpHdr *)(p->data + sizeof(eth_hdr)); }
+ IpHdr *operator->() { return get(); }
+ IpHdr &operator*() { return *get(); }
- const IpHdr *operator->() const { return h(); }
- const IpHdr &operator*() const { return *h(); }
- operator const IpHdr *() const { return h(); }
+ const IpHdr *get() const
+ { return (const IpHdr *)(p->data + sizeof(eth_hdr)); }
+ const IpHdr *operator->() const { return get(); }
+ const IpHdr &operator*() const { return *get(); }
const IpPtr &operator=(const EthPacketPtr &ptr) { set(ptr); return *this; }
const IpPtr &operator=(const EthPtr &ptr) { set(ptr.p); return *this; }
@@ -214,7 +218,8 @@ class IpPtr
EthPacketPtr packet() { return p; }
bool operator!() const { return !p; }
operator bool() const { return p; }
- operator bool() { return p; }
+ int off() const { return sizeof(eth_hdr); }
+ int pstart() const { return off() + get()->size(); }
};
uint16_t cksum(const IpPtr &ptr);
@@ -262,6 +267,8 @@ struct TcpHdr : public tcp_hdr
uint16_t urp() const { return ntohs(th_urp); }
void sum(uint16_t sum) { th_sum = sum; }
+ void seq(uint32_t _seq) { th_seq = htonl(_seq); }
+ void flags(uint8_t _flags) { th_flags = _flags; }
bool options(std::vector<const TcpOpt *> &vec) const;
@@ -276,41 +283,39 @@ class TcpPtr
{
protected:
EthPacketPtr p;
- int off;
-
- const TcpHdr *h() const { return (const TcpHdr *)(p->data + off); }
- TcpHdr *h() { return (TcpHdr *)(p->data + off); }
+ int _off;
- void set(const EthPacketPtr &ptr, int offset) { p = ptr; off = offset; }
+ void set(const EthPacketPtr &ptr, int offset) { p = ptr; _off = offset; }
void set(const IpPtr &ptr)
{
- if (ptr->proto() == IP_PROTO_TCP)
+ if (ptr && ptr->proto() == IP_PROTO_TCP)
set(ptr.p, sizeof(eth_hdr) + ptr->hlen());
else
set(0, 0);
}
public:
- TcpPtr() {}
- TcpPtr(const IpPtr &ptr) { set(ptr); }
- TcpPtr(const TcpPtr &ptr) : p(ptr.p), off(ptr.off) {}
+ TcpPtr() : p(0), _off(0) {}
+ TcpPtr(const IpPtr &ptr) : p(0), _off(0) { set(ptr); }
+ TcpPtr(const TcpPtr &ptr) : p(ptr.p), _off(ptr._off) {}
- TcpHdr *operator->() { return h(); }
- TcpHdr &operator*() { return *h(); }
- operator TcpHdr *() { return h(); }
+ TcpHdr *get() { return (TcpHdr *)(p->data + _off); }
+ TcpHdr *operator->() { return get(); }
+ TcpHdr &operator*() { return *get(); }
- const TcpHdr *operator->() const { return h(); }
- const TcpHdr &operator*() const { return *h(); }
- operator const TcpHdr *() const { return h(); }
+ const TcpHdr *get() const { return (const TcpHdr *)(p->data + _off); }
+ const TcpHdr *operator->() const { return get(); }
+ const TcpHdr &operator*() const { return *get(); }
const TcpPtr &operator=(const IpPtr &i) { set(i); return *this; }
- const TcpPtr &operator=(const TcpPtr &t) { set(t.p, t.off); return *this; }
+ const TcpPtr &operator=(const TcpPtr &t) { set(t.p, t._off); return *this; }
const EthPacketPtr packet() const { return p; }
EthPacketPtr packet() { return p; }
bool operator!() const { return !p; }
operator bool() const { return p; }
- operator bool() { return p; }
+ int off() const { return _off; }
+ int pstart() const { return off() + get()->size(); }
};
uint16_t cksum(const TcpPtr &ptr);
@@ -354,6 +359,7 @@ struct UdpHdr : public udp_hdr
uint16_t sum() const { return uh_sum; }
void sum(uint16_t sum) { uh_sum = sum; }
+ void len(uint16_t _len) { uh_ulen = htons(_len); }
int size() const { return sizeof(udp_hdr); }
const uint8_t *bytes() const { return (const uint8_t *)this; }
@@ -366,45 +372,45 @@ class UdpPtr
{
protected:
EthPacketPtr p;
- int off;
+ int _off;
- const UdpHdr *h() const { return (const UdpHdr *)(p->data + off); }
- UdpHdr *h() { return (UdpHdr *)(p->data + off); }
-
- void set(const EthPacketPtr &ptr, int offset) { p = ptr; off = offset; }
+ void set(const EthPacketPtr &ptr, int offset) { p = ptr; _off = offset; }
void set(const IpPtr &ptr)
{
- if (ptr->proto() == IP_PROTO_UDP)
+ if (ptr && ptr->proto() == IP_PROTO_UDP)
set(ptr.p, sizeof(eth_hdr) + ptr->hlen());
else
set(0, 0);
}
public:
- UdpPtr() {}
- UdpPtr(const IpPtr &ptr) { set(ptr); }
- UdpPtr(const UdpPtr &ptr) : p(ptr.p), off(ptr.off) {}
+ UdpPtr() : p(0), _off(0) {}
+ UdpPtr(const IpPtr &ptr) : p(0), _off(0) { set(ptr); }
+ UdpPtr(const UdpPtr &ptr) : p(ptr.p), _off(ptr._off) {}
- UdpHdr *operator->() { return h(); }
- UdpHdr &operator*() { return *h(); }
- operator UdpHdr *() { return h(); }
+ UdpHdr *get() { return (UdpHdr *)(p->data + _off); }
+ UdpHdr *operator->() { return get(); }
+ UdpHdr &operator*() { return *get(); }
- const UdpHdr *operator->() const { return h(); }
- const UdpHdr &operator*() const { return *h(); }
- operator const UdpHdr *() const { return h(); }
+ const UdpHdr *get() const { return (const UdpHdr *)(p->data + _off); }
+ const UdpHdr *operator->() const { return get(); }
+ const UdpHdr &operator*() const { return *get(); }
const UdpPtr &operator=(const IpPtr &i) { set(i); return *this; }
- const UdpPtr &operator=(const UdpPtr &t) { set(t.p, t.off); return *this; }
+ const UdpPtr &operator=(const UdpPtr &t) { set(t.p, t._off); return *this; }
const EthPacketPtr packet() const { return p; }
EthPacketPtr packet() { return p; }
bool operator!() const { return !p; }
operator bool() const { return p; }
- operator bool() { return p; }
+ int off() const { return _off; }
+ int pstart() const { return off() + get()->size(); }
};
uint16_t cksum(const UdpPtr &ptr);
+int hsplit(const EthPacketPtr &ptr);
+
/* namespace Net */ }
#endif // __BASE_INET_HH__
diff --git a/src/base/inifile.cc b/src/base/inifile.cc
index 809cbe172..24d0013c4 100644
--- a/src/base/inifile.cc
+++ b/src/base/inifile.cc
@@ -29,22 +29,8 @@
* Steve Reinhardt
*/
-#define USE_CPP
-
-#ifdef USE_CPP
-#include <sys/signal.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-
-#include <libgen.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#endif
-
#include <fstream>
#include <iostream>
-
#include <vector>
#include <string>
@@ -67,103 +53,6 @@ IniFile::~IniFile()
}
}
-
-#ifdef USE_CPP
-bool
-IniFile::loadCPP(const string &file, vector<char *> &cppArgs)
-{
- // Open the file just to verify that we can. Otherwise if the
- // file doesn't exist or has bad permissions the user will get
- // confusing errors from cpp/g++.
- ifstream tmpf(file.c_str());
-
- if (!tmpf.is_open())
- return false;
-
- tmpf.close();
-
- char *cfile = strncpy(new char[file.size() + 1], file.c_str(),
- file.size());
- char *dir = dirname(cfile);
- char *dir_arg = NULL;
- if (*dir != '.') {
- string arg = "-I";
- arg += dir;
-
- dir_arg = new char[arg.size() + 1];
- strncpy(dir_arg, arg.c_str(), arg.size());
- }
-
- delete [] cfile;
-
- char tempfile[] = "/tmp/configXXXXXX";
- int tmp_fd = mkstemp(tempfile);
-
- int pid = fork();
-
- if (pid == -1)
- return false;
-
- if (pid == 0) {
- char filename[FILENAME_MAX];
- string::size_type i = file.copy(filename, sizeof(filename) - 1);
- filename[i] = '\0';
-
- int arg_count = cppArgs.size();
-
- const char **args = new const char *[arg_count + 20];
-
- int nextArg = 0;
- args[nextArg++] = "g++";
- args[nextArg++] = "-E";
- args[nextArg++] = "-P";
- args[nextArg++] = "-nostdinc";
- args[nextArg++] = "-nostdinc++";
- args[nextArg++] = "-x";
- args[nextArg++] = "c++";
- args[nextArg++] = "-undef";
-
- for (int i = 0; i < arg_count; i++)
- args[nextArg++] = cppArgs[i];
-
- if (dir_arg)
- args[nextArg++] = dir_arg;
-
- args[nextArg++] = filename;
- args[nextArg++] = NULL;
-
- close(STDOUT_FILENO);
- if (dup2(tmp_fd, STDOUT_FILENO) == -1)
- exit(1);
-
- // execvp signature is intentionally broken wrt const-ness for
- // backwards compatibility... see man page
- execvp("g++", const_cast<char * const *>(args));
-
- exit(0);
- }
-
- int retval;
- waitpid(pid, &retval, 0);
-
- delete [] dir_arg;
-
- // check for normal completion of CPP
- if (!WIFEXITED(retval) || WEXITSTATUS(retval) != 0)
- return false;
-
- close(tmp_fd);
-
- bool status = false;
-
- status = load(tempfile);
-
- unlink(tempfile);
-
- return status;
-}
-#endif
-
bool
IniFile::load(const string &file)
{
diff --git a/src/base/inifile.hh b/src/base/inifile.hh
index 631b29b87..83cf80cf0 100644
--- a/src/base/inifile.hh
+++ b/src/base/inifile.hh
@@ -61,8 +61,8 @@ class IniFile
///
class Entry
{
- std::string value; ///< The entry value.
- mutable bool referenced; ///< Has this entry been used?
+ std::string value; ///< The entry value.
+ mutable bool referenced; ///< Has this entry been used?
public:
/// Constructor.
@@ -96,8 +96,8 @@ class IniFile
/// EntryTable type. Map of strings to Entry object pointers.
typedef m5::hash_map<std::string, Entry *> EntryTable;
- EntryTable table; ///< Table of entries.
- mutable bool referenced; ///< Has this section been used?
+ EntryTable table; ///< Table of entries.
+ mutable bool referenced; ///< Has this section been used?
public:
/// Constructor.
@@ -167,14 +167,6 @@ class IniFile
/// @retval True if successful, false if errors were encountered.
bool load(std::istream &f);
- /// Load the specified file, passing it through the C preprocessor.
- /// Parameter settings found in the file will be merged with any
- /// already defined in this object.
- /// @param file The path of the file to load.
- /// @param cppFlags Vector of extra flags to pass to cpp.
- /// @retval True if successful, false if errors were encountered.
- bool loadCPP(const std::string &file, std::vector<char *> &cppFlags);
-
/// Load the specified file.
/// Parameter settings found in the file will be merged with any
/// already defined in this object.
diff --git a/src/base/intmath.hh b/src/base/intmath.hh
index 227012e30..c536fda51 100644
--- a/src/base/intmath.hh
+++ b/src/base/intmath.hh
@@ -197,9 +197,9 @@ roundDown(T val, int align)
inline bool
isHex(char c)
{
- return c >= '0' && c <= '9' ||
- c >= 'A' && c <= 'F' ||
- c >= 'a' && c <= 'f';
+ return (c >= '0' && c <= '9') ||
+ (c >= 'A' && c <= 'F') ||
+ (c >= 'a' && c <= 'f');
}
inline bool
diff --git a/src/base/loader/aout_object.cc b/src/base/loader/aout_object.cc
index 8fbad8030..1412adfc3 100644
--- a/src/base/loader/aout_object.cc
+++ b/src/base/loader/aout_object.cc
@@ -34,7 +34,7 @@
#include "base/loader/symtab.hh"
-#include "base/trace.hh" // for DPRINTF
+#include "base/trace.hh" // for DPRINTF
#include "base/loader/exec_aout.h"
diff --git a/src/base/loader/coff_sym.h b/src/base/loader/coff_sym.h
index 4c6540395..be0631141 100644
--- a/src/base/loader/coff_sym.h
+++ b/src/base/loader/coff_sym.h
@@ -65,7 +65,7 @@
*
* Symbols are assumed to be in 'encounter order' - i.e. the order that
* the things they represent were encountered by the compiler/assembler/loader.
- * EXCEPT for globals! These are assumed to be bunched together,
+ * EXCEPT for globals! These are assumed to be bunched together,
* probably right after the last 'normal' symbol. Globals ARE sorted
* in ascending order.
*
@@ -76,13 +76,13 @@
* All "ifooMax" values are the highest legal value PLUS ONE. This makes
* them good for allocating arrays, etc. All checks are "ifoo < ifooMax".
*
- * "isym" Index into the SYMbol table.
- * "ipd" Index into the Procedure Descriptor array.
- * "ifd" Index into the File Descriptor array.
- * "iss" Index into String Space.
- * "cb" Count of Bytes.
- * "rgPd" array whose domain is "0..ipdMax-1" and RanGe is PDR.
- * "rgFd" array whose domain is "0..ifdMax-1" and RanGe is FDR.
+ * "isym" Index into the SYMbol table.
+ * "ipd" Index into the Procedure Descriptor array.
+ * "ifd" Index into the File Descriptor array.
+ * "iss" Index into String Space.
+ * "cb" Count of Bytes.
+ * "rgPd" array whose domain is "0..ipdMax-1" and RanGe is PDR.
+ * "rgFd" array whose domain is "0..ifdMax-1" and RanGe is FDR.
*/
@@ -97,31 +97,31 @@
*/
typedef struct ecoff_symhdr {
- coff_short magic; /* to verify validity of the table */
- coff_short vstamp; /* version stamp */
- coff_int ilineMax; /* number of line number entries */
- coff_int idnMax; /* max index into dense number table */
- coff_int ipdMax; /* number of procedures */
- coff_int isymMax; /* number of local symbols */
- coff_int ioptMax; /* max index into optimization symbol entries */
- coff_int iauxMax; /* number of auxillary symbol entries */
- coff_int issMax; /* max index into local strings */
- coff_int issExtMax; /* max index into external strings */
- coff_int ifdMax; /* number of file descriptor entries */
- coff_int crfd; /* number of relative file descriptor entries */
- coff_int iextMax; /* max index into external symbols */
- coff_addr cbLine; /* number of bytes for line number entries */
- coff_addr cbLineOffset; /* offset to start of line number entries*/
- coff_addr cbDnOffset; /* offset to start dense number table */
- coff_addr cbPdOffset; /* offset to procedure descriptor table */
- coff_addr cbSymOffset; /* offset to start of local symbols*/
- coff_addr cbOptOffset; /* offset to optimization symbol entries */
- coff_addr cbAuxOffset; /* offset to start of auxillary symbol entries*/
- coff_addr cbSsOffset; /* offset to start of local strings */
- coff_addr cbSsExtOffset; /* offset to start of external strings */
- coff_addr cbFdOffset; /* offset to file descriptor table */
- coff_addr cbRfdOffset; /* offset to relative file descriptor table */
- coff_addr cbExtOffset; /* offset to start of external symbol entries*/
+ coff_short magic; /* to verify validity of the table */
+ coff_short vstamp; /* version stamp */
+ coff_int ilineMax; /* number of line number entries */
+ coff_int idnMax; /* max index into dense number table */
+ coff_int ipdMax; /* number of procedures */
+ coff_int isymMax; /* number of local symbols */
+ coff_int ioptMax; /* max index into optimization symbol entries */
+ coff_int iauxMax; /* number of auxillary symbol entries */
+ coff_int issMax; /* max index into local strings */
+ coff_int issExtMax; /* max index into external strings */
+ coff_int ifdMax; /* number of file descriptor entries */
+ coff_int crfd; /* number of relative file descriptor entries */
+ coff_int iextMax; /* max index into external symbols */
+ coff_addr cbLine; /* number of bytes for line number entries */
+ coff_addr cbLineOffset; /* offset to start of line number entries*/
+ coff_addr cbDnOffset; /* offset to start dense number table */
+ coff_addr cbPdOffset; /* offset to procedure descriptor table */
+ coff_addr cbSymOffset; /* offset to start of local symbols*/
+ coff_addr cbOptOffset; /* offset to optimization symbol entries */
+ coff_addr cbAuxOffset; /* offset to start of auxillary symbol entries*/
+ coff_addr cbSsOffset; /* offset to start of local strings */
+ coff_addr cbSsExtOffset; /* offset to start of external strings */
+ coff_addr cbFdOffset; /* offset to file descriptor table */
+ coff_addr cbRfdOffset; /* offset to relative file descriptor table */
+ coff_addr cbExtOffset; /* offset to start of external symbol entries*/
/* If you add machine dependent fields, add them here */
} HDRR, *pHDRR;
#define cbHDRR sizeof(HDRR)
@@ -138,39 +138,39 @@ typedef struct ecoff_symhdr {
*
* There is one of these for EVERY FILE, whether compiled with
* full debugging symbols or not. The name of a file should be
- * the path name given to the compiler. This allows the user
+ * the path name given to the compiler. This allows the user
* to simply specify the names of the directories where the COMPILES
* were done, and we will be able to find their files.
* A field whose comment starts with "R - " indicates that it will be
* setup at runtime.
*/
typedef struct ecoff_fdr {
- coff_addr adr; /* memory address of beginning of file */
- coff_addr cbLineOffset; /* byte offset from header for this file ln's */
- coff_addr cbLine; /* size of lines for this file */
- coff_addr cbSs; /* number of bytes in the ss */
- coff_int rss; /* file name (of source, if known) */
- coff_int issBase; /* file's string space */
- coff_int isymBase; /* beginning of symbols */
- coff_int csym; /* count file's of symbols */
- coff_int ilineBase; /* file's line symbols */
- coff_int cline; /* count of file's line symbols */
- coff_int ioptBase; /* file's optimization entries */
- coff_int copt; /* count of file's optimization entries */
- coff_int ipdFirst; /* start of procedures for this file */
- coff_int cpd; /* count of procedures for this file */
- coff_int iauxBase; /* file's auxiliary entries */
- coff_int caux; /* count of file's auxiliary entries */
- coff_int rfdBase; /* index into the file indirect table */
- coff_int crfd; /* count file indirect entries */
- unsigned lang: 5; /* language for this file */
- unsigned fMerge : 1; /* whether this file can be merged */
- unsigned fReadin : 1; /* true if it was read in (not just created) */
+ coff_addr adr; /* memory address of beginning of file */
+ coff_addr cbLineOffset; /* byte offset from header for this file ln's */
+ coff_addr cbLine; /* size of lines for this file */
+ coff_addr cbSs; /* number of bytes in the ss */
+ coff_int rss; /* file name (of source, if known) */
+ coff_int issBase; /* file's string space */
+ coff_int isymBase; /* beginning of symbols */
+ coff_int csym; /* count file's of symbols */
+ coff_int ilineBase; /* file's line symbols */
+ coff_int cline; /* count of file's line symbols */
+ coff_int ioptBase; /* file's optimization entries */
+ coff_int copt; /* count of file's optimization entries */
+ coff_int ipdFirst; /* start of procedures for this file */
+ coff_int cpd; /* count of procedures for this file */
+ coff_int iauxBase; /* file's auxiliary entries */
+ coff_int caux; /* count of file's auxiliary entries */
+ coff_int rfdBase; /* index into the file indirect table */
+ coff_int crfd; /* count file indirect entries */
+ unsigned lang: 5; /* language for this file */
+ unsigned fMerge : 1; /* whether this file can be merged */
+ unsigned fReadin : 1; /* true if it was read in (not just created) */
unsigned fBigendian : 1;/* if set, was compiled on big endian machine */
- /* aux's will be in compile host's sex */
- unsigned glevel : 2; /* level this file was compiled with */
+ /* aux's will be in compile host's sex */
+ unsigned glevel : 2; /* level this file was compiled with */
unsigned reserved : 22; /* reserved for future use */
- coff_uint reserved2;
+ coff_uint reserved2;
} FDR, *pFDR;
#define cbFDR sizeof(FDR)
#define fdNil ((pFDR)0)
@@ -189,31 +189,31 @@ typedef struct ecoff_fdr {
*/
typedef struct pdr {
- coff_addr adr; /* memory address of start of procedure */
- coff_addr cbLineOffset; /* byte offset for this procedure from the fd base */
- coff_int isym; /* start of local symbol entries */
- coff_int iline; /* start of line number entries*/
- coff_uint regmask; /* save register mask */
- coff_int regoffset; /* save register offset */
- coff_int iopt; /* start of optimization symbol entries*/
- coff_uint fregmask; /* save floating point register mask */
- coff_int fregoffset; /* save floating point register offset */
- coff_int frameoffset; /* frame size */
- coff_int lnLow; /* lowest line in the procedure */
- coff_int lnHigh; /* highest line in the procedure */
+ coff_addr adr; /* memory address of start of procedure */
+ coff_addr cbLineOffset; /* byte offset for this procedure from the fd base */
+ coff_int isym; /* start of local symbol entries */
+ coff_int iline; /* start of line number entries*/
+ coff_uint regmask; /* save register mask */
+ coff_int regoffset; /* save register offset */
+ coff_int iopt; /* start of optimization symbol entries*/
+ coff_uint fregmask; /* save floating point register mask */
+ coff_int fregoffset; /* save floating point register offset */
+ coff_int frameoffset; /* frame size */
+ coff_int lnLow; /* lowest line in the procedure */
+ coff_int lnHigh; /* highest line in the procedure */
/* These fields are new for 64 bit ECOFF. */
unsigned gp_prologue : 8; /* byte size of GP prologue */
- unsigned gp_used : 1; /* true if the procedure uses GP */
- unsigned reg_frame : 1; /* true if register frame procedure */
- unsigned prof : 1; /* true if compiled with -pg */
- unsigned reserved : 13; /* reserved: must be zero */
- unsigned localoff : 8; /* offset of local variables from vfp */
- coff_short framereg; /* frame pointer register */
- coff_short pcreg; /* offset or reg of return pc */
+ unsigned gp_used : 1; /* true if the procedure uses GP */
+ unsigned reg_frame : 1; /* true if register frame procedure */
+ unsigned prof : 1; /* true if compiled with -pg */
+ unsigned reserved : 13; /* reserved: must be zero */
+ unsigned localoff : 8; /* offset of local variables from vfp */
+ coff_short framereg; /* frame pointer register */
+ coff_short pcreg; /* offset or reg of return pc */
} PDR, *pPDR;
#define cbPDR sizeof(PDR)
#define pdNil ((pPDR) 0)
-#define ipdNil -1
+#define ipdNil -1
/*
* The structure of the runtime procedure descriptor created by the loader
@@ -225,16 +225,16 @@ typedef struct pdr {
*/
#if 0
typedef struct runtime_pdr {
- coff_addr adr; /* memory address of start of procedure */
- coff_uint regmask; /* save register mask */
- coff_int regoffset; /* save register offset */
- coff_uint fregmask; /* save floating point register mask */
- coff_int fregoffset; /* save floating point register offset */
- coff_int frameoffset; /* frame size */
- coff_ushort framereg; /* frame pointer register */
- coff_ushort pcreg; /* offset or reg of return pc */
- coff_int irpss; /* index into the runtime string table */
- coff_uint reserved;
+ coff_addr adr; /* memory address of start of procedure */
+ coff_uint regmask; /* save register mask */
+ coff_int regoffset; /* save register offset */
+ coff_uint fregmask; /* save floating point register mask */
+ coff_int fregoffset; /* save floating point register offset */
+ coff_int frameoffset; /* frame size */
+ coff_ushort framereg; /* frame pointer register */
+ coff_ushort pcreg; /* offset or reg of return pc */
+ coff_int irpss; /* index into the runtime string table */
+ coff_uint reserved;
struct exception_info *exception_info;/* pointer to exception array */
} RPDR, *pRPDR;
#define cbRPDR sizeof(RPDR)
@@ -253,24 +253,24 @@ typedef struct runtime_pdr {
* the first line of a procedure and represent the first address.
*/
-typedef coff_int LINER, *pLINER;
+typedef coff_int LINER, *pLINER;
#define lineNil ((pLINER)0)
#define cbLINER sizeof(LINER)
-#define ilineNil -1
+#define ilineNil -1
/*
- * The Symbol Structure (GFW, to those who Know!)
+ * The Symbol Structure (GFW, to those who Know!)
*/
typedef struct ecoff_sym {
- coff_long value; /* value of symbol */
- coff_int iss; /* index into String Space of name */
- unsigned st : 6; /* symbol type */
- unsigned sc : 5; /* storage class - text, data, etc */
- unsigned reserved : 1; /* reserved */
- unsigned index : 20; /* index into sym/aux table */
+ coff_long value; /* value of symbol */
+ coff_int iss; /* index into String Space of name */
+ unsigned st : 6; /* symbol type */
+ unsigned sc : 5; /* storage class - text, data, etc */
+ unsigned reserved : 1; /* reserved */
+ unsigned index : 20; /* index into sym/aux table */
} SYMR, *pSYMR;
#define symNil ((pSYMR)0)
#define cbSYMR sizeof(SYMR)
@@ -287,22 +287,22 @@ typedef struct ecoff_sym {
/* E X T E R N A L S Y M B O L R E C O R D
*
- * Same as the SYMR except it contains file context to determine where
- * the index is.
+ * Same as the SYMR except it contains file context to determine where
+ * the index is.
*/
typedef struct ecoff_extsym {
- SYMR asym; /* symbol for the external */
- unsigned jmptbl:1; /* symbol is a jump table entry for shlibs */
- unsigned cobol_main:1; /* symbol is a cobol main procedure */
- unsigned weakext:1; /* symbol is weak external */
- unsigned reserved:29; /* reserved for future use */
- coff_int ifd; /* where the iss and index fields point into */
+ SYMR asym; /* symbol for the external */
+ unsigned jmptbl:1; /* symbol is a jump table entry for shlibs */
+ unsigned cobol_main:1; /* symbol is a cobol main procedure */
+ unsigned weakext:1; /* symbol is weak external */
+ unsigned reserved:29; /* reserved for future use */
+ coff_int ifd; /* where the iss and index fields point into */
} EXTR, *pEXTR;
#define extNil ((pEXTR)0)
#define cbEXTR sizeof(EXTR)
-/* A U X I L L A R Y T Y P E I N F O R M A T I O N */
+/* A U X I L L A R Y T Y P E I N F O R M A T I O N */
/*
* Type Information Record
@@ -310,12 +310,12 @@ typedef struct ecoff_extsym {
typedef struct {
unsigned fBitfield : 1; /* set if bit width is specified */
unsigned continued : 1; /* indicates additional TQ info in next AUX */
- unsigned bt : 6; /* basic type */
+ unsigned bt : 6; /* basic type */
unsigned tq4 : 4;
unsigned tq5 : 4;
/* ---- 16 bit boundary ---- */
unsigned tq0 : 4;
- unsigned tq1 : 4; /* 6 type qualifiers - tqPtr, etc. */
+ unsigned tq1 : 4; /* 6 type qualifiers - tqPtr, etc. */
unsigned tq2 : 4;
unsigned tq3 : 4;
} TIR, *pTIR;
@@ -327,22 +327,22 @@ typedef struct {
* Relative symbol record
*
* If the rfd field is 4095, the index field indexes into the global symbol
- * table.
+ * table.
*/
typedef struct {
- unsigned rfd : 12; /* index into the file indirect table */
- unsigned index : 20; /* index int sym/aux/iss tables */
+ unsigned rfd : 12; /* index into the file indirect table */
+ unsigned index : 20; /* index int sym/aux/iss tables */
} RNDXR, *pRNDXR;
#define cbRNDXR sizeof(RNDXR)
#define rndxNil ((pRNDXR)0)
/* dense numbers or sometimes called block numbers are stored in this type,
- * a rfd of 0xffffffff is an index into the global table.
+ * a rfd of 0xffffffff is an index into the global table.
*/
typedef struct {
- coff_uint rfd; /* index into the file table */
- coff_uint index; /* index int sym/aux/iss tables */
+ coff_uint rfd; /* index into the file table */
+ coff_uint index; /* index int sym/aux/iss tables */
} DNR, *pDNR;
#define cbDNR sizeof(DNR)
#define dnNil ((pDNR)0)
@@ -353,36 +353,36 @@ typedef struct {
* Auxillary information occurs only if needed.
* It ALWAYS occurs in this order when present.
- isymMac used by stProc only
- TIR type info
- TIR additional TQ info (if first TIR was not enough)
- rndx if (bt == btStruct,btUnion,btEnum,btSet,btRange,
+ isymMac used by stProc only
+ TIR type info
+ TIR additional TQ info (if first TIR was not enough)
+ rndx if (bt == btStruct,btUnion,btEnum,btSet,btRange,
btTypedef):
rsym.index == iaux for btSet or btRange
else rsym.index == isym
- dimLow btRange, btSet
- dimMac btRange, btSet
- rndx0 As many as there are tq arrays
+ dimLow btRange, btSet
+ dimMac btRange, btSet
+ rndx0 As many as there are tq arrays
dimLow0
dimHigh0
...
rndxMax-1
dimLowMax-1
dimHighMax-1
- width in bits if (bit field), width in bits.
+ width in bits if (bit field), width in bits.
*/
#define cAuxMax (6 + (idimMax*3))
/* a union of all possible info in the AUX universe */
typedef union {
- TIR ti; /* type information record */
- RNDXR rndx; /* relative index into symbol table */
- coff_int dnLow; /* low dimension */
- coff_int dnHigh; /* high dimension */
- coff_int isym; /* symbol table index (end of proc) */
- coff_int iss; /* index into string space (not used) */
- coff_int width; /* width for non-default sized struc fields */
- coff_int count; /* count of ranges for variant arm */
+ TIR ti; /* type information record */
+ RNDXR rndx; /* relative index into symbol table */
+ coff_int dnLow; /* low dimension */
+ coff_int dnHigh; /* high dimension */
+ coff_int isym; /* symbol table index (end of proc) */
+ coff_int iss; /* index into string space (not used) */
+ coff_int width; /* width for non-default sized struc fields */
+ coff_int count; /* count of ranges for variant arm */
} AUXU, *pAUXU;
#define cbAUXU sizeof(AUXU)
#define auxNil ((pAUXU)0)
@@ -401,12 +401,12 @@ typedef union {
*/
typedef struct {
- unsigned ot: 8; /* optimization type */
- unsigned value: 24; /* address where we are moving it to */
- RNDXR rndx; /* points to a symbol or opt entry */
- coff_ulong offset; /* relative offset this occured */
+ unsigned ot: 8; /* optimization type */
+ unsigned value: 24; /* address where we are moving it to */
+ RNDXR rndx; /* points to a symbol or opt entry */
+ coff_ulong offset; /* relative offset this occured */
} OPTR, *pOPTR;
-#define optNil ((pOPTR) 0)
+#define optNil ((pOPTR) 0)
#define cbOPTR sizeof(OPTR)
#define ioptNil -1
@@ -414,15 +414,15 @@ typedef struct {
* File Indirect
*
* When a symbol is referenced across files the following procedure is used:
- * 1) use the file index to get the File indirect entry.
- * 2) use the file indirect entry to get the File descriptor.
- * 3) add the sym index to the base of that file's sym table
+ * 1) use the file index to get the File indirect entry.
+ * 2) use the file indirect entry to get the File descriptor.
+ * 3) add the sym index to the base of that file's sym table
*
*/
typedef coff_long RFDT, *pRFDT;
#define cbRFDT sizeof(RFDT)
-#define rfdNil -1
+#define rfdNil -1
/*
* The file indirect table in the mips loader is known as an array of FITs.
@@ -430,9 +430,9 @@ typedef coff_long RFDT, *pRFDT;
* these tables are merged. Note this is only a name change.
*/
typedef coff_int FIT, *pFIT;
-#define cbFIT sizeof(FIT)
-#define ifiNil -1
-#define fiNil ((pFIT) 0)
+#define cbFIT sizeof(FIT)
+#define ifiNil -1
+#define fiNil ((pFIT) 0)
#ifdef _LANGUAGE_PASCAL
#define ifdNil -1
@@ -448,18 +448,18 @@ typedef coff_int FIT, *pFIT;
#define ioptNil -1
#define rfdNil -1
#define ifiNil -1
-#endif /* _LANGUAGE_PASCAL */
+#endif /* _LANGUAGE_PASCAL */
/* Dense numbers
*
* Rather than use file index, symbol index pairs to represent symbols
- * and globals, we use dense number so that they can be easily embeded
- * in intermediate code and the programs that process them can
- * use direct access tabls instead of hash table (which would be
- * necesary otherwise because of the sparse name space caused by
- * file index, symbol index pairs. Dense number are represented
- * by RNDXRs.
+ * and globals, we use dense number so that they can be easily embeded
+ * in intermediate code and the programs that process them can
+ * use direct access tabls instead of hash table (which would be
+ * necesary otherwise because of the sparse name space caused by
+ * file index, symbol index pairs. Dense number are represented
+ * by RNDXRs.
*/
/*
@@ -467,7 +467,7 @@ typedef coff_int FIT, *pFIT;
* a function of the "st". (scD/B == scData OR scBss)
*
* Note: the value "isymMac" is used by symbols that have the concept
- * of enclosing a block of related information. This value is the
+ * of enclosing a block of related information. This value is the
* isym of the first symbol AFTER the end associated with the primary
* symbol. For example if a procedure was at isym==90 and had an
* isymMac==155, the associated end would be at isym==154, and the
@@ -477,42 +477,42 @@ typedef coff_int FIT, *pFIT;
* isym of the primary symbol that started the block.
*
-ST SC VALUE INDEX
--------- ------ -------- ------
-stFile scText address isymMac
-stLabel scText address ---
-stGlobal scD/B address iaux
-stStatic scD/B address iaux
-stParam scAbs offset iaux
-stLocal scAbs offset iaux
-stProc scText address iaux (isymMac is first AUX)
-stStaticProc scText address iaux (isymMac is first AUX)
-
-stMember scNil ordinal --- (if member of enum)
+ST SC VALUE INDEX
+-------- ------ -------- ------
+stFile scText address isymMac
+stLabel scText address ---
+stGlobal scD/B address iaux
+stStatic scD/B address iaux
+stParam scAbs offset iaux
+stLocal scAbs offset iaux
+stProc scText address iaux (isymMac is first AUX)
+stStaticProc scText address iaux (isymMac is first AUX)
+
+stMember scNil ordinal --- (if member of enum)
(mipsread thinks the case below has a bit, not byte, offset.)
-stMember scNil byte offset iaux (if member of struct/union)
-stMember scBits bit offset iaux (bit field spec)
+stMember scNil byte offset iaux (if member of struct/union)
+stMember scBits bit offset iaux (bit field spec)
-stBlock scText address isymMac (text block)
+stBlock scText address isymMac (text block)
(the code seems to think that rather than scNil, we see scInfo for
the two cases below.)
-stBlock scNil cb isymMac (struct/union member define)
-stBlock scNil cMembers isymMac (enum member define)
+stBlock scNil cb isymMac (struct/union member define)
+stBlock scNil cMembers isymMac (enum member define)
(New types added by SGI to simplify things:)
-stStruct scInfo cb isymMac (struct type define)
-stUnion scInfo cb isymMac (union type define)
-stEnum scInfo cMembers isymMac (enum type define)
+stStruct scInfo cb isymMac (struct type define)
+stUnion scInfo cb isymMac (union type define)
+stEnum scInfo cMembers isymMac (enum type define)
-stEnd scText address isymStart
-stEnd scNil ------- isymStart (struct/union/enum)
+stEnd scText address isymStart
+stEnd scNil ------- isymStart (struct/union/enum)
-stTypedef scNil ------- iaux
-stRegReloc sc??? value old register number
-stForward sc??? new address isym to original symbol
+stTypedef scNil ------- iaux
+stRegReloc sc??? value old register number
+stForward sc??? new address isym to original symbol
-stConstant scInfo value --- (scalar)
-stConstant scInfo iss --- (complex, e.g. string)
+stConstant scInfo value --- (scalar)
+stConstant scInfo iss --- (complex, e.g. string)
*
*/
diff --git a/src/base/loader/coff_symconst.h b/src/base/loader/coff_symconst.h
index f383c19e6..18529113f 100644
--- a/src/base/loader/coff_symconst.h
+++ b/src/base/loader/coff_symconst.h
@@ -59,30 +59,30 @@
*/
/* glevels for field in FDR */
-#define GLEVEL_0 2
-#define GLEVEL_1 1
-#define GLEVEL_2 0 /* for upward compat reasons. */
-#define GLEVEL_3 3
+#define GLEVEL_0 2
+#define GLEVEL_1 1
+#define GLEVEL_2 0 /* for upward compat reasons. */
+#define GLEVEL_3 3
/* magic number fo symheader */
-#define magicSym 0x7009
+#define magicSym 0x7009
/* The Alpha uses this value instead, for some reason. */
-#define magicSym2 0x1992
+#define magicSym2 0x1992
/* Language codes */
-#define langC 0
-#define langPascal 1
-#define langFortran 2
-#define langAssembler 3 /* one Assembley inst might map to many mach */
-#define langMachine 4
-#define langNil 5
-#define langAda 6
-#define langPl1 7
-#define langCobol 8
-#define langStdc 9 /* FIXME: Collides with SGI langCplusplus */
-#define langCplusplus 9 /* FIXME: Collides with langStdc */
-#define langCplusplusV2 10 /* SGI addition */
-#define langMax 11 /* maximun allowed 32 -- 5 bits */
+#define langC 0
+#define langPascal 1
+#define langFortran 2
+#define langAssembler 3 /* one Assembley inst might map to many mach */
+#define langMachine 4
+#define langNil 5
+#define langAda 6
+#define langPl1 7
+#define langCobol 8
+#define langStdc 9 /* FIXME: Collides with SGI langCplusplus */
+#define langCplusplus 9 /* FIXME: Collides with langStdc */
+#define langCplusplusV2 10 /* SGI addition */
+#define langMax 11 /* maximun allowed 32 -- 5 bits */
/* The following are value definitions for the fields in the SYMR */
@@ -90,111 +90,111 @@
* Storage Classes
*/
-#define scNil 0
-#define scText 1 /* text symbol */
-#define scData 2 /* initialized data symbol */
-#define scBss 3 /* un-initialized data symbol */
-#define scRegister 4 /* value of symbol is register number */
-#define scAbs 5 /* value of symbol is absolute */
-#define scUndefined 6 /* who knows? */
-#define scCdbLocal 7 /* variable's value is IN se->va.?? */
-#define scBits 8 /* this is a bit field */
-#define scCdbSystem 9 /* variable's value is IN CDB's address space */
-#define scDbx 9 /* overlap dbx internal use */
-#define scRegImage 10 /* register value saved on stack */
-#define scInfo 11 /* symbol contains debugger information */
-#define scUserStruct 12 /* address in struct user for current process */
-#define scSData 13 /* load time only small data */
-#define scSBss 14 /* load time only small common */
-#define scRData 15 /* load time only read only data */
-#define scVar 16 /* Var parameter (fortran,pascal) */
-#define scCommon 17 /* common variable */
-#define scSCommon 18 /* small common */
-#define scVarRegister 19 /* Var parameter in a register */
-#define scVariant 20 /* Variant record */
-#define scSUndefined 21 /* small undefined(external) data */
-#define scInit 22 /* .init section symbol */
-#define scBasedVar 23 /* Fortran or PL/1 ptr based var */
+#define scNil 0
+#define scText 1 /* text symbol */
+#define scData 2 /* initialized data symbol */
+#define scBss 3 /* un-initialized data symbol */
+#define scRegister 4 /* value of symbol is register number */
+#define scAbs 5 /* value of symbol is absolute */
+#define scUndefined 6 /* who knows? */
+#define scCdbLocal 7 /* variable's value is IN se->va.?? */
+#define scBits 8 /* this is a bit field */
+#define scCdbSystem 9 /* variable's value is IN CDB's address space */
+#define scDbx 9 /* overlap dbx internal use */
+#define scRegImage 10 /* register value saved on stack */
+#define scInfo 11 /* symbol contains debugger information */
+#define scUserStruct 12 /* address in struct user for current process */
+#define scSData 13 /* load time only small data */
+#define scSBss 14 /* load time only small common */
+#define scRData 15 /* load time only read only data */
+#define scVar 16 /* Var parameter (fortran,pascal) */
+#define scCommon 17 /* common variable */
+#define scSCommon 18 /* small common */
+#define scVarRegister 19 /* Var parameter in a register */
+#define scVariant 20 /* Variant record */
+#define scSUndefined 21 /* small undefined(external) data */
+#define scInit 22 /* .init section symbol */
+#define scBasedVar 23 /* Fortran or PL/1 ptr based var */
#define scXData 24 /* exception handling data */
#define scPData 25 /* Procedure section */
#define scFini 26 /* .fini section */
-#define scRConst 27 /* .rconst section */
-#define scMax 32
+#define scRConst 27 /* .rconst section */
+#define scMax 32
/*
* Symbol Types
*/
-#define stNil 0 /* Nuthin' special */
-#define stGlobal 1 /* external symbol */
-#define stStatic 2 /* static */
-#define stParam 3 /* procedure argument */
-#define stLocal 4 /* local variable */
-#define stLabel 5 /* label */
-#define stProc 6 /* " " Procedure */
-#define stBlock 7 /* beginnning of block */
-#define stEnd 8 /* end (of anything) */
-#define stMember 9 /* member (of anything - struct/union/enum */
-#define stTypedef 10 /* type definition */
-#define stFile 11 /* file name */
-#define stRegReloc 12 /* register relocation */
-#define stForward 13 /* forwarding address */
-#define stStaticProc 14 /* load time only static procs */
-#define stConstant 15 /* const */
-#define stStaParam 16 /* Fortran static parameters */
+#define stNil 0 /* Nuthin' special */
+#define stGlobal 1 /* external symbol */
+#define stStatic 2 /* static */
+#define stParam 3 /* procedure argument */
+#define stLocal 4 /* local variable */
+#define stLabel 5 /* label */
+#define stProc 6 /* " " Procedure */
+#define stBlock 7 /* beginnning of block */
+#define stEnd 8 /* end (of anything) */
+#define stMember 9 /* member (of anything - struct/union/enum */
+#define stTypedef 10 /* type definition */
+#define stFile 11 /* file name */
+#define stRegReloc 12 /* register relocation */
+#define stForward 13 /* forwarding address */
+#define stStaticProc 14 /* load time only static procs */
+#define stConstant 15 /* const */
+#define stStaParam 16 /* Fortran static parameters */
/* These new symbol types have been recently added to SGI machines. */
-#define stStruct 26 /* Beginning of block defining a struct type */
-#define stUnion 27 /* Beginning of block defining a union type */
-#define stEnum 28 /* Beginning of block defining an enum type */
-#define stIndirect 34 /* Indirect type specification */
+#define stStruct 26 /* Beginning of block defining a struct type */
+#define stUnion 27 /* Beginning of block defining a union type */
+#define stEnum 28 /* Beginning of block defining an enum type */
+#define stIndirect 34 /* Indirect type specification */
/* Pseudo-symbols - internal to debugger */
-#define stStr 60 /* string */
-#define stNumber 61 /* pure number (ie. 4 NOR 2+2) */
-#define stExpr 62 /* 2+2 vs. 4 */
-#define stType 63 /* post-coersion SER */
-#define stMax 64
+#define stStr 60 /* string */
+#define stNumber 61 /* pure number (ie. 4 NOR 2+2) */
+#define stExpr 62 /* 2+2 vs. 4 */
+#define stType 63 /* post-coersion SER */
+#define stMax 64
/* definitions for fields in TIR */
/* type qualifiers for ti.tq0 -> ti.(itqMax-1) */
-#define tqNil 0 /* bt is what you see */
-#define tqPtr 1 /* pointer */
-#define tqProc 2 /* procedure */
-#define tqArray 3 /* duh */
-#define tqFar 4 /* longer addressing - 8086/8 land */
-#define tqVol 5 /* volatile */
-#define tqConst 6 /* const */
-#define tqMax 8
+#define tqNil 0 /* bt is what you see */
+#define tqPtr 1 /* pointer */
+#define tqProc 2 /* procedure */
+#define tqArray 3 /* duh */
+#define tqFar 4 /* longer addressing - 8086/8 land */
+#define tqVol 5 /* volatile */
+#define tqConst 6 /* const */
+#define tqMax 8
/* basic types as seen in ti.bt */
-#define btNil 0 /* undefined (also, enum members) */
-#define btAdr 1 /* address - integer same size as pointer */
-#define btChar 2 /* character */
-#define btUChar 3 /* unsigned character */
-#define btShort 4 /* short */
-#define btUShort 5 /* unsigned short */
-#define btInt 6 /* int */
-#define btUInt 7 /* unsigned int */
-#define btLong 8 /* long */
-#define btULong 9 /* unsigned long */
-#define btFloat 10 /* float (real) */
-#define btDouble 11 /* Double (real) */
-#define btStruct 12 /* Structure (Record) */
-#define btUnion 13 /* Union (variant) */
-#define btEnum 14 /* Enumerated */
-#define btTypedef 15 /* defined via a typedef, isymRef points */
-#define btRange 16 /* subrange of int */
-#define btSet 17 /* pascal sets */
-#define btComplex 18 /* fortran complex */
-#define btDComplex 19 /* fortran double complex */
-#define btIndirect 20 /* forward or unnamed typedef */
-#define btFixedDec 21 /* Fixed Decimal */
-#define btFloatDec 22 /* Float Decimal */
-#define btString 23 /* Varying Length Character String */
-#define btBit 24 /* Aligned Bit String */
-#define btPicture 25 /* Picture */
-#define btVoid 26 /* void */
-#define btLongLong 27 /* long long */
-#define btULongLong 28 /* unsigned long long */
-#define btMax 64
+#define btNil 0 /* undefined (also, enum members) */
+#define btAdr 1 /* address - integer same size as pointer */
+#define btChar 2 /* character */
+#define btUChar 3 /* unsigned character */
+#define btShort 4 /* short */
+#define btUShort 5 /* unsigned short */
+#define btInt 6 /* int */
+#define btUInt 7 /* unsigned int */
+#define btLong 8 /* long */
+#define btULong 9 /* unsigned long */
+#define btFloat 10 /* float (real) */
+#define btDouble 11 /* Double (real) */
+#define btStruct 12 /* Structure (Record) */
+#define btUnion 13 /* Union (variant) */
+#define btEnum 14 /* Enumerated */
+#define btTypedef 15 /* defined via a typedef, isymRef points */
+#define btRange 16 /* subrange of int */
+#define btSet 17 /* pascal sets */
+#define btComplex 18 /* fortran complex */
+#define btDComplex 19 /* fortran double complex */
+#define btIndirect 20 /* forward or unnamed typedef */
+#define btFixedDec 21 /* Fixed Decimal */
+#define btFloatDec 22 /* Float Decimal */
+#define btString 23 /* Varying Length Character String */
+#define btBit 24 /* Aligned Bit String */
+#define btPicture 25 /* Picture */
+#define btVoid 26 /* void */
+#define btLongLong 27 /* long long */
+#define btULongLong 28 /* unsigned long long */
+#define btMax 64
diff --git a/src/base/loader/ecoff_object.cc b/src/base/loader/ecoff_object.cc
index a5a0ad9a4..d1719f1c6 100644
--- a/src/base/loader/ecoff_object.cc
+++ b/src/base/loader/ecoff_object.cc
@@ -34,7 +34,7 @@
#include "base/misc.hh"
#include "base/loader/symtab.hh"
-#include "base/trace.hh" // for DPRINTF
+#include "base/trace.hh" // for DPRINTF
#include "base/loader/exec_ecoff.h"
#include "base/loader/coff_sym.h"
diff --git a/src/base/loader/elf_object.cc b/src/base/loader/elf_object.cc
index 8e41ffd16..16fc698dd 100644
--- a/src/base/loader/elf_object.cc
+++ b/src/base/loader/elf_object.cc
@@ -29,6 +29,7 @@
* Ali Saidi
*/
+#include <cassert>
#include <string>
#include "gelf.h"
@@ -36,7 +37,7 @@
#include "base/loader/elf_object.hh"
#include "base/loader/symtab.hh"
#include "base/misc.hh"
-#include "base/trace.hh" // for DPRINTF
+#include "base/trace.hh" // for DPRINTF
#include "sim/byteswap.hh"
using namespace std;
@@ -79,13 +80,19 @@ ElfObject::tryFile(const string &fname, int fd, size_t len, uint8_t *data)
arch = ObjectFile::SPARC32;
} else if (ehdr.e_machine == EM_MIPS
&& ehdr.e_ident[EI_CLASS] == ELFCLASS32) {
- arch = ObjectFile::Mips;
+ if (ehdr.e_ident[EI_DATA] == ELFDATA2LSB) {
+ arch = ObjectFile::Mips;
+ } else {
+ fatal("The binary you're trying to load is compiled for big "
+ "endian MIPS. M5\nonly supports little endian MIPS. "
+ "Please recompile your binary.\n");
+ }
} else if (ehdr.e_machine == EM_X86_64 &&
ehdr.e_ident[EI_CLASS] == ELFCLASS64) {
- //In the future, we might want to differentiate between 32 bit
- //and 64 bit x86 processes in case there are differences in their
- //initial stack frame.
- arch = ObjectFile::X86;
+ arch = ObjectFile::X86_64;
+ } else if (ehdr.e_machine == EM_386 &&
+ ehdr.e_ident[EI_CLASS] == ELFCLASS32) {
+ arch = ObjectFile::I386;
} else if (ehdr.e_ident[EI_CLASS] == ELFCLASS64) {
arch = ObjectFile::Alpha;
} else if (ehdr.e_machine == EM_ARM) {
@@ -284,6 +291,8 @@ ElfObject::ElfObject(const string &_filename, int _fd,
data.size = phdr.p_filesz;
data.fileImage = fileData + phdr.p_offset;
} else {
+ // If it's none of the above but is loadable,
+ // load the filesize worth of data
Segment extra;
extra.baseAddr = phdr.p_paddr;
extra.size = phdr.p_filesz;
diff --git a/src/base/loader/hex_file.cc b/src/base/loader/hex_file.cc
index 1855ebe0c..61d6c8009 100755
--- a/src/base/loader/hex_file.cc
+++ b/src/base/loader/hex_file.cc
@@ -28,134 +28,111 @@
* Authors: Jaidev Patwardhan
*/
+#include <cctype>
+#include <cstdio>
#include <list>
#include <string>
-#include <sys/types.h>
-#include <sys/mman.h>
-#include <fcntl.h>
-#include <stdio.h>
-#include <unistd.h>
-
#include "base/cprintf.hh"
#include "base/loader/hex_file.hh"
#include "base/loader/symtab.hh"
-
-
#include "mem/translating_port.hh"
using namespace std;
-/* Load a Hex File into memory.
- Currently only used with MIPS BARE_IRON mode.
- A hex file consists of [Address Data] tuples that get directly loaded into
- physical memory. The address specified is a word address (i.e., to get the byte address, shift left by 2)
- The data is a full 32-bit hex value.
+/*
+ * Load a Hex File into memory. Currently only used with MIPS
+ * BARE_IRON mode. A hex file consists of [Address Data] tuples that
+ * get directly loaded into physical memory. The address specified is
+ * a word address (i.e., to get the byte address, shift left by 2) The
+ * data is a full 32-bit hex value.
*/
HexFile::HexFile(const string _filename)
: filename(_filename)
{
- fp = fopen(filename.c_str(),"r");
- if(fp == NULL)
- {
- panic("Unable to open %s\n",filename.c_str());
- }
-
+ fp = fopen(filename.c_str(), "r");
+ if (fp == NULL)
+ panic("Unable to open %s\n", filename.c_str());
}
HexFile::~HexFile()
{
}
-
bool
-HexFile::loadSections(Port *memPort, Addr addrMask)
+HexFile::loadSections(Port *memPort)
{
- char Line[64];
- Addr MemAddr;
- uint32_t Data;
- while(!feof(fp))
- {
- fgets(Line,64,fp);
- parseLine(Line,&MemAddr,&Data);
- // printf("Hex:%u\n",Data);
-
- if(MemAddr != 0)
- {
- // Now, write to memory
- memPort->writeBlob(MemAddr<<2,(uint8_t *)&Data,sizeof(Data));
+ char Line[64];
+ Addr MemAddr;
+ uint32_t Data;
+ while (!feof(fp)) {
+ char *ret = fgets(Line, sizeof(Line), fp);
+ if (!ret)
+ panic("malformed file");
+ parseLine(Line, &MemAddr, &Data);
+ if (MemAddr != 0) {
+ // Now, write to memory
+ memPort->writeBlob(MemAddr << 2, (uint8_t *)&Data, sizeof(Data));
}
}
return true;
}
-void HexFile::parseLine(char *Str,Addr *A, uint32_t *D)
-{
- int i=0;
- bool Flag = false;
- *A = 0;
- *D = 0;
- int Digit = 0;
- unsigned Number = 0;
- /* Skip white spaces */
- while(Str[i] != '\0' && Str[i]==' ')
- i++;
- /* Ok, we're at some character...process things */
- while(Str[i] != '\0')
- {
- if(Str[i]>='0' && Str[i]<='9')
- {
- Digit=Str[i]-'0';
- }
- else if(Str[i]>='a' && Str[i]<='f')
- {
- Digit=Str[i]-'a'+10;
- }
- else if(Str[i]>='A' && Str[i]<='F')
- {
+void
+HexFile::parseLine(char *Str, Addr *A, uint32_t *D)
+{
+ int i = 0;
+ bool Flag = false;
+ *A = 0;
+ *D = 0;
+ int Digit = 0;
+ unsigned Number = 0;
+
+ /* Skip white spaces */
+ while (Str[i] != '\0' && Str[i]==' ')
+ i++;
+
+ /* Ok, we're at some character...process things */
+ while (Str[i] != '\0') {
+ if (Str[i] >= '0' && Str[i] <= '9') {
+ Digit = Str[i] - '0';
+ } else if (Str[i] >= 'a' && Str[i] <= 'f') {
+ Digit = Str[i] - 'a' + 10;
+ } else if (Str[i] >= 'A' && Str[i] <= 'F') {
Digit=Str[i]-'A'+10;
- }
- else if(Str[i] == ' ' || Str[i]=='\n')
- {
- if(Number == 0)
- return;
- if(Flag == false)
- {
- *A = Number;
- Number = 0;
- Flag = true;
- }
- else
- {
- *D = Number;
- return;
+ } else if (Str[i] == ' ' || Str[i] == '\n') {
+ if (Number == 0)
+ return;
+ if (Flag == false) {
+ *A = Number;
+ Number = 0;
+ Flag = true;
+ } else {
+ *D = Number;
+ return;
}
+ } else {
+ // Ok, we've encountered a non-hex character, cannot be a
+ // valid line, skip and return 0's
+ *A = 0;
+ *D = 0;
+ return;
}
- else
- {
- // Ok, we've encountered a non-hex character, cannot be a valid line, skip and return 0's
- *A = 0;
- *D = 0;
- return;
- }
- Number<<=4;
- Number+=Digit;
- i++;
+ Number <<= 4;
+ Number += Digit;
+ i++;
}
- if(Flag != true)
- {
- *A = 0;
- *D = 0;
- }
- else
- *D = Number;
+ if (Flag != true) {
+ *A = 0;
+ *D = 0;
+ } else {
+ *D = Number;
+ }
}
-
-
void
HexFile::close()
{
- fclose(fp);
+ fclose(fp);
}
diff --git a/src/base/loader/hex_file.hh b/src/base/loader/hex_file.hh
index 1dbfd034f..40483e684 100755
--- a/src/base/loader/hex_file.hh
+++ b/src/base/loader/hex_file.hh
@@ -28,50 +28,31 @@
* Authors: Jaidev Patwardhan
*/
-#ifndef __HEX_FILE_HH__
-#define __HEX_FILE_HH__
+#ifndef __BASE_LOADER_HEX_FILE_HH__
+#define __BASE_LOADER_HEX_FILE_HH__
+#include <cstdio>
#include <limits>
#include <string>
-#include "sim/host.hh" // for Addr
-#include <fstream>
+#include "sim/host.hh" // for Addr
class Port;
class HexFile
{
- public:
-
-
protected:
const std::string filename;
FILE *fp;
+ void parseLine(char *, Addr *, uint32_t *);
+
public:
- virtual ~HexFile();
HexFile(const std::string _filename);
+ virtual ~HexFile();
void close();
-
- bool loadSections(Port *memPort, Addr addrMask =
- std::numeric_limits<Addr>::max());
-
- protected:
-
- typedef struct {
- Addr MemAddr;
- uint32_t Data;
- } HexLine;
-
- Addr entry;
- Addr globalPtr;
-
- public:
- void parseLine(char *,Addr *,uint32_t *);
- Addr entryPoint() const { return entry; }
- Addr globalPointer() const { return globalPtr; }
-
+ bool loadSections(Port *memPort);
};
-#endif // __HEX_FILE_HH__
+#endif // __BASE_LOADER_HEX_FILE_HH__
diff --git a/src/base/loader/object_file.hh b/src/base/loader/object_file.hh
index 7f2bef0bf..d363cde84 100644
--- a/src/base/loader/object_file.hh
+++ b/src/base/loader/object_file.hh
@@ -35,7 +35,7 @@
#include <limits>
#include <string>
-#include "sim/host.hh" // for Addr
+#include "sim/host.hh" // for Addr
class Port;
class SymbolTable;
@@ -50,7 +50,8 @@ class ObjectFile
SPARC64,
SPARC32,
Mips,
- X86,
+ X86_64,
+ I386,
Arm
};
diff --git a/src/base/loader/symtab.hh b/src/base/loader/symtab.hh
index 184c0a996..cc1dc368f 100644
--- a/src/base/loader/symtab.hh
+++ b/src/base/loader/symtab.hh
@@ -34,8 +34,9 @@
#include <iosfwd>
#include <map>
+#include <string>
-#include "sim/host.hh" // for Addr
+#include "sim/host.hh" // for Addr
class Checkpoint;
class SymbolTable
diff --git a/src/base/misc.cc b/src/base/misc.cc
index afb48ca80..035282baf 100644
--- a/src/base/misc.cc
+++ b/src/base/misc.cc
@@ -28,8 +28,10 @@
* Authors: Nathan Binkert
*/
+#include <cstdlib>
#include <iostream>
#include <string>
+#include <zlib.h>
#include "base/cprintf.hh"
#include "base/hostinfo.hh"
@@ -42,42 +44,24 @@
using namespace std;
-void
-__panic(const char *func, const char *file, int line, const char *fmt,
- CPRINTF_DEFINITION)
-{
- string format = "panic: ";
- format += fmt;
- switch (format[format.size() - 1]) {
- case '\n':
- case '\r':
- break;
- default:
- format += "\n";
- }
-
- format += " @ cycle %d\n[%s:%s, line %d]\n";
-
- CPrintfArgsList args(VARARGS_ALLARGS);
-
- args.push_back(curTick);
- args.push_back(func);
- args.push_back(file);
- args.push_back(line);
+bool want_warn = true;
+bool want_info = true;
+bool want_hack = true;
- ccprintf(cerr, format.c_str(), args);
-
- abort();
-}
+bool warn_verbose = false;
+bool info_verbose = false;
+bool hack_verbose = false;
void
-__fatal(const char *func, const char *file, int line, const char *fmt,
- CPRINTF_DEFINITION)
+__exit_message(const char *prefix, int code,
+ const char *func, const char *file, int line,
+ const char *fmt, CPRINTF_DEFINITION)
{
CPrintfArgsList args(VARARGS_ALLARGS);
- string format = "fatal: ";
- format += fmt;
+ string format = prefix;
+ format += ": ";
+ format += fmt;
switch (format[format.size() - 1]) {
case '\n':
case '\r':
@@ -85,28 +69,39 @@ __fatal(const char *func, const char *file, int line, const char *fmt,
default:
format += "\n";
}
+
+ uint32_t crc = crc32(0, (const Bytef*)fmt, strlen(fmt));
format += " @ cycle %d\n[%s:%s, line %d]\n";
format += "Memory Usage: %ld KBytes\n";
+ format += "For more information see: http://www.m5sim.org/%s/%x\n";
args.push_back(curTick);
args.push_back(func);
args.push_back(file);
args.push_back(line);
args.push_back(memUsage());
+ args.push_back(prefix);
+ args.push_back(crc);
ccprintf(cerr, format.c_str(), args);
- exit(1);
+ if (code < 0)
+ abort();
+ else
+ exit(code);
}
void
-__warn(const char *func, const char *file, int line, const char *fmt,
- CPRINTF_DEFINITION)
+__base_message(std::ostream &stream, const char *prefix, bool verbose,
+ const char *func, const char *file, int line,
+ const char *fmt, CPRINTF_DEFINITION)
{
- string format = "warn: ";
- format += fmt;
+ CPrintfArgsList args(VARARGS_ALLARGS);
+ string format = prefix;
+ format += ": ";
+ format += fmt;
switch (format[format.size() - 1]) {
case '\n':
case '\r':
@@ -114,21 +109,22 @@ __warn(const char *func, const char *file, int line, const char *fmt,
default:
format += "\n";
}
+
+ uint32_t crc = crc32(0, (const Bytef*)fmt, strlen(fmt));
+
+ if (verbose) {
+ format += " @ cycle %d\n[%s:%s, line %d]\n";
+ args.push_back(curTick);
+ args.push_back(func);
+ args.push_back(file);
+ args.push_back(line);
+ }
-#ifdef VERBOSE_WARN
- format += " @ cycle %d\n[%s:%s, line %d]\n";
-#endif
-
- CPrintfArgsList args(VARARGS_ALLARGS);
-
-#ifdef VERBOSE_WARN
- args.push_back(curTick);
- args.push_back(func);
- args.push_back(file);
- args.push_back(line);
-#endif
+ if (strcmp(prefix, "warn") == 0) {
+ format += "For more information see: http://www.m5sim.org/%s/%x\n";
+ args.push_back(prefix);
+ args.push_back(crc);
+ }
- ccprintf(cerr, format.c_str(), args);
- if (simout.isFile(*outputStream))
- ccprintf(*outputStream, format.c_str(), args);
+ ccprintf(stream, format.c_str(), args);
}
diff --git a/src/base/misc.hh b/src/base/misc.hh
index 1509ea2d2..25dcbaa62 100644
--- a/src/base/misc.hh
+++ b/src/base/misc.hh
@@ -29,10 +29,8 @@
* Dave Greene
*/
-#ifndef __MISC_HH__
-#define __MISC_HH__
-
-#include <cassert>
+#ifndef __BASE_MISC_HH__
+#define __BASE_MISC_HH__
#include "base/compiler.hh"
#include "base/cprintf.hh"
@@ -42,6 +40,30 @@
#define __FUNCTION__ "how to fix me?"
#endif
+// General exit message, these functions will never return and will
+// either abort() if code is < 0 or exit with the code if >= 0
+void __exit_message(const char *prefix, int code,
+ const char *func, const char *file, int line,
+ const char *format, CPRINTF_DECLARATION) M5_ATTR_NORETURN;
+
+void __exit_message(const char *prefix, int code,
+ const char *func, const char *file, int line,
+ const std::string &format, CPRINTF_DECLARATION) M5_ATTR_NORETURN;
+
+inline void
+__exit_message(const char *prefix, int code,
+ const char *func, const char *file, int line,
+ const std::string& format, CPRINTF_DEFINITION)
+{
+ __exit_message(prefix, code, func, file, line, format.c_str(),
+ VARARGS_ALLARGS);
+}
+
+M5_PRAGMA_NORETURN(__exit_message)
+#define exit_message(prefix, code, ...) \
+ __exit_message(prefix, code, __FUNCTION__, __FILE__, __LINE__, \
+ __VA_ARGS__)
+
//
// This implements a cprintf based panic() function. panic() should
// be called when something happens that should never ever happen
@@ -49,20 +71,7 @@
// calls abort which can dump core or enter the debugger.
//
//
-void __panic(const char *func, const char *file, int line, const char *format,
- CPRINTF_DECLARATION) M5_ATTR_NORETURN;
-void __panic(const char *func, const char *file, int line,
- const std::string &format, CPRINTF_DECLARATION)
-M5_ATTR_NORETURN;
-
-inline void
-__panic(const char *func, const char *file, int line,
- const std::string &format, CPRINTF_DEFINITION)
-{
- __panic(func, file, line, format.c_str(), VARARGS_ALLARGS);
-}
-M5_PRAGMA_NORETURN(__panic)
-#define panic(...) __panic(__FUNCTION__, __FILE__, __LINE__, __VA_ARGS__)
+#define panic(...) exit_message("panic", -1, __VA_ARGS__)
//
// This implements a cprintf based fatal() function. fatal() should
@@ -72,54 +81,70 @@ M5_PRAGMA_NORETURN(__panic)
// "normal" exit with an error code, as opposed to abort() like
// panic() does.
//
-void __fatal(const char *func, const char *file, int line, const char *format,
- CPRINTF_DECLARATION) M5_ATTR_NORETURN;
-void __fatal(const char *func, const char *file, int line,
- const std::string &format, CPRINTF_DECLARATION)
- M5_ATTR_NORETURN;
+#define fatal(...) exit_message("fatal", 1, __VA_ARGS__)
-inline void
-__fatal(const char *func, const char *file, int line,
- const std::string &format, CPRINTF_DEFINITION)
-{
- __fatal(func, file, line, format.c_str(), VARARGS_ALLARGS);
-}
-M5_PRAGMA_NORETURN(__fatal)
-#define fatal(...) __fatal(__FUNCTION__, __FILE__, __LINE__, __VA_ARGS__)
+void
+__base_message(std::ostream &stream, const char *prefix, bool verbose,
+ const char *func, const char *file, int line,
+ const char *format, CPRINTF_DECLARATION);
-//
-// This implements a cprintf based warn
-//
-void __warn(const char *func, const char *file, int line, const char *format,
- CPRINTF_DECLARATION);
inline void
-__warn(const char *func, const char *file, int line, const std::string &format,
- CPRINTF_DECLARATION)
+__base_message(std::ostream &stream, const char *prefix, bool verbose,
+ const char *func, const char *file, int line,
+ const std::string &format, CPRINTF_DECLARATION)
{
- __warn(func, file, line, format, VARARGS_ALLARGS);
+ __base_message(stream, prefix, verbose, func, file, line, format.c_str(),
+ VARARGS_ALLARGS);
}
-#define warn(...) __warn(__FUNCTION__, __FILE__, __LINE__, __VA_ARGS__)
-
-// Only print the warning message the first time it is seen. This
-// doesn't check the warning string itself, it just only lets one
-// warning come from the statement. So, even if the arguments change
-// and that would have resulted in a different warning message,
-// subsequent messages would still be supressed.
-#define warn_once(...) do { \
- static bool once = false; \
- if (!once) { \
- warn(__VA_ARGS__); \
- once = true; \
- } \
+
+#define base_message(stream, prefix, verbose, ...) \
+ __base_message(stream, prefix, verbose, __FUNCTION__, __FILE__, __LINE__, \
+ __VA_ARGS__)
+
+// Only print the message the first time this expression is
+// encountered. i.e. This doesn't check the string itself and
+// prevent duplicate strings, this prevents the statement from
+// happening more than once. So, even if the arguments change and that
+// would have resulted in a different message thoes messages would be
+// supressed.
+#define base_message_once(...) do { \
+ static bool once = false; \
+ if (!once) { \
+ base_message(__VA_ARGS__); \
+ once = true; \
+ } \
} while (0)
-//
-// assert() that prints out the current cycle
-//
-#define m5_assert(TEST) do { \
- if (!(TEST)) \
- ccprintf(std::cerr, "Assertion failure, curTick = %d\n", curTick); \
- assert(TEST); \
-} while (0)
+#define cond_message(cond, ...) do { \
+ if (cond) \
+ base_message(__VA_ARGS__); \
+ } while (0)
+
+#define cond_message_once(cond, ...) do { \
+ static bool once = false; \
+ if (!once && cond) { \
+ base_message(__VA_ARGS__); \
+ once = true; \
+ } \
+ } while (0)
+
+
+extern bool want_warn, warn_verbose;
+extern bool want_info, info_verbose;
+extern bool want_hack, hack_verbose;
+
+#define warn(...) \
+ cond_message(want_warn, std::cerr, "warn", warn_verbose, __VA_ARGS__)
+#define inform(...) \
+ cond_message(want_info, std::cout, "info", info_verbose, __VA_ARGS__)
+#define hack(...) \
+ cond_message(want_hack, std::cerr, "hack", hack_verbose, __VA_ARGS__)
+
+#define warn_once(...) \
+ cond_message_once(want_warn, std::cerr, "warn", warn_verbose, __VA_ARGS__)
+#define inform_once(...) \
+ cond_message_once(want_info, std::cout, "info", info_verbose, __VA_ARGS__)
+#define hack_once(...) \
+ cond_message_once(want_hack, std::cerr, "hack", hack_verbose, __VA_ARGS__)
-#endif // __MISC_HH__
+#endif // __BASE_MISC_HH__
diff --git a/src/base/output.cc b/src/base/output.cc
index 9d02a4a71..ea13e23d4 100644
--- a/src/base/output.cc
+++ b/src/base/output.cc
@@ -36,6 +36,8 @@
#include <fstream>
+#include <gzstream.hh>
+
#include "base/misc.hh"
#include "base/output.hh"
@@ -50,7 +52,45 @@ OutputDirectory::OutputDirectory()
{}
OutputDirectory::~OutputDirectory()
-{}
+{
+ for (map_t::iterator i = files.begin(); i != files.end(); i++) {
+ if (i->second)
+ delete i->second;
+ }
+}
+
+std::ostream *
+OutputDirectory::checkForStdio(const string &name) const
+{
+ if (name == "cerr" || name == "stderr")
+ return &cerr;
+
+ if (name == "cout" || name == "stdout")
+ return &cout;
+
+ return NULL;
+}
+
+ostream *
+OutputDirectory::openFile(const string &filename,
+ ios_base::openmode mode) const
+{
+ if (filename.find(".gz", filename.length()-3) < filename.length()) {
+ ogzstream *file = new ogzstream(filename.c_str(), mode);
+
+ if (!file->is_open())
+ fatal("Cannot open file %s", filename);
+
+ return file;
+ } else {
+ ofstream *file = new ofstream(filename.c_str(), mode);
+
+ if (!file->is_open())
+ fatal("Cannot open file %s", filename);
+
+ return file;
+ }
+}
void
OutputDirectory::setDirectory(const string &d)
@@ -60,19 +100,13 @@ OutputDirectory::setDirectory(const string &d)
dir = d;
- if (dir != ".") {
- if (mkdir(dir.c_str(), 0777) < 0 && errno != EEXIST)
- panic("couldn't make output dir %s: %s\n",
- dir, strerror(errno));
- }
-
// guarantee that directory ends with a '/'
if (dir[dir.size() - 1] != '/')
dir += "/";
}
const string &
-OutputDirectory::directory()
+OutputDirectory::directory() const
{
if (dir.empty())
panic("Output directory not set!");
@@ -80,8 +114,8 @@ OutputDirectory::directory()
return dir;
}
-string
-OutputDirectory::resolve(const string &name)
+inline string
+OutputDirectory::resolve(const string &name) const
{
return (name[0] != '/') ? dir + name : name;
}
@@ -89,16 +123,14 @@ OutputDirectory::resolve(const string &name)
ostream *
OutputDirectory::create(const string &name, bool binary)
{
- if (name == "cerr" || name == "stderr")
- return &cerr;
-
- if (name == "cout" || name == "stdout")
- return &cout;
+ ostream *file = checkForStdio(name);
+ if (file)
+ return file;
- ofstream *file = new ofstream(resolve(name).c_str(),
- ios::trunc | binary ? ios::binary : (ios::openmode)0);
- if (!file->is_open())
- panic("Cannot open file %s", name);
+ string filename = resolve(name);
+ ios_base::openmode mode =
+ ios::trunc | binary ? ios::binary : (ios::openmode)0;
+ file = openFile(filename, mode);
return file;
}
@@ -106,21 +138,16 @@ OutputDirectory::create(const string &name, bool binary)
ostream *
OutputDirectory::find(const string &name)
{
- if (name == "cerr" || name == "stderr")
- return &cerr;
-
- if (name == "cout" || name == "stdout")
- return &cout;
+ ostream *file = checkForStdio(name);
+ if (file)
+ return file;
string filename = resolve(name);
map_t::iterator i = files.find(filename);
if (i != files.end())
return (*i).second;
- ofstream *file = new ofstream(filename.c_str(), ios::trunc);
- if (!file->is_open())
- panic("Cannot open file %s", filename);
-
+ file = openFile(filename);
files[filename] = file;
return file;
}
diff --git a/src/base/output.hh b/src/base/output.hh
index 5de0c4005..38c63714c 100644
--- a/src/base/output.hh
+++ b/src/base/output.hh
@@ -31,7 +31,7 @@
#ifndef __BASE_OUTPUT_HH__
#define __BASE_OUTPUT_HH__
-#include <iosfwd>
+#include <ios>
#include <map>
#include <string>
@@ -43,14 +43,20 @@ class OutputDirectory
map_t files;
std::string dir;
+ std::string resolve(const std::string &name) const;
+
+ protected:
+ std::ostream *checkForStdio(const std::string &name) const;
+ std::ostream *openFile(const std::string &filename,
+ std::ios_base::openmode mode = std::ios::trunc) const;
+
public:
OutputDirectory();
~OutputDirectory();
void setDirectory(const std::string &dir);
- const std::string &directory();
+ const std::string &directory() const;
- std::string resolve(const std::string &name);
std::ostream *create(const std::string &name, bool binary = false);
std::ostream *find(const std::string &name);
diff --git a/src/base/random_mt.cc b/src/base/random_mt.cc
index 1492240ee..6ea54ec03 100644
--- a/src/base/random_mt.cc
+++ b/src/base/random_mt.cc
@@ -123,15 +123,15 @@ Random::genrand()
int kk;
for (kk = 0; kk < N - M; kk++) {
- y = mt[kk] & UPPER_MASK | mt[kk+1] & LOWER_MASK;
+ y = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK);
mt[kk] = mt[kk + M] ^ (y >> 1) ^ mag01[y & 0x1UL];
}
for (; kk < N - 1; kk++) {
- y = mt[kk] & UPPER_MASK | mt[kk+1] & LOWER_MASK;
+ y = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK);
mt[kk] = mt[kk + (M - N)] ^ (y >> 1) ^ mag01[y & 0x1UL];
}
- y = mt[N - 1] & UPPER_MASK | mt[0] & LOWER_MASK;
+ y = (mt[N - 1] & UPPER_MASK) | (mt[0] & LOWER_MASK);
mt[N - 1] = mt[M - 1] ^ (y >> 1) ^ mag01[y & 0x1UL];
mti = 0;
diff --git a/src/base/range_map.hh b/src/base/range_map.hh
index 6d3450739..0ffc28ed9 100644
--- a/src/base/range_map.hh
+++ b/src/base/range_map.hh
@@ -46,7 +46,8 @@ class range_map
typedef typename RangeMap::iterator iterator;
template <class U>
- const iterator find(const Range<U> &r)
+ const iterator
+ find(const Range<U> &r)
{
iterator i;
@@ -69,7 +70,15 @@ class range_map
}
template <class U>
- bool intersect(const Range<U> &r)
+ const iterator
+ find(const U &r)
+ {
+ return find(RangeSize(r, 1));
+ }
+
+ template <class U>
+ bool
+ intersect(const Range<U> &r)
{
iterator i;
i = find(r);
@@ -80,7 +89,8 @@ class range_map
template <class U,class W>
- iterator insert(const Range<U> &r, const W d)
+ iterator
+ insert(const Range<U> &r, const W d)
{
if (intersect(r))
return tree.end();
@@ -88,42 +98,50 @@ class range_map
return tree.insert(std::make_pair<Range<T>,V>(r, d)).first;
}
- size_t erase(T k)
+ size_t
+ erase(T k)
{
return tree.erase(k);
}
- void erase(iterator p)
+ void
+ erase(iterator p)
{
tree.erase(p);
}
- void erase(iterator p, iterator q)
+ void
+ erase(iterator p, iterator q)
{
tree.erase(p,q);
}
- void clear()
+ void
+ clear()
{
tree.erase(tree.begin(), tree.end());
}
- iterator begin()
+ iterator
+ begin()
{
return tree.begin();
}
- iterator end()
+ iterator
+ end()
{
return tree.end();
}
- size_t size()
+ size_t
+ size()
{
return tree.size();
}
- bool empty()
+ bool
+ empty()
{
return tree.empty();
}
@@ -180,7 +198,8 @@ class range_multimap
}
template <class U>
- bool intersect(const Range<U> &r)
+ bool
+ intersect(const Range<U> &r)
{
std::pair<iterator,iterator> p;
p = find(r);
@@ -191,7 +210,8 @@ class range_multimap
template <class U,class W>
- iterator insert(const Range<U> &r, const W d)
+ iterator
+ insert(const Range<U> &r, const W d)
{
std::pair<iterator,iterator> p;
p = find(r);
@@ -202,42 +222,50 @@ class range_multimap
return tree.end();
}
- size_t erase(T k)
+ size_t
+ erase(T k)
{
return tree.erase(k);
}
- void erase(iterator p)
+ void
+ erase(iterator p)
{
tree.erase(p);
}
- void erase(iterator p, iterator q)
+ void
+ erase(iterator p, iterator q)
{
tree.erase(p,q);
}
- void clear()
+ void
+ clear()
{
tree.erase(tree.begin(), tree.end());
}
- iterator begin()
+ iterator
+ begin()
{
return tree.begin();
}
- iterator end()
+ iterator
+ end()
{
return tree.end();
}
- size_t size()
+ size_t
+ size()
{
return tree.size();
}
- bool empty()
+ bool
+ empty()
{
return tree.empty();
}
diff --git a/src/base/remote_gdb.cc b/src/base/remote_gdb.cc
index d5095e7f9..93d86447e 100644
--- a/src/base/remote_gdb.cc
+++ b/src/base/remote_gdb.cc
@@ -30,7 +30,7 @@
/*
* Copyright (c) 1990, 1993
- * The Regents of the University of California. All rights reserved.
+ * The Regents of the University of California. All rights reserved.
*
* This software was developed by the Computer Systems Engineering group
* at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
@@ -38,8 +38,8 @@
*
* All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Lawrence Berkeley Laboratories.
+ * This product includes software developed by the University of
+ * California, Lawrence Berkeley Laboratories.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -51,8 +51,8 @@
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
@@ -69,7 +69,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)kgdb_stub.c 8.4 (Berkeley) 1/12/94
+ * @(#)kgdb_stub.c 8.4 (Berkeley) 1/12/94
*/
/*-
@@ -89,8 +89,8 @@
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
- * This product includes software developed by the NetBSD
- * Foundation, Inc. and its contributors.
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
* 4. Neither the name of The NetBSD Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
@@ -195,6 +195,11 @@ GDBListener::name()
void
GDBListener::listen()
{
+ if (ListenSocket::allDisabled()) {
+ warn_once("Sockets disabled, not accepting gdb connections");
+ return;
+ }
+
while (!listener.listen(port, true)) {
DPRINTF(GDBMisc, "Can't bind port %d\n", port);
port++;
@@ -341,14 +346,16 @@ uint8_t
BaseRemoteGDB::getbyte()
{
uint8_t b;
- ::read(fd, &b, 1);
+ if (::read(fd, &b, 1) != 1)
+ warn("could not read byte from debugger");
return b;
}
void
BaseRemoteGDB::putbyte(uint8_t b)
{
- ::write(fd, &b, 1);
+ if (::write(fd, &b, 1) != 1)
+ warn("could not write byte to debugger");
}
// Send a packet to gdb
@@ -454,14 +461,11 @@ BaseRemoteGDB::read(Addr vaddr, size_t size, char *data)
DPRINTF(GDBRead, "read: addr=%#x, size=%d", vaddr, size);
#if FULL_SYSTEM
- VirtualPort *port = context->getVirtPort(context);
+ VirtualPort *port = context->getVirtPort();
#else
TranslatingPort *port = context->getMemPort();
#endif
port->readBlob(vaddr, (uint8_t*)data, size);
-#if FULL_SYSTEM
- context->delVirtPort(port);
-#endif
#if TRACING_ON
if (DTRACE(GDBRead)) {
@@ -499,14 +503,12 @@ BaseRemoteGDB::write(Addr vaddr, size_t size, const char *data)
DPRINTFNR("\n");
}
#if FULL_SYSTEM
- VirtualPort *port = context->getVirtPort(context);
+ VirtualPort *port = context->getVirtPort();
#else
TranslatingPort *port = context->getMemPort();
#endif
port->writeBlob(vaddr, (uint8_t*)data, size);
-#if FULL_SYSTEM
- context->delVirtPort(port);
-#else
+#if !FULL_SYSTEM
delete port;
#endif
diff --git a/src/base/res_list.hh b/src/base/res_list.hh
index 442280e15..024b56982 100644
--- a/src/base/res_list.hh
+++ b/src/base/res_list.hh
@@ -635,7 +635,7 @@ res_list<T>::remove(iterator q)
// A little "garbage collection"
if (++remove_count > 10) {
- // free_extras();
+ // free_extras();
remove_count = 0;
}
diff --git a/src/base/sat_counter.hh b/src/base/sat_counter.hh
index 79de11156..38c4ec74f 100644
--- a/src/base/sat_counter.hh
+++ b/src/base/sat_counter.hh
@@ -64,13 +64,13 @@ class SaturatingCounterPred : public GenericPredictor
unsigned *table;
// Statistics
- Stats::Scalar<> predicted_one; // Total predictions of one, preds_one
- Stats::Scalar<> predicted_zero; // Total predictions of zero, preds_zero
- Stats::Scalar<> correct_pred_one; // Total correct predictions of one, correct_one
- Stats::Scalar<> correct_pred_zero; // Total correct predictions of zero, correct_zero
+ Stats::Scalar predicted_one; // Total predictions of one, preds_one
+ Stats::Scalar predicted_zero; // Total predictions of zero, preds_zero
+ Stats::Scalar correct_pred_one; // Total correct predictions of one, correct_one
+ Stats::Scalar correct_pred_zero; // Total correct predictions of zero, correct_zero
- Stats::Scalar<> record_zero; //updates_zero
- Stats::Scalar<> record_one; //updates_one
+ Stats::Scalar record_zero; //updates_zero
+ Stats::Scalar record_one; //updates_one
Stats::Formula preds_total;
Stats::Formula pred_frac_zero;
diff --git a/src/base/socket.cc b/src/base/socket.cc
index adcc48735..bcc5236b0 100644
--- a/src/base/socket.cc
+++ b/src/base/socket.cc
@@ -43,6 +43,23 @@
using namespace std;
+bool ListenSocket::listeningDisabled = false;
+bool ListenSocket::anyListening = false;
+
+void
+ListenSocket::disableAll()
+{
+ if (anyListening)
+ panic("Too late to disable all listeners, already have a listener");
+ listeningDisabled = true;
+}
+
+bool
+ListenSocket::allDisabled()
+{
+ return listeningDisabled;
+}
+
////////////////////////////////////////////////////////////////////////
//
//
@@ -92,6 +109,7 @@ ListenSocket::listen(int port, bool reuse)
listening = true;
+ anyListening = true;
return true;
}
diff --git a/src/base/socket.hh b/src/base/socket.hh
index 8e55eae72..942318e45 100644
--- a/src/base/socket.hh
+++ b/src/base/socket.hh
@@ -34,6 +34,14 @@
class ListenSocket
{
protected:
+ static bool listeningDisabled;
+ static bool anyListening;
+
+ public:
+ static void disableAll();
+ static bool allDisabled();
+
+ protected:
bool listening;
int fd;
diff --git a/src/base/statistics.cc b/src/base/statistics.cc
index 2acef83c5..0a59248e7 100644
--- a/src/base/statistics.cc
+++ b/src/base/statistics.cc
@@ -32,81 +32,106 @@
#include <fstream>
#include <list>
#include <map>
+#include <set>
#include <string>
#include "base/callback.hh"
#include "base/cprintf.hh"
+#include "base/debug.hh"
#include "base/hostinfo.hh"
#include "base/misc.hh"
#include "base/statistics.hh"
#include "base/str.hh"
#include "base/time.hh"
#include "base/trace.hh"
-#include "base/stats/statdb.hh"
using namespace std;
namespace Stats {
-StatData *
-DataAccess::find() const
+typedef map<const void *, Info *> MapType;
+
+// We wrap these in a function to make sure they're built in time.
+list<Info *> &
+statsList()
{
- return Database::find(const_cast<void *>((const void *)this));
+ static list<Info *> the_list;
+ return the_list;
}
-const StatData *
-getStatData(const void *stat)
+MapType &
+statsMap()
{
- return Database::find(const_cast<void *>(stat));
+ static MapType the_map;
+ return the_map;
}
void
-DataAccess::map(StatData *data)
+InfoAccess::setInfo(Info *info)
{
- Database::regStat(this, data);
+ if (statsMap().find(this) != statsMap().end())
+ panic("shouldn't register stat twice!");
+
+ statsList().push_back(info);
+
+#ifndef NDEBUG
+ pair<MapType::iterator, bool> result =
+#endif
+ statsMap().insert(make_pair(this, info));
+ assert(result.second && "this should never fail");
+ assert(statsMap().find(this) != statsMap().end());
}
-StatData *
-DataAccess::statData()
+void
+InfoAccess::setParams(const StorageParams *params)
{
- StatData *ptr = find();
- assert(ptr);
- return ptr;
+ info()->storageParams = params;
}
-const StatData *
-DataAccess::statData() const
+void
+InfoAccess::setInit()
{
- const StatData *ptr = find();
- assert(ptr);
- return ptr;
+ info()->flags |= init;
}
-void
-DataAccess::setInit()
+Info *
+InfoAccess::info()
{
- statData()->flags |= init;
+ MapType::const_iterator i = statsMap().find(this);
+ assert(i != statsMap().end());
+ return (*i).second;
}
-void
-DataAccess::setPrint()
+const Info *
+InfoAccess::info() const
{
- Database::regPrint(this);
+ MapType::const_iterator i = statsMap().find(this);
+ assert(i != statsMap().end());
+ return (*i).second;
}
-StatData::StatData()
- : flags(none), precision(-1), prereq(0)
+StorageParams::~StorageParams()
{
- static int count = 0;
- id = count++;
}
-StatData::~StatData()
+int Info::id_count = 0;
+
+int debug_break_id = -1;
+
+Info::Info()
+ : flags(none), precision(-1), prereq(0), storageParams(NULL)
+{
+ id = id_count++;
+ if (debug_break_id >= 0 and debug_break_id == id)
+ debug_break();
+}
+
+Info::~Info()
{
}
bool
-StatData::less(StatData *stat1, StatData *stat2)
+Info::less(Info *stat1, Info *stat2)
{
const string &name1 = stat1->name;
const string &name2 = stat2->name;
@@ -117,8 +142,8 @@ StatData::less(StatData *stat1, StatData *stat2)
tokenize(v1, name1, '.');
tokenize(v2, name2, '.');
- int last = min(v1.size(), v2.size()) - 1;
- for (int i = 0; i < last; ++i)
+ size_type last = min(v1.size(), v2.size()) - 1;
+ for (off_type i = 0; i < last; ++i)
if (v1[i] != v2[i])
return v1[i] < v2[i];
@@ -132,9 +157,9 @@ StatData::less(StatData *stat1, StatData *stat2)
}
bool
-StatData::baseCheck() const
+Info::baseCheck() const
{
- if (!(flags & init)) {
+ if (!(flags & Stats::init)) {
#ifdef DEBUG
cprintf("this is stat number %d\n", id);
#endif
@@ -150,54 +175,40 @@ StatData::baseCheck() const
return true;
}
-
void
-FormulaBase::result(VResult &vec) const
-{
- if (root)
- vec = root->result();
-}
-
-Result
-FormulaBase::total() const
-{
- return root ? root->total() : 0.0;
-}
-
-size_t
-FormulaBase::size() const
+Info::enable()
{
- if (!root)
- return 0;
- else
- return root->size();
}
void
-FormulaBase::reset()
+VectorInfoBase::enable()
{
-}
-
-bool
-FormulaBase::zero() const
-{
- VResult vec;
- result(vec);
- for (int i = 0; i < vec.size(); ++i)
- if (vec[i] != 0.0)
- return false;
- return true;
+ size_type s = size();
+ if (subnames.size() < s)
+ subnames.resize(s);
+ if (subdescs.size() < s)
+ subdescs.resize(s);
}
void
-FormulaBase::update(StatData *)
+VectorDistInfoBase::enable()
{
+ size_type s = size();
+ if (subnames.size() < s)
+ subnames.resize(s);
+ if (subdescs.size() < s)
+ subdescs.resize(s);
}
-string
-FormulaBase::str() const
+void
+Vector2dInfoBase::enable()
{
- return root ? root->str() : "";
+ if (subnames.size() < x)
+ subnames.resize(x);
+ if (subdescs.size() < x)
+ subdescs.resize(x);
+ if (y_subnames.size() < y)
+ y_subnames.resize(y);
}
Formula::Formula()
@@ -232,38 +243,86 @@ Formula::operator+=(Temp r)
}
void
-check()
+Formula::result(VResult &vec) const
{
- typedef Database::stat_list_t::iterator iter_t;
-
- iter_t i, end = Database::stats().end();
- for (i = Database::stats().begin(); i != end; ++i) {
- StatData *data = *i;
- assert(data);
- if (!data->check() || !data->baseCheck())
- panic("stat check failed for %s\n", data->name);
- }
+ if (root)
+ vec = root->result();
+}
- int j = 0;
- for (i = Database::stats().begin(); i != end; ++i) {
- StatData *data = *i;
- if (!(data->flags & print))
- data->name = "__Stat" + to_string(j++);
- }
+Result
+Formula::total() const
+{
+ return root ? root->total() : 0.0;
+}
+
+size_type
+Formula::size() const
+{
+ if (!root)
+ return 0;
+ else
+ return root->size();
+}
+
+void
+Formula::reset()
+{
+}
+
+bool
+Formula::zero() const
+{
+ VResult vec;
+ result(vec);
+ for (off_t i = 0; i < vec.size(); ++i)
+ if (vec[i] != 0.0)
+ return false;
+ return true;
+}
- Database::stats().sort(StatData::less);
+string
+Formula::str() const
+{
+ return root ? root->str() : "";
+}
- if (i == end)
- return;
+void
+enable()
+{
+ typedef list<Info *>::iterator iter_t;
+
+ iter_t i, end = statsList().end();
+ for (i = statsList().begin(); i != end; ++i) {
+ Info *info = *i;
+ assert(info);
+ if (!info->check() || !info->baseCheck())
+ panic("stat check failed for '%s' %d\n", info->name, info->id);
+ }
- iter_t last = i;
- ++i;
+ off_t j = 0;
+ for (i = statsList().begin(); i != end; ++i) {
+ Info *info = *i;
+ if (!(info->flags & print))
+ info->name = "__Stat" + to_string(j++);
+ }
- for (i = Database::stats().begin(); i != end; ++i) {
- if ((*i)->name == (*last)->name)
- panic("same name used twice! name=%s\n", (*i)->name);
+ statsList().sort(Info::less);
+
+ for (i = statsList().begin(); i != end; ++i) {
+ Info *info = *i;
+ info->enable();
+ }
+}
- last = i;
+void
+prepare()
+{
+ list<Info *>::iterator i = statsList().begin();
+ list<Info *>::iterator end = statsList().end();
+ while (i != end) {
+ Info *info = *i;
+ info->prepare();
+ ++i;
}
}
@@ -272,11 +331,11 @@ CallbackQueue resetQueue;
void
reset()
{
- Database::stat_list_t::iterator i = Database::stats().begin();
- Database::stat_list_t::iterator end = Database::stats().end();
+ list<Info *>::iterator i = statsList().begin();
+ list<Info *>::iterator end = statsList().end();
while (i != end) {
- StatData *data = *i;
- data->reset();
+ Info *info = *i;
+ info->reset();
++i;
}
diff --git a/src/base/statistics.hh b/src/base/statistics.hh
index 3a859d364..88704207d 100644
--- a/src/base/statistics.hh
+++ b/src/base/statistics.hh
@@ -26,7 +26,6 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Nathan Binkert
- * Erik Hallnor
*/
/** @file
@@ -56,9 +55,11 @@
#include <cmath>
#include <functional>
#include <iosfwd>
+#include <list>
#include <string>
#include <vector>
+#include "base/cast.hh"
#include "base/cprintf.hh"
#include "base/intmath.hh"
#include "base/refcnt.hh"
@@ -76,14 +77,19 @@ extern Tick curTick;
/* A namespace for all of the Statistics */
namespace Stats {
-/* Contains the statistic implementation details */
+struct StorageParams
+{
+ virtual ~StorageParams();
+};
+
//////////////////////////////////////////////////////////////////////
//
// Statistics Framework Base classes
//
//////////////////////////////////////////////////////////////////////
-struct StatData
+class Info
{
+ public:
/** The name of the stat. */
std::string name;
/** The description of the stat. */
@@ -93,18 +99,41 @@ struct StatData
/** The display precision. */
int precision;
/** A pointer to a prerequisite Stat. */
- const StatData *prereq;
+ const Info *prereq;
/**
* A unique stat ID for each stat in the simulator.
* Can be used externally for lookups as well as for debugging.
*/
+ static int id_count;
int id;
- StatData();
- virtual ~StatData();
+ public:
+ const StorageParams *storageParams;
+
+ public:
+ Info();
+ virtual ~Info();
+
+ /**
+ * Check that this stat has been set up properly and is ready for
+ * use
+ * @return true for success
+ */
+ virtual bool check() const = 0;
+ bool baseCheck() const;
+
+ /**
+ * Enable the stat for use
+ */
+ virtual void enable();
+
+ /**
+ * Prepare the stat for dumping.
+ */
+ virtual void prepare() = 0;
/**
- * Reset the corresponding stat to the default state.
+ * Reset the stat to the default state.
*/
virtual void reset() = 0;
@@ -115,14 +144,6 @@ struct StatData
virtual bool zero() const = 0;
/**
- * Check that this stat has been set up properly and is ready for
- * use
- * @return true for success
- */
- virtual bool check() const = 0;
- bool baseCheck() const;
-
- /**
* Visitor entry for outputing statistics data
*/
virtual void visit(Visit &visitor) = 0;
@@ -135,94 +156,95 @@ struct StatData
* @param stat2 The second stat.
* @return stat1's name is alphabetically before stat2's
*/
- static bool less(StatData *stat1, StatData *stat2);
+ static bool less(Info *stat1, Info *stat2);
+};
+
+template <class Stat, class Base>
+class InfoWrap : public Base
+{
+ protected:
+ Stat &s;
+
+ public:
+ InfoWrap(Stat &stat) : s(stat) {}
+
+ bool check() const { return s.check(); }
+ void prepare() { s.prepare(); }
+ void reset() { s.reset(); }
+ void
+ visit(Visit &visitor)
+ {
+ visitor.visit(*static_cast<Base *>(this));
+ }
+ bool zero() const { return s.zero(); }
};
-class ScalarData : public StatData
+class ScalarInfoBase : public Info
{
public:
virtual Counter value() const = 0;
virtual Result result() const = 0;
virtual Result total() const = 0;
- virtual void visit(Visit &visitor) { visitor.visit(*this); }
};
template <class Stat>
-class ScalarStatData : public ScalarData
+class ScalarInfo : public InfoWrap<Stat, ScalarInfoBase>
{
- protected:
- Stat &s;
-
public:
- ScalarStatData(Stat &stat) : s(stat) {}
+ ScalarInfo(Stat &stat) : InfoWrap<Stat, ScalarInfoBase>(stat) {}
- virtual bool check() const { return s.check(); }
- virtual Counter value() const { return s.value(); }
- virtual Result result() const { return s.result(); }
- virtual Result total() const { return s.total(); }
- virtual void reset() { s.reset(); }
- virtual bool zero() const { return s.zero(); }
+ Counter value() const { return this->s.value(); }
+ Result result() const { return this->s.result(); }
+ Result total() const { return this->s.total(); }
};
-struct VectorData : public StatData
+class VectorInfoBase : public Info
{
+ public:
/** Names and descriptions of subfields. */
- mutable std::vector<std::string> subnames;
- mutable std::vector<std::string> subdescs;
+ std::vector<std::string> subnames;
+ std::vector<std::string> subdescs;
+
+ public:
+ void enable();
- virtual size_t size() const = 0;
+ public:
+ virtual size_type size() const = 0;
virtual const VCounter &value() const = 0;
virtual const VResult &result() const = 0;
- virtual Result total() const = 0;
- void update()
- {
- if (!subnames.empty()) {
- int s = size();
- if (subnames.size() < s)
- subnames.resize(s);
-
- if (subdescs.size() < s)
- subdescs.resize(s);
- }
- }
+ virtual Result total() const = 0;
};
template <class Stat>
-class VectorStatData : public VectorData
+class VectorInfo : public InfoWrap<Stat, VectorInfoBase>
{
protected:
- Stat &s;
mutable VCounter cvec;
mutable VResult rvec;
public:
- VectorStatData(Stat &stat) : s(stat) {}
+ VectorInfo(Stat &stat) : InfoWrap<Stat, VectorInfoBase>(stat) {}
- virtual bool check() const { return s.check(); }
- virtual bool zero() const { return s.zero(); }
- virtual void reset() { s.reset(); }
+ size_type size() const { return this->s.size(); }
- virtual size_t size() const { return s.size(); }
- virtual VCounter &value() const
+ VCounter &
+ value() const
{
- s.value(cvec);
+ this->s.value(cvec);
return cvec;
}
- virtual const VResult &result() const
+
+ const VResult &
+ result() const
{
- s.result(rvec);
+ this->s.result(rvec);
return rvec;
}
- virtual Result total() const { return s.total(); }
- virtual void visit(Visit &visitor)
- {
- update();
- s.update(this);
- visitor.visit(*this);
- }
+
+ Result total() const { return this->s.total(); }
};
-struct DistDataData
+struct DistData
{
Counter min_val;
Counter max_val;
@@ -232,173 +254,146 @@ struct DistDataData
Counter sum;
Counter squares;
Counter samples;
-
- Counter min;
- Counter max;
- Counter bucket_size;
- int size;
- bool fancy;
};
-struct DistData : public StatData
+class DistInfoBase : public Info
{
+ public:
/** Local storage for the entry values, used for printing. */
- DistDataData data;
+ DistData data;
};
template <class Stat>
-class DistStatData : public DistData
+class DistInfo : public InfoWrap<Stat, DistInfoBase>
{
- protected:
- Stat &s;
-
public:
- DistStatData(Stat &stat) : s(stat) {}
-
- virtual bool check() const { return s.check(); }
- virtual void reset() { s.reset(); }
- virtual bool zero() const { return s.zero(); }
- virtual void visit(Visit &visitor)
- {
- s.update(this);
- visitor.visit(*this);
- }
+ DistInfo(Stat &stat) : InfoWrap<Stat, DistInfoBase>(stat) {}
};
-struct VectorDistData : public StatData
+class VectorDistInfoBase : public Info
{
- std::vector<DistDataData> data;
+ public:
+ std::vector<DistData> data;
- /** Names and descriptions of subfields. */
- mutable std::vector<std::string> subnames;
- mutable std::vector<std::string> subdescs;
+ /** Names and descriptions of subfields. */
+ std::vector<std::string> subnames;
+ std::vector<std::string> subdescs;
+ void enable();
+ protected:
/** Local storage for the entry values, used for printing. */
mutable VResult rvec;
- virtual size_t size() const = 0;
- void update()
- {
- int s = size();
- if (subnames.size() < s)
- subnames.resize(s);
-
- if (subdescs.size() < s)
- subdescs.resize(s);
- }
+ public:
+ virtual size_type size() const = 0;
};
template <class Stat>
-class VectorDistStatData : public VectorDistData
+class VectorDistInfo : public InfoWrap<Stat, VectorDistInfoBase>
{
- protected:
- Stat &s;
-
public:
- VectorDistStatData(Stat &stat) : s(stat) {}
+ VectorDistInfo(Stat &stat) : InfoWrap<Stat, VectorDistInfoBase>(stat) {}
- virtual bool check() const { return s.check(); }
- virtual void reset() { s.reset(); }
- virtual size_t size() const { return s.size(); }
- virtual bool zero() const { return s.zero(); }
- virtual void visit(Visit &visitor)
- {
- update();
- s.update(this);
- visitor.visit(*this);
- }
+ size_type size() const { return this->s.size(); }
};
-struct Vector2dData : public StatData
+class Vector2dInfoBase : public Info
{
+ public:
/** Names and descriptions of subfields. */
std::vector<std::string> subnames;
std::vector<std::string> subdescs;
std::vector<std::string> y_subnames;
+ size_type x;
+ size_type y;
+
/** Local storage for the entry values, used for printing. */
mutable VCounter cvec;
- mutable int x;
- mutable int y;
- void update()
- {
- if (subnames.size() < x)
- subnames.resize(x);
- }
+ void enable();
};
template <class Stat>
-class Vector2dStatData : public Vector2dData
+class Vector2dInfo : public InfoWrap<Stat, Vector2dInfoBase>
{
- protected:
- Stat &s;
-
public:
- Vector2dStatData(Stat &stat) : s(stat) {}
-
- virtual bool check() const { return s.check(); }
- virtual void reset() { s.reset(); }
- virtual bool zero() const { return s.zero(); }
- virtual void visit(Visit &visitor)
- {
- update();
- s.update(this);
- visitor.visit(*this);
- }
+ Vector2dInfo(Stat &stat) : InfoWrap<Stat, Vector2dInfoBase>(stat) {}
};
-class DataAccess
+class InfoAccess
{
protected:
- StatData *find() const;
- void map(StatData *data);
+ /** Set up an info class for this statistic */
+ void setInfo(Info *info);
+ /** Save Storage class parameters if any */
+ void setParams(const StorageParams *params);
+ /** Save Storage class parameters if any */
+ void setInit();
- StatData *statData();
- const StatData *statData() const;
+ /** Grab the information class for this statistic */
+ Info *info();
+ /** Grab the information class for this statistic */
+ const Info *info() const;
- void setInit();
- void setPrint();
+ public:
+ /**
+ * Reset the stat to the default state.
+ */
+ void reset() { }
+
+ /**
+ * @return true if this stat has a value and satisfies its
+ * requirement as a prereq
+ */
+ bool zero() const { return true; }
+
+ /**
+ * Check that this stat has been set up properly and is ready for
+ * use
+ * @return true for success
+ */
+ bool check() const { return true; }
};
-template <class Parent, class Child, template <class> class Data>
-class Wrap : public Child
+template <class Derived, template <class> class InfoType>
+class DataWrap : public InfoAccess
{
+ public:
+ typedef InfoType<Derived> Info;
+
protected:
- Parent &self() { return *reinterpret_cast<Parent *>(this); }
+ Derived &self() { return *static_cast<Derived *>(this); }
protected:
- Data<Child> *statData()
+ Info *
+ info()
{
- StatData *__data = DataAccess::statData();
- Data<Child> *ptr = dynamic_cast<Data<Child> *>(__data);
- assert(ptr);
- return ptr;
+ return safe_cast<Info *>(InfoAccess::info());
}
public:
- const Data<Child> *statData() const
+ const Info *
+ info() const
{
- const StatData *__data = DataAccess::statData();
- const Data<Child> *ptr = dynamic_cast<const Data<Child> *>(__data);
- assert(ptr);
- return ptr;
+ return safe_cast<const Info *>(InfoAccess::info());
}
protected:
/**
* Copy constructor, copies are not allowed.
*/
- Wrap(const Wrap &stat);
+ DataWrap(const DataWrap &stat);
+
/**
* Can't copy stats.
*/
- void operator=(const Wrap &);
+ void operator=(const DataWrap &);
public:
- Wrap()
+ DataWrap()
{
- this->map(new Data<Child>(*this));
+ this->setInfo(new Info(self()));
}
/**
@@ -406,13 +401,15 @@ class Wrap : public Child
* @param name The new name.
* @return A reference to this stat.
*/
- Parent &name(const std::string &_name)
+ Derived &
+ name(const std::string &_name)
{
- Data<Child> *data = this->statData();
- data->name = _name;
- this->setPrint();
+ Info *info = this->info();
+ info->name = _name;
+ info->flags |= print;
return this->self();
}
+ const std::string &name() const { return this->info()->name; }
/**
* Set the description and marks this stat to print at the end of
@@ -420,20 +417,22 @@ class Wrap : public Child
* @param desc The new description.
* @return A reference to this stat.
*/
- Parent &desc(const std::string &_desc)
+ Derived &
+ desc(const std::string &_desc)
{
- this->statData()->desc = _desc;
+ this->info()->desc = _desc;
return this->self();
}
/**
* Set the precision and marks this stat to print at the end of simulation.
- * @param p The new precision
+ * @param _precision The new precision
* @return A reference to this stat.
*/
- Parent &precision(int _precision)
+ Derived &
+ precision(int _precision)
{
- this->statData()->precision = _precision;
+ this->info()->precision = _precision;
return this->self();
}
@@ -442,9 +441,10 @@ class Wrap : public Child
* @param f The new flags.
* @return A reference to this stat.
*/
- Parent &flags(StatFlags _flags)
+ Derived &
+ flags(StatFlags _flags)
{
- this->statData()->flags |= _flags;
+ this->info()->flags |= _flags;
return this->self();
}
@@ -455,17 +455,20 @@ class Wrap : public Child
* @return A reference to this stat.
*/
template <class Stat>
- Parent &prereq(const Stat &prereq)
+ Derived &
+ prereq(const Stat &prereq)
{
- this->statData()->prereq = prereq.statData();
+ this->info()->prereq = prereq.info();
return this->self();
}
};
-template <class Parent, class Child, template <class Child> class Data>
-class WrapVec : public Wrap<Parent, Child, Data>
+template <class Derived, template <class> class InfoType>
+class DataWrapVec : public DataWrap<Derived, InfoType>
{
public:
+ typedef InfoType<Derived> Info;
+
// The following functions are specific to vectors. If you use them
// in a non vector context, you will get a nice compiler error!
@@ -476,15 +479,23 @@ class WrapVec : public Wrap<Parent, Child, Data>
* @param name The new name of the subfield.
* @return A reference to this stat.
*/
- Parent &subname(int index, const std::string &name)
+ Derived &
+ subname(off_type index, const std::string &name)
{
- std::vector<std::string> &subn = this->statData()->subnames;
+ Derived &self = this->self();
+ Info *info = self.info();
+
+ std::vector<std::string> &subn = info->subnames;
if (subn.size() <= index)
subn.resize(index + 1);
subn[index] = name;
- return this->self();
+ return self;
}
+ // The following functions are specific to 2d vectors. If you use
+ // them in a non vector context, you will get a nice compiler
+ // error because info doesn't have the right variables.
+
/**
* Set the subfield description for the given index and marks this stat to
* print at the end of simulation.
@@ -492,9 +503,12 @@ class WrapVec : public Wrap<Parent, Child, Data>
* @param desc The new description of the subfield
* @return A reference to this stat.
*/
- Parent &subdesc(int index, const std::string &desc)
+ Derived &
+ subdesc(off_type index, const std::string &desc)
{
- std::vector<std::string> &subd = this->statData()->subdescs;
+ Info *info = this->info();
+
+ std::vector<std::string> &subd = info->subdescs;
if (subd.size() <= index)
subd.resize(index + 1);
subd[index] = desc;
@@ -502,31 +516,61 @@ class WrapVec : public Wrap<Parent, Child, Data>
return this->self();
}
+ void
+ prepare()
+ {
+ Derived &self = this->self();
+ Info *info = this->info();
+
+ size_t size = self.size();
+ for (off_type i = 0; i < size; ++i)
+ self.data(i)->prepare(info);
+ }
+
+ void
+ reset()
+ {
+ Derived &self = this->self();
+ Info *info = this->info();
+
+ size_t size = self.size();
+ for (off_type i = 0; i < size; ++i)
+ self.data(i)->reset(info);
+ }
};
-template <class Parent, class Child, template <class Child> class Data>
-class WrapVec2d : public WrapVec<Parent, Child, Data>
+template <class Derived, template <class> class InfoType>
+class DataWrapVec2d : public DataWrapVec<Derived, InfoType>
{
public:
+ typedef InfoType<Derived> Info;
+
/**
* @warning This makes the assumption that if you're gonna subnames a 2d
* vector, you're subnaming across all y
*/
- Parent &ysubnames(const char **names)
+ Derived &
+ ysubnames(const char **names)
{
- Data<Child> *data = this->statData();
- data->y_subnames.resize(this->y);
- for (int i = 0; i < this->y; ++i)
- data->y_subnames[i] = names[i];
- return this->self();
+ Derived &self = this->self();
+ Info *info = this->info();
+
+ info->y_subnames.resize(self.y);
+ for (off_type i = 0; i < self.y; ++i)
+ info->y_subnames[i] = names[i];
+ return self;
}
- Parent &ysubname(int index, const std::string subname)
+
+ Derived &
+ ysubname(off_type index, const std::string subname)
{
- Data<Child> *data = this->statData();
- assert(index < this->y);
- data->y_subnames.resize(this->y);
- data->y_subnames[index] = subname.c_str();
- return this->self();
+ Derived &self = this->self();
+ Info *info = this->info();
+
+ assert(index < self.y);
+ info->y_subnames.resize(self.y);
+ info->y_subnames[index] = subname.c_str();
+ return self;
}
};
@@ -539,57 +583,57 @@ class WrapVec2d : public WrapVec<Parent, Child, Data>
/**
* Templatized storage and interface for a simple scalar stat.
*/
-struct StatStor
+class StatStor
{
- public:
- /** The paramaters for this storage type, none for a scalar. */
- struct Params { };
-
private:
/** The statistic value. */
Counter data;
public:
+ struct Params : public StorageParams {};
+
+ public:
/**
* Builds this storage element and calls the base constructor of the
* datatype.
*/
- StatStor(const Params &) : data(Counter()) {}
+ StatStor(Info *info)
+ : data(Counter())
+ { }
/**
* The the stat to the given value.
* @param val The new value.
- * @param p The paramters of this storage type.
*/
- void set(Counter val, const Params &p) { data = val; }
+ void set(Counter val) { data = val; }
/**
* Increment the stat by the given value.
* @param val The new value.
- * @param p The paramters of this storage type.
*/
- void inc(Counter val, const Params &p) { data += val; }
+ void inc(Counter val) { data += val; }
/**
* Decrement the stat by the given value.
* @param val The new value.
- * @param p The paramters of this storage type.
*/
- void dec(Counter val, const Params &p) { data -= val; }
+ void dec(Counter val) { data -= val; }
/**
* Return the value of this stat as its base type.
- * @param p The params of this storage type.
* @return The value of this stat.
*/
- Counter value(const Params &p) const { return data; }
+ Counter value() const { return data; }
/**
* Return the value of this stat as a result type.
- * @param p The parameters of this storage type.
* @return The value of this stat.
*/
- Result result(const Params &p) const { return (Result)data; }
+ Result result() const { return (Result)data; }
+ /**
+ * Prepare stat data for dumping or serialization
+ */
+ void prepare(Info *info) { }
/**
* Reset stat value to default
*/
- void reset() { data = Counter(); }
+ void reset(Info *info) { data = Counter(); }
/**
* @return true if zero value
@@ -604,12 +648,8 @@ struct StatStor
* being watched. This is good for keeping track of residencies in structures
* among other things.
*/
-struct AvgStor
+class AvgStor
{
- public:
- /** The paramaters for this storage type */
- struct Params { };
-
private:
/** The current count. */
Counter current;
@@ -619,18 +659,24 @@ struct AvgStor
mutable Tick last;
public:
+ struct Params : public StorageParams {};
+
+ public:
/**
* Build and initializes this stat storage.
*/
- AvgStor(Params &p) : current(0), total(0), last(0) { }
+ AvgStor(Info *info)
+ : current(0), total(0), last(0)
+ { }
/**
* Set the current count to the one provided, update the total and last
* set values.
* @param val The new count.
- * @param p The parameters for this storage.
*/
- void set(Counter val, Params &p) {
+ void
+ set(Counter val)
+ {
total += current * (curTick - last);
last = curTick;
current = val;
@@ -639,71 +685,74 @@ struct AvgStor
/**
* Increment the current count by the provided value, calls set.
* @param val The amount to increment.
- * @param p The parameters for this storage.
*/
- void inc(Counter val, Params &p) { set(current + val, p); }
+ void inc(Counter val) { set(current + val); }
/**
* Deccrement the current count by the provided value, calls set.
* @param val The amount to decrement.
- * @param p The parameters for this storage.
*/
- void dec(Counter val, Params &p) { set(current - val, p); }
+ void dec(Counter val) { set(current - val); }
/**
* Return the current count.
- * @param p The parameters for this storage.
* @return The current count.
*/
- Counter value(const Params &p) const { return current; }
+ Counter value() const { return current; }
/**
* Return the current average.
- * @param p The parameters for this storage.
* @return The current average.
*/
- Result result(const Params &p) const
+ Result
+ result() const
{
- total += current * (curTick - last);
- last = curTick;
+ assert(last == curTick);
return (Result)(total + current) / (Result)(curTick + 1);
}
/**
- * Reset stat value to default
+ * @return true if zero value
*/
- void reset()
+ bool zero() const { return total == 0.0; }
+
+ /**
+ * Prepare stat data for dumping or serialization
+ */
+ void
+ prepare(Info *info)
{
- total = 0;
+ total += current * (curTick - last);
last = curTick;
}
/**
- * @return true if zero value
+ * Reset stat value to default
*/
- bool zero() const { return total == 0.0; }
+ void
+ reset(Info *info)
+ {
+ total = 0.0;
+ last = curTick;
+ }
+
};
/**
* Implementation of a scalar stat. The type of stat is determined by the
* Storage template.
*/
-template <class Stor>
-class ScalarBase : public DataAccess
+template <class Derived, class Stor>
+class ScalarBase : public DataWrap<Derived, ScalarInfo>
{
public:
typedef Stor Storage;
-
- /** Define the params of the storage class. */
- typedef typename Storage::Params Params;
+ typedef typename Stor::Params Params;
protected:
/** The storage of this stat. */
char storage[sizeof(Storage)] __attribute__ ((aligned (8)));
- /** The parameters for this stat. */
- Params params;
-
protected:
/**
* Retrieve the storage.
@@ -731,8 +780,8 @@ class ScalarBase : public DataAccess
void
doInit()
{
- new (storage) Storage(params);
- setInit();
+ new (storage) Storage(this->info());
+ this->setInit();
}
public:
@@ -740,14 +789,13 @@ class ScalarBase : public DataAccess
* Return the current value of this stat as its base type.
* @return The current value.
*/
- Counter value() const { return data()->value(params); }
+ Counter value() const { return data()->value(); }
public:
- /**
- * Create and initialize this stat, register it with the database.
- */
ScalarBase()
- { }
+ {
+ this->doInit();
+ }
public:
// Common operators for stats
@@ -755,12 +803,12 @@ class ScalarBase : public DataAccess
* Increment the stat by 1. This calls the associated storage object inc
* function.
*/
- void operator++() { data()->inc(1, params); }
+ void operator++() { data()->inc(1); }
/**
* Decrement the stat by 1. This calls the associated storage object dec
* function.
*/
- void operator--() { data()->dec(1, params); }
+ void operator--() { data()->dec(1); }
/** Increment the stat by 1. */
void operator++(int) { ++*this; }
@@ -773,7 +821,7 @@ class ScalarBase : public DataAccess
* @param v The new value.
*/
template <typename U>
- void operator=(const U &v) { data()->set(v, params); }
+ void operator=(const U &v) { data()->set(v); }
/**
* Increment the stat by the given value. This calls the associated
@@ -781,7 +829,7 @@ class ScalarBase : public DataAccess
* @param v The value to add.
*/
template <typename U>
- void operator+=(const U &v) { data()->inc(v, params); }
+ void operator+=(const U &v) { data()->inc(v); }
/**
* Decrement the stat by the given value. This calls the associated
@@ -789,99 +837,102 @@ class ScalarBase : public DataAccess
* @param v The value to substract.
*/
template <typename U>
- void operator-=(const U &v) { data()->dec(v, params); }
+ void operator-=(const U &v) { data()->dec(v); }
/**
* Return the number of elements, always 1 for a scalar.
* @return 1.
*/
- size_t size() const { return 1; }
+ size_type size() const { return 1; }
- bool check() const { return true; }
-
- /**
- * Reset stat value to default
- */
- void reset() { data()->reset(); }
+ Counter value() { return data()->value(); }
- Counter value() { return data()->value(params); }
-
- Result result() { return data()->result(params); }
+ Result result() { return data()->result(); }
Result total() { return result(); }
bool zero() { return result() == 0.0; }
+ void reset() { data()->reset(this->info()); }
+ void prepare() { data()->prepare(this->info()); }
};
-class ProxyData : public ScalarData
+class ProxyInfo : public ScalarInfoBase
{
public:
- virtual void visit(Visit &visitor) { visitor.visit(*this); }
- virtual std::string str() const { return to_string(value()); }
- virtual size_t size() const { return 1; }
- virtual bool zero() const { return value() == 0; }
- virtual bool check() const { return true; }
- virtual void reset() { }
+ std::string str() const { return to_string(value()); }
+ size_type size() const { return 1; }
+ bool check() const { return true; }
+ void prepare() { }
+ void reset() { }
+ bool zero() const { return value() == 0; }
+
+ void visit(Visit &visitor) { visitor.visit(*this); }
};
template <class T>
-class ValueProxy : public ProxyData
+class ValueProxy : public ProxyInfo
{
private:
T *scalar;
public:
ValueProxy(T &val) : scalar(&val) {}
- virtual Counter value() const { return *scalar; }
- virtual Result result() const { return *scalar; }
- virtual Result total() const { return *scalar; }
+ Counter value() const { return *scalar; }
+ Result result() const { return *scalar; }
+ Result total() const { return *scalar; }
};
template <class T>
-class FunctorProxy : public ProxyData
+class FunctorProxy : public ProxyInfo
{
private:
T *functor;
public:
FunctorProxy(T &func) : functor(&func) {}
- virtual Counter value() const { return (*functor)(); }
- virtual Result result() const { return (*functor)(); }
- virtual Result total() const { return (*functor)(); }
+ Counter value() const { return (*functor)(); }
+ Result result() const { return (*functor)(); }
+ Result total() const { return (*functor)(); }
};
-class ValueBase : public DataAccess
+template <class Derived>
+class ValueBase : public DataWrap<Derived, ScalarInfo>
{
private:
- ProxyData *proxy;
+ ProxyInfo *proxy;
public:
ValueBase() : proxy(NULL) { }
~ValueBase() { if (proxy) delete proxy; }
template <class T>
- void scalar(T &value)
+ Derived &
+ scalar(T &value)
{
proxy = new ValueProxy<T>(value);
- setInit();
+ this->setInit();
+ return this->self();
}
template <class T>
- void functor(T &func)
+ Derived &
+ functor(T &func)
{
proxy = new FunctorProxy<T>(func);
- setInit();
+ this->setInit();
+ return this->self();
}
Counter value() { return proxy->value(); }
Result result() const { return proxy->result(); }
Result total() const { return proxy->total(); };
- size_t size() const { return proxy->size(); }
+ size_type size() const { return proxy->size(); }
std::string str() const { return proxy->str(); }
bool zero() const { return proxy->zero(); }
bool check() const { return proxy != NULL; }
+ void prepare() { }
void reset() { }
};
@@ -900,34 +951,32 @@ class ScalarProxy
{
private:
/** Pointer to the parent Vector. */
- Stat *stat;
+ Stat &stat;
/** The index to access in the parent VectorBase. */
- int index;
+ off_type index;
public:
/**
* Return the current value of this stat as its base type.
* @return The current value.
*/
- Counter value() const { return stat->data(index)->value(stat->params); }
+ Counter value() const { return stat.data(index)->value(); }
/**
* Return the current value of this statas a result type.
* @return The current value.
*/
- Result result() const { return stat->data(index)->result(stat->params); }
+ Result result() const { return stat.data(index)->result(); }
public:
/**
* Create and initialize this proxy, do not register it with the database.
- * @param p The params to use.
* @param i The index to access.
*/
- ScalarProxy(Stat *s, int i)
+ ScalarProxy(Stat &s, off_type i)
: stat(s), index(i)
{
- assert(stat);
}
/**
@@ -943,7 +992,9 @@ class ScalarProxy
* @param sp The proxy to copy.
* @return A reference to this proxy.
*/
- const ScalarProxy &operator=(const ScalarProxy &sp) {
+ const ScalarProxy &
+ operator=(const ScalarProxy &sp)
+ {
stat = sp.stat;
index = sp.index;
return *this;
@@ -955,12 +1006,12 @@ class ScalarProxy
* Increment the stat by 1. This calls the associated storage object inc
* function.
*/
- void operator++() { stat->data(index)->inc(1, stat->params); }
+ void operator++() { stat.data(index)->inc(1); }
/**
* Decrement the stat by 1. This calls the associated storage object dec
* function.
*/
- void operator--() { stat->data(index)->dec(1, stat->params); }
+ void operator--() { stat.data(index)->dec(1); }
/** Increment the stat by 1. */
void operator++(int) { ++*this; }
@@ -973,7 +1024,11 @@ class ScalarProxy
* @param v The new value.
*/
template <typename U>
- void operator=(const U &v) { stat->data(index)->set(v, stat->params); }
+ void
+ operator=(const U &v)
+ {
+ stat.data(index)->set(v);
+ }
/**
* Increment the stat by the given value. This calls the associated
@@ -981,7 +1036,11 @@ class ScalarProxy
* @param v The value to add.
*/
template <typename U>
- void operator+=(const U &v) { stat->data(index)->inc(v, stat->params); }
+ void
+ operator+=(const U &v)
+ {
+ stat.data(index)->inc(v);
+ }
/**
* Decrement the stat by the given value. This calls the associated
@@ -989,25 +1048,23 @@ class ScalarProxy
* @param v The value to substract.
*/
template <typename U>
- void operator-=(const U &v) { stat->data(index)->dec(v, stat->params); }
+ void
+ operator-=(const U &v)
+ {
+ stat.data(index)->dec(v);
+ }
/**
* Return the number of elements, always 1 for a scalar.
* @return 1.
*/
- size_t size() const { return 1; }
-
- /**
- * This stat has no state. Nothing to reset
- */
- void reset() { }
+ size_type size() const { return 1; }
public:
std::string
str() const
{
- return csprintf("%s[%d]", stat->str(), index);
-
+ return csprintf("%s[%d]", stat.info()->name, index);
}
};
@@ -1015,27 +1072,22 @@ class ScalarProxy
* Implementation of a vector of stats. The type of stat is determined by the
* Storage class. @sa ScalarBase
*/
-template <class Stor>
-class VectorBase : public DataAccess
+template <class Derived, class Stor>
+class VectorBase : public DataWrapVec<Derived, VectorInfo>
{
public:
typedef Stor Storage;
-
- /** Define the params of the storage class. */
- typedef typename Storage::Params Params;
+ typedef typename Stor::Params Params;
/** Proxy type */
- typedef ScalarProxy<VectorBase<Storage> > Proxy;
-
- friend class ScalarProxy<VectorBase<Storage> >;
+ typedef ScalarProxy<Derived> Proxy;
+ friend class ScalarProxy<Derived>;
+ friend class DataWrapVec<Derived, VectorInfo>;
protected:
/** The storage of this stat. */
Storage *storage;
- size_t _size;
-
- /** The parameters for this stat. */
- Params params;
+ size_type _size;
protected:
/**
@@ -1043,17 +1095,17 @@ class VectorBase : public DataAccess
* @param index The vector index to access.
* @return The storage object at the given index.
*/
- Storage *data(int index) { return &storage[index]; }
+ Storage *data(off_type index) { return &storage[index]; }
/**
* Retrieve a const pointer to the storage.
* @param index The vector index to access.
* @return A const pointer to the storage object at the given index.
*/
- const Storage *data(int index) const { return &storage[index]; }
+ const Storage *data(off_type index) const { return &storage[index]; }
void
- doInit(int s)
+ doInit(size_type s)
{
assert(s > 0 && "size must be positive!");
assert(!storage && "already initialized");
@@ -1062,51 +1114,55 @@ class VectorBase : public DataAccess
char *ptr = new char[_size * sizeof(Storage)];
storage = reinterpret_cast<Storage *>(ptr);
- for (int i = 0; i < _size; ++i)
- new (&storage[i]) Storage(params);
+ for (off_type i = 0; i < _size; ++i)
+ new (&storage[i]) Storage(this->info());
- setInit();
+ this->setInit();
}
public:
- void value(VCounter &vec) const
+ void
+ value(VCounter &vec) const
{
vec.resize(size());
- for (int i = 0; i < size(); ++i)
- vec[i] = data(i)->value(params);
+ for (off_type i = 0; i < size(); ++i)
+ vec[i] = data(i)->value();
}
/**
* Copy the values to a local vector and return a reference to it.
* @return A reference to a vector of the stat values.
*/
- void result(VResult &vec) const
+ void
+ result(VResult &vec) const
{
vec.resize(size());
- for (int i = 0; i < size(); ++i)
- vec[i] = data(i)->result(params);
+ for (off_type i = 0; i < size(); ++i)
+ vec[i] = data(i)->result();
}
/**
* Return a total of all entries in this vector.
* @return The total of all vector entries.
*/
- Result total() const {
+ Result
+ total() const
+ {
Result total = 0.0;
- for (int i = 0; i < size(); ++i)
- total += data(i)->result(params);
+ for (off_type i = 0; i < size(); ++i)
+ total += data(i)->result();
return total;
}
/**
* @return the number of elements in this vector.
*/
- size_t size() const { return _size; }
+ size_type size() const { return _size; }
bool
zero() const
{
- for (int i = 0; i < size(); ++i)
+ for (off_type i = 0; i < size(); ++i)
if (data(i)->zero())
return false;
return true;
@@ -1118,13 +1174,6 @@ class VectorBase : public DataAccess
return storage != NULL;
}
- void
- reset()
- {
- for (int i = 0; i < size(); ++i)
- data(i)->reset();
- }
-
public:
VectorBase()
: storage(NULL)
@@ -1135,49 +1184,60 @@ class VectorBase : public DataAccess
if (!storage)
return;
- for (int i = 0; i < _size; ++i)
+ for (off_type i = 0; i < _size; ++i)
data(i)->~Storage();
delete [] reinterpret_cast<char *>(storage);
}
/**
+ * Set this vector to have the given size.
+ * @param size The new size.
+ * @return A reference to this stat.
+ */
+ Derived &
+ init(size_type size)
+ {
+ Derived &self = this->self();
+ self.doInit(size);
+ return self;
+ }
+
+ /**
* Return a reference (ScalarProxy) to the stat at the given index.
* @param index The vector index to access.
* @return A reference of the stat.
*/
Proxy
- operator[](int index)
+ operator[](off_type index)
{
assert (index >= 0 && index < size());
- return Proxy(this, index);
+ return Proxy(this->self(), index);
}
-
- void update(StatData *data) {}
};
template <class Stat>
class VectorProxy
{
private:
- Stat *stat;
- int offset;
- int len;
+ Stat &stat;
+ off_type offset;
+ size_type len;
private:
mutable VResult vec;
typename Stat::Storage *
- data(int index)
+ data(off_type index)
{
assert(index < len);
- return stat->data(offset + index);
+ return stat.data(offset + index);
}
const typename Stat::Storage *
- data(int index) const
+ data(off_type index) const
{
assert(index < len);
- return const_cast<Stat *>(stat)->data(offset + index);
+ return stat.data(offset + index);
}
public:
@@ -1186,8 +1246,8 @@ class VectorProxy
{
vec.resize(size());
- for (int i = 0; i < size(); ++i)
- vec[i] = data(i)->result(stat->params);
+ for (off_type i = 0; i < size(); ++i)
+ vec[i] = data(i)->result();
return vec;
}
@@ -1195,14 +1255,14 @@ class VectorProxy
Result
total() const
{
- Result total = 0;
- for (int i = 0; i < size(); ++i)
- total += data(i)->result(stat->params);
+ Result total = 0.0;
+ for (off_type i = 0; i < size(); ++i)
+ total += data(i)->result();
return total;
}
public:
- VectorProxy(Stat *s, int o, int l)
+ VectorProxy(Stat &s, off_type o, size_type l)
: stat(s), offset(o), len(l)
{
}
@@ -1221,63 +1281,38 @@ class VectorProxy
return *this;
}
- ScalarProxy<Stat> operator[](int index)
+ ScalarProxy<Stat>
+ operator[](off_type index)
{
assert (index >= 0 && index < size());
return ScalarProxy<Stat>(stat, offset + index);
}
- size_t size() const { return len; }
-
- /**
- * This stat has no state. Nothing to reset.
- */
- void reset() { }
+ size_type size() const { return len; }
};
-template <class Stor>
-class Vector2dBase : public DataAccess
+template <class Derived, class Stor>
+class Vector2dBase : public DataWrapVec2d<Derived, Vector2dInfo>
{
public:
+ typedef Vector2dInfo<Derived> Info;
typedef Stor Storage;
- typedef typename Storage::Params Params;
- typedef VectorProxy<Vector2dBase<Storage> > Proxy;
- friend class ScalarProxy<Vector2dBase<Storage> >;
- friend class VectorProxy<Vector2dBase<Storage> >;
+ typedef typename Stor::Params Params;
+ typedef VectorProxy<Derived> Proxy;
+ friend class ScalarProxy<Derived>;
+ friend class VectorProxy<Derived>;
+ friend class DataWrapVec<Derived, Vector2dInfo>;
+ friend class DataWrapVec2d<Derived, Vector2dInfo>;
protected:
- size_t x;
- size_t y;
- size_t _size;
+ size_type x;
+ size_type y;
+ size_type _size;
Storage *storage;
- Params params;
protected:
- Storage *data(int index) { return &storage[index]; }
- const Storage *data(int index) const { return &storage[index]; }
-
- void
- doInit(int _x, int _y)
- {
- assert(_x > 0 && _y > 0 && "sizes must be positive!");
- assert(!storage && "already initialized");
-
- Vector2dData *statdata = dynamic_cast<Vector2dData *>(find());
-
- x = _x;
- y = _y;
- statdata->x = _x;
- statdata->y = _y;
- _size = x * y;
-
- char *ptr = new char[_size * sizeof(Storage)];
- storage = reinterpret_cast<Storage *>(ptr);
-
- for (int i = 0; i < _size; ++i)
- new (&storage[i]) Storage(params);
-
- setInit();
- }
+ Storage *data(off_type index) { return &storage[index]; }
+ const Storage *data(off_type index) const { return &storage[index]; }
public:
Vector2dBase()
@@ -1289,32 +1324,49 @@ class Vector2dBase : public DataAccess
if (!storage)
return;
- for (int i = 0; i < _size; ++i)
+ for (off_type i = 0; i < _size; ++i)
data(i)->~Storage();
delete [] reinterpret_cast<char *>(storage);
}
- void
- update(Vector2dData *newdata)
+ Derived &
+ init(size_type _x, size_type _y)
{
- int size = this->size();
- newdata->cvec.resize(size);
- for (int i = 0; i < size; ++i)
- newdata->cvec[i] = data(i)->value(params);
+ assert(_x > 0 && _y > 0 && "sizes must be positive!");
+ assert(!storage && "already initialized");
+
+ Derived &self = this->self();
+ Info *info = this->info();
+
+ x = _x;
+ y = _y;
+ info->x = _x;
+ info->y = _y;
+ _size = x * y;
+
+ char *ptr = new char[_size * sizeof(Storage)];
+ storage = reinterpret_cast<Storage *>(ptr);
+
+ for (off_type i = 0; i < _size; ++i)
+ new (&storage[i]) Storage(info);
+
+ this->setInit();
+
+ return self;
}
- std::string ysubname(int i) const { return (*this->y_subnames)[i]; }
+ std::string ysubname(off_type i) const { return (*this->y_subnames)[i]; }
Proxy
- operator[](int index)
+ operator[](off_type index)
{
- int offset = index * y;
+ off_type offset = index * y;
assert (index >= 0 && offset + index < size());
- return Proxy(this, offset, y);
+ return Proxy(this->self(), offset, y);
}
- size_t
+ size_type
size() const
{
return _size;
@@ -1325,25 +1377,41 @@ class Vector2dBase : public DataAccess
{
return data(0)->zero();
#if 0
- for (int i = 0; i < size(); ++i)
+ for (off_type i = 0; i < size(); ++i)
if (!data(i)->zero())
return false;
return true;
#endif
}
+ void
+ prepare()
+ {
+ Info *info = this->info();
+ size_type size = this->size();
+
+ for (off_type i = 0; i < size; ++i)
+ data(i)->prepare(info);
+
+ info->cvec.resize(size);
+ for (off_type i = 0; i < size; ++i)
+ info->cvec[i] = data(i)->value();
+ }
+
/**
* Reset stat value to default
*/
void
reset()
{
- for (int i = 0; i < size(); ++i)
- data(i)->reset();
+ Info *info = this->info();
+ size_type size = this->size();
+ for (off_type i = 0; i < size; ++i)
+ data(i)->reset(info);
}
bool
- check()
+ check() const
{
return storage != NULL;
}
@@ -1355,27 +1423,44 @@ class Vector2dBase : public DataAccess
//
//////////////////////////////////////////////////////////////////////
+struct DistParams : public StorageParams
+{
+ const bool fancy;
+
+ /** The minimum value to track. */
+ Counter min;
+ /** The maximum value to track. */
+ Counter max;
+ /** The number of entries in each bucket. */
+ Counter bucket_size;
+ /** The number of buckets. Equal to (max-min)/bucket_size. */
+ size_type buckets;
+
+ explicit DistParams(bool f) : fancy(f) {}
+};
+
/**
* Templatized storage and interface for a distrbution stat.
*/
-struct DistStor
+class DistStor
{
public:
/** The parameters for a distribution stat. */
- struct Params
- {
- /** The minimum value to track. */
- Counter min;
- /** The maximum value to track. */
- Counter max;
- /** The number of entries in each bucket. */
- Counter bucket_size;
- /** The number of buckets. Equal to (max-min)/bucket_size. */
- int size;
+ struct Params : public DistParams
+ {
+ Params() : DistParams(false) {}
};
- enum { fancy = false };
private:
+ /** The minimum value to track. */
+ Counter min_track;
+ /** The maximum value to track. */
+ Counter max_track;
+ /** The number of entries in each bucket. */
+ Counter bucket_size;
+ /** The number of buckets. Equal to (max-min)/bucket_size. */
+ size_type buckets;
+
/** The smallest value sampled. */
Counter min_val;
/** The largest value sampled. */
@@ -1394,27 +1479,28 @@ struct DistStor
VCounter cvec;
public:
- DistStor(const Params &params)
- : cvec(params.size)
+ DistStor(Info *info)
+ : cvec(safe_cast<const Params *>(info->storageParams)->buckets)
{
- reset();
+ reset(info);
}
/**
* Add a value to the distribution for the given number of times.
* @param val The value to add.
* @param number The number of times to add the value.
- * @param params The paramters of the distribution.
*/
- void sample(Counter val, int number, const Params &params)
+ void
+ sample(Counter val, int number)
{
- if (val < params.min)
+ if (val < min_track)
underflow += number;
- else if (val > params.max)
+ else if (val > max_track)
overflow += number;
else {
- int index = (int)std::floor((val - params.min) / params.bucket_size);
- assert(index < size(params));
+ size_type index =
+ (size_type)std::floor((val - min_track) / bucket_size);
+ assert(index < size());
cvec[index] += number;
}
@@ -1433,52 +1519,57 @@ struct DistStor
/**
* Return the number of buckets in this distribution.
* @return the number of buckets.
- * @todo Is it faster to return the size from the parameters?
*/
- size_t size(const Params &) const { return cvec.size(); }
+ size_type size() const { return cvec.size(); }
/**
* Returns true if any calls to sample have been made.
- * @param params The paramters of the distribution.
* @return True if any values have been sampled.
*/
- bool zero(const Params &params) const
+ bool
+ zero() const
{
return samples == Counter();
}
- void update(DistDataData *data, const Params &params)
+ void
+ prepare(Info *info, DistData &data)
{
- data->min = params.min;
- data->max = params.max;
- data->bucket_size = params.bucket_size;
- data->size = params.size;
+ const Params *params = safe_cast<const Params *>(info->storageParams);
- data->min_val = (min_val == INT_MAX) ? 0 : min_val;
- data->max_val = (max_val == INT_MIN) ? 0 : max_val;
- data->underflow = underflow;
- data->overflow = overflow;
- data->cvec.resize(params.size);
- for (int i = 0; i < params.size; ++i)
- data->cvec[i] = cvec[i];
+ data.min_val = (min_val == CounterLimits::max()) ? 0 : min_val;
+ data.max_val = (max_val == CounterLimits::min()) ? 0 : max_val;
+ data.underflow = underflow;
+ data.overflow = overflow;
- data->sum = sum;
- data->squares = squares;
- data->samples = samples;
+ int buckets = params->buckets;
+ data.cvec.resize(buckets);
+ for (off_type i = 0; i < buckets; ++i)
+ data.cvec[i] = cvec[i];
+
+ data.sum = sum;
+ data.squares = squares;
+ data.samples = samples;
}
/**
* Reset stat value to default
*/
- void reset()
+ void
+ reset(Info *info)
{
- min_val = INT_MAX;
- max_val = INT_MIN;
+ const Params *params = safe_cast<const Params *>(info->storageParams);
+ min_track = params->min;
+ max_track = params->max;
+ bucket_size = params->bucket_size;
+
+ min_val = CounterLimits::max();
+ max_val = CounterLimits::min();
underflow = 0;
overflow = 0;
- int size = cvec.size();
- for (int i = 0; i < size; ++i)
+ size_type size = cvec.size();
+ for (off_type i = 0; i < size; ++i)
cvec[i] = Counter();
sum = Counter();
@@ -1491,14 +1582,13 @@ struct DistStor
* Templatized storage and interface for a distribution that calculates mean
* and variance.
*/
-struct FancyStor
+class FancyStor
{
public:
- /**
- * No paramters for this storage.
- */
- struct Params {};
- enum { fancy = true };
+ struct Params : public DistParams
+ {
+ Params() : DistParams(true) {}
+ };
private:
/** The current sum. */
@@ -1512,7 +1602,7 @@ struct FancyStor
/**
* Create and initialize this storage.
*/
- FancyStor(const Params &)
+ FancyStor(Info *info)
: sum(Counter()), squares(Counter()), samples(Counter())
{ }
@@ -1522,9 +1612,9 @@ struct FancyStor
* values seen by the given number.
* @param val The value to add.
* @param number The number of times to add the value.
- * @param p The parameters of this stat.
*/
- void sample(Counter val, int number, const Params &p)
+ void
+ sample(Counter val, int number)
{
Counter value = val * number;
sum += value;
@@ -1532,29 +1622,31 @@ struct FancyStor
samples += number;
}
- void update(DistDataData *data, const Params &params)
- {
- data->sum = sum;
- data->squares = squares;
- data->samples = samples;
- }
-
/**
* Return the number of entries in this stat, 1
* @return 1.
*/
- size_t size(const Params &) const { return 1; }
+ size_type size() const { return 1; }
/**
* Return true if no samples have been added.
* @return True if no samples have been added.
*/
- bool zero(const Params &) const { return samples == Counter(); }
+ bool zero() const { return samples == Counter(); }
+
+ void
+ prepare(Info *info, DistData &data)
+ {
+ data.sum = sum;
+ data.squares = squares;
+ data.samples = samples;
+ }
/**
* Reset stat value to default
*/
- void reset()
+ void
+ reset(Info *info)
{
sum = Counter();
squares = Counter();
@@ -1566,12 +1658,13 @@ struct FancyStor
* Templatized storage for distribution that calculates per tick mean and
* variance.
*/
-struct AvgFancy
+class AvgFancy
{
public:
- /** No parameters for this storage. */
- struct Params {};
- enum { fancy = true };
+ struct Params : public DistParams
+ {
+ Params() : DistParams(true) {}
+ };
private:
/** Current total. */
@@ -1583,43 +1676,49 @@ struct AvgFancy
/**
* Create and initialize this storage.
*/
- AvgFancy(const Params &) : sum(Counter()), squares(Counter()) {}
+ AvgFancy(Info *info)
+ : sum(Counter()), squares(Counter())
+ {}
/**
* Add a value to the distribution for the given number of times.
* Update the running sum and sum of squares.
* @param val The value to add.
* @param number The number of times to add the value.
- * @param p The paramters of the distribution.
*/
- void sample(Counter val, int number, const Params &p)
+ void
+ sample(Counter val, int number)
{
Counter value = val * number;
sum += value;
squares += value * value;
}
- void update(DistDataData *data, const Params &params)
- {
- data->sum = sum;
- data->squares = squares;
- data->samples = curTick;
- }
-
/**
* Return the number of entries, in this case 1.
* @return 1.
*/
- size_t size(const Params &params) const { return 1; }
+ size_type size() const { return 1; }
+
/**
* Return true if no samples have been added.
* @return True if the sum is zero.
*/
- bool zero(const Params &params) const { return sum == Counter(); }
+ bool zero() const { return sum == Counter(); }
+
+ void
+ prepare(Info *info, DistData &data)
+ {
+ data.sum = sum;
+ data.squares = squares;
+ data.samples = curTick;
+ }
+
/**
* Reset stat value to default
*/
- void reset()
+ void
+ reset(Info *info)
{
sum = Counter();
squares = Counter();
@@ -1630,27 +1729,25 @@ struct AvgFancy
* Implementation of a distribution stat. The type of distribution is
* determined by the Storage template. @sa ScalarBase
*/
-template <class Stor>
-class DistBase : public DataAccess
+template <class Derived, class Stor>
+class DistBase : public DataWrap<Derived, DistInfo>
{
public:
+ typedef DistInfo<Derived> Info;
typedef Stor Storage;
- /** Define the params of the storage class. */
- typedef typename Storage::Params Params;
+ typedef typename Stor::Params Params;
protected:
/** The storage for this stat. */
char storage[sizeof(Storage)] __attribute__ ((aligned (8)));
- /** The parameters for this stat. */
- Params params;
-
protected:
/**
* Retrieve the storage.
* @return The storage object for this stat.
*/
- Storage *data()
+ Storage *
+ data()
{
return reinterpret_cast<Storage *>(storage);
}
@@ -1668,8 +1765,8 @@ class DistBase : public DataAccess
void
doInit()
{
- new (storage) Storage(params);
- setInit();
+ new (storage) Storage(this->info());
+ this->setInit();
}
public:
@@ -1682,23 +1779,24 @@ class DistBase : public DataAccess
* @param n The number of times to add it, defaults to 1.
*/
template <typename U>
- void sample(const U &v, int n = 1) { data()->sample(v, n, params); }
+ void sample(const U &v, int n = 1) { data()->sample(v, n); }
/**
* Return the number of entries in this stat.
* @return The number of entries.
*/
- size_t size() const { return data()->size(params); }
+ size_type size() const { return data()->size(); }
/**
* Return true if no samples have been added.
* @return True if there haven't been any samples.
*/
- bool zero() const { return data()->zero(params); }
+ bool zero() const { return data()->zero(); }
- void update(DistData *base)
+ void
+ prepare()
{
- base->data.fancy = Storage::fancy;
- data()->update(&(base->data), params);
+ Info *info = this->info();
+ data()->prepare(info, info->data);
}
/**
@@ -1707,48 +1805,43 @@ class DistBase : public DataAccess
void
reset()
{
- data()->reset();
- }
-
- bool
- check()
- {
- return true;
+ data()->reset(this->info());
}
};
template <class Stat>
class DistProxy;
-template <class Stor>
-class VectorDistBase : public DataAccess
+template <class Derived, class Stor>
+class VectorDistBase : public DataWrapVec<Derived, VectorDistInfo>
{
public:
+ typedef VectorDistInfo<Derived> Info;
typedef Stor Storage;
- typedef typename Storage::Params Params;
- typedef DistProxy<VectorDistBase<Storage> > Proxy;
- friend class DistProxy<VectorDistBase<Storage> >;
+ typedef typename Stor::Params Params;
+ typedef DistProxy<Derived> Proxy;
+ friend class DistProxy<Derived>;
+ friend class DataWrapVec<Derived, VectorDistInfo>;
protected:
Storage *storage;
- size_t _size;
- Params params;
+ size_type _size;
protected:
Storage *
- data(int index)
+ data(off_type index)
{
return &storage[index];
}
const Storage *
- data(int index) const
+ data(off_type index) const
{
return &storage[index];
}
void
- doInit(int s)
+ doInit(size_type s)
{
assert(s > 0 && "size must be positive!");
assert(!storage && "already initialized");
@@ -1757,10 +1850,11 @@ class VectorDistBase : public DataAccess
char *ptr = new char[_size * sizeof(Storage)];
storage = reinterpret_cast<Storage *>(ptr);
- for (int i = 0; i < _size; ++i)
- new (&storage[i]) Storage(params);
+ Info *info = this->info();
+ for (off_type i = 0; i < _size; ++i)
+ new (&storage[i]) Storage(info);
- setInit();
+ this->setInit();
}
public:
@@ -1773,14 +1867,14 @@ class VectorDistBase : public DataAccess
if (!storage)
return ;
- for (int i = 0; i < _size; ++i)
+ for (off_type i = 0; i < _size; ++i)
data(i)->~Storage();
delete [] reinterpret_cast<char *>(storage);
}
- Proxy operator[](int index);
+ Proxy operator[](off_type index);
- size_t
+ size_type
size() const
{
return _size;
@@ -1791,39 +1885,28 @@ class VectorDistBase : public DataAccess
{
return false;
#if 0
- for (int i = 0; i < size(); ++i)
- if (!data(i)->zero(params))
+ for (off_type i = 0; i < size(); ++i)
+ if (!data(i)->zero())
return false;
return true;
#endif
}
- /**
- * Reset stat value to default
- */
void
- reset()
+ prepare()
{
- for (int i = 0; i < size(); ++i)
- data(i)->reset();
+ Info *info = this->info();
+ size_type size = this->size();
+ info->data.resize(size);
+ for (off_type i = 0; i < size; ++i)
+ data(i)->prepare(info, info->data[i]);
}
bool
- check()
+ check() const
{
return storage != NULL;
}
-
- void
- update(VectorDistData *base)
- {
- int size = this->size();
- base->data.resize(size);
- for (int i = 0; i < size; ++i) {
- base->data[i].fancy = Storage::fancy;
- data(i)->update(&(base->data[i]), params);
- }
- }
};
template <class Stat>
@@ -1831,14 +1914,14 @@ class DistProxy
{
private:
Stat *stat;
- int index;
+ off_type index;
protected:
typename Stat::Storage *data() { return stat->data(index); }
const typename Stat::Storage *data() const { return stat->data(index); }
public:
- DistProxy(Stat *s, int i)
+ DistProxy(Stat *s, off_type i)
: stat(s), index(i)
{}
@@ -1846,7 +1929,8 @@ class DistProxy
: stat(sp.stat), index(sp.index)
{}
- const DistProxy &operator=(const DistProxy &sp)
+ const DistProxy &
+ operator=(const DistProxy &sp)
{
stat = sp.stat;
index = sp.index;
@@ -1858,10 +1942,10 @@ class DistProxy
void
sample(const U &v, int n = 1)
{
- data()->sample(v, n, stat->params);
+ data()->sample(v, n);
}
- size_t
+ size_type
size() const
{
return 1;
@@ -1870,7 +1954,7 @@ class DistProxy
bool
zero() const
{
- return data()->zero(stat->params);
+ return data()->zero();
}
/**
@@ -1879,23 +1963,23 @@ class DistProxy
void reset() { }
};
-template <class Storage>
-inline typename VectorDistBase<Storage>::Proxy
-VectorDistBase<Storage>::operator[](int index)
+template <class Derived, class Stor>
+inline typename VectorDistBase<Derived, Stor>::Proxy
+VectorDistBase<Derived, Stor>::operator[](off_type index)
{
assert (index >= 0 && index < size());
- return typename VectorDistBase<Storage>::Proxy(this, index);
+ typedef typename VectorDistBase<Derived, Stor>::Proxy Proxy;
+ return Proxy(this, index);
}
#if 0
template <class Storage>
Result
-VectorDistBase<Storage>::total(int index) const
+VectorDistBase<Storage>::total(off_type index) const
{
- int total = 0;
- for (int i = 0; i < x_size(); ++i) {
- total += data(i)->result(stat->params);
- }
+ Result total = 0.0;
+ for (off_type i = 0; i < x_size(); ++i)
+ total += data(i)->result();
}
#endif
@@ -1916,7 +2000,7 @@ class Node : public RefCounted
* Return the number of nodes in the subtree starting at this node.
* @return the number of nodes in this subtree.
*/
- virtual size_t size() const = 0;
+ virtual size_type size() const = 0;
/**
* Return the result vector of this subtree.
* @return The result vector of this subtree.
@@ -1940,24 +2024,27 @@ typedef RefCountingPtr<Node> NodePtr;
class ScalarStatNode : public Node
{
private:
- const ScalarData *data;
+ const ScalarInfoBase *data;
mutable VResult vresult;
public:
- ScalarStatNode(const ScalarData *d) : data(d), vresult(1) {}
- virtual const VResult &result() const
+ ScalarStatNode(const ScalarInfoBase *d) : data(d), vresult(1) {}
+
+ const VResult &
+ result() const
{
vresult[0] = data->result();
return vresult;
}
- virtual Result total() const { return data->result(); };
- virtual size_t size() const { return 1; }
+ Result total() const { return data->result(); };
+
+ size_type size() const { return 1; }
/**
*
*/
- virtual std::string str() const { return data->name; }
+ std::string str() const { return data->name; }
};
template <class Stat>
@@ -1972,20 +2059,20 @@ class ScalarProxyNode : public Node
: proxy(p), vresult(1)
{ }
- virtual const VResult &
+ const VResult &
result() const
{
vresult[0] = proxy.result();
return vresult;
}
- virtual Result
+ Result
total() const
{
return proxy.result();
}
- virtual size_t
+ size_type
size() const
{
return 1;
@@ -1994,7 +2081,7 @@ class ScalarProxyNode : public Node
/**
*
*/
- virtual std::string
+ std::string
str() const
{
return proxy.str();
@@ -2004,16 +2091,16 @@ class ScalarProxyNode : public Node
class VectorStatNode : public Node
{
private:
- const VectorData *data;
+ const VectorInfoBase *data;
public:
- VectorStatNode(const VectorData *d) : data(d) { }
- virtual const VResult &result() const { return data->result(); }
- virtual Result total() const { return data->total(); };
+ VectorStatNode(const VectorInfoBase *d) : data(d) { }
+ const VResult &result() const { return data->result(); }
+ Result total() const { return data->total(); };
- virtual size_t size() const { return data->size(); }
+ size_type size() const { return data->size(); }
- virtual std::string str() const { return data->name; }
+ std::string str() const { return data->name; }
};
template <class T>
@@ -2025,9 +2112,9 @@ class ConstNode : public Node
public:
ConstNode(T s) : vresult(1, (Result)s) {}
const VResult &result() const { return vresult; }
- virtual Result total() const { return vresult[0]; };
- virtual size_t size() const { return 1; }
- virtual std::string str() const { return to_string(vresult[0]); }
+ Result total() const { return vresult[0]; };
+ size_type size() const { return 1; }
+ std::string str() const { return to_string(vresult[0]); }
};
template <class T>
@@ -2039,25 +2126,25 @@ class ConstVectorNode : public Node
public:
ConstVectorNode(const T &s) : vresult(s.begin(), s.end()) {}
const VResult &result() const { return vresult; }
- virtual Result total() const
+
+ Result
+ total() const
{
- int size = this->size();
+ size_type size = this->size();
Result tmp = 0;
- for (int i = 0; i < size; i++)
- {
+ for (off_type i = 0; i < size; i++)
tmp += vresult[i];
- }
return tmp;
}
- virtual size_t size() const { return vresult.size(); }
- virtual std::string str() const
+
+ size_type size() const { return vresult.size(); }
+ std::string
+ str() const
{
- int size = this->size();
+ size_type size = this->size();
std::string tmp = "(";
- for (int i = 0; i < size; i++)
- {
+ for (off_type i = 0; i < size; i++)
tmp += csprintf("%s ",to_string(vresult[i]));
- }
tmp += ")";
return tmp;
}
@@ -2112,33 +2199,36 @@ class UnaryNode : public Node
public:
UnaryNode(NodePtr &p) : l(p) {}
- const VResult &result() const
+ const VResult &
+ result() const
{
const VResult &lvec = l->result();
- int size = lvec.size();
+ size_type size = lvec.size();
assert(size > 0);
vresult.resize(size);
Op op;
- for (int i = 0; i < size; ++i)
+ for (off_type i = 0; i < size; ++i)
vresult[i] = op(lvec[i]);
return vresult;
}
- Result total() const
+ Result
+ total() const
{
const VResult &vec = this->result();
- Result total = 0;
- for (int i = 0; i < size(); i++)
+ Result total = 0.0;
+ for (off_type i = 0; i < size(); i++)
total += vec[i];
return total;
}
- virtual size_t size() const { return l->size(); }
+ size_type size() const { return l->size(); }
- virtual std::string str() const
+ std::string
+ str() const
{
return OpString<Op>::str() + l->str();
}
@@ -2155,7 +2245,8 @@ class BinaryNode : public Node
public:
BinaryNode(NodePtr &a, NodePtr &b) : l(a), r(b) {}
- const VResult &result() const
+ const VResult &
+ result() const
{
Op op;
const VResult &lvec = l->result();
@@ -2167,48 +2258,52 @@ class BinaryNode : public Node
vresult.resize(1);
vresult[0] = op(lvec[0], rvec[0]);
} else if (lvec.size() == 1) {
- int size = rvec.size();
+ size_type size = rvec.size();
vresult.resize(size);
- for (int i = 0; i < size; ++i)
+ for (off_type i = 0; i < size; ++i)
vresult[i] = op(lvec[0], rvec[i]);
} else if (rvec.size() == 1) {
- int size = lvec.size();
+ size_type size = lvec.size();
vresult.resize(size);
- for (int i = 0; i < size; ++i)
+ for (off_type i = 0; i < size; ++i)
vresult[i] = op(lvec[i], rvec[0]);
} else if (rvec.size() == lvec.size()) {
- int size = rvec.size();
+ size_type size = rvec.size();
vresult.resize(size);
- for (int i = 0; i < size; ++i)
+ for (off_type i = 0; i < size; ++i)
vresult[i] = op(lvec[i], rvec[i]);
}
return vresult;
}
- Result total() const
+ Result
+ total() const
{
const VResult &vec = this->result();
- Result total = 0;
- for (int i = 0; i < size(); i++)
+ Result total = 0.0;
+ for (off_type i = 0; i < size(); i++)
total += vec[i];
return total;
}
- virtual size_t size() const {
- int ls = l->size();
- int rs = r->size();
- if (ls == 1)
+ size_type
+ size() const
+ {
+ size_type ls = l->size();
+ size_type rs = r->size();
+ if (ls == 1) {
return rs;
- else if (rs == 1)
+ } else if (rs == 1) {
return ls;
- else {
+ } else {
assert(ls == rs && "Node vector sizes are not equal");
return ls;
}
}
- virtual std::string str() const
+ std::string
+ str() const
{
return csprintf("(%s %s %s)", l->str(), OpString<Op>::str(), r->str());
}
@@ -2224,39 +2319,42 @@ class SumNode : public Node
public:
SumNode(NodePtr &p) : l(p), vresult(1) {}
- const VResult &result() const
+ const VResult &
+ result() const
{
const VResult &lvec = l->result();
- int size = lvec.size();
+ size_type size = lvec.size();
assert(size > 0);
vresult[0] = 0.0;
Op op;
- for (int i = 0; i < size; ++i)
+ for (off_type i = 0; i < size; ++i)
vresult[0] = op(vresult[0], lvec[i]);
return vresult;
}
- Result total() const
+ Result
+ total() const
{
const VResult &lvec = l->result();
- int size = lvec.size();
+ size_type size = lvec.size();
assert(size > 0);
Result vresult = 0.0;
Op op;
- for (int i = 0; i < size; ++i)
+ for (off_type i = 0; i < size; ++i)
vresult = op(vresult, lvec[i]);
return vresult;
}
- virtual size_t size() const { return 1; }
+ size_type size() const { return 1; }
- virtual std::string str() const
+ std::string
+ str() const
{
return csprintf("total(%s)", l->str());
}
@@ -2278,145 +2376,57 @@ class SumNode : public Node
* This is a simple scalar statistic, like a counter.
* @sa Stat, ScalarBase, StatStor
*/
-template<int N = 0>
-class Scalar : public Wrap<Scalar<N>, ScalarBase<StatStor>, ScalarStatData>
+class Scalar : public ScalarBase<Scalar, StatStor>
{
public:
- /** The base implementation. */
- typedef ScalarBase<StatStor> Base;
-
- Scalar()
- {
- this->doInit();
- }
-
- /**
- * Sets the stat equal to the given value. Calls the base implementation
- * of operator=
- * @param v The new value.
- */
- template <typename U>
- void operator=(const U &v) { Base::operator=(v); }
-};
-
-class Value : public Wrap<Value, ValueBase, ScalarStatData>
-{
- public:
- /** The base implementation. */
- typedef ValueBase Base;
-
- template <class T>
- Value &scalar(T &value)
- {
- Base::scalar(value);
- return *this;
- }
-
- template <class T>
- Value &functor(T &func)
- {
- Base::functor(func);
- return *this;
- }
+ using ScalarBase<Scalar, StatStor>::operator=;
};
/**
* A stat that calculates the per tick average of a value.
* @sa Stat, ScalarBase, AvgStor
*/
-template<int N = 0>
-class Average : public Wrap<Average<N>, ScalarBase<AvgStor>, ScalarStatData>
+class Average : public ScalarBase<Average, AvgStor>
{
public:
- /** The base implementation. */
- typedef ScalarBase<AvgStor> Base;
-
- Average()
- {
- this->doInit();
- }
+ using ScalarBase<Average, AvgStor>::operator=;
+};
- /**
- * Sets the stat equal to the given value. Calls the base implementation
- * of operator=
- * @param v The new value.
- */
- template <typename U>
- void operator=(const U &v) { Base::operator=(v); }
+class Value : public ValueBase<Value>
+{
};
/**
* A vector of scalar stats.
* @sa Stat, VectorBase, StatStor
*/
-template<int N = 0>
-class Vector : public WrapVec<Vector<N>, VectorBase<StatStor>, VectorStatData>
+class Vector : public VectorBase<Vector, StatStor>
{
- public:
- /** The base implementation. */
- typedef ScalarBase<StatStor> Base;
-
- /**
- * Set this vector to have the given size.
- * @param size The new size.
- * @return A reference to this stat.
- */
- Vector &init(size_t size) {
- this->doInit(size);
- return *this;
- }
};
/**
* A vector of Average stats.
* @sa Stat, VectorBase, AvgStor
*/
-template<int N = 0>
-class AverageVector
- : public WrapVec<AverageVector<N>, VectorBase<AvgStor>, VectorStatData>
+class AverageVector : public VectorBase<AverageVector, AvgStor>
{
- public:
- /**
- * Set this vector to have the given size.
- * @param size The new size.
- * @return A reference to this stat.
- */
- AverageVector &init(size_t size) {
- this->doInit(size);
- return *this;
- }
};
/**
* A 2-Dimensional vecto of scalar stats.
* @sa Stat, Vector2dBase, StatStor
*/
-template<int N = 0>
-class Vector2d
- : public WrapVec2d<Vector2d<N>, Vector2dBase<StatStor>, Vector2dStatData>
+class Vector2d : public Vector2dBase<Vector2d, StatStor>
{
- public:
- Vector2d &init(size_t x, size_t y) {
- this->doInit(x, y);
- return *this;
- }
};
/**
* A simple distribution stat.
* @sa Stat, DistBase, DistStor
*/
-template<int N = 0>
-class Distribution
- : public Wrap<Distribution<N>, DistBase<DistStor>, DistStatData>
+class Distribution : public DistBase<Distribution, DistStor>
{
public:
- /** Base implementation. */
- typedef DistBase<DistStor> Base;
- /** The Parameter type. */
- typedef DistStor::Params Params;
-
- public:
/**
* Set the parameters of this distribution. @sa DistStor::Params
* @param min The minimum value of the distribution.
@@ -2424,13 +2434,17 @@ class Distribution
* @param bkt The number of values in each bucket.
* @return A reference to this distribution.
*/
- Distribution &init(Counter min, Counter max, Counter bkt) {
- this->params.min = min;
- this->params.max = max;
- this->params.bucket_size = bkt;
- this->params.size = (int)rint((max - min) / bkt + 1.0);
+ Distribution &
+ init(Counter min, Counter max, Counter bkt)
+ {
+ DistStor::Params *params = new DistStor::Params;
+ params->min = min;
+ params->max = max;
+ params->bucket_size = bkt;
+ params->buckets = (size_type)rint((max - min) / bkt + 1.0);
+ this->setParams(params);
this->doInit();
- return *this;
+ return this->self();
}
};
@@ -2438,21 +2452,14 @@ class Distribution
* Calculates the mean and variance of all the samples.
* @sa Stat, DistBase, FancyStor
*/
-template<int N = 0>
-class StandardDeviation
- : public Wrap<StandardDeviation<N>, DistBase<FancyStor>, DistStatData>
+class StandardDeviation : public DistBase<StandardDeviation, FancyStor>
{
public:
- /** The base implementation */
- typedef DistBase<DistStor> Base;
- /** The parameter type. */
- typedef DistStor::Params Params;
-
- public:
/**
* Construct and initialize this distribution.
*/
- StandardDeviation() {
+ StandardDeviation()
+ {
this->doInit();
}
};
@@ -2461,17 +2468,9 @@ class StandardDeviation
* Calculates the per tick mean and variance of the samples.
* @sa Stat, DistBase, AvgFancy
*/
-template<int N = 0>
-class AverageDeviation
- : public Wrap<AverageDeviation<N>, DistBase<AvgFancy>, DistStatData>
+class AverageDeviation : public DistBase<AverageDeviation, AvgFancy>
{
public:
- /** The base implementation */
- typedef DistBase<DistStor> Base;
- /** The parameter type. */
- typedef DistStor::Params Params;
-
- public:
/**
* Construct and initialize this distribution.
*/
@@ -2485,19 +2484,9 @@ class AverageDeviation
* A vector of distributions.
* @sa Stat, VectorDistBase, DistStor
*/
-template<int N = 0>
-class VectorDistribution
- : public WrapVec<VectorDistribution<N>,
- VectorDistBase<DistStor>,
- VectorDistStatData>
+class VectorDistribution : public VectorDistBase<VectorDistribution, DistStor>
{
public:
- /** The base implementation */
- typedef VectorDistBase<DistStor> Base;
- /** The parameter type. */
- typedef DistStor::Params Params;
-
- public:
/**
* Initialize storage and parameters for this distribution.
* @param size The size of the vector (the number of distributions).
@@ -2506,13 +2495,17 @@ class VectorDistribution
* @param bkt The number of values in each bucket.
* @return A reference to this distribution.
*/
- VectorDistribution &init(int size, Counter min, Counter max, Counter bkt) {
- this->params.min = min;
- this->params.max = max;
- this->params.bucket_size = bkt;
- this->params.size = (int)rint((max - min) / bkt + 1.0);
+ VectorDistribution &
+ init(size_type size, Counter min, Counter max, Counter bkt)
+ {
+ DistStor::Params *params = new DistStor::Params;
+ params->min = min;
+ params->max = max;
+ params->bucket_size = bkt;
+ params->buckets = (size_type)rint((max - min) / bkt + 1.0);
+ this->setParams(params);
this->doInit(size);
- return *this;
+ return this->self();
}
};
@@ -2520,27 +2513,20 @@ class VectorDistribution
* This is a vector of StandardDeviation stats.
* @sa Stat, VectorDistBase, FancyStor
*/
-template<int N = 0>
class VectorStandardDeviation
- : public WrapVec<VectorStandardDeviation<N>,
- VectorDistBase<FancyStor>,
- VectorDistStatData>
+ : public VectorDistBase<VectorStandardDeviation, FancyStor>
{
public:
- /** The base implementation */
- typedef VectorDistBase<FancyStor> Base;
- /** The parameter type. */
- typedef DistStor::Params Params;
-
- public:
/**
* Initialize storage for this distribution.
* @param size The size of the vector.
* @return A reference to this distribution.
*/
- VectorStandardDeviation &init(int size) {
+ VectorStandardDeviation &
+ init(size_type size)
+ {
this->doInit(size);
- return *this;
+ return this->self();
}
};
@@ -2548,36 +2534,60 @@ class VectorStandardDeviation
* This is a vector of AverageDeviation stats.
* @sa Stat, VectorDistBase, AvgFancy
*/
-template<int N = 0>
class VectorAverageDeviation
- : public WrapVec<VectorAverageDeviation<N>,
- VectorDistBase<AvgFancy>,
- VectorDistStatData>
+ : public VectorDistBase<VectorAverageDeviation, AvgFancy>
{
public:
- /** The base implementation */
- typedef VectorDistBase<AvgFancy> Base;
- /** The parameter type. */
- typedef DistStor::Params Params;
-
- public:
/**
* Initialize storage for this distribution.
* @param size The size of the vector.
* @return A reference to this distribution.
*/
- VectorAverageDeviation &init(int size) {
+ VectorAverageDeviation &
+ init(size_type size)
+ {
this->doInit(size);
- return *this;
+ return this->self();
+ }
+};
+
+class FormulaInfoBase : public VectorInfoBase
+{
+ public:
+ virtual std::string str() const = 0;
+};
+
+template <class Stat>
+class FormulaInfo : public InfoWrap<Stat, FormulaInfoBase>
+{
+ protected:
+ mutable VResult vec;
+ mutable VCounter cvec;
+
+ public:
+ FormulaInfo(Stat &stat) : InfoWrap<Stat, FormulaInfoBase>(stat) {}
+
+ size_type size() const { return this->s.size(); }
+
+ const VResult &
+ result() const
+ {
+ this->s.result(vec);
+ return vec;
}
+ Result total() const { return this->s.total(); }
+ VCounter &value() const { return cvec; }
+
+ std::string str() const { return this->s.str(); }
};
+class Temp;
/**
* A formula for statistics that is calculated when printed. A formula is
* stored as a tree of Nodes that represent the equation to calculate.
* @sa Stat, ScalarStat, VectorStat, Node, Temp
*/
-class FormulaBase : public DataAccess
+class Formula : public DataWrapVec<Formula, FormulaInfo>
{
protected:
/** The root of the tree which represents the Formula */
@@ -2586,6 +2596,31 @@ class FormulaBase : public DataAccess
public:
/**
+ * Create and initialize thie formula, and register it with the database.
+ */
+ Formula();
+
+ /**
+ * Create a formula with the given root node, register it with the
+ * database.
+ * @param r The root of the expression tree.
+ */
+ Formula(Temp r);
+
+ /**
+ * Set an unitialized Formula to the given root.
+ * @param r The root of the expression tree.
+ * @return a reference to this formula.
+ */
+ const Formula &operator=(Temp r);
+
+ /**
+ * Add the given tree to the existing one.
+ * @param r The root of the expression tree.
+ * @return a reference to this formula.
+ */
+ const Formula &operator+=(Temp r);
+ /**
* Return the result of the Fomula in a vector. If there were no Vector
* components to the Formula, then the vector is size 1. If there were,
* like x/y with x being a vector of size 3, then the result returned will
@@ -2609,9 +2644,9 @@ class FormulaBase : public DataAccess
/**
* Return the number of elements in the tree.
*/
- size_t size() const;
+ size_type size() const;
- bool check() const { return true; }
+ void prepare() { }
/**
* Formulas don't need to be reset
@@ -2623,86 +2658,9 @@ class FormulaBase : public DataAccess
*/
bool zero() const;
- /**
- *
- */
- void update(StatData *);
-
std::string str() const;
};
-class FormulaData : public VectorData
-{
- public:
- virtual std::string str() const = 0;
- virtual bool check() const { return true; }
-};
-
-template <class Stat>
-class FormulaStatData : public FormulaData
-{
- protected:
- Stat &s;
- mutable VResult vec;
- mutable VCounter cvec;
-
- public:
- FormulaStatData(Stat &stat) : s(stat) {}
-
- virtual bool zero() const { return s.zero(); }
- virtual void reset() { s.reset(); }
-
- virtual size_t size() const { return s.size(); }
- virtual const VResult &result() const
- {
- s.result(vec);
- return vec;
- }
- virtual Result total() const { return s.total(); }
- virtual VCounter &value() const { return cvec; }
- virtual void visit(Visit &visitor)
- {
- update();
- s.update(this);
- visitor.visit(*this);
- }
- virtual std::string str() const { return s.str(); }
-};
-
-class Temp;
-class Formula
- : public WrapVec<Formula,
- FormulaBase,
- FormulaStatData>
-{
- public:
- /**
- * Create and initialize thie formula, and register it with the database.
- */
- Formula();
-
- /**
- * Create a formula with the given root node, register it with the
- * database.
- * @param r The root of the expression tree.
- */
- Formula(Temp r);
-
- /**
- * Set an unitialized Formula to the given root.
- * @param r The root of the expression tree.
- * @return a reference to this formula.
- */
- const Formula &operator=(Temp r);
-
- /**
- * Add the given tree to the existing one.
- * @param r The root of the expression tree.
- * @return a reference to this formula.
- */
- const Formula &operator+=(Temp r);
-};
-
class FormulaNode : public Node
{
private:
@@ -2712,11 +2670,11 @@ class FormulaNode : public Node
public:
FormulaNode(const Formula &f) : formula(f) {}
- virtual size_t size() const { return formula.size(); }
- virtual const VResult &result() const { formula.result(vec); return vec; }
- virtual Result total() const { return formula.total(); }
+ size_type size() const { return formula.size(); }
+ const VResult &result() const { formula.result(vec); return vec; }
+ Result total() const { return formula.total(); }
- virtual std::string str() const { return formula.str(); }
+ std::string str() const { return formula.str(); }
};
/**
@@ -2741,45 +2699,47 @@ class Temp
* Return the node pointer.
* @return the node pointer.
*/
- operator NodePtr&() { return node;}
+ operator NodePtr&() { return node; }
public:
/**
* Create a new ScalarStatNode.
* @param s The ScalarStat to place in a node.
*/
- template <int N>
- Temp(const Scalar<N> &s)
- : node(new ScalarStatNode(s.statData())) { }
+ Temp(const Scalar &s)
+ : node(new ScalarStatNode(s.info()))
+ { }
/**
* Create a new ScalarStatNode.
* @param s The ScalarStat to place in a node.
*/
Temp(const Value &s)
- : node(new ScalarStatNode(s.statData())) { }
+ : node(new ScalarStatNode(s.info()))
+ { }
/**
* Create a new ScalarStatNode.
* @param s The ScalarStat to place in a node.
*/
- template <int N>
- Temp(const Average<N> &s)
- : node(new ScalarStatNode(s.statData())) { }
+ Temp(const Average &s)
+ : node(new ScalarStatNode(s.info()))
+ { }
/**
* Create a new VectorStatNode.
* @param s The VectorStat to place in a node.
*/
- template <int N>
- Temp(const Vector<N> &s)
- : node(new VectorStatNode(s.statData())) { }
+ Temp(const Vector &s)
+ : node(new VectorStatNode(s.info()))
+ { }
/**
*
*/
Temp(const Formula &f)
- : node(new FormulaNode(f)) { }
+ : node(new FormulaNode(f))
+ { }
/**
* Create a new ScalarProxyNode.
@@ -2787,91 +2747,104 @@ class Temp
*/
template <class Stat>
Temp(const ScalarProxy<Stat> &p)
- : node(new ScalarProxyNode<Stat>(p)) { }
+ : node(new ScalarProxyNode<Stat>(p))
+ { }
/**
* Create a ConstNode
* @param value The value of the const node.
*/
Temp(signed char value)
- : node(new ConstNode<signed char>(value)) {}
+ : node(new ConstNode<signed char>(value))
+ { }
/**
* Create a ConstNode
* @param value The value of the const node.
*/
Temp(unsigned char value)
- : node(new ConstNode<unsigned char>(value)) {}
+ : node(new ConstNode<unsigned char>(value))
+ { }
/**
* Create a ConstNode
* @param value The value of the const node.
*/
Temp(signed short value)
- : node(new ConstNode<signed short>(value)) {}
+ : node(new ConstNode<signed short>(value))
+ { }
/**
* Create a ConstNode
* @param value The value of the const node.
*/
Temp(unsigned short value)
- : node(new ConstNode<unsigned short>(value)) {}
+ : node(new ConstNode<unsigned short>(value))
+ { }
/**
* Create a ConstNode
* @param value The value of the const node.
*/
Temp(signed int value)
- : node(new ConstNode<signed int>(value)) {}
+ : node(new ConstNode<signed int>(value))
+ { }
/**
* Create a ConstNode
* @param value The value of the const node.
*/
Temp(unsigned int value)
- : node(new ConstNode<unsigned int>(value)) {}
+ : node(new ConstNode<unsigned int>(value))
+ { }
/**
* Create a ConstNode
* @param value The value of the const node.
*/
Temp(signed long value)
- : node(new ConstNode<signed long>(value)) {}
+ : node(new ConstNode<signed long>(value))
+ { }
/**
* Create a ConstNode
* @param value The value of the const node.
*/
Temp(unsigned long value)
- : node(new ConstNode<unsigned long>(value)) {}
+ : node(new ConstNode<unsigned long>(value))
+ { }
/**
* Create a ConstNode
* @param value The value of the const node.
*/
Temp(signed long long value)
- : node(new ConstNode<signed long long>(value)) {}
+ : node(new ConstNode<signed long long>(value))
+ { }
/**
* Create a ConstNode
* @param value The value of the const node.
*/
Temp(unsigned long long value)
- : node(new ConstNode<unsigned long long>(value)) {}
+ : node(new ConstNode<unsigned long long>(value))
+ { }
/**
* Create a ConstNode
* @param value The value of the const node.
*/
Temp(float value)
- : node(new ConstNode<float>(value)) {}
+ : node(new ConstNode<float>(value))
+ { }
/**
* Create a ConstNode
* @param value The value of the const node.
*/
Temp(double value)
- : node(new ConstNode<double>(value)) {}
+ : node(new ConstNode<double>(value))
+ { }
};
@@ -2879,11 +2852,6 @@ class Temp
* @}
*/
-void check();
-void dump();
-void reset();
-void registerResetCallback(Callback *cb);
-
inline Temp
operator+(Temp l, Temp r)
{
@@ -2934,6 +2902,36 @@ sum(Temp val)
return NodePtr(new SumNode<std::plus<Result> >(val));
}
+/**
+ * Enable the statistics package. Before the statistics package is
+ * enabled, all statistics must be created and initialized and once
+ * the package is enabled, no more statistics can be created.
+ */
+void enable();
+
+/**
+ * Prepare all stats for data access. This must be done before
+ * dumping and serialization.
+ */
+void prepare();
+
+/**
+ * Dump all statistics data to the registered outputs
+ */
+void dump();
+
+/**
+ * Reset all statistics to the base state
+ */
+void reset();
+/**
+ * Register a callback that should be called whenever statistics are
+ * reset
+ */
+void registerResetCallback(Callback *cb);
+
+std::list<Info *> &statsList();
+
/* namespace Stats */ }
#endif // __BASE_STATISTICS_HH__
diff --git a/src/base/stats/events.cc b/src/base/stats/events.cc
index dc56fe75f..dcf52e6d8 100644
--- a/src/base/stats/events.cc
+++ b/src/base/stats/events.cc
@@ -38,7 +38,7 @@ using namespace std;
namespace Stats {
-Tick EventStart = ULL(0x7fffffffffffffff);
+Tick EventStart = MaxTick;
extern list<Output *> OutputList;
diff --git a/src/base/stats/flags.hh b/src/base/stats/flags.hh
index 69f73f66a..77eedaee8 100644
--- a/src/base/stats/flags.hh
+++ b/src/base/stats/flags.hh
@@ -30,6 +30,7 @@
#ifndef __BASE_STATS_FLAGS_HH__
#define __BASE_STATS_FLAGS_HH__
+
namespace Stats {
/**
@@ -39,28 +40,28 @@ namespace Stats {
typedef uint32_t StatFlags;
/** Nothing extra to print. */
-const StatFlags none = 0x00000000;
+const StatFlags none = 0x00000000;
/** This Stat is Initialized */
-const StatFlags init = 0x00000001;
+const StatFlags init = 0x00000001;
/** Print this stat. */
-const StatFlags print = 0x00000002;
+const StatFlags print = 0x00000002;
/** Print the total. */
-const StatFlags total = 0x00000010;
+const StatFlags total = 0x00000010;
/** Print the percent of the total that this entry represents. */
-const StatFlags pdf = 0x00000020;
+const StatFlags pdf = 0x00000020;
/** Print the cumulative percentage of total upto this entry. */
-const StatFlags cdf = 0x00000040;
+const StatFlags cdf = 0x00000040;
/** Print the distribution. */
-const StatFlags dist = 0x00000080;
+const StatFlags dist = 0x00000080;
/** Don't print if this is zero. */
-const StatFlags nozero = 0x00000100;
+const StatFlags nozero = 0x00000100;
/** Don't print if this is NAN */
-const StatFlags nonan = 0x00000200;
+const StatFlags nonan = 0x00000200;
/** Used for SS compatability. */
-const StatFlags __substat = 0x80000000;
+const StatFlags __substat = 0x80000000;
/** Mask of flags that can't be set directly */
-const StatFlags __reserved = init | print | __substat;
+const StatFlags __reserved = init | print | __substat;
enum DisplayMode
{
diff --git a/src/base/stats/mysql.cc b/src/base/stats/mysql.cc
index 39a687fff..1e0c923f1 100644
--- a/src/base/stats/mysql.cc
+++ b/src/base/stats/mysql.cc
@@ -40,7 +40,6 @@
#include "base/stats/flags.hh"
#include "base/stats/mysql.hh"
#include "base/stats/mysql_run.hh"
-#include "base/stats/statdb.hh"
#include "base/stats/types.hh"
#include "base/str.hh"
#include "base/userinfo.hh"
@@ -458,7 +457,7 @@ InsertSubData::setup(MySqlRun *run)
mysql.query(insert);
// if (mysql.error)
-// panic("could not insert subdata\n%s\n", mysql.error);
+// panic("could not insert subdata\n%s\n", mysql.error);
if (mysql.commit())
panic("could not commit transaction\n%s\n", mysql.error);
@@ -493,21 +492,19 @@ MySql::configure()
/*
* set up all stats!
*/
- using namespace Database;
-
MySQL::Connection &mysql = run->conn();
- stat_list_t::const_iterator i, end = stats().end();
- for (i = stats().begin(); i != end; ++i) {
+ list<Info *>::const_iterator i, end = statsList().end();
+ for (i = statsList().begin(); i != end; ++i) {
(*i)->visit(*this);
}
- for (i = stats().begin(); i != end; ++i) {
- StatData *data = *i;
- if (data->prereq) {
+ for (i = statsList().begin(); i != end; ++i) {
+ Info *info = *i;
+ if (info->prereq) {
// update the prerequisite
- uint16_t stat_id = find(data->id);
- uint16_t prereq_id = find(data->prereq->id);
+ uint16_t stat_id = find(info->id);
+ uint16_t prereq_id = find(info->prereq->id);
assert(stat_id && prereq_id);
stringstream update;
@@ -528,153 +525,156 @@ MySql::configure()
configured = true;
}
-
bool
-MySql::configure(const StatData &data, string type)
+MySql::configure(const Info &info, string type)
{
stat.init();
- stat.name = data.name;
- stat.descr = data.desc;
+ stat.name = info.name;
+ stat.descr = info.desc;
stat.type = type;
- stat.print = data.flags & print;
- stat.prec = data.precision;
- stat.nozero = data.flags & nozero;
- stat.nonan = data.flags & nonan;
- stat.total = data.flags & total;
- stat.pdf = data.flags & pdf;
- stat.cdf = data.flags & cdf;
+ stat.print = info.flags & print;
+ stat.prec = info.precision;
+ stat.nozero = info.flags & nozero;
+ stat.nonan = info.flags & nonan;
+ stat.total = info.flags & total;
+ stat.pdf = info.flags & pdf;
+ stat.cdf = info.flags & cdf;
return stat.print;
}
void
-MySql::configure(const ScalarData &data)
+MySql::configure(const ScalarInfoBase &info)
{
- if (!configure(data, "SCALAR"))
+ if (!configure(info, "SCALAR"))
return;
- insert(data.id, stat.setup(run));
+ insert(info.id, stat.setup(run));
}
void
-MySql::configure(const VectorData &data)
+MySql::configure(const VectorInfoBase &info)
{
- if (!configure(data, "VECTOR"))
+ if (!configure(info, "VECTOR"))
return;
uint16_t statid = stat.setup(run);
- if (!data.subnames.empty()) {
+ if (!info.subnames.empty()) {
InsertSubData subdata;
subdata.stat = statid;
subdata.y = 0;
- for (int i = 0; i < data.subnames.size(); ++i) {
+ for (off_type i = 0; i < info.subnames.size(); ++i) {
subdata.x = i;
- subdata.name = data.subnames[i];
- subdata.descr = data.subdescs.empty() ? "" : data.subdescs[i];
+ subdata.name = info.subnames[i];
+ subdata.descr = info.subdescs.empty() ? "" : info.subdescs[i];
if (!subdata.name.empty() || !subdata.descr.empty())
subdata.setup(run);
}
}
- insert(data.id, statid);
+ insert(info.id, statid);
}
void
-MySql::configure(const DistData &data)
+MySql::configure(const DistInfoBase &info)
{
- if (!configure(data, "DIST"))
+ if (!configure(info, "DIST"))
return;
- if (!data.data.fancy) {
- stat.size = data.data.size;
- stat.min = data.data.min;
- stat.max = data.data.max;
- stat.bktsize = data.data.bucket_size;
+ const DistParams *params =
+ safe_cast<const DistParams *>(info.storageParams);
+ if (!params->fancy) {
+ stat.size = params->buckets;
+ stat.min = params->min;
+ stat.max = params->max;
+ stat.bktsize = params->bucket_size;
}
- insert(data.id, stat.setup(run));
+ insert(info.id, stat.setup(run));
}
void
-MySql::configure(const VectorDistData &data)
+MySql::configure(const VectorDistInfoBase &info)
{
- if (!configure(data, "VECTORDIST"))
+ if (!configure(info, "VECTORDIST"))
return;
- if (!data.data[0].fancy) {
- stat.size = data.data[0].size;
- stat.min = data.data[0].min;
- stat.max = data.data[0].max;
- stat.bktsize = data.data[0].bucket_size;
+ const DistParams *params =
+ safe_cast<const DistParams *>(info.storageParams);
+ if (!params->fancy) {
+ stat.size = params->buckets;
+ stat.min = params->min;
+ stat.max = params->max;
+ stat.bktsize = params->bucket_size;
}
uint16_t statid = stat.setup(run);
- if (!data.subnames.empty()) {
+ if (!info.subnames.empty()) {
InsertSubData subdata;
subdata.stat = statid;
subdata.y = 0;
- for (int i = 0; i < data.subnames.size(); ++i) {
+ for (off_type i = 0; i < info.subnames.size(); ++i) {
subdata.x = i;
- subdata.name = data.subnames[i];
- subdata.descr = data.subdescs.empty() ? "" : data.subdescs[i];
+ subdata.name = info.subnames[i];
+ subdata.descr = info.subdescs.empty() ? "" : info.subdescs[i];
if (!subdata.name.empty() || !subdata.descr.empty())
subdata.setup(run);
}
}
- insert(data.id, statid);
+ insert(info.id, statid);
}
void
-MySql::configure(const Vector2dData &data)
+MySql::configure(const Vector2dInfoBase &info)
{
- if (!configure(data, "VECTOR2D"))
+ if (!configure(info, "VECTOR2D"))
return;
uint16_t statid = stat.setup(run);
- if (!data.subnames.empty()) {
+ if (!info.subnames.empty()) {
InsertSubData subdata;
subdata.stat = statid;
subdata.y = -1;
- for (int i = 0; i < data.subnames.size(); ++i) {
+ for (off_type i = 0; i < info.subnames.size(); ++i) {
subdata.x = i;
- subdata.name = data.subnames[i];
- subdata.descr = data.subdescs.empty() ? "" : data.subdescs[i];
+ subdata.name = info.subnames[i];
+ subdata.descr = info.subdescs.empty() ? "" : info.subdescs[i];
if (!subdata.name.empty() || !subdata.descr.empty())
subdata.setup(run);
}
}
- if (!data.y_subnames.empty()) {
+ if (!info.y_subnames.empty()) {
InsertSubData subdata;
subdata.stat = statid;
subdata.x = -1;
subdata.descr = "";
- for (int i = 0; i < data.y_subnames.size(); ++i) {
+ for (off_type i = 0; i < info.y_subnames.size(); ++i) {
subdata.y = i;
- subdata.name = data.y_subnames[i];
+ subdata.name = info.y_subnames[i];
if (!subdata.name.empty())
subdata.setup(run);
}
}
- insert(data.id, statid);
+ insert(info.id, statid);
}
void
-MySql::configure(const FormulaData &data)
+MySql::configure(const FormulaInfoBase &info)
{
MySQL::Connection &mysql = run->conn();
assert(mysql.connected());
- configure(data, "FORMULA");
- insert(data.id, stat.setup(run));
+ configure(info, "FORMULA");
+ insert(info.id, stat.setup(run));
- uint16_t stat = find(data.id);
- string formula = data.str();
+ uint16_t stat = find(info.id);
+ string formula = info.str();
stringstream insert_formula;
ccprintf(insert_formula,
@@ -683,7 +683,7 @@ MySql::configure(const FormulaData &data)
mysql.query(insert_formula);
// if (mysql.error)
-// panic("could not insert formula\n%s\n", mysql.error);
+// panic("could not insert formula\n%s\n", mysql.error);
stringstream insert_ref;
ccprintf(insert_ref,
@@ -692,7 +692,7 @@ MySql::configure(const FormulaData &data)
mysql.query(insert_ref);
// if (mysql.error)
-// panic("could not insert formula reference\n%s\n", mysql.error);
+// panic("could not insert formula reference\n%s\n", mysql.error);
if (mysql.commit())
panic("could not commit transaction\n%s\n", mysql.error);
@@ -707,7 +707,6 @@ MySql::valid() const
void
MySql::output()
{
- using namespace Database;
assert(valid());
if (!configured)
@@ -718,9 +717,9 @@ MySql::output()
MySQL::Connection &mysql = run->conn();
- Database::stat_list_t::const_iterator i, end = Database::stats().end();
- for (i = Database::stats().begin(); i != end; ++i) {
- StatData *stat = *i;
+ list<Info *>::const_iterator i, end = statsList().end();
+ for (i = statsList().begin(); i != end; ++i) {
+ Info *stat = *i;
stat->visit(*this);
if (mysql.commit())
panic("could not commit transaction\n%s\n", mysql.error);
@@ -735,33 +734,32 @@ MySql::event(const std::string &event)
newevent.insert(event);
}
-
void
-MySql::output(const ScalarData &data)
+MySql::output(const ScalarInfoBase &info)
{
- if (!(data.flags & print))
+ if (!(info.flags & print))
return;
- newdata.stat = find(data.id);
+ newdata.stat = find(info.id);
newdata.x = 0;
newdata.y = 0;
- newdata.data = data.value();
+ newdata.data = info.value();
newdata.insert();
}
void
-MySql::output(const VectorData &data)
+MySql::output(const VectorInfoBase &info)
{
- if (!(data.flags & print))
+ if (!(info.flags & print))
return;
- newdata.stat = find(data.id);
+ newdata.stat = find(info.id);
newdata.y = 0;
- const VCounter &cvec = data.value();
- int size = data.size();
- for (int x = 0; x < size; x++) {
+ const VCounter &cvec = info.value();
+ size_type size = info.size();
+ for (off_type x = 0; x < size; x++) {
newdata.x = x;
newdata.data = cvec[x];
newdata.insert();
@@ -769,7 +767,7 @@ MySql::output(const VectorData &data)
}
void
-MySql::output(const DistDataData &data)
+MySql::output(const DistData &data, const DistParams *params)
{
const int db_sum = -1;
const int db_squares = -2;
@@ -791,7 +789,7 @@ MySql::output(const DistDataData &data)
newdata.data = data.samples;
newdata.insert();
- if (data.samples && !data.fancy) {
+ if (data.samples && !params->fancy) {
newdata.x = db_min_val;
newdata.data = data.min_val;
newdata.insert();
@@ -808,8 +806,8 @@ MySql::output(const DistDataData &data)
newdata.data = data.overflow;
newdata.insert();
- int size = data.cvec.size();
- for (int x = 0; x < size; x++) {
+ size_type size = data.cvec.size();
+ for (off_type x = 0; x < size; x++) {
newdata.x = x;
newdata.data = data.cvec[x];
newdata.insert();
@@ -817,54 +815,54 @@ MySql::output(const DistDataData &data)
}
}
-
void
-MySql::output(const DistData &data)
+MySql::output(const DistInfoBase &info)
{
- if (!(data.flags & print))
+ if (!(info.flags & print))
return;
- newdata.stat = find(data.id);
+ newdata.stat = find(info.id);
newdata.y = 0;
- output(data.data);
+ output(info.data, safe_cast<const DistParams *>(info.storageParams));
}
void
-MySql::output(const VectorDistData &data)
+MySql::output(const VectorDistInfoBase &info)
{
- if (!(data.flags & print))
+ if (!(info.flags & print))
return;
- newdata.stat = find(data.id);
+ newdata.stat = find(info.id);
- int size = data.data.size();
- for (int y = 0; y < size; ++y) {
+ size_type size = info.data.size();
+ for (off_type y = 0; y < size; ++y) {
newdata.y = y;
- output(data.data[y]);
+ output(info.data[y],
+ safe_cast<const DistParams *>(info.storageParams));
}
}
void
-MySql::output(const Vector2dData &data)
+MySql::output(const Vector2dInfoBase &info)
{
- if (!(data.flags & print))
+ if (!(info.flags & print))
return;
- newdata.stat = find(data.id);
+ newdata.stat = find(info.id);
- int index = 0;
- for (int x = 0; x < data.x; x++) {
+ off_type index = 0;
+ for (off_type x = 0; x < info.x; x++) {
newdata.x = x;
- for (int y = 0; y < data.y; y++) {
+ for (off_type y = 0; y < info.y; y++) {
newdata.y = y;
- newdata.data = data.cvec[index++];
+ newdata.data = info.cvec[index++];
newdata.insert();
}
}
}
void
-MySql::output(const FormulaData &data)
+MySql::output(const FormulaInfoBase &info)
{
}
@@ -872,65 +870,65 @@ MySql::output(const FormulaData &data)
* Implement the visitor
*/
void
-MySql::visit(const ScalarData &data)
+MySql::visit(const ScalarInfoBase &info)
{
if (!configured)
- configure(data);
+ configure(info);
else
- output(data);
+ output(info);
}
void
-MySql::visit(const VectorData &data)
+MySql::visit(const VectorInfoBase &info)
{
if (!configured)
- configure(data);
+ configure(info);
else
- output(data);
+ output(info);
}
void
-MySql::visit(const DistData &data)
+MySql::visit(const DistInfoBase &info)
{
return;
if (!configured)
- configure(data);
+ configure(info);
else
- output(data);
+ output(info);
}
void
-MySql::visit(const VectorDistData &data)
+MySql::visit(const VectorDistInfoBase &info)
{
return;
if (!configured)
- configure(data);
+ configure(info);
else
- output(data);
+ output(info);
}
void
-MySql::visit(const Vector2dData &data)
+MySql::visit(const Vector2dInfoBase &info)
{
return;
if (!configured)
- configure(data);
+ configure(info);
else
- output(data);
+ output(info);
}
void
-MySql::visit(const FormulaData &data)
+MySql::visit(const FormulaInfoBase &info)
{
if (!configured)
- configure(data);
+ configure(info);
else
- output(data);
+ output(info);
}
bool
initMySQL(string host, string user, string password, string database,
- string project, string name, string sample)
+ string project, string name, string sample)
{
extern list<Output *> OutputList;
static MySql mysql;
diff --git a/src/base/stats/mysql.hh b/src/base/stats/mysql.hh
index 0ce381c2f..86a4d6d23 100644
--- a/src/base/stats/mysql.hh
+++ b/src/base/stats/mysql.hh
@@ -40,7 +40,7 @@
namespace MySQL { class Connection; }
namespace Stats {
-class DistDataData;
+class DistInfoBase;
class MySqlRun;
struct SetupStat
@@ -56,6 +56,7 @@ struct SetupStat
bool total;
bool pdf;
bool cdf;
+
double min;
double max;
double bktsize;
@@ -69,9 +70,9 @@ class InsertData
{
private:
char *query;
- int size;
+ size_type size;
bool first;
- static const int maxsize = 1024*1024;
+ static const size_type maxsize = 1024*1024;
public:
MySqlRun *run;
@@ -95,9 +96,9 @@ class InsertEvent
{
private:
char *query;
- int size;
+ size_type size;
bool first;
- static const int maxsize = 1024*1024;
+ static const size_type maxsize = 1024*1024;
typedef std::map<std::string, uint32_t> event_map_t;
event_map_t events;
@@ -121,19 +122,21 @@ class MySql : public Output
SetupStat stat;
InsertData newdata;
InsertEvent newevent;
- std::list<FormulaData *> formulas;
+ std::list<FormulaInfoBase *> formulas;
bool configured;
protected:
std::map<int, int> idmap;
- void insert(int sim_id, int db_id)
+ void
+ insert(int sim_id, int db_id)
{
using namespace std;
idmap.insert(make_pair(sim_id, db_id));
}
- int find(int sim_id)
+ int
+ find(int sim_id)
{
using namespace std;
map<int,int>::const_iterator i = idmap.find(sim_id);
@@ -146,19 +149,19 @@ class MySql : public Output
~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);
+ 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);
- virtual void visit(const VectorData &data);
- virtual void visit(const DistData &data);
- virtual void visit(const VectorDistData &data);
- virtual void visit(const Vector2dData &data);
- virtual void visit(const FormulaData &data);
+ virtual void visit(const ScalarInfoBase &info);
+ virtual void visit(const VectorInfoBase &info);
+ virtual void visit(const DistInfoBase &info);
+ virtual void visit(const VectorDistInfoBase &info);
+ virtual void visit(const Vector2dInfoBase &info);
+ virtual void visit(const FormulaInfoBase &info);
// Implement Output
virtual bool valid() const;
@@ -169,33 +172,33 @@ class MySql : public Output
protected:
// Output helper
- void output(const DistDataData &data);
- void output(const ScalarData &data);
- void output(const VectorData &data);
- void output(const DistData &data);
- void output(const VectorDistData &data);
- void output(const Vector2dData &data);
- void output(const FormulaData &data);
+ void output(const ScalarInfoBase &info);
+ void output(const VectorInfoBase &info);
+ void output(const DistInfoBase &info);
+ void output(const VectorDistInfoBase &info);
+ void output(const Vector2dInfoBase &info);
+ void output(const FormulaInfoBase &info);
+ void output(const DistData &data, const DistParams *params);
void configure();
- bool configure(const StatData &data, std::string type);
- void configure(const ScalarData &data);
- void configure(const VectorData &data);
- void configure(const DistData &data);
- void configure(const VectorDistData &data);
- void configure(const Vector2dData &data);
- void configure(const FormulaData &data);
+ bool configure(const Info &info, std::string type);
+ void configure(const ScalarInfoBase &info);
+ void configure(const VectorInfoBase &info);
+ void configure(const DistInfoBase &info);
+ void configure(const VectorDistInfoBase &info);
+ void configure(const Vector2dInfoBase &info);
+ void configure(const FormulaInfoBase &info);
};
bool initMySQL(std::string host, std::string database, std::string user,
- std::string passwd, std::string project, std::string name,
- std::string sample);
+ std::string passwd, std::string project, std::string name,
+ std::string sample);
#if !USE_MYSQL
inline bool
initMySQL(std::string host, std::string user, std::string password,
- std::string database, std::string project, std::string name,
- std::string sample)
+ std::string database, std::string project, std::string name,
+ std::string sample)
{
return false;
}
diff --git a/src/base/stats/mysql_run.hh b/src/base/stats/mysql_run.hh
index 487224551..7c606370e 100644
--- a/src/base/stats/mysql_run.hh
+++ b/src/base/stats/mysql_run.hh
@@ -46,7 +46,7 @@ struct MySqlRun
protected:
void setup(const std::string &name, const std::string &sample,
- const std::string &user, const std::string &project);
+ const std::string &user, const std::string &project);
void remove(const std::string &name);
void cleanup();
@@ -54,9 +54,9 @@ struct MySqlRun
public:
bool connected() const { return mysql.connected(); }
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);
+ const std::string &passwd, const std::string &db,
+ const std::string &name, const std::string &sample,
+ const std::string &project);
MySQL::Connection &conn() { return mysql; }
uint16_t run() const { return run_id; }
diff --git a/src/base/stats/output.cc b/src/base/stats/output.cc
index 9f2b91c77..31aa21c45 100644
--- a/src/base/stats/output.cc
+++ b/src/base/stats/output.cc
@@ -30,6 +30,7 @@
#include <list>
+#include "base/statistics.hh"
#include "base/stats/output.hh"
#include "sim/eventq.hh"
#include "sim/host.hh"
@@ -49,6 +50,8 @@ dump()
return;
lastDump = curTick;
+ prepare();
+
list<Output *>::iterator i = OutputList.begin();
list<Output *>::iterator end = OutputList.end();
for (; i != end; ++i) {
diff --git a/src/base/stats/text.cc b/src/base/stats/text.cc
index a018c4837..c3e484cf4 100644
--- a/src/base/stats/text.cc
+++ b/src/base/stats/text.cc
@@ -43,7 +43,6 @@
#include "base/misc.hh"
#include "base/statistics.hh"
-#include "base/stats/statdb.hh"
#include "base/stats/text.hh"
#include "base/stats/visit.hh"
@@ -107,7 +106,8 @@ Text::open(std::ostream &_stream)
mystream = false;
stream = &_stream;
- assert(valid());
+ if (!valid())
+ fatal("Unable to open output stream for writing\n");
}
void
@@ -118,35 +118,34 @@ Text::open(const std::string &file)
mystream = true;
stream = new ofstream(file.c_str(), ios::trunc);
- assert(valid());
+ if (!valid())
+ fatal("Unable to open statistics file for writing\n");
}
bool
Text::valid() const
{
- return stream != NULL;
+ return stream != NULL && stream->good();
}
void
Text::output()
{
- using namespace Database;
-
ccprintf(*stream, "\n---------- Begin Simulation Statistics ----------\n");
- stat_list_t::const_iterator i, end = stats().end();
- for (i = stats().begin(); i != end; ++i)
+ list<Info *>::const_iterator i, end = statsList().end();
+ for (i = statsList().begin(); i != end; ++i)
(*i)->visit(*this);
ccprintf(*stream, "\n---------- End Simulation Statistics ----------\n");
stream->flush();
}
bool
-Text::noOutput(const StatData &data)
+Text::noOutput(const Info &info)
{
- if (!(data.flags & print))
+ if (!(info.flags & print))
return true;
- if (data.prereq && data.prereq->zero())
+ if (info.prereq && info.prereq->zero())
return true;
return false;
@@ -191,8 +190,8 @@ struct ScalarPrint
void
ScalarPrint::operator()(ostream &stream) const
{
- if (flags & nozero && value == 0.0 ||
- flags & nonan && isnan(value))
+ if ((flags & nozero && value == 0.0) ||
+ (flags & nonan && isnan(value)))
return;
stringstream pdfstr, cdfstr;
@@ -237,11 +236,11 @@ struct VectorPrint
void
VectorPrint::operator()(std::ostream &stream) const
{
- int _size = vec.size();
+ size_type _size = vec.size();
Result _total = 0.0;
if (flags & (pdf | cdf)) {
- for (int i = 0; i < _size; ++i) {
+ for (off_type i = 0; i < _size; ++i) {
_total += vec[i];
}
}
@@ -264,7 +263,7 @@ VectorPrint::operator()(std::ostream &stream) const
print.value = vec[0];
print(stream);
} else if (!compat) {
- for (int i = 0; i < _size; ++i) {
+ for (off_type i = 0; i < _size; ++i) {
if (havesub && (i >= subnames.size() || subnames[i].empty()))
continue;
@@ -296,7 +295,7 @@ VectorPrint::operator()(std::ostream &stream) const
Result _cdf = 0.0;
if (flags & dist) {
ccprintf(stream, "%s.start_dist\n", name);
- for (int i = 0; i < _size; ++i) {
+ for (off_type i = 0; i < _size; ++i) {
print.name = havesub ? subnames[i] : to_string(i);
print.desc = subdescs.empty() ? desc : subdescs[i];
print.flags |= __substat;
@@ -316,7 +315,7 @@ VectorPrint::operator()(std::ostream &stream) const
}
ccprintf(stream, "%s.end_dist\n", name);
} else {
- for (int i = 0; i < _size; ++i) {
+ for (off_type i = 0; i < _size; ++i) {
if (havesub && subnames[i].empty())
continue;
@@ -352,27 +351,63 @@ struct DistPrint
bool descriptions;
int precision;
- Result min_val;
- Result max_val;
- Result underflow;
- Result overflow;
- VResult vec;
- Result sum;
- Result squares;
- Result samples;
-
Counter min;
Counter max;
Counter bucket_size;
- int size;
+ size_type size;
bool fancy;
+ const DistData &data;
+
+ DistPrint(const DistInfoBase &info);
+ DistPrint(const VectorDistInfoBase &info, int i);
+ void init(const Info &info, const DistParams *params);
void operator()(ostream &stream) const;
};
+DistPrint::DistPrint(const DistInfoBase &info)
+ : data(info.data)
+{
+ init(info, safe_cast<const DistParams *>(info.storageParams));
+}
+
+DistPrint::DistPrint(const VectorDistInfoBase &info, int i)
+ : data(info.data[i])
+{
+ init(info, safe_cast<const DistParams *>(info.storageParams));
+
+ name = info.name + "_" +
+ (info.subnames[i].empty() ? (to_string(i)) : info.subnames[i]);
+
+ if (!info.subdescs[i].empty())
+ desc = info.subdescs[i];
+}
+
+void
+DistPrint::init(const Info &info, const DistParams *params)
+{
+ name = info.name;
+ desc = info.desc;
+ flags = info.flags;
+ compat = compat;
+ descriptions = descriptions;
+ precision = info.precision;
+
+ fancy = params->fancy;
+ min = params->min;
+ max = params->max;
+ bucket_size = params->bucket_size;
+ size = params->buckets;
+}
+
void
DistPrint::operator()(ostream &stream) const
{
+ Result stdev = NAN;
+ if (data.samples)
+ stdev = sqrt((data.samples * data.squares - data.sum * data.sum) /
+ (data.samples * (data.samples - 1.0)));
+
if (fancy) {
ScalarPrint print;
string base = name + (compat ? "_" : "::");
@@ -386,28 +421,27 @@ DistPrint::operator()(ostream &stream) const
print.cdf = NAN;
print.name = base + "mean";
- print.value = samples ? sum / samples : NAN;
+ print.value = data.samples ? data.sum / data.samples : NAN;
print(stream);
print.name = base + "stdev";
- print.value = samples ? sqrt((samples * squares - sum * sum) /
- (samples * (samples - 1.0))) : NAN;
+ print.value = stdev;
print(stream);
print.name = "**Ignore: " + base + "TOT";
- print.value = samples;
+ print.value = data.samples;
print(stream);
return;
}
- assert(size == vec.size());
+ assert(size == data.cvec.size());
Result total = 0.0;
- total += underflow;
- for (int i = 0; i < size; ++i)
- total += vec[i];
- total += overflow;
+ total += data.underflow;
+ for (off_type i = 0; i < size; ++i)
+ total += data.cvec[i];
+ total += data.overflow;
string base = name + (compat ? "." : "::");
@@ -428,28 +462,27 @@ DistPrint::operator()(ostream &stream) const
}
print.name = base + "samples";
- print.value = samples;
+ print.value = data.samples;
print(stream);
print.name = base + "min_value";
- print.value = min_val;
+ print.value = data.min_val;
print(stream);
- if (!compat || underflow > 0.0) {
+ if (!compat || data.underflow > 0.0) {
print.name = base + "underflows";
- print.value = underflow;
+ print.value = data.underflow;
if (!compat && total) {
- print.pdf = underflow / total;
+ print.pdf = data.underflow / total;
print.cdf += print.pdf;
}
print(stream);
}
-
if (!compat) {
- for (int i = 0; i < size; ++i) {
+ for (off_type i = 0; i < size; ++i) {
stringstream namestr;
- namestr << name;
+ namestr << base;
Counter low = i * bucket_size + min;
Counter high = ::min(low + bucket_size, max);
@@ -458,14 +491,13 @@ DistPrint::operator()(ostream &stream) const
namestr << "-" << high;
print.name = namestr.str();
- print.value = vec[i];
+ print.value = data.cvec[i];
if (total) {
- print.pdf = vec[i] / total;
+ print.pdf = data.cvec[i] / total;
print.cdf += print.pdf;
}
print(stream);
}
-
} else {
Counter _min;
Result _pdf;
@@ -473,18 +505,18 @@ DistPrint::operator()(ostream &stream) const
print.flags = flags | __substat;
- for (int i = 0; i < size; ++i) {
- if (flags & nozero && vec[i] == 0.0 ||
- flags & nonan && isnan(vec[i]))
+ for (off_type i = 0; i < size; ++i) {
+ if ((flags & nozero && data.cvec[i] == 0.0) ||
+ (flags & nonan && isnan(data.cvec[i])))
continue;
_min = i * bucket_size + min;
- _pdf = vec[i] / total * 100.0;
+ _pdf = data.cvec[i] / total * 100.0;
_cdf += _pdf;
print.name = ValueToString(_min, 0, compat);
- print.value = vec[i];
+ print.value = data.cvec[i];
print.pdf = (flags & pdf) ? _pdf : NAN;
print.cdf = (flags & cdf) ? _cdf : NAN;
print(stream);
@@ -493,11 +525,11 @@ DistPrint::operator()(ostream &stream) const
print.flags = flags;
}
- if (!compat || overflow > 0.0) {
+ if (!compat || data.overflow > 0.0) {
print.name = base + "overflows";
- print.value = overflow;
+ print.value = data.overflow;
if (!compat && total) {
- print.pdf = overflow / total;
+ print.pdf = data.overflow / total;
print.cdf += print.pdf;
} else {
print.pdf = NAN;
@@ -516,17 +548,16 @@ DistPrint::operator()(ostream &stream) const
}
print.name = base + "max_value";
- print.value = max_val;
+ print.value = data.max_val;
print(stream);
- if (!compat && samples != 0) {
+ if (!compat && data.samples != 0) {
print.name = base + "mean";
- print.value = sum / samples;
+ print.value = data.sum / data.samples;
print(stream);
print.name = base + "stdev";
- print.value = sqrt((samples * squares - sum * sum) /
- (samples * (samples - 1.0)));
+ print.value = stdev;
print(stream);
}
@@ -535,19 +566,19 @@ DistPrint::operator()(ostream &stream) const
}
void
-Text::visit(const ScalarData &data)
+Text::visit(const ScalarInfoBase &info)
{
- if (noOutput(data))
+ if (noOutput(info))
return;
ScalarPrint print;
- print.value = data.result();
- print.name = data.name;
- print.desc = data.desc;
- print.flags = data.flags;
+ print.value = info.result();
+ print.name = info.name;
+ print.desc = info.desc;
+ print.flags = info.flags;
print.compat = compat;
print.descriptions = descriptions;
- print.precision = data.precision;
+ print.precision = info.precision;
print.pdf = NAN;
print.cdf = NAN;
@@ -555,32 +586,32 @@ Text::visit(const ScalarData &data)
}
void
-Text::visit(const VectorData &data)
+Text::visit(const VectorInfoBase &info)
{
- if (noOutput(data))
+ if (noOutput(info))
return;
- int size = data.size();
+ size_type size = info.size();
VectorPrint print;
- print.name = data.name;
- print.desc = data.desc;
- print.flags = data.flags;
+ print.name = info.name;
+ print.desc = info.desc;
+ print.flags = info.flags;
print.compat = compat;
print.descriptions = descriptions;
- print.precision = data.precision;
- print.vec = data.result();
- print.total = data.total();
-
- if (!data.subnames.empty()) {
- for (int i = 0; i < size; ++i) {
- if (!data.subnames[i].empty()) {
- print.subnames = data.subnames;
+ print.precision = info.precision;
+ print.vec = info.result();
+ print.total = info.total();
+
+ if (!info.subnames.empty()) {
+ for (off_type i = 0; i < size; ++i) {
+ if (!info.subnames[i].empty()) {
+ print.subnames = info.subnames;
print.subnames.resize(size);
- for (int i = 0; i < size; ++i) {
- if (!data.subnames[i].empty() &&
- !data.subdescs[i].empty()) {
- print.subdescs = data.subdescs;
+ for (off_type i = 0; i < size; ++i) {
+ if (!info.subnames[i].empty() &&
+ !info.subdescs[i].empty()) {
+ print.subdescs = info.subdescs;
print.subdescs.resize(size);
break;
}
@@ -594,53 +625,54 @@ Text::visit(const VectorData &data)
}
void
-Text::visit(const Vector2dData &data)
+Text::visit(const Vector2dInfoBase &info)
{
- if (noOutput(data))
+ if (noOutput(info))
return;
bool havesub = false;
VectorPrint print;
- print.subnames = data.y_subnames;
- print.flags = data.flags;
+ print.subnames = info.y_subnames;
+ print.flags = info.flags;
print.compat = compat;
print.descriptions = descriptions;
- print.precision = data.precision;
+ print.precision = info.precision;
- if (!data.subnames.empty()) {
- for (int i = 0; i < data.x; ++i)
- if (!data.subnames[i].empty())
+ if (!info.subnames.empty()) {
+ for (off_type i = 0; i < info.x; ++i)
+ if (!info.subnames[i].empty())
havesub = true;
}
- VResult tot_vec(data.y);
+ VResult tot_vec(info.y);
Result super_total = 0.0;
- for (int i = 0; i < data.x; ++i) {
- if (havesub && (i >= data.subnames.size() || data.subnames[i].empty()))
+ for (off_type i = 0; i < info.x; ++i) {
+ if (havesub && (i >= info.subnames.size() || info.subnames[i].empty()))
continue;
- int iy = i * data.y;
- VResult yvec(data.y);
+ off_type iy = i * info.y;
+ VResult yvec(info.y);
Result total = 0.0;
- for (int j = 0; j < data.y; ++j) {
- yvec[j] = data.cvec[iy + j];
+ for (off_type j = 0; j < info.y; ++j) {
+ yvec[j] = info.cvec[iy + j];
tot_vec[j] += yvec[j];
total += yvec[j];
super_total += yvec[j];
}
- print.name = data.name + "_" + (havesub ? data.subnames[i] : to_string(i));
- print.desc = data.desc;
+ print.name = info.name + "_" +
+ (havesub ? info.subnames[i] : to_string(i));
+ print.desc = info.desc;
print.vec = yvec;
print.total = total;
print(*stream);
}
- if ((data.flags & ::Stats::total) && (data.x > 1)) {
- print.name = data.name;
- print.desc = data.desc;
+ if ((info.flags & ::Stats::total) && (info.x > 1)) {
+ print.name = info.name;
+ print.desc = info.desc;
print.vec = tot_vec;
print.total = super_total;
print(*stream);
@@ -648,82 +680,31 @@ Text::visit(const Vector2dData &data)
}
void
-Text::visit(const DistData &data)
+Text::visit(const DistInfoBase &info)
{
- if (noOutput(data))
+ if (noOutput(info))
return;
- DistPrint print;
-
- print.name = data.name;
- print.desc = data.desc;
- print.flags = data.flags;
- print.compat = compat;
- print.descriptions = descriptions;
- print.precision = data.precision;
-
- print.min_val = data.data.min_val;
- print.max_val = data.data.max_val;
- print.underflow = data.data.underflow;
- print.overflow = data.data.overflow;
- print.vec.resize(data.data.cvec.size());
- for (int i = 0; i < print.vec.size(); ++i)
- print.vec[i] = (Result)data.data.cvec[i];
- print.sum = data.data.sum;
- print.squares = data.data.squares;
- print.samples = data.data.samples;
-
- print.min = data.data.min;
- print.max = data.data.max;
- print.bucket_size = data.data.bucket_size;
- print.size = data.data.size;
- print.fancy = data.data.fancy;
-
+ DistPrint print(info);
print(*stream);
}
void
-Text::visit(const VectorDistData &data)
+Text::visit(const VectorDistInfoBase &info)
{
- if (noOutput(data))
+ if (noOutput(info))
return;
- for (int i = 0; i < data.size(); ++i) {
- DistPrint print;
-
- print.name = data.name +
- (data.subnames[i].empty() ? ("_" + to_string(i)) : data.subnames[i]);
- print.desc = data.subdescs[i].empty() ? data.desc : data.subdescs[i];
- print.flags = data.flags;
- print.compat = compat;
- print.descriptions = descriptions;
- print.precision = data.precision;
-
- print.min_val = data.data[i].min_val;
- print.max_val = data.data[i].max_val;
- print.underflow = data.data[i].underflow;
- print.overflow = data.data[i].overflow;
- print.vec.resize(data.data[i].cvec.size());
- for (int j = 0; j < print.vec.size(); ++j)
- print.vec[j] = (Result)data.data[i].cvec[j];
- print.sum = data.data[i].sum;
- print.squares = data.data[i].squares;
- print.samples = data.data[i].samples;
-
- print.min = data.data[i].min;
- print.max = data.data[i].max;
- print.bucket_size = data.data[i].bucket_size;
- print.size = data.data[i].size;
- print.fancy = data.data[i].fancy;
-
+ for (off_type i = 0; i < info.size(); ++i) {
+ DistPrint print(info, i);
print(*stream);
}
}
void
-Text::visit(const FormulaData &data)
+Text::visit(const FormulaInfoBase &info)
{
- visit((const VectorData &)data);
+ visit((const VectorInfoBase &)info);
}
bool
@@ -746,5 +727,4 @@ initText(const string &filename, bool desc, bool compat)
return true;
}
-
/* namespace Stats */ }
diff --git a/src/base/stats/text.hh b/src/base/stats/text.hh
index 781d1083d..38e0202eb 100644
--- a/src/base/stats/text.hh
+++ b/src/base/stats/text.hh
@@ -46,7 +46,7 @@ class Text : public Output
std::ostream *stream;
protected:
- bool noOutput(const StatData &data);
+ bool noOutput(const Info &info);
public:
bool compat;
@@ -62,12 +62,12 @@ class Text : public Output
void open(const std::string &file);
// Implement Visit
- virtual void visit(const ScalarData &data);
- virtual void visit(const VectorData &data);
- virtual void visit(const DistData &data);
- virtual void visit(const VectorDistData &data);
- virtual void visit(const Vector2dData &data);
- virtual void visit(const FormulaData &data);
+ virtual void visit(const ScalarInfoBase &info);
+ virtual void visit(const VectorInfoBase &info);
+ virtual void visit(const DistInfoBase &info);
+ virtual void visit(const VectorDistInfoBase &info);
+ virtual void visit(const Vector2dInfoBase &info);
+ virtual void visit(const FormulaInfoBase &info);
// Implement Output
virtual bool valid() const;
diff --git a/src/base/stats/types.hh b/src/base/stats/types.hh
index b64e8fb17..e561f94ad 100644
--- a/src/base/stats/types.hh
+++ b/src/base/stats/types.hh
@@ -31,7 +31,9 @@
#ifndef __BASE_STATS_TYPES_HH__
#define __BASE_STATS_TYPES_HH__
+#include <limits>
#include <vector>
+
#include "sim/host.hh"
namespace Stats {
@@ -41,11 +43,16 @@ typedef double Counter;
/** vector of counters. */
typedef std::vector<Counter> VCounter;
+typedef std::numeric_limits<Counter> CounterLimits;
+
/** All results are doubles. */
typedef double Result;
/** vector of results. */
typedef std::vector<Result> VResult;
+typedef unsigned int size_type;
+typedef unsigned int off_type;
+
/* namespace Stats */ }
#endif // __BASE_STATS_TYPES_HH__
diff --git a/src/base/stats/visit.hh b/src/base/stats/visit.hh
index 0087c227c..9d6996689 100644
--- a/src/base/stats/visit.hh
+++ b/src/base/stats/visit.hh
@@ -38,26 +38,26 @@
namespace Stats {
-class StatData;
-class ScalarData;
-class VectorData;
-class DistDataData;
-class DistData;
-class VectorDistData;
-class Vector2dData;
-class FormulaData;
+class Info;
+class ScalarInfoBase;
+class VectorInfoBase;
+class DistInfoBase;
+class DistInfoBase;
+class VectorDistInfoBase;
+class Vector2dInfoBase;
+class FormulaInfoBase;
struct Visit
{
Visit();
virtual ~Visit();
- virtual void visit(const ScalarData &data) = 0;
- virtual void visit(const VectorData &data) = 0;
- virtual void visit(const DistData &data) = 0;
- virtual void visit(const VectorDistData &data) = 0;
- virtual void visit(const Vector2dData &data) = 0;
- virtual void visit(const FormulaData &data) = 0;
+ virtual void visit(const ScalarInfoBase &info) = 0;
+ virtual void visit(const VectorInfoBase &info) = 0;
+ virtual void visit(const DistInfoBase &info) = 0;
+ virtual void visit(const VectorDistInfoBase &info) = 0;
+ virtual void visit(const Vector2dInfoBase &info) = 0;
+ virtual void visit(const FormulaInfoBase &info) = 0;
};
/* namespace Stats */ }
diff --git a/src/base/str.cc b/src/base/str.cc
index 0a517dff5..2df1c103c 100644
--- a/src/base/str.cc
+++ b/src/base/str.cc
@@ -28,10 +28,10 @@
* Authors: Nathan Binkert
*/
-#include <ctype.h>
-
+#include <cctype>
#include <cstring>
#include <iostream>
+#include <limits>
#include <string>
#include <vector>
@@ -117,12 +117,11 @@ inline bool
__to_number(string value, T &retval)
{
static const T maxnum = ((T)-1);
- static const bool sign = maxnum < 0;
- static const int bits = sizeof(T) * 8;
- static const T hexmax = maxnum & (((T)1 << (bits - 4 - sign)) - 1);
- static const T octmax = maxnum & (((T)1 << (bits - 3 - sign)) - 1);
- static const T signmax =
- (sign) ? maxnum & (((T)1 << (bits - 1)) - 1) : maxnum;
+ static const bool sign = numeric_limits<T>::is_signed;
+ static const int bits = numeric_limits<T>::digits;
+ static const T hexmax = maxnum & (((T)1 << (bits - 4)) - 1);
+ static const T octmax = maxnum & (((T)1 << (bits - 3)) - 1);
+ static const T signmax = numeric_limits<T>::max();
static const T decmax = signmax / 10;
#if 0
diff --git a/src/base/time.cc b/src/base/time.cc
index 76ba355b7..a1732773e 100644
--- a/src/base/time.cc
+++ b/src/base/time.cc
@@ -28,9 +28,9 @@
* Authors: Nathan Binkert
*/
-#include <sys/types.h>
-#include <sys/time.h>
-#include <time.h>
+#include <cctype>
+#include <cstring>
+#include <ctime>
#include <iostream>
#include <string>
diff --git a/src/base/time.hh b/src/base/time.hh
index f10cc5d6c..565ea0aac 100644
--- a/src/base/time.hh
+++ b/src/base/time.hh
@@ -68,7 +68,7 @@ std::ostream &operator<<(std::ostream &out, const Time &time);
/*
* Copyright (c) 1982, 1986, 1993
- * The Regents of the University of California. All rights reserved.
+ * The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -94,7 +94,7 @@ std::ostream &operator<<(std::ostream &out, const Time &time);
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)time.h 8.2 (Berkeley) 7/10/94
+ * @(#)time.h 8.2 (Berkeley) 7/10/94
*/
#if defined(__sun)
diff --git a/src/base/timebuf.hh b/src/base/timebuf.hh
index 348f7a673..9f9fc32b5 100644
--- a/src/base/timebuf.hh
+++ b/src/base/timebuf.hh
@@ -43,6 +43,7 @@ class TimeBuffer
int past;
int future;
int size;
+ int _id;
char *data;
std::vector<char *> index;
@@ -148,6 +149,8 @@ class TimeBuffer
new (ptr) T;
ptr += sizeof(T);
}
+
+ _id = -1;
}
TimeBuffer()
@@ -162,6 +165,16 @@ class TimeBuffer
delete [] data;
}
+ void id(int id)
+ {
+ _id = id;
+ }
+
+ int id()
+ {
+ return _id;
+ }
+
void
advance()
{
diff --git a/src/base/trace.hh b/src/base/trace.hh
index c1b506187..fa24e9c48 100644
--- a/src/base/trace.hh
+++ b/src/base/trace.hh
@@ -97,6 +97,12 @@ inline const std::string &name() { return Trace::DefaultName; }
Trace::dprintf(curTick, name(), __VA_ARGS__); \
} while (0)
+#define DPRINTFS(x,s, ...) do { \
+ if (DTRACE(x)) \
+ Trace::dprintf(curTick, s->name(), __VA_ARGS__); \
+} while (0)
+
+
#define DPRINTFR(x, ...) do { \
if (DTRACE(x)) \
Trace::dprintf((Tick)-1, std::string(), __VA_ARGS__); \
@@ -119,11 +125,12 @@ inline const std::string &name() { return Trace::DefaultName; }
#define DTRACE(x) (false)
#define DDUMP(x, data, count) do {} while (0)
#define DPRINTF(x, ...) do {} while (0)
+#define DPRINTFS(x, ...) do {} while (0)
#define DPRINTFR(...) do {} while (0)
#define DDUMPN(data, count) do {} while (0)
#define DPRINTFN(...) do {} while (0)
#define DPRINTFNR(...) do {} while (0)
-#endif // TRACING_ON
+#endif // TRACING_ON
#endif // __BASE_TRACE_HH__
diff --git a/src/base/varargs.hh b/src/base/varargs.hh
index 2ba8c240a..4328f2057 100644
--- a/src/base/varargs.hh
+++ b/src/base/varargs.hh
@@ -147,15 +147,31 @@ struct Any : public Base<RECV>
}
};
+template <typename T, class RECV>
+struct Any<T *, RECV> : public Base<RECV>
+{
+ const T *argument;
+
+ Any(const T *arg) : argument(arg) {}
+
+ virtual void
+ add_arg(RECV &receiver) const
+ {
+ receiver.add_arg(argument);
+ }
+};
+
template <class RECV>
struct Argument : public RefCountingPtr<Base<RECV> >
{
- typedef RefCountingPtr<Base<RECV> > Base;
+ typedef RefCountingPtr<VarArgs::Base<RECV> > Base;
Argument() { }
Argument(const Null &null) { }
template <typename T>
Argument(const T& arg) : Base(new Any<T, RECV>(arg)) { }
+ template <typename T>
+ Argument(const T* arg) : Base(new Any<T *, RECV>(arg)) { }
void
add_arg(RECV &receiver) const
@@ -169,7 +185,7 @@ template<class RECV>
class List
{
public:
- typedef Argument<RECV> Argument;
+ typedef VarArgs::Argument<RECV> Argument;
typedef std::list<Argument> list;
typedef typename list::iterator iterator;
typedef typename list::const_iterator const_iterator;