diff options
author | Gabe Black <gblack@eecs.umich.edu> | 2009-04-06 10:19:36 -0700 |
---|---|---|
committer | Gabe Black <gblack@eecs.umich.edu> | 2009-04-06 10:19:36 -0700 |
commit | d080581db1f9ee4e1e6d07d2b01c13c67908a391 (patch) | |
tree | cc484b289fa5a30c4631f9faa1d8b456bffeebfc /src/base | |
parent | 7a7c4c5fca83a8d47c7e71c9c080a882ebe204a9 (diff) | |
parent | 639cb0a42d953ee32bc7e96b0cdfa96cd40e9fc1 (diff) | |
download | gem5-d080581db1f9ee4e1e6d07d2b01c13c67908a391.tar.xz |
Merge ARM into the head. ARM will compile but may not actually work.
Diffstat (limited to 'src/base')
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 §ion) +{ + 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 §ion) +{ + 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 §ion); + + }; + + 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 §ion); + +}; +#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 ¶ms) - : 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 ¶ms) + 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 ¶ms) const + bool + zero() const { return samples == Counter(); } - void update(DistDataData *data, const Params ¶ms) + 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 ¶ms) - { - 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 ¶ms) - { - 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 ¶ms) 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 ¶ms) 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; |