summaryrefslogtreecommitdiff
path: root/src/base
diff options
context:
space:
mode:
Diffstat (limited to 'src/base')
-rw-r--r--src/base/SConscript83
-rw-r--r--src/base/annotate.cc2
-rw-r--r--src/base/bigint.cc47
-rw-r--r--src/base/bigint.hh97
-rw-r--r--src/base/bitfield.hh294
-rw-r--r--src/base/cprintf.cc427
-rw-r--r--src/base/cprintf.hh205
-rw-r--r--src/base/cprintf_formats.hh4
-rw-r--r--src/base/loader/elf_object.cc15
-rw-r--r--src/base/loader/object_file.hh6
-rw-r--r--src/base/misc.cc90
-rw-r--r--src/base/misc.hh71
-rw-r--r--src/base/pollevent.cc2
-rw-r--r--src/base/pollevent.hh2
-rw-r--r--src/base/random.cc48
-rw-r--r--src/base/random.hh18
-rw-r--r--src/base/statistics.hh19
-rw-r--r--src/base/stats/events.cc131
-rw-r--r--src/base/stats/events.hh10
-rw-r--r--src/base/stats/mysql.cc253
-rw-r--r--src/base/stats/mysql.hh60
-rw-r--r--src/base/stats/output.cc70
-rw-r--r--src/base/stats/output.hh1
-rw-r--r--src/base/stats/text.cc22
-rw-r--r--src/base/stats/text.hh6
-rw-r--r--src/base/trace.cc283
-rw-r--r--src/base/trace.hh175
-rw-r--r--src/base/traceflags.py304
-rw-r--r--src/base/varargs.hh292
29 files changed, 1903 insertions, 1134 deletions
diff --git a/src/base/SConscript b/src/base/SConscript
new file mode 100644
index 000000000..788aa3e6f
--- /dev/null
+++ b/src/base/SConscript
@@ -0,0 +1,83 @@
+# -*- mode:python -*-
+
+# Copyright (c) 2006 The Regents of The University of Michigan
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met: redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer;
+# redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution;
+# neither the name of the copyright holders nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# Authors: Nathan Binkert
+
+Import('*')
+
+# base/traceflags.{cc,hh} are generated from base/traceflags.py.
+# $TARGET.base will expand to "<build-dir>/base/traceflags".
+env.Command(['traceflags.hh', 'traceflags.cc'], 'traceflags.py',
+ 'python $SOURCE $TARGET.base')
+
+Source('annotate.cc')
+Source('bigint.cc')
+Source('circlebuf.cc')
+Source('cprintf.cc')
+Source('crc.cc')
+Source('fast_alloc.cc')
+Source('fifo_buffer.cc')
+Source('hostinfo.cc')
+Source('hybrid_pred.cc')
+Source('inet.cc')
+Source('inifile.cc')
+Source('intmath.cc')
+Source('match.cc')
+Source('misc.cc')
+Source('output.cc')
+Source('pollevent.cc')
+Source('random.cc')
+Source('range.cc')
+Source('remote_gdb.cc')
+Source('sat_counter.cc')
+Source('socket.cc')
+Source('statistics.cc')
+Source('str.cc')
+Source('time.cc')
+Source('trace.cc')
+Source('traceflags.cc')
+Source('userinfo.cc')
+
+Source('compression/lzss_compression.cc')
+
+Source('loader/aout_object.cc')
+Source('loader/ecoff_object.cc')
+Source('loader/elf_object.cc')
+Source('loader/object_file.cc')
+Source('loader/raw_object.cc')
+Source('loader/symtab.cc')
+
+Source('stats/events.cc')
+Source('stats/output.cc')
+Source('stats/statdb.cc')
+Source('stats/text.cc')
+Source('stats/visit.cc')
+
+if env['USE_MYSQL']:
+ Source('mysql.cc')
+ Source('stats/mysql.cc')
diff --git a/src/base/annotate.cc b/src/base/annotate.cc
index ba2fb1788..de7eeed51 100644
--- a/src/base/annotate.cc
+++ b/src/base/annotate.cc
@@ -32,7 +32,7 @@
#include "base/callback.hh"
#include "base/output.hh"
#include "base/trace.hh"
-#include "sim/root.hh"
+#include "sim/core.hh"
#include "sim/sim_exit.hh"
#include "sim/system.hh"
diff --git a/src/base/bigint.cc b/src/base/bigint.cc
new file mode 100644
index 000000000..ce9942c9c
--- /dev/null
+++ b/src/base/bigint.cc
@@ -0,0 +1,47 @@
+/*
+ * 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: Gabe Black
+ */
+
+#include "base/bigint.hh"
+
+#include <iostream>
+
+using namespace std;
+
+ostream & operator << (ostream & os, const Twin64_t & t)
+{
+ os << t.a << ", " << t.b;
+ return os;
+}
+
+ostream & operator << (ostream & os, const Twin32_t & t)
+{
+ os << t.a << ", " << t.b;
+ return os;
+}
diff --git a/src/base/bigint.hh b/src/base/bigint.hh
new file mode 100644
index 000000000..d60684231
--- /dev/null
+++ b/src/base/bigint.hh
@@ -0,0 +1,97 @@
+/*
+ * 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/misc.hh"
+
+#include <iostream>
+
+#ifndef __BASE_BIGINT_HH__
+#define __BASE_BIGINT_HH__
+// Create a couple of large int types for atomic reads
+struct m5_twin64_t {
+ uint64_t a;
+ uint64_t b;
+ m5_twin64_t()
+ {}
+ m5_twin64_t(const uint64_t x)
+ {
+ a = x;
+ b = x;
+ }
+ inline m5_twin64_t& operator=(const uint64_t x)
+ {
+ a = x;
+ b = x;
+ return *this;
+ }
+
+ operator uint64_t()
+ {
+ panic("Tried to cram a twin64_t into an integer!\n");
+ return a;
+ }
+};
+
+struct m5_twin32_t {
+ uint32_t a;
+ uint32_t b;
+ m5_twin32_t()
+ {}
+ m5_twin32_t(const uint32_t x)
+ {
+ a = x;
+ b = x;
+ }
+ inline m5_twin32_t& operator=(const uint32_t x)
+ {
+ a = x;
+ b = x;
+ return *this;
+ }
+
+ operator uint32_t()
+ {
+ panic("Tried to cram a twin32_t into an integer!\n");
+ return a;
+ }
+};
+
+
+// This is for twin loads (two 64 bit values), not 1 128 bit value (as far as
+// endian conversion is concerned!
+typedef m5_twin64_t Twin64_t;
+typedef m5_twin32_t Twin32_t;
+
+// Output operator overloads
+std::ostream & operator << (std::ostream & os, const Twin64_t & t);
+std::ostream & operator << (std::ostream & os, const Twin32_t & t);
+
+#endif // __BASE_BIGINT_HH__
+
diff --git a/src/base/bitfield.hh b/src/base/bitfield.hh
index 1fc0bad5d..69cce2245 100644
--- a/src/base/bitfield.hh
+++ b/src/base/bitfield.hh
@@ -44,6 +44,7 @@ mask(int nbits)
}
+
/**
* Extract the bitfield from position 'first' to 'last' (inclusive)
* from 'val' and right justify it. MSB is numbered 63, LSB is 0.
@@ -69,6 +70,12 @@ mbits(T val, int first, int last)
return val & (mask(first+1) & ~mask(last));
}
+inline uint64_t
+mask(int first, int last)
+{
+ return mbits((uint64_t)-1LL, first, last);
+}
+
/**
* Sign-extend an N-bit value to 64 bits.
*/
@@ -105,4 +112,291 @@ replaceBits(T& val, int first, int last, B bit_val)
val = insertBits(val, first, last, bit_val);
}
+/**
+ * Returns the bit position of the MSB that is set in the input
+ */
+inline
+int
+findMsbSet(uint64_t val) {
+ int msb = 0;
+ if (!val)
+ return 0;
+ if (bits(val, 63,32)) { msb += 32; val >>= 32; }
+ if (bits(val, 31,16)) { msb += 16; val >>= 16; }
+ if (bits(val, 15,8)) { msb += 8; val >>= 8; }
+ if (bits(val, 7,4)) { msb += 4; val >>= 4; }
+ if (bits(val, 3,2)) { msb += 2; val >>= 2; }
+ if (bits(val, 1,1)) { msb += 1; }
+ return msb;
+}
+
+// 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
+//overlap. This allows all of the bitfields to manipulate the same data
+//without having to have access to each other. More details are provided with the
+//individual components.
+
+//This namespace is for classes which implement the backend of the BitUnion
+//stuff. Don't use any of these directly, except for the Bitfield classes in
+//the *BitfieldTypes class(es).
+namespace BitfieldBackend
+{
+ //A base class for all bitfields. It instantiates the actual storage,
+ //and provides getBits and setBits functions for manipulating it. The
+ //Data template parameter is type of the underlying storage.
+ template<class Data>
+ class BitfieldBase
+ {
+ protected:
+ Data __data;
+
+ //This function returns a range of bits from the underlying storage.
+ //It relies on the "bits" function above. It's the user's
+ //responsibility to make sure that there is a properly overloaded
+ //version of this function for whatever type they want to overlay.
+ inline uint64_t
+ getBits(int first, int last) const
+ {
+ return bits(__data, first, last);
+ }
+
+ //Similar to the above, but for settings bits with replaceBits.
+ inline void
+ setBits(int first, int last, uint64_t val)
+ {
+ replaceBits(__data, first, last, val);
+ }
+ };
+
+ //This class contains all the "regular" bitfield classes. It is inherited
+ //by all BitUnions which give them access to those types.
+ template<class Type>
+ class RegularBitfieldTypes
+ {
+ protected:
+ //This class implements ordinary bitfields, that is a span of bits
+ //who's msb is "first", and who's lsb is "last".
+ template<int first, int last=first>
+ class Bitfield : public BitfieldBase<Type>
+ {
+ public:
+ operator uint64_t () const
+ {
+ return this->getBits(first, last);
+ }
+
+ uint64_t
+ operator=(const uint64_t _data)
+ {
+ this->setBits(first, last, _data);
+ return _data;
+ }
+ };
+
+ //A class which specializes the above so that it can only be read
+ //from. This is accomplished explicitly making sure the assignment
+ //operator is blocked. The conversion operator is carried through
+ //inheritance. This will unfortunately need to be copied into each
+ //bitfield type due to limitations with how templates work
+ template<int first, int last=first>
+ class BitfieldRO : public Bitfield<first, last>
+ {
+ private:
+ uint64_t
+ operator=(const uint64_t _data);
+ };
+
+ //Similar to the above, but only allows writing.
+ template<int first, int last=first>
+ class BitfieldWO : public Bitfield<first, last>
+ {
+ private:
+ operator uint64_t () const;
+
+ public:
+ using Bitfield<first, last>::operator=;
+ };
+ };
+
+ //This class contains all the "regular" bitfield classes. It is inherited
+ //by all BitUnions which give them access to those types.
+ template<class Type>
+ class SignedBitfieldTypes
+ {
+ protected:
+ //This class implements ordinary bitfields, that is a span of bits
+ //who's msb is "first", and who's lsb is "last".
+ template<int first, int last=first>
+ class SignedBitfield : public BitfieldBase<Type>
+ {
+ public:
+ operator int64_t () const
+ {
+ return sext<first - last + 1>(this->getBits(first, last));
+ }
+
+ int64_t
+ operator=(const int64_t _data)
+ {
+ this->setBits(first, last, _data);
+ return _data;
+ }
+ };
+
+ //A class which specializes the above so that it can only be read
+ //from. This is accomplished explicitly making sure the assignment
+ //operator is blocked. The conversion operator is carried through
+ //inheritance. This will unfortunately need to be copied into each
+ //bitfield type due to limitations with how templates work
+ template<int first, int last=first>
+ class SignedBitfieldRO : public SignedBitfield<first, last>
+ {
+ private:
+ int64_t
+ operator=(const int64_t _data);
+ };
+
+ //Similar to the above, but only allows writing.
+ template<int first, int last=first>
+ class SignedBitfieldWO : public SignedBitfield<first, last>
+ {
+ private:
+ operator int64_t () const;
+
+ public:
+ int64_t operator=(const int64_t _data)
+ {
+ *((SignedBitfield<first, last> *)this) = _data;
+ return _data;
+ }
+ };
+ };
+
+ template<class Type>
+ class BitfieldTypes : public RegularBitfieldTypes<Type>,
+ public SignedBitfieldTypes<Type>
+ {};
+
+ //When a BitUnion is set up, an underlying class is created which holds
+ //the actual union. This class then inherits from it, and provids the
+ //implementations for various operators. Setting things up this way
+ //prevents having to redefine these functions in every different BitUnion
+ //type. More operators could be implemented in the future, as the need
+ //arises.
+ template <class Type, class Base>
+ class BitUnionOperators : public Base
+ {
+ public:
+ operator Type () const
+ {
+ return Base::__data;
+ }
+
+ Type
+ operator=(const Type & _data)
+ {
+ Base::__data = _data;
+ return _data;
+ }
+
+ bool
+ operator<(const Base & base) const
+ {
+ return Base::__data < base.__data;
+ }
+
+ bool
+ operator==(const Base & base) const
+ {
+ return Base::__data == base.__data;
+ }
+ };
+}
+
+//This macro is a backend for other macros that specialize it slightly.
+//First, it creates/extends a namespace "BitfieldUnderlyingClasses" and
+//sticks the class which has the actual union in it, which
+//BitfieldOperators above inherits from. Putting these classes in a special
+//namespace ensures that there will be no collisions with other names as long
+//as the BitUnion names themselves are all distinct and nothing else uses
+//the BitfieldUnderlyingClasses namespace, which is unlikely. The class itself
+//creates a typedef of the "type" parameter called __DataType. This allows
+//the type to propagate outside of the macro itself in a controlled way.
+//Finally, the base storage is defined which BitfieldOperators will refer to
+//in the operators it defines. This macro is intended to be followed by
+//bitfield definitions which will end up inside it's union. As explained
+//above, these is overlayed the __data member in its entirety by each of the
+//bitfields which are defined in the union, creating shared storage with no
+//overhead.
+#define __BitUnion(type, name) \
+ namespace BitfieldUnderlyingClasses \
+ { \
+ class name; \
+ } \
+ class BitfieldUnderlyingClasses::name : \
+ public BitfieldBackend::BitfieldTypes<type> \
+ { \
+ public: \
+ typedef type __DataType; \
+ union { \
+ type __data;\
+
+//This closes off the class and union started by the above macro. It is
+//followed by a typedef which makes "name" refer to a BitfieldOperator
+//class inheriting from the class and union just defined, which completes
+//building up the type for the user.
+#define EndBitUnion(name) \
+ }; \
+ }; \
+ typedef BitfieldBackend::BitUnionOperators< \
+ 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
+//BitUnion. Like everything else, it overlays with the top level storage, so
+//making it a regular bitfield type makes the entire thing function as a
+//regular bitfield when referred to by itself.
+#define __SubBitUnion(fieldType, first, last, name) \
+ class : public BitfieldBackend::BitfieldTypes<__DataType> \
+ { \
+ public: \
+ union { \
+ fieldType<first, last> __data;
+
+//This closes off the union created above and gives it a name. Unlike the top
+//level BitUnion, we're interested in creating an object instead of a type.
+//The operators are defined in the macro itself instead of a class for
+//technical reasons. If someone determines a way to move them to one, please
+//do so.
+#define EndSubBitUnion(name) \
+ }; \
+ inline operator const __DataType () \
+ { return __data; } \
+ \
+ inline const __DataType operator = (const __DataType & _data) \
+ { __data = _data; } \
+ } name;
+
+//Regular bitfields
+//These define macros for read/write regular bitfield based subbitfields.
+#define SubBitUnion(name, first, last) \
+ __SubBitUnion(Bitfield, first, last, name)
+
+//Regular bitfields
+//These define macros for read/write regular bitfield based subbitfields.
+#define SignedSubBitUnion(name, first, last) \
+ __SubBitUnion(SignedBitfield, first, last, name)
+
+//Use this to define an arbitrary type overlayed with bitfields.
+#define BitUnion(type, name) __BitUnion(type, name)
+
+//Use this to define conveniently sized values overlayed with bitfields.
+#define BitUnion64(name) __BitUnion(uint64_t, name)
+#define BitUnion32(name) __BitUnion(uint32_t, name)
+#define BitUnion16(name) __BitUnion(uint16_t, name)
+#define BitUnion8(name) __BitUnion(uint8_t, name)
+
#endif // __BASE_BITFIELD_HH__
diff --git a/src/base/cprintf.cc b/src/base/cprintf.cc
index dd8ce858b..d4ba9ca21 100644
--- a/src/base/cprintf.cc
+++ b/src/base/cprintf.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002-2005 The Regents of The University of Michigan
+ * Copyright (c) 2002-2006 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -39,232 +39,247 @@ using namespace std;
namespace cp {
-ArgList::~ArgList()
+Print::Print(std::ostream &stream, const std::string &format)
+ : stream(stream), format(format.c_str()), ptr(format.c_str())
+{
+ saved_flags = stream.flags();
+ saved_fill = stream.fill();
+ saved_precision = stream.precision();
+}
+
+Print::Print(std::ostream &stream, const char *format)
+ : stream(stream), format(format), ptr(format)
+{
+ saved_flags = stream.flags();
+ saved_fill = stream.fill();
+ saved_precision = stream.precision();
+}
+
+Print::~Print()
{
- while (!objects.empty()) {
- delete objects.front();
- objects.pop_front();
- }
}
void
-ArgList::dump(const string &format)
+Print::process(Format &fmt)
{
- list_t::iterator iter = objects.begin();
- list_t::iterator end = objects.end();
-
- const char *p = format.c_str();
-
- stream->fill(' ');
- stream->flags((ios::fmtflags)0);
-
- while (*p) {
- switch (*p) {
- case '%': {
- if (p[1] == '%') {
- *stream << '%';
- p += 2;
- continue;
- }
-
- Format fmt;
- bool done = false;
- bool end_number = false;
- bool have_precision = false;
- int number = 0;
-
- while (!done) {
- ++p;
- if (*p >= '0' && *p <= '9') {
- if (end_number)
- continue;
- } else if (number > 0)
- end_number = true;
-
- switch (*p) {
- case 's':
- fmt.format = Format::string;
- done = true;
- break;
-
- case 'c':
- fmt.format = Format::character;
- done = true;
- break;
-
- case 'l':
- continue;
-
- case 'p':
- fmt.format = Format::integer;
- fmt.base = Format::hex;
- fmt.alternate_form = true;
- done = true;
- break;
-
- case 'X':
- fmt.uppercase = true;
- case 'x':
- fmt.base = Format::hex;
- fmt.format = Format::integer;
- done = true;
- break;
-
- case 'o':
- fmt.base = Format::oct;
- fmt.format = Format::integer;
- done = true;
- break;
-
- case 'd':
- case 'i':
- case 'u':
- fmt.format = Format::integer;
- done = true;
- break;
-
- case 'G':
- fmt.uppercase = true;
- case 'g':
- fmt.format = Format::floating;
- fmt.float_format = Format::best;
- done = true;
- break;
-
- case 'E':
- fmt.uppercase = true;
- case 'e':
- fmt.format = Format::floating;
- fmt.float_format = Format::scientific;
- done = true;
- break;
-
- case 'f':
- fmt.format = Format::floating;
- fmt.float_format = Format::fixed;
- done = true;
- break;
-
- case 'n':
- *stream << "we don't do %n!!!\n";
- done = true;
- break;
-
- case '#':
- fmt.alternate_form = true;
- break;
-
- case '-':
- fmt.flush_left = true;
- break;
-
- case '+':
- fmt.print_sign = true;
- break;
-
- case ' ':
- fmt.blank_space = true;
- break;
-
- case '.':
- fmt.width = number;
- fmt.precision = 0;
- have_precision = true;
- number = 0;
- end_number = false;
- break;
-
- case '0':
- if (number == 0) {
- fmt.fill_zero = true;
- break;
- }
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- number = number * 10 + (*p - '0');
- break;
-
- case '%':
- assert("we shouldn't get here");
- break;
-
- default:
- done = true;
- break;
- }
-
- if (end_number) {
- if (have_precision)
- fmt.precision = number;
- else
- fmt.width = number;
-
- end_number = false;
- number = 0;
- }
- }
-
- if (iter != end)
- {
- ios::fmtflags saved_flags = stream->flags();
- char old_fill = stream->fill();
- int old_precision = stream->precision();
-
- (*iter)->process(*stream, fmt);
-
- stream->flags(saved_flags);
- stream->fill(old_fill);
- stream->precision(old_precision);
-
- ++iter;
- } else {
- *stream << "<missing arg for format>";
- }
-
- ++p;
- }
+ size_t len;
+
+ while (*ptr) {
+ switch (*ptr) {
+ case '%':
+ if (ptr[1] != '%')
+ goto processing;
+
+ stream.put('%');
+ ptr += 2;
break;
case '\n':
- *stream << endl;
- ++p;
+ stream << endl;
+ ++ptr;
break;
case '\r':
- ++p;
- if (*p != '\n')
- *stream << endl;
+ ++ptr;
+ if (*ptr != '\n')
+ stream << endl;
break;
- default: {
- size_t len = strcspn(p, "%\n\r\0");
- stream->write(p, len);
- p += len;
- }
+ default:
+ len = strcspn(ptr, "%\n\r\0");
+ stream.write(ptr, len);
+ ptr += len;
break;
}
}
- while (iter != end) {
- *stream << "<extra arg>";
- ++iter;
+ return;
+
+ processing:
+ bool done = false;
+ bool end_number = false;
+ bool have_precision = false;
+ int number = 0;
+
+ stream.fill(' ');
+ stream.flags((ios::fmtflags)0);
+
+ while (!done) {
+ ++ptr;
+ if (*ptr >= '0' && *ptr <= '9') {
+ if (end_number)
+ continue;
+ } else if (number > 0)
+ end_number = true;
+
+ switch (*ptr) {
+ case 's':
+ fmt.format = Format::string;
+ done = true;
+ break;
+
+ case 'c':
+ fmt.format = Format::character;
+ done = true;
+ break;
+
+ case 'l':
+ continue;
+
+ case 'p':
+ fmt.format = Format::integer;
+ fmt.base = Format::hex;
+ fmt.alternate_form = true;
+ done = true;
+ break;
+
+ case 'X':
+ fmt.uppercase = true;
+ case 'x':
+ fmt.base = Format::hex;
+ fmt.format = Format::integer;
+ done = true;
+ break;
+
+ case 'o':
+ fmt.base = Format::oct;
+ fmt.format = Format::integer;
+ done = true;
+ break;
+
+ case 'd':
+ case 'i':
+ case 'u':
+ fmt.format = Format::integer;
+ done = true;
+ break;
+
+ case 'G':
+ fmt.uppercase = true;
+ case 'g':
+ fmt.format = Format::floating;
+ fmt.float_format = Format::best;
+ done = true;
+ break;
+
+ case 'E':
+ fmt.uppercase = true;
+ case 'e':
+ fmt.format = Format::floating;
+ fmt.float_format = Format::scientific;
+ done = true;
+ break;
+
+ case 'f':
+ fmt.format = Format::floating;
+ fmt.float_format = Format::fixed;
+ done = true;
+ break;
+
+ case 'n':
+ stream << "we don't do %n!!!\n";
+ done = true;
+ break;
+
+ case '#':
+ fmt.alternate_form = true;
+ break;
+
+ case '-':
+ fmt.flush_left = true;
+ break;
+
+ case '+':
+ fmt.print_sign = true;
+ break;
+
+ case ' ':
+ fmt.blank_space = true;
+ break;
+
+ case '.':
+ fmt.width = number;
+ fmt.precision = 0;
+ have_precision = true;
+ number = 0;
+ end_number = false;
+ break;
+
+ case '0':
+ if (number == 0) {
+ fmt.fill_zero = true;
+ break;
+ }
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ number = number * 10 + (*ptr - '0');
+ break;
+
+ case '%':
+ assert("we shouldn't get here");
+ break;
+
+ default:
+ done = true;
+ break;
+ }
+
+ if (end_number) {
+ if (have_precision)
+ fmt.precision = number;
+ else
+ fmt.width = number;
+
+ end_number = false;
+ number = 0;
+ }
}
+
+ ++ptr;
}
-string
-ArgList::dumpToString(const string &format)
+void
+Print::end_args()
{
- stringstream ss;
+ size_t len;
- dump(ss, format);
+ while (*ptr) {
+ switch (*ptr) {
+ case '%':
+ if (ptr[1] != '%')
+ stream << "<extra arg>";
- return ss.str();
-}
+ stream.put('%');
+ ptr += 2;
+ break;
+ case '\n':
+ stream << endl;
+ ++ptr;
+ break;
+ case '\r':
+ ++ptr;
+ if (*ptr != '\n')
+ stream << endl;
+ break;
+
+ default:
+ len = strcspn(ptr, "%\n\r\0");
+ stream.write(ptr, len);
+ ptr += len;
+ break;
+ }
+ }
+
+ stream.flags(saved_flags);
+ stream.fill(saved_fill);
+ stream.precision(saved_precision);
}
+
+/* end namespace cp */ }
diff --git a/src/base/cprintf.hh b/src/base/cprintf.hh
index dd2256e69..cff73a228 100644
--- a/src/base/cprintf.hh
+++ b/src/base/cprintf.hh
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002-2005 The Regents of The University of Michigan
+ * Copyright (c) 2002-2006 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -29,142 +29,135 @@
* Steve Reinhardt
*/
-#ifndef __CPRINTF_HH__
-#define __CPRINTF_HH__
+#ifndef __BASE_CPRINTF_HH__
+#define __BASE_CPRINTF_HH__
+#include <ios>
#include <iostream>
#include <list>
#include <string>
+#include "base/varargs.hh"
#include "base/cprintf_formats.hh"
namespace cp {
-class ArgList
+#define CPRINTF_DECLARATION VARARGS_DECLARATION(cp::Print)
+#define CPRINTF_DEFINITION VARARGS_DEFINITION(cp::Print)
+
+struct Print
{
- private:
- class Base
- {
- public:
- virtual ~Base() {}
- virtual void process(std::ostream &out, Format &fmt) = 0;
- };
+ protected:
+ std::ostream &stream;
+ const char *format;
+ const char *ptr;
+
+ std::ios::fmtflags saved_flags;
+ char saved_fill;
+ int saved_precision;
+
+ void process(Format &fmt);
+
+ public:
+ Print(std::ostream &stream, const std::string &format);
+ Print(std::ostream &stream, const char *format);
+ ~Print();
template <typename T>
- class Node : public Base
+ void
+ add_arg(const T &data)
{
- public:
- const T &data;
-
- public:
- Node(const T &d) : data(d) {}
- virtual void process(std::ostream &out, Format &fmt) {
- switch (fmt.format) {
- case Format::character:
- format_char(out, data, fmt);
- break;
-
- case Format::integer:
- format_integer(out, data, fmt);
- break;
-
- case Format::floating:
- format_float(out, data, fmt);
- break;
-
- case Format::string:
- format_string(out, data, fmt);
- break;
-
- default:
- out << "<bad format>";
- break;
- }
- }
- };
+ Format fmt;
+ process(fmt);
- typedef std::list<Base *> list_t;
+ switch (fmt.format) {
+ case Format::character:
+ format_char(stream, data, fmt);
+ break;
- protected:
- list_t objects;
- std::ostream *stream;
+ case Format::integer:
+ format_integer(stream, data, fmt);
+ break;
- public:
- ArgList() : stream(&std::cout) {}
- ~ArgList();
+ case Format::floating:
+ format_float(stream, data, fmt);
+ break;
- template<class T>
- void append(const T &data) {
- Base *obj = new ArgList::Node<T>(data);
- objects.push_back(obj);
- }
+ case Format::string:
+ format_string(stream, data, fmt);
+ break;
- template<class T>
- void prepend(const T &data) {
- Base *obj = new ArgList::Node<T>(data);
- objects.push_front(obj);
+ default:
+ stream << "<bad format>";
+ break;
+ }
}
- void dump(const std::string &format);
- void dump(std::ostream &strm, const std::string &fmt)
- { stream = &strm; dump(fmt); }
+ void end_args();
+};
- std::string dumpToString(const std::string &format);
+/* end namespace cp */ }
- friend ArgList &operator<<(std::ostream &str, ArgList &list);
-};
+typedef VarArgs::List<cp::Print> CPrintfArgsList;
+
+inline void
+ccprintf(std::ostream &stream, const char *format, const CPrintfArgsList &args)
+{
+ cp::Print print(stream, format);
+ args.add_args(print);
+}
-template<class T>
-inline ArgList &
-operator,(ArgList &alist, const T &data)
+inline void
+ccprintf(std::ostream &stream, const char *format, CPRINTF_DECLARATION)
{
- alist.append(data);
- return alist;
+ cp::Print print(stream, format);
+ VARARGS_ADDARGS(print);
}
-class ArgListNull {
-};
+inline void
+cprintf(const char *format, CPRINTF_DECLARATION)
+{
+ ccprintf(std::cout, format, VARARGS_ALLARGS);
+}
+
+inline std::string
+csprintf(const char *format, CPRINTF_DECLARATION)
+{
+ std::stringstream stream;
+ ccprintf(stream, format, VARARGS_ALLARGS);
+ return stream.str();
+}
-inline ArgList &
-operator,(ArgList &alist, ArgListNull)
-{ return alist; }
+/*
+ * functions again with std::string. We have both so we don't waste
+ * time converting const char * to std::string since we don't take
+ * advantage of it.
+ */
+inline void
+ccprintf(std::ostream &stream, const std::string &format,
+ const CPrintfArgsList &args)
+{
+ ccprintf(stream, format.c_str(), args);
+}
-//
-// cprintf(format, args, ...) prints to cout
-// (analogous to printf())
-//
inline void
-__cprintf(const std::string &format, ArgList &args)
-{ args.dump(format); delete &args; }
-#define __cprintf__(format, ...) \
- cp::__cprintf(format, (*(new cp::ArgList), __VA_ARGS__))
-#define cprintf(...) \
- __cprintf__(__VA_ARGS__, cp::ArgListNull())
-
-//
-// ccprintf(stream, format, args, ...) prints to the specified stream
-// (analogous to fprintf())
-//
+ccprintf(std::ostream &stream, const std::string &format, CPRINTF_DECLARATION)
+{
+ ccprintf(stream, format.c_str(), VARARGS_ALLARGS);
+}
+
inline void
-__ccprintf(std::ostream &stream, const std::string &format, ArgList &args)
-{ args.dump(stream, format); delete &args; }
-#define __ccprintf__(stream, format, ...) \
- cp::__ccprintf(stream, format, (*(new cp::ArgList), __VA_ARGS__))
-#define ccprintf(stream, ...) \
- __ccprintf__(stream, __VA_ARGS__, cp::ArgListNull())
-
-//
-// csprintf(format, args, ...) returns a string
-// (roughly analogous to sprintf())
-//
-inline std::string
-__csprintf(const std::string &format, ArgList &args)
-{ std::string s = args.dumpToString(format); delete &args; return s; }
-#define __csprintf__(format, ...) \
- cp::__csprintf(format, (*(new cp::ArgList), __VA_ARGS__))
-#define csprintf(...) \
- __csprintf__(__VA_ARGS__, cp::ArgListNull())
+cprintf(const std::string &format, CPRINTF_DECLARATION)
+{
+ ccprintf(std::cout, format.c_str(), VARARGS_ALLARGS);
+}
+inline std::string
+csprintf(const std::string &format, CPRINTF_DECLARATION)
+{
+ std::stringstream stream;
+ ccprintf(stream, format.c_str(), VARARGS_ALLARGS);
+ return stream.str();
}
#endif // __CPRINTF_HH__
diff --git a/src/base/cprintf_formats.hh b/src/base/cprintf_formats.hh
index 0af493217..4e8b2b09e 100644
--- a/src/base/cprintf_formats.hh
+++ b/src/base/cprintf_formats.hh
@@ -28,8 +28,8 @@
* Authors: Nathan Binkert
*/
-#ifndef __CPRINTF_FORMATS_HH__
-#define __CPRINTF_FORMATS_HH__
+#ifndef __BASE_CPRINTF_FORMATS_HH__
+#define __BASE_CPRINTF_FORMATS_HH__
#include <sstream>
#include <ostream>
diff --git a/src/base/loader/elf_object.cc b/src/base/loader/elf_object.cc
index d59affe85..8f157da28 100644
--- a/src/base/loader/elf_object.cc
+++ b/src/base/loader/elf_object.cc
@@ -78,12 +78,23 @@ ElfObject::tryFile(const string &fname, int fd, size_t len, uint8_t *data)
//just assume if it wasn't something else and it's 64 bit, that's
//what it must be.
if (ehdr.e_machine == EM_SPARC64 ||
- ehdr.e_machine == EM_SPARC ||
+ (ehdr.e_machine == EM_SPARC &&
+ ehdr.e_ident[EI_CLASS] == ELFCLASS64)||
ehdr.e_machine == EM_SPARCV9) {
- arch = ObjectFile::SPARC;
+ arch = ObjectFile::SPARC64;
+ } else if (ehdr.e_machine == EM_SPARC32PLUS ||
+ (ehdr.e_machine == EM_SPARC &&
+ ehdr.e_ident[EI_CLASS] == ELFCLASS32)) {
+ arch = ObjectFile::SPARC32;
} else if (ehdr.e_machine == EM_MIPS
&& ehdr.e_ident[EI_CLASS] == ELFCLASS32) {
arch = ObjectFile::Mips;
+ } 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;
} else if (ehdr.e_ident[EI_CLASS] == ELFCLASS64) {
arch = ObjectFile::Alpha;
} else {
diff --git a/src/base/loader/object_file.hh b/src/base/loader/object_file.hh
index 18e6482be..4b44a6e22 100644
--- a/src/base/loader/object_file.hh
+++ b/src/base/loader/object_file.hh
@@ -47,8 +47,10 @@ class ObjectFile
enum Arch {
UnknownArch,
Alpha,
- SPARC,
- Mips
+ SPARC64,
+ SPARC32,
+ Mips,
+ X86
};
enum OpSys {
diff --git a/src/base/misc.cc b/src/base/misc.cc
index 991a33736..afb48ca80 100644
--- a/src/base/misc.cc
+++ b/src/base/misc.cc
@@ -36,91 +36,99 @@
#include "base/misc.hh"
#include "base/output.hh"
#include "base/trace.hh"
+#include "base/varargs.hh"
#include "sim/host.hh"
-#include "sim/root.hh"
+#include "sim/core.hh"
using namespace std;
void
-__panic(const string &format, cp::ArgList &args, const char *func,
- const char *file, int line)
+__panic(const char *func, const char *file, int line, const char *fmt,
+ CPRINTF_DEFINITION)
{
- string fmt = "panic: " + format;
- switch (fmt[fmt.size() - 1]) {
+ string format = "panic: ";
+ format += fmt;
+ switch (format[format.size() - 1]) {
case '\n':
case '\r':
break;
default:
- fmt += "\n";
+ format += "\n";
}
- fmt += " @ cycle %d\n[%s:%s, line %d]\n";
+ format += " @ cycle %d\n[%s:%s, line %d]\n";
- args.append(curTick);
- args.append(func);
- args.append(file);
- args.append(line);
- args.dump(cerr, fmt);
+ CPrintfArgsList args(VARARGS_ALLARGS);
- delete &args;
+ args.push_back(curTick);
+ args.push_back(func);
+ args.push_back(file);
+ args.push_back(line);
+
+ ccprintf(cerr, format.c_str(), args);
abort();
}
void
-__fatal(const string &format, cp::ArgList &args, const char *func,
- const char *file, int line)
+__fatal(const char *func, const char *file, int line, const char *fmt,
+ CPRINTF_DEFINITION)
{
- string fmt = "fatal: " + format;
+ CPrintfArgsList args(VARARGS_ALLARGS);
+ string format = "fatal: ";
+ format += fmt;
- switch (fmt[fmt.size() - 1]) {
+ switch (format[format.size() - 1]) {
case '\n':
case '\r':
break;
default:
- fmt += "\n";
+ format += "\n";
}
- fmt += " @ cycle %d\n[%s:%s, line %d]\n";
- fmt += "Memory Usage: %ld KBytes\n";
+ format += " @ cycle %d\n[%s:%s, line %d]\n";
+ format += "Memory Usage: %ld KBytes\n";
- args.append(curTick);
- args.append(func);
- args.append(file);
- args.append(line);
- args.append(memUsage());
- args.dump(cerr, fmt);
+ args.push_back(curTick);
+ args.push_back(func);
+ args.push_back(file);
+ args.push_back(line);
+ args.push_back(memUsage());
- delete &args;
+ ccprintf(cerr, format.c_str(), args);
exit(1);
}
void
-__warn(const string &format, cp::ArgList &args, const char *func,
- const char *file, int line)
+__warn(const char *func, const char *file, int line, const char *fmt,
+ CPRINTF_DEFINITION)
{
- string fmt = "warn: " + format;
+ string format = "warn: ";
+ format += fmt;
- switch (fmt[fmt.size() - 1]) {
+ switch (format[format.size() - 1]) {
case '\n':
case '\r':
break;
default:
- fmt += "\n";
+ format += "\n";
}
#ifdef VERBOSE_WARN
- fmt += " @ cycle %d\n[%s:%s, line %d]\n";
- args.append(curTick);
- args.append(func);
- args.append(file);
- args.append(line);
+ format += " @ cycle %d\n[%s:%s, line %d]\n";
#endif
- args.dump(cerr, fmt);
- if (simout.isFile(*outputStream))
- args.dump(*outputStream, fmt);
+ CPrintfArgsList args(VARARGS_ALLARGS);
+
+#ifdef VERBOSE_WARN
+ args.push_back(curTick);
+ args.push_back(func);
+ args.push_back(file);
+ args.push_back(line);
+#endif
- delete &args;
+ ccprintf(cerr, format.c_str(), args);
+ if (simout.isFile(*outputStream))
+ ccprintf(*outputStream, format.c_str(), args);
}
diff --git a/src/base/misc.hh b/src/base/misc.hh
index c12c2fe20..1509ea2d2 100644
--- a/src/base/misc.hh
+++ b/src/base/misc.hh
@@ -32,9 +32,11 @@
#ifndef __MISC_HH__
#define __MISC_HH__
-#include <assert.h>
+#include <cassert>
+
#include "base/compiler.hh"
#include "base/cprintf.hh"
+#include "base/varargs.hh"
#if defined(__SUNPRO_CC)
#define __FUNCTION__ "how to fix me?"
@@ -47,14 +49,20 @@
// calls abort which can dump core or enter the debugger.
//
//
-void __panic(const std::string&, cp::ArgList &, const char*, const char*, int)
- M5_ATTR_NORETURN;
-#define __panic__(format, ...) \
- __panic(format, (*(new cp::ArgList), __VA_ARGS__), \
- __FUNCTION__ , __FILE__, __LINE__)
-#define panic(...) \
- __panic__(__VA_ARGS__, cp::ArgListNull())
+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__)
//
// This implements a cprintf based fatal() function. fatal() should
@@ -64,34 +72,43 @@ M5_PRAGMA_NORETURN(__panic)
// "normal" exit with an error code, as opposed to abort() like
// panic() does.
//
-void __fatal(const std::string&, cp::ArgList &, const char*, const char*, int)
+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__(format, ...) \
- __fatal(format, (*(new cp::ArgList), __VA_ARGS__), \
- __FUNCTION__ , __FILE__, __LINE__)
-#define fatal(...) \
- __fatal__(__VA_ARGS__, cp::ArgListNull())
+
+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__)
//
// This implements a cprintf based warn
//
-void __warn(const std::string&, cp::ArgList &, const char*, const char*, int);
-#define __warn__(format, ...) \
- __warn(format, (*(new cp::ArgList), __VA_ARGS__), \
- __FUNCTION__ , __FILE__, __LINE__)
-#define warn(...) \
- __warn__(__VA_ARGS__, cp::ArgListNull())
+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)
+{
+ __warn(func, file, line, format, 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 { \
+#define warn_once(...) do { \
static bool once = false; \
if (!once) { \
- __warn__(__VA_ARGS__, cp::ArgListNull()); \
+ warn(__VA_ARGS__); \
once = true; \
} \
} while (0)
@@ -99,10 +116,10 @@ void __warn(const std::string&, cp::ArgList &, const char*, const char*, int);
//
// assert() that prints out the current cycle
//
-#define m5_assert(TEST) \
- if (!(TEST)) { \
- std::cerr << "Assertion failure, curTick = " << curTick << std::endl; \
- } \
- assert(TEST);
+#define m5_assert(TEST) do { \
+ if (!(TEST)) \
+ ccprintf(std::cerr, "Assertion failure, curTick = %d\n", curTick); \
+ assert(TEST); \
+} while (0)
#endif // __MISC_HH__
diff --git a/src/base/pollevent.cc b/src/base/pollevent.cc
index 32724b74d..331b5eac6 100644
--- a/src/base/pollevent.cc
+++ b/src/base/pollevent.cc
@@ -42,7 +42,7 @@
#include "sim/host.hh"
#include "base/misc.hh"
#include "base/pollevent.hh"
-#include "sim/root.hh"
+#include "sim/core.hh"
#include "sim/serialize.hh"
using namespace std;
diff --git a/src/base/pollevent.hh b/src/base/pollevent.hh
index 5b84650cb..ecaeb94ce 100644
--- a/src/base/pollevent.hh
+++ b/src/base/pollevent.hh
@@ -33,7 +33,7 @@
#include <vector>
#include <poll.h>
-#include "sim/root.hh"
+#include "sim/core.hh"
class Checkpoint;
class PollQueue;
diff --git a/src/base/random.cc b/src/base/random.cc
index 0ccedcb00..ceab337d9 100644
--- a/src/base/random.cc
+++ b/src/base/random.cc
@@ -40,38 +40,20 @@
#include <cstdlib>
#include <cmath>
-
-#include "sim/param.hh"
#include "base/random.hh"
-#include "base/trace.hh"
using namespace std;
-class RandomContext : public ParamContext
-{
- public:
- RandomContext(const string &_iniSection)
- : ::ParamContext(_iniSection) {}
- ~RandomContext() {}
-
- void checkParams();
-};
-
-RandomContext paramContext("random");
-
-Param<unsigned>
-seed(&paramContext, "seed", "seed to random number generator", 1);
-
-void
-RandomContext::checkParams()
+uint32_t
+getInt32()
{
- ::srand48(seed);
+ return mrand48() & 0xffffffff;
}
-long
-getLong()
+double
+getDouble()
{
- return mrand48();
+ return drand48();
}
double
@@ -105,21 +87,3 @@ getUniformPos(uint64_t min, uint64_t max)
return (uint64_t)m5round(r);
}
-
-
-// idea for generating a double from erand48
-double
-getDouble()
-{
- union {
- uint32_t _long[2];
- uint16_t _short[4];
- };
-
- _long[0] = mrand48();
- _long[1] = mrand48();
-
- return ldexp((double) _short[0], -48) +
- ldexp((double) _short[1], -32) +
- ldexp((double) _short[2], -16);
-}
diff --git a/src/base/random.hh b/src/base/random.hh
index 40d62da7f..0cd88728d 100644
--- a/src/base/random.hh
+++ b/src/base/random.hh
@@ -34,7 +34,7 @@
#include "sim/host.hh"
-long getLong();
+uint32_t getUInt32();
double getDouble();
double m5random(double r);
uint64_t getUniformPos(uint64_t min, uint64_t max);
@@ -46,7 +46,7 @@ struct Random;
template<> struct Random<int8_t>
{
static int8_t get()
- { return getLong() & (int8_t)-1; }
+ { return getUInt32() & (int8_t)-1; }
static int8_t uniform(int8_t min, int8_t max)
{ return getUniform(min, max); }
@@ -55,7 +55,7 @@ template<> struct Random<int8_t>
template<> struct Random<uint8_t>
{
static uint8_t get()
- { return getLong() & (uint8_t)-1; }
+ { return getUInt32() & (uint8_t)-1; }
static uint8_t uniform(uint8_t min, uint8_t max)
{ return getUniformPos(min, max); }
@@ -64,7 +64,7 @@ template<> struct Random<uint8_t>
template<> struct Random<int16_t>
{
static int16_t get()
- { return getLong() & (int16_t)-1; }
+ { return getUInt32() & (int16_t)-1; }
static int16_t uniform(int16_t min, int16_t max)
{ return getUniform(min, max); }
@@ -73,7 +73,7 @@ template<> struct Random<int16_t>
template<> struct Random<uint16_t>
{
static uint16_t get()
- { return getLong() & (uint16_t)-1; }
+ { return getUInt32() & (uint16_t)-1; }
static uint16_t uniform(uint16_t min, uint16_t max)
{ return getUniformPos(min, max); }
@@ -82,7 +82,7 @@ template<> struct Random<uint16_t>
template<> struct Random<int32_t>
{
static int32_t get()
- { return (int32_t)getLong(); }
+ { return (int32_t)getUInt32(); }
static int32_t uniform(int32_t min, int32_t max)
{ return getUniform(min, max); }
@@ -91,7 +91,7 @@ template<> struct Random<int32_t>
template<> struct Random<uint32_t>
{
static uint32_t get()
- { return (uint32_t)getLong(); }
+ { return (uint32_t)getUInt32(); }
static uint32_t uniform(uint32_t min, uint32_t max)
{ return getUniformPos(min, max); }
@@ -100,7 +100,7 @@ template<> struct Random<uint32_t>
template<> struct Random<int64_t>
{
static int64_t get()
- { return (int64_t)getLong() << 32 || (uint64_t)getLong(); }
+ { return (int64_t)getUInt32() << 32 || (uint64_t)getUInt32(); }
static int64_t uniform(int64_t min, int64_t max)
{ return getUniform(min, max); }
@@ -109,7 +109,7 @@ template<> struct Random<int64_t>
template<> struct Random<uint64_t>
{
static uint64_t get()
- { return (uint64_t)getLong() << 32 || (uint64_t)getLong(); }
+ { return (uint64_t)getUInt32() << 32 || (uint64_t)getUInt32(); }
static uint64_t uniform(uint64_t min, uint64_t max)
{ return getUniformPos(min, max); }
diff --git a/src/base/statistics.hh b/src/base/statistics.hh
index 2b1b327e5..761b30c2b 100644
--- a/src/base/statistics.hh
+++ b/src/base/statistics.hh
@@ -70,7 +70,7 @@
class Callback;
-/** The current simulated cycle. */
+/** The current simulated tick. */
extern Tick curTick;
/* A namespace for all of the Statistics */
@@ -598,9 +598,9 @@ struct StatStor
};
/**
- * Templatized storage and interface to a per-cycle average stat. This keeps
- * a current count and updates a total (count * cycles) when this count
- * changes. This allows the quick calculation of a per cycle count of the item
+ * Templatized storage and interface to a per-tick average stat. This keeps
+ * a current count and updates a total (count * ticks) when this count
+ * changes. This allows the quick calculation of a per tick count of the item
* being watched. This is good for keeping track of residencies in structures
* among other things.
*/
@@ -613,9 +613,9 @@ struct AvgStor
private:
/** The current count. */
Counter current;
- /** The total count for all cycles. */
+ /** The total count for all tick. */
mutable Result total;
- /** The cycle that current last changed. */
+ /** The tick that current last changed. */
mutable Tick last;
public:
@@ -1563,7 +1563,7 @@ struct FancyStor
};
/**
- * Templatized storage for distribution that calculates per cycle mean and
+ * Templatized storage for distribution that calculates per tick mean and
* variance.
*/
struct AvgFancy
@@ -2280,7 +2280,7 @@ class Value : public Wrap<Value, ValueBase, ScalarStatData>
};
/**
- * A stat that calculates the per cycle average of a value.
+ * A stat that calculates the per tick average of a value.
* @sa Stat, ScalarBase, AvgStor
*/
template<int N = 0>
@@ -2417,7 +2417,7 @@ class StandardDeviation
};
/**
- * Calculates the per cycle mean and variance of the samples.
+ * Calculates the per tick mean and variance of the samples.
* @sa Stat, DistBase, AvgFancy
*/
template<int N = 0>
@@ -2839,6 +2839,7 @@ class Temp
*/
void check();
+void dump();
void reset();
void registerResetCallback(Callback *cb);
diff --git a/src/base/stats/events.cc b/src/base/stats/events.cc
index 6ecc5434c..dc56fe75f 100644
--- a/src/base/stats/events.cc
+++ b/src/base/stats/events.cc
@@ -31,20 +31,8 @@
#include <vector>
#include "base/stats/events.hh"
-
-#if USE_MYSQL
-#include "base/cprintf.hh"
-#include "base/misc.hh"
-#include "base/mysql.hh"
-#include "base/stats/mysql.hh"
-#include "base/stats/mysql_run.hh"
-#include "base/str.hh"
-#endif
-
-#include "base/match.hh"
+#include "base/stats/output.hh"
#include "sim/host.hh"
-#include "sim/sim_object.hh"
-#include "sim/root.hh"
using namespace std;
@@ -52,118 +40,21 @@ namespace Stats {
Tick EventStart = ULL(0x7fffffffffffffff);
-ObjectMatch event_ignore;
+extern list<Output *> OutputList;
#if USE_MYSQL
-class InsertEvent
-{
- private:
- char *query;
- int size;
- bool first;
- static const int maxsize = 1024*1024;
-
- typedef map<string, uint32_t> event_map_t;
- event_map_t events;
-
- MySQL::Connection &mysql;
- uint16_t run;
-
- public:
- InsertEvent()
- : mysql(MySqlDB.conn()), run(MySqlDB.run())
- {
- query = new char[maxsize + 1];
- size = 0;
- first = true;
- flush();
- }
- ~InsertEvent()
- {
- flush();
- }
-
- void flush();
- void insert(const string &stat);
-};
-
void
-InsertEvent::insert(const string &stat)
+__event(const string &event)
{
- assert(mysql.connected());
-
- event_map_t::iterator i = events.find(stat);
- uint32_t event;
- if (i == events.end()) {
- mysql.query(
- csprintf("SELECT en_id "
- "from event_names "
- "where en_name=\"%s\"",
- stat));
-
- MySQL::Result result = mysql.store_result();
- if (!result)
- panic("could not get a run\n%s\n", mysql.error);
-
- assert(result.num_fields() == 1);
- MySQL::Row row = result.fetch_row();
- if (row) {
- if (!to_number(row[0], event))
- panic("invalid event id: %s\n", row[0]);
- } else {
- mysql.query(
- csprintf("INSERT INTO "
- "event_names(en_name)"
- "values(\"%s\")",
- stat));
-
- if (mysql.error)
- panic("could not get a run\n%s\n", mysql.error);
-
- event = mysql.insert_id();
- }
- } else {
- event = (*i).second;
+ list<Output *>::iterator i = OutputList.begin();
+ list<Output *>::iterator end = OutputList.end();
+ for (; i != end; ++i) {
+ Output *output = *i;
+ if (!output->valid())
+ continue;
+
+ output->event(event);
}
-
- if (size + 1024 > maxsize)
- flush();
-
- if (!first) {
- query[size++] = ',';
- query[size] = '\0';
- }
-
- first = false;
-
- size += sprintf(query + size, "(%u,%u,%llu)",
- event, run, (unsigned long long)curTick);
-}
-
-void
-InsertEvent::flush()
-{
- static const char query_header[] = "INSERT INTO "
- "events(ev_event, ev_run, ev_tick)"
- "values";
-
- if (size) {
- MySQL::Connection &mysql = MySqlDB.conn();
- assert(mysql.connected());
- mysql.query(query);
- }
-
- query[0] = '\0';
- size = sizeof(query_header);
- first = true;
- memcpy(query, query_header, size);
-}
-
-void
-__event(const string &stat)
-{
- static InsertEvent event;
- event.insert(stat);
}
#endif
diff --git a/src/base/stats/events.hh b/src/base/stats/events.hh
index b09b91c7c..8ba9cece5 100644
--- a/src/base/stats/events.hh
+++ b/src/base/stats/events.hh
@@ -42,11 +42,10 @@ extern Tick EventStart;
#if USE_MYSQL
void __event(const std::string &stat);
-bool MySqlConnected();
+#else
+inline void __event(const std::string &stat) {}
#endif
-bool ignoreEvent(const std::string &name);
-
inline void
recordEvent(const std::string &stat)
{
@@ -55,12 +54,7 @@ recordEvent(const std::string &stat)
DPRINTF(StatEvents, "Statistics Event: %s\n", stat);
-#if USE_MYSQL
- if (!MySqlConnected())
- return;
-
__event(stat);
-#endif
}
/* namespace Stats */ }
diff --git a/src/base/stats/mysql.cc b/src/base/stats/mysql.cc
index 0fb31f4ce..39a687fff 100644
--- a/src/base/stats/mysql.cc
+++ b/src/base/stats/mysql.cc
@@ -43,20 +43,13 @@
#include "base/stats/statdb.hh"
#include "base/stats/types.hh"
#include "base/str.hh"
+#include "base/userinfo.hh"
#include "sim/host.hh"
using namespace std;
namespace Stats {
-MySqlRun MySqlDB;
-
-bool
-MySqlConnected()
-{
- return MySqlDB.connected();
-}
-
void
MySqlRun::connect(const string &host, const string &user, const string &passwd,
const string &db, const string &name, const string &sample,
@@ -196,9 +189,9 @@ SetupStat::init()
}
unsigned
-SetupStat::setup()
+SetupStat::setup(MySqlRun *run)
{
- MySQL::Connection &mysql = MySqlDB.conn();
+ MySQL::Connection &mysql = run->conn();
stringstream insert;
ccprintf(insert,
@@ -301,7 +294,8 @@ SetupStat::setup()
return statid;
}
-InsertData::InsertData()
+InsertData::InsertData(MySqlRun *_run)
+ : run(_run)
{
query = new char[maxsize + 1];
size = 0;
@@ -317,7 +311,7 @@ void
InsertData::flush()
{
if (size) {
- MySQL::Connection &mysql = MySqlDB.conn();
+ MySQL::Connection &mysql = run->conn();
assert(mysql.connected());
mysql.query(query);
if (mysql.error)
@@ -349,10 +343,97 @@ InsertData::insert()
first = false;
size += sprintf(query + size, "(%u,%d,%d,%u,%llu,\"%f\")",
- stat, x, y, MySqlDB.run(), (unsigned long long)tick,
+ stat, x, y, run->run(), (unsigned long long)tick,
data);
}
+InsertEvent::InsertEvent(MySqlRun *_run)
+ : run(_run)
+{
+ query = new char[maxsize + 1];
+ size = 0;
+ first = true;
+ flush();
+}
+
+InsertEvent::~InsertEvent()
+{
+ flush();
+}
+
+void
+InsertEvent::insert(const string &stat)
+{
+ MySQL::Connection &mysql = run->conn();
+ assert(mysql.connected());
+
+ event_map_t::iterator i = events.find(stat);
+ uint32_t event;
+ if (i == events.end()) {
+ mysql.query(
+ csprintf("SELECT en_id "
+ "from event_names "
+ "where en_name=\"%s\"",
+ stat));
+
+ MySQL::Result result = mysql.store_result();
+ if (!result)
+ panic("could not get a run\n%s\n", mysql.error);
+
+ assert(result.num_fields() == 1);
+ MySQL::Row row = result.fetch_row();
+ if (row) {
+ if (!to_number(row[0], event))
+ panic("invalid event id: %s\n", row[0]);
+ } else {
+ mysql.query(
+ csprintf("INSERT INTO "
+ "event_names(en_name)"
+ "values(\"%s\")",
+ stat));
+
+ if (mysql.error)
+ panic("could not get a run\n%s\n", mysql.error);
+
+ event = mysql.insert_id();
+ }
+ } else {
+ event = (*i).second;
+ }
+
+ if (size + 1024 > maxsize)
+ flush();
+
+ if (!first) {
+ query[size++] = ',';
+ query[size] = '\0';
+ }
+
+ first = false;
+
+ size += sprintf(query + size, "(%u,%u,%llu)",
+ event, run->run(), (unsigned long long)curTick);
+}
+
+void
+InsertEvent::flush()
+{
+ static const char query_header[] = "INSERT INTO "
+ "events(ev_event, ev_run, ev_tick)"
+ "values";
+
+ MySQL::Connection &mysql = run->conn();
+ assert(mysql.connected());
+
+ if (size)
+ mysql.query(query);
+
+ query[0] = '\0';
+ size = sizeof(query_header);
+ first = true;
+ memcpy(query, query_header, size);
+}
+
struct InsertSubData
{
uint16_t stat;
@@ -361,13 +442,13 @@ struct InsertSubData
string name;
string descr;
- void setup();
+ void setup(MySqlRun *run);
};
void
-InsertSubData::setup()
+InsertSubData::setup(MySqlRun *run)
{
- MySQL::Connection &mysql = MySqlDB.conn();
+ MySQL::Connection &mysql = run->conn();
assert(mysql.connected());
stringstream insert;
ccprintf(insert,
@@ -383,47 +464,27 @@ InsertSubData::setup()
panic("could not commit transaction\n%s\n", mysql.error);
}
-void
-InsertFormula(uint16_t stat, const string &formula)
-{
- MySQL::Connection &mysql = MySqlDB.conn();
- assert(mysql.connected());
- stringstream insert_formula;
- ccprintf(insert_formula,
- "INSERT INTO formulas(fm_stat,fm_formula) values(%d, \"%s\")",
- stat, formula);
+MySql::MySql()
+ : run(new MySqlRun), newdata(run), newevent(run)
+{}
- mysql.query(insert_formula);
-// if (mysql.error)
-// panic("could not insert formula\n%s\n", mysql.error);
-
- stringstream insert_ref;
- ccprintf(insert_ref,
- "INSERT INTO formula_ref(fr_stat,fr_run) values(%d, %d)",
- stat, MySqlDB.run());
-
- mysql.query(insert_ref);
-// if (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);
+MySql::~MySql()
+{
+ delete run;
}
void
-UpdatePrereq(uint16_t stat, uint16_t prereq)
+MySql::connect(const string &host, const string &user, const string &passwd,
+ const string &db, const string &name, const string &sample,
+ const string &project)
{
- MySQL::Connection &mysql = MySqlDB.conn();
- assert(mysql.connected());
- stringstream update;
- ccprintf(update, "UPDATE stats SET st_prereq=%d WHERE st_id=%d",
- prereq, stat);
- mysql.query(update);
- if (mysql.error)
- panic("could not update prereq\n%s\n", mysql.error);
+ run->connect(host, user, passwd, db, name, sample, project);
+}
- if (mysql.commit())
- panic("could not commit transaction\n%s\n", mysql.error);
+bool
+MySql::connected() const
+{
+ return run->connected();
}
void
@@ -434,7 +495,7 @@ MySql::configure()
*/
using namespace Database;
- MySQL::Connection &mysql = MySqlDB.conn();
+ MySQL::Connection &mysql = run->conn();
stat_list_t::const_iterator i, end = stats().end();
for (i = stats().begin(); i != end; ++i) {
@@ -444,11 +505,20 @@ MySql::configure()
for (i = stats().begin(); i != end; ++i) {
StatData *data = *i;
if (data->prereq) {
+ // update the prerequisite
uint16_t stat_id = find(data->id);
uint16_t prereq_id = find(data->prereq->id);
assert(stat_id && prereq_id);
- UpdatePrereq(stat_id, prereq_id);
+ stringstream update;
+ ccprintf(update, "UPDATE stats SET st_prereq=%d WHERE st_id=%d",
+ prereq_id, stat_id);
+ mysql.query(update);
+ if (mysql.error)
+ panic("could not update prereq\n%s\n", mysql.error);
+
+ if (mysql.commit())
+ panic("could not commit transaction\n%s\n", mysql.error);
}
}
@@ -483,7 +553,7 @@ MySql::configure(const ScalarData &data)
if (!configure(data, "SCALAR"))
return;
- insert(data.id, stat.setup());
+ insert(data.id, stat.setup(run));
}
void
@@ -492,7 +562,7 @@ MySql::configure(const VectorData &data)
if (!configure(data, "VECTOR"))
return;
- uint16_t statid = stat.setup();
+ uint16_t statid = stat.setup(run);
if (!data.subnames.empty()) {
InsertSubData subdata;
@@ -504,7 +574,7 @@ MySql::configure(const VectorData &data)
subdata.descr = data.subdescs.empty() ? "" : data.subdescs[i];
if (!subdata.name.empty() || !subdata.descr.empty())
- subdata.setup();
+ subdata.setup(run);
}
}
@@ -523,7 +593,7 @@ MySql::configure(const DistData &data)
stat.max = data.data.max;
stat.bktsize = data.data.bucket_size;
}
- insert(data.id, stat.setup());
+ insert(data.id, stat.setup(run));
}
void
@@ -539,7 +609,7 @@ MySql::configure(const VectorDistData &data)
stat.bktsize = data.data[0].bucket_size;
}
- uint16_t statid = stat.setup();
+ uint16_t statid = stat.setup(run);
if (!data.subnames.empty()) {
InsertSubData subdata;
@@ -550,7 +620,7 @@ MySql::configure(const VectorDistData &data)
subdata.name = data.subnames[i];
subdata.descr = data.subdescs.empty() ? "" : data.subdescs[i];
if (!subdata.name.empty() || !subdata.descr.empty())
- subdata.setup();
+ subdata.setup(run);
}
}
@@ -563,7 +633,7 @@ MySql::configure(const Vector2dData &data)
if (!configure(data, "VECTOR2D"))
return;
- uint16_t statid = stat.setup();
+ uint16_t statid = stat.setup(run);
if (!data.subnames.empty()) {
InsertSubData subdata;
@@ -574,7 +644,7 @@ MySql::configure(const Vector2dData &data)
subdata.name = data.subnames[i];
subdata.descr = data.subdescs.empty() ? "" : data.subdescs[i];
if (!subdata.name.empty() || !subdata.descr.empty())
- subdata.setup();
+ subdata.setup(run);
}
}
@@ -587,7 +657,7 @@ MySql::configure(const Vector2dData &data)
subdata.y = i;
subdata.name = data.y_subnames[i];
if (!subdata.name.empty())
- subdata.setup();
+ subdata.setup(run);
}
}
@@ -597,15 +667,41 @@ MySql::configure(const Vector2dData &data)
void
MySql::configure(const FormulaData &data)
{
+ MySQL::Connection &mysql = run->conn();
+ assert(mysql.connected());
+
configure(data, "FORMULA");
- insert(data.id, stat.setup());
- InsertFormula(find(data.id), data.str());
+ insert(data.id, stat.setup(run));
+
+ uint16_t stat = find(data.id);
+ string formula = data.str();
+
+ stringstream insert_formula;
+ ccprintf(insert_formula,
+ "INSERT INTO formulas(fm_stat,fm_formula) values(%d, \"%s\")",
+ stat, formula);
+
+ mysql.query(insert_formula);
+// if (mysql.error)
+// panic("could not insert formula\n%s\n", mysql.error);
+
+ stringstream insert_ref;
+ ccprintf(insert_ref,
+ "INSERT INTO formula_ref(fr_stat,fr_run) values(%d, %d)",
+ stat, run->run());
+
+ mysql.query(insert_ref);
+// if (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);
}
bool
MySql::valid() const
{
- return MySqlDB.connected();
+ return run->connected();
}
void
@@ -620,7 +716,7 @@ MySql::output()
// store sample #
newdata.tick = curTick;
- MySQL::Connection &mysql = MySqlDB.conn();
+ MySQL::Connection &mysql = run->conn();
Database::stat_list_t::const_iterator i, end = Database::stats().end();
for (i = Database::stats().begin(); i != end; ++i) {
@@ -634,6 +730,13 @@ MySql::output()
}
void
+MySql::event(const std::string &event)
+{
+ newevent.insert(event);
+}
+
+
+void
MySql::output(const ScalarData &data)
{
if (!(data.flags & print))
@@ -825,4 +928,20 @@ MySql::visit(const FormulaData &data)
output(data);
}
-/* namespace Stats */ }
+bool
+initMySQL(string host, string user, string password, string database,
+ string project, string name, string sample)
+{
+ extern list<Output *> OutputList;
+ static MySql mysql;
+
+ if (mysql.connected())
+ return false;
+
+ mysql.connect(host, user, password, database, name, sample, project);
+ OutputList.push_back(&mysql);
+
+ return true;
+}
+
+/* end namespace Stats */ }
diff --git a/src/base/stats/mysql.hh b/src/base/stats/mysql.hh
index 50f7d9e97..0ce381c2f 100644
--- a/src/base/stats/mysql.hh
+++ b/src/base/stats/mysql.hh
@@ -35,14 +35,13 @@
#include <string>
#include "base/stats/output.hh"
+#include "config/use_mysql.hh"
namespace MySQL { class Connection; }
namespace Stats {
class DistDataData;
class MySqlRun;
-bool MySqlConnected();
-extern MySqlRun MySqlDB;
struct SetupStat
{
@@ -63,7 +62,7 @@ struct SetupStat
uint16_t size;
void init();
- unsigned setup();
+ unsigned setup(MySqlRun *run);
};
class InsertData
@@ -85,18 +84,43 @@ class InsertData
int16_t y;
public:
- InsertData();
+ InsertData(MySqlRun *_run);
~InsertData();
void flush();
void insert();
};
+class InsertEvent
+{
+ private:
+ char *query;
+ int size;
+ bool first;
+ static const int maxsize = 1024*1024;
+
+ typedef std::map<std::string, uint32_t> event_map_t;
+ event_map_t events;
+
+ MySqlRun *run;
+
+ public:
+ InsertEvent(MySqlRun *_run);
+ ~InsertEvent();
+
+ void flush();
+ void insert(const std::string &stat);
+};
+
class MySql : public Output
{
protected:
+ MySqlRun *run; /* Hide the implementation so we don't have a
+ #include mess */
+
SetupStat stat;
InsertData newdata;
+ InsertEvent newevent;
std::list<FormulaData *> formulas;
bool configured;
@@ -116,6 +140,17 @@ class MySql : public Output
assert(i != idmap.end());
return (*i).second;
}
+
+ public:
+ MySql();
+ ~MySql();
+
+ void connect(const std::string &host, const std::string &user,
+ const std::string &passwd, const std::string &db,
+ const std::string &name, const std::string &sample,
+ const std::string &project);
+ bool connected() const;
+
public:
// Implement Visit
virtual void visit(const ScalarData &data);
@@ -129,6 +164,9 @@ class MySql : public Output
virtual bool valid() const;
virtual void output();
+ // Implement Event Output
+ virtual void event(const std::string &event);
+
protected:
// Output helper
void output(const DistDataData &data);
@@ -149,6 +187,20 @@ class MySql : public Output
void configure(const FormulaData &data);
};
+bool initMySQL(std::string host, std::string database, std::string user,
+ std::string passwd, std::string 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)
+{
+ return false;
+}
+#endif
+
/* namespace Stats */ }
#endif // __BASE_STATS_MYSQL_HH__
diff --git a/src/base/stats/output.cc b/src/base/stats/output.cc
new file mode 100644
index 000000000..9f2b91c77
--- /dev/null
+++ b/src/base/stats/output.cc
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2004-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Nathan Binkert
+ */
+
+#include <list>
+
+#include "base/stats/output.hh"
+#include "sim/eventq.hh"
+#include "sim/host.hh"
+
+using namespace std;
+
+namespace Stats {
+
+Tick lastDump(0);
+list<Output *> OutputList;
+
+void
+dump()
+{
+ assert(lastDump <= curTick);
+ if (lastDump == curTick)
+ return;
+ lastDump = curTick;
+
+ list<Output *>::iterator i = OutputList.begin();
+ list<Output *>::iterator end = OutputList.end();
+ for (; i != end; ++i) {
+ Output *output = *i;
+ if (!output->valid())
+ continue;
+
+ output->output();
+ }
+}
+
+/* namespace Stats */ }
+
+void
+debugDumpStats()
+{
+ Stats::dump();
+}
+
diff --git a/src/base/stats/output.hh b/src/base/stats/output.hh
index 4fe93791f..c7ffcaade 100644
--- a/src/base/stats/output.hh
+++ b/src/base/stats/output.hh
@@ -42,6 +42,7 @@ struct Output : public Visit
inline void operator()() { output(); }
virtual void output() = 0;
virtual bool valid() const = 0;
+ virtual void event(const std::string &event) = 0;
};
/* namespace Stats */ }
diff --git a/src/base/stats/text.cc b/src/base/stats/text.cc
index ae0d65537..a018c4837 100644
--- a/src/base/stats/text.cc
+++ b/src/base/stats/text.cc
@@ -251,6 +251,7 @@ VectorPrint::operator()(std::ostream &stream) const
ScalarPrint print;
print.name = name;
print.desc = desc;
+ print.compat = compat;
print.precision = precision;
print.descriptions = descriptions;
print.flags = flags;
@@ -725,4 +726,25 @@ Text::visit(const FormulaData &data)
visit((const VectorData &)data);
}
+bool
+initText(const string &filename, bool desc, bool compat)
+{
+ static Text text;
+ static bool connected = false;
+
+ if (connected)
+ return false;
+
+ extern list<Output *> OutputList;
+
+ text.open(*simout.find(filename));
+ text.descriptions = desc;
+ text.compat = compat;
+ OutputList.push_back(&text);
+ connected = true;
+
+ return true;
+}
+
+
/* namespace Stats */ }
diff --git a/src/base/stats/text.hh b/src/base/stats/text.hh
index b3faf5ad5..781d1083d 100644
--- a/src/base/stats/text.hh
+++ b/src/base/stats/text.hh
@@ -34,6 +34,7 @@
#include <iosfwd>
#include <string>
+#include "base/output.hh"
#include "base/stats/output.hh"
namespace Stats {
@@ -71,8 +72,13 @@ class Text : public Output
// Implement Output
virtual bool valid() const;
virtual void output();
+
+ // Implement Event Output
+ virtual void event(const std::string &event) {}
};
+bool initText(const std::string &filename, bool desc=true, bool compat=true);
+
/* namespace Stats */ }
#endif // __BASE_STATS_TEXT_HH__
diff --git a/src/base/trace.cc b/src/base/trace.cc
index 9fa615f4d..0a7e6e833 100644
--- a/src/base/trace.cc
+++ b/src/base/trace.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001-2005 The Regents of The University of Michigan
+ * Copyright (c) 2001-2006 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -37,14 +37,17 @@
#include <vector>
#include "base/misc.hh"
-#include "base/trace.hh"
+#include "base/output.hh"
#include "base/str.hh"
+#include "base/trace.hh"
+#include "base/varargs.hh"
using namespace std;
namespace Trace {
const string DefaultName("global");
FlagVec flags(NumFlags, false);
+bool enabled = false;
//
// This variable holds the output stream for debug information. Other
@@ -53,151 +56,74 @@ FlagVec flags(NumFlags, false);
// output.
//
ostream *dprintf_stream = &cerr;
-
-ObjectMatch ignore;
-
-Log theLog;
-
-Log::Log()
+ostream &
+output()
{
- size = 0;
- buffer = NULL;
+ return *dprintf_stream;
}
-
void
-Log::init(int _size)
+setOutput(const string &filename)
{
- if (buffer != NULL) {
- fatal("Trace::Log::init called twice!");
- }
-
- size = _size;
-
- buffer = new Record *[size];
-
- for (int i = 0; i < size; ++i) {
- buffer[i] = NULL;
- }
-
- nextRecPtr = &buffer[0];
- wrapRecPtr = &buffer[size];
+ dprintf_stream = simout.find(filename);
}
+ObjectMatch ignore;
-Log::~Log()
+void
+dprintf(Tick when, const std::string &name, const char *format,
+ CPRINTF_DEFINITION)
{
- for (int i = 0; i < size; ++i) {
- delete buffer[i];
- }
-
- delete [] buffer;
-}
+ if (!name.empty() && ignore.match(name))
+ return;
+ std::ostream &os = *dprintf_stream;
-void
-Log::append(Record *rec)
-{
- // dump record to output stream if there's one open
- if (dprintf_stream != NULL) {
- rec->dump(*dprintf_stream);
- } else {
- rec->dump(cout);
- }
+ string fmt = "";
+ CPrintfArgsList args(VARARGS_ALLARGS);
- // no buffering: justget rid of it now
- if (buffer == NULL) {
- delete rec;
- return;
+ if (!name.empty()) {
+ fmt = "%s: " + fmt;
+ args.push_front(name);
}
- Record *oldRec = *nextRecPtr;
-
- if (oldRec != NULL) {
- // log has wrapped: overwrite
- delete oldRec;
+ if (when != (Tick)-1) {
+ fmt = "%7d: " + fmt;
+ args.push_front(when);
}
- *nextRecPtr = rec;
+ fmt += format;
- if (++nextRecPtr == wrapRecPtr) {
- nextRecPtr = &buffer[0];
- }
+ ccprintf(os, fmt.c_str(), args);
+ os.flush();
}
-
void
-Log::dump(ostream &os)
+dump(Tick when, const std::string &name, const void *d, int len)
{
- if (buffer == NULL) {
+ if (!name.empty() && ignore.match(name))
return;
- }
-
- Record **bufPtr = nextRecPtr;
-
- if (*bufPtr == NULL) {
- // next record slot is empty: log must not be full yet.
- // start dumping from beginning of buffer
- bufPtr = buffer;
- }
- do {
- Record *rec = *bufPtr;
-
- rec->dump(os);
-
- if (++bufPtr == wrapRecPtr) {
- bufPtr = &buffer[0];
- }
- } while (bufPtr != nextRecPtr);
-}
-
-PrintfRecord::~PrintfRecord()
-{
- delete &args;
-}
+ std::ostream &os = *dprintf_stream;
-void
-PrintfRecord::dump(ostream &os)
-{
string fmt = "";
+ CPrintfArgsList args;
if (!name.empty()) {
fmt = "%s: " + fmt;
- args.prepend(name);
+ args.push_front(name);
}
- if (cycle != (Tick)-1) {
+ if (when != (Tick)-1) {
fmt = "%7d: " + fmt;
- args.prepend(cycle);
+ args.push_front(when);
}
- fmt += format;
-
- args.dump(os, fmt);
- os.flush();
-}
-
-DataRecord::DataRecord(Tick _cycle, const string &_name,
- const void *_data, int _len)
- : Record(_cycle), name(_name), len(_len)
-{
- data = new uint8_t[len];
- memcpy(data, _data, len);
-}
-
-DataRecord::~DataRecord()
-{
- delete [] data;
-}
-
-void
-DataRecord::dump(ostream &os)
-{
+ const char *data = static_cast<const char *>(d);
int c, i, j;
-
for (i = 0; i < len; i += 16) {
- ccprintf(os, "%d: %s: %08x ", cycle, name, i);
+ ccprintf(os, fmt, args);
+ ccprintf(os, "%08x ", i);
c = len - i;
if (c > 16) c = 16;
@@ -213,8 +139,7 @@ DataRecord::dump(ostream &os)
for (j = 0; j < c; j++) {
int ch = data[i + j] & 0x7f;
- ccprintf(os,
- "%c", (char)(isprint(ch) ? ch : ' '));
+ ccprintf(os, "%c", (char)(isprint(ch) ? ch : ' '));
}
ccprintf(os, "\n");
@@ -223,126 +148,64 @@ DataRecord::dump(ostream &os)
break;
}
}
-} // namespace Trace
-//
-// Returns the current output stream for debug information. As a
-// wrapper around Trace::dprintf_stream, this handles cases where debug
-// information is generated in the process of parsing .ini options,
-// before we process the option that sets up the debug output stream
-// itself.
-//
-std::ostream &
-DebugOut()
-{
- return *Trace::dprintf_stream;
-}
-
-/////////////////////////////////////////////
-//
-// C-linkage functions for invoking from gdb
-//
-/////////////////////////////////////////////
-
-//
-// Dump trace buffer to specified file (cout if NULL)
-//
-void
-dumpTrace(const char *filename)
-{
- if (filename != NULL) {
- ofstream out(filename);
- Trace::theLog.dump(out);
- out.close();
- }
- else {
- Trace::theLog.dump(cout);
- }
-}
-
-
-//
-// Turn on/off trace output to cerr. Typically used when trace output
-// is only going to circular buffer, but you want to see what's being
-// sent there as you step through some code in gdb. This uses the
-// same facility as the "trace to file" feature, and will print error
-// messages rather than clobbering an existing ostream pointer.
-//
-void
-echoTrace(bool on)
-{
- if (on) {
- if (Trace::dprintf_stream != NULL) {
- cerr << "Already echoing trace to a file... go do a 'tail -f'"
- << " on that file instead." << endl;
- } else {
- Trace::dprintf_stream = &cerr;
- }
- } else {
- if (Trace::dprintf_stream != &cerr) {
- cerr << "Not echoing trace to cerr." << endl;
- } else {
- Trace::dprintf_stream = NULL;
- }
- }
-}
-
-void
-printTraceFlags()
-{
- using namespace Trace;
- for (int i = 0; i < numFlagStrings; ++i)
- if (flags[i])
- cprintf("%s\n", flagStrings[i]);
-}
-
-void
-tweakTraceFlag(const char *string, bool value)
+bool
+changeFlag(const char *s, bool value)
{
using namespace Trace;
- std::string str(string);
+ std::string str(s);
for (int i = 0; i < numFlagStrings; ++i) {
if (str != flagStrings[i])
continue;
- int idx = i;
-
- if (idx < NumFlags) {
- flags[idx] = value;
+ if (i < NumFlags) {
+ flags[i] = value;
} else {
- idx -= NumFlags;
- if (idx >= NumCompoundFlags) {
- ccprintf(cerr, "Invalid compound flag");
- return;
- }
-
- const Flags *flagVec = compoundFlags[idx];
+ i -= NumFlags;
+ const Flags *flagVec = compoundFlags[i];
for (int j = 0; flagVec[j] != -1; ++j) {
- if (flagVec[j] >= NumFlags) {
- ccprintf(cerr, "Invalid compound flag");
- return;
- }
- flags[flagVec[j]] = value;
+ if (flagVec[j] < NumFlags)
+ flags[flagVec[j]] = value;
}
}
- cprintf("flag %s was %s\n", string, value ? "set" : "cleared");
- return;
+ return true;
}
- cprintf("could not find flag %s\n", string);
+ // the flag was not found.
+ return false;
+}
+
+void
+dumpStatus()
+{
+ using namespace Trace;
+ for (int i = 0; i < numFlagStrings; ++i) {
+ if (flags[i])
+ cprintf("%s\n", flagStrings[i]);
+ }
}
+/* namespace Trace */ }
+
+
+// add a set of functions that can easily be invoked from gdb
void
setTraceFlag(const char *string)
{
- tweakTraceFlag(string, true);
+ Trace::changeFlag(string, true);
}
void
clearTraceFlag(const char *string)
{
- tweakTraceFlag(string, false);
+ Trace::changeFlag(string, false);
+}
+
+void
+dumpTraceStatus()
+{
+ Trace::dumpStatus();
}
diff --git a/src/base/trace.hh b/src/base/trace.hh
index a46643159..c1b506187 100644
--- a/src/base/trace.hh
+++ b/src/base/trace.hh
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001-2005 The Regents of The University of Michigan
+ * Copyright (c) 2001-2006 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -32,125 +32,35 @@
#ifndef __BASE_TRACE_HH__
#define __BASE_TRACE_HH__
+#include <string>
#include <vector>
#include "base/cprintf.hh"
#include "base/match.hh"
-#include "sim/host.hh"
-#include "sim/root.hh"
-
#include "base/traceflags.hh"
+#include "sim/host.hh"
+#include "sim/core.hh"
namespace Trace {
- typedef std::vector<bool> FlagVec;
+std::ostream &output();
+void setOutput(const std::string &filename);
- extern FlagVec flags;
+extern bool enabled;
+typedef std::vector<bool> FlagVec;
+extern FlagVec flags;
+inline bool IsOn(int t) { return flags[t]; }
+bool changeFlag(const char *str, bool value);
+void dumpStatus();
-#if TRACING_ON
- const bool On = true;
-#else
- const bool On = false;
-#endif
-
- inline bool
- IsOn(int t)
- {
- return flags[t];
-
- }
-
- void dump(const uint8_t *data, int count);
-
- class Record
- {
- protected:
- Tick cycle;
-
- Record(Tick _cycle)
- : cycle(_cycle)
- {
- }
-
- public:
- virtual ~Record() {}
-
- virtual void dump(std::ostream &) = 0;
- };
-
- class PrintfRecord : public Record
- {
- private:
- const char *format;
- const std::string &name;
- cp::ArgList &args;
-
- public:
- PrintfRecord(const char *_format, cp::ArgList &_args,
- Tick cycle, const std::string &_name)
- : Record(cycle), format(_format), name(_name), args(_args)
- {
- }
-
- virtual ~PrintfRecord();
-
- virtual void dump(std::ostream &);
- };
-
- class DataRecord : public Record
- {
- private:
- const std::string &name;
- uint8_t *data;
- int len;
-
- public:
- DataRecord(Tick cycle, const std::string &name,
- const void *_data, int _len);
- virtual ~DataRecord();
-
- virtual void dump(std::ostream &);
- };
-
- class Log
- {
- private:
- int size; // number of records in log
- Record **buffer; // array of 'size' Record ptrs (circular buf)
- Record **nextRecPtr; // next slot to use in buffer
- Record **wrapRecPtr; // &buffer[size], for quick wrap check
-
- public:
-
- Log();
- ~Log();
-
- void init(int _size);
-
- void append(Record *); // append trace record to log
- void dump(std::ostream &); // dump contents to stream
- };
-
- extern Log theLog;
-
- extern ObjectMatch ignore;
-
- inline void
- dprintf(const char *format, cp::ArgList &args, Tick cycle,
- const std::string &name)
- {
- if (name.empty() || !ignore.match(name))
- theLog.append(new Trace::PrintfRecord(format, args, cycle, name));
- }
-
- inline void
- dataDump(Tick cycle, const std::string &name, const void *data, int len)
- {
- theLog.append(new Trace::DataRecord(cycle, name, data, len));
- }
-
- extern const std::string DefaultName;
-};
+extern ObjectMatch ignore;
+extern const std::string DefaultName;
+
+void dprintf(Tick when, const std::string &name, const char *format,
+ CPRINTF_DECLARATION);
+void dump(Tick when, const std::string &name, const void *data, int len);
+
+/* namespace Trace */ }
// This silly little class allows us to wrap a string in a functor
// object so that we can give a name() that DPRINTF will like
@@ -162,7 +72,6 @@ struct StringWrap
};
inline const std::string &name() { return Trace::DefaultName; }
-std::ostream &DebugOut();
//
// DPRINTF is a debugging trace facility that allows one to
@@ -176,50 +85,44 @@ std::ostream &DebugOut();
#if TRACING_ON
-#define DTRACE(x) (Trace::IsOn(Trace::x))
-
-#define DCOUT(x) if (Trace::IsOn(Trace::x)) DebugOut()
+#define DTRACE(x) (Trace::IsOn(Trace::x) && Trace::enabled)
-#define DDUMP(x, data, count) \
-do { \
- if (Trace::IsOn(Trace::x)) \
- Trace::dataDump(curTick, name(), data, count); \
+#define DDUMP(x, data, count) do { \
+ if (DTRACE(x)) \
+ Trace::dump(curTick, name(), data, count); \
} while (0)
-#define __dprintf(cycle, name, format, ...) \
- Trace::dprintf(format, (*(new cp::ArgList), __VA_ARGS__), cycle, name)
+#define DPRINTF(x, ...) do { \
+ if (DTRACE(x)) \
+ Trace::dprintf(curTick, name(), __VA_ARGS__); \
+} while (0)
-#define DPRINTF(x, ...) \
-do { \
- if (Trace::IsOn(Trace::x)) \
- __dprintf(curTick, name(), __VA_ARGS__, cp::ArgListNull()); \
+#define DPRINTFR(x, ...) do { \
+ if (DTRACE(x)) \
+ Trace::dprintf((Tick)-1, std::string(), __VA_ARGS__); \
} while (0)
-#define DPRINTFR(x, ...) \
-do { \
- if (Trace::IsOn(Trace::x)) \
- __dprintf((Tick)-1, std::string(), __VA_ARGS__, cp::ArgListNull()); \
+#define DDUMPN(data, count) do { \
+ Trace::dump(curTick, name(), data, count); \
} while (0)
-#define DPRINTFN(...) \
-do { \
- __dprintf(curTick, name(), __VA_ARGS__, cp::ArgListNull()); \
+#define DPRINTFN(...) do { \
+ Trace::dprintf(curTick, name(), __VA_ARGS__); \
} while (0)
-#define DPRINTFNR(...) \
-do { \
- __dprintf((Tick)-1, string(), __VA_ARGS__, cp::ArgListNull()); \
+#define DPRINTFNR(...) do { \
+ Trace::dprintf((Tick)-1, string(), __VA_ARGS__); \
} while (0)
#else // !TRACING_ON
#define DTRACE(x) (false)
-#define DCOUT(x) if (0) DebugOut()
+#define DDUMP(x, data, count) do {} while (0)
#define DPRINTF(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)
-#define DDUMP(x, data, count) do {} while (0)
#endif // TRACING_ON
diff --git a/src/base/traceflags.py b/src/base/traceflags.py
index c06399f81..e57bfa350 100644
--- a/src/base/traceflags.py
+++ b/src/base/traceflags.py
@@ -29,19 +29,7 @@
# Authors: Nathan Binkert
# Steve Reinhardt
-#
-# This file generates the header and source files for the flags
-# that control the tracing facility.
-#
-
-import sys
-
-if len(sys.argv) != 2:
- print "%s: Need argument (basename of cc/hh files)" % sys.argv[0]
- sys.exit(1)
-
-hhfilename = sys.argv[1] + '.hh'
-ccfilename = sys.argv[1] + '.cc'
+__all__ = [ 'allFlags', 'baseFlags', 'compoundFlagsMap', 'compoundFlags' ]
#
# The list of trace flags that can be used to condition DPRINTFs etc.
@@ -89,6 +77,20 @@ baseFlags = [
'EthernetPIO',
'EthernetSM',
'Event',
+ 'ExecEnable',
+ 'ExecCPSeq',
+ 'ExecEffAddr',
+ 'ExecFetchSeq',
+ 'ExecIntRegs',
+ 'ExecIntel',
+ 'ExecLegion',
+ 'ExecOpClass',
+ 'ExecRegDelta',
+ 'ExecResult',
+ 'ExecSpeculative',
+ 'ExecSymbol',
+ 'ExecThread',
+ 'ExecTicks',
'FE',
'Fault',
'Fetch',
@@ -114,7 +116,7 @@ baseFlags = [
'ISP',
'IdeCtrl',
'IdeDisk',
- 'InstExec',
+ 'Iob',
'Interrupt',
'LLSC',
'LSQ',
@@ -135,6 +137,7 @@ baseFlags = [
'PciConfigAll',
'Pipeline',
'Printf',
+ 'Predecoder',
'Quiesce',
'ROB',
'Regs',
@@ -167,6 +170,7 @@ baseFlags = [
'VtoPhys',
'WriteBarrier',
'Writeback',
+ 'X86',
]
#
@@ -178,111 +182,119 @@ baseFlags = [
# following the existing examples.
#
compoundFlagMap = {
- 'GDBAll' : [ 'GDBMisc', 'GDBAcc', 'GDBRead', 'GDBWrite', 'GDBSend', 'GDBRecv', 'GDBExtra' ],
- 'ScsiAll' : [ 'ScsiDisk', 'ScsiCtrl', 'ScsiNone' ],
- 'DiskImageAll' : [ 'DiskImage', 'DiskImageRead', 'DiskImageWrite' ],
- 'EthernetAll' : [ 'Ethernet', 'EthernetPIO', 'EthernetDMA', 'EthernetData' , 'EthernetDesc', 'EthernetIntr', 'EthernetSM', 'EthernetCksum' ],
- 'EthernetNoData' : [ 'Ethernet', 'EthernetPIO', 'EthernetDesc', 'EthernetIntr', 'EthernetSM', 'EthernetCksum' ],
- 'IdeAll' : [ 'IdeCtrl', 'IdeDisk' ],
- 'O3CPUAll' : [ 'Fetch', 'Decode', 'Rename', 'IEW', 'Commit', 'IQ', 'ROB', 'FreeList', 'RenameMap', 'LSQ', 'LSQUnit', 'StoreSet', 'MemDepUnit', 'DynInst', 'FullCPU', 'O3CPU', 'Activity','Scoreboard','Writeback'],
- 'OzoneCPUAll' : [ 'BE', 'FE', 'IBE', 'OzoneLSQ', 'OzoneCPU'],
- 'All' : baseFlags
+ 'All' : baseFlags,
+ 'DiskImageAll' : [ 'DiskImage', 'DiskImageRead', 'DiskImageWrite' ],
+ 'EthernetAll' : [ 'Ethernet', 'EthernetPIO', 'EthernetDMA',
+ 'EthernetData' , 'EthernetDesc', 'EthernetIntr',
+ 'EthernetSM', 'EthernetCksum' ],
+ 'EthernetNoData' : [ 'Ethernet', 'EthernetPIO', 'EthernetDesc',
+ 'EthernetIntr', 'EthernetSM', 'EthernetCksum' ],
+ 'Exec' : [ 'ExecEnable', 'ExecTicks', 'ExecOpClass',
+ 'ExecThread', 'ExecEffAddr', 'ExecResult',
+ 'ExecSymbol' ],
+ 'GDBAll' : [ 'GDBMisc', 'GDBAcc', 'GDBRead', 'GDBWrite', 'GDBSend',
+ 'GDBRecv', 'GDBExtra' ],
+ 'IdeAll' : [ 'IdeCtrl', 'IdeDisk' ],
+ 'O3CPUAll' : [ 'Fetch', 'Decode', 'Rename', 'IEW', 'Commit', 'IQ',
+ 'ROB', 'FreeList', 'RenameMap', 'LSQ', 'LSQUnit',
+ 'StoreSet', 'MemDepUnit', 'DynInst', 'FullCPU',
+ 'O3CPU', 'Activity','Scoreboard','Writeback' ],
+ 'OzoneCPUAll' : [ 'BE', 'FE', 'IBE', 'OzoneLSQ', 'OzoneCPU' ],
+ 'ScsiAll' : [ 'ScsiDisk', 'ScsiCtrl', 'ScsiNone' ]
}
-#############################################################
-#
-# Everything below this point generates the appropriate C++
-# declarations and definitions for the trace flags. If you are simply
-# adding or modifying flag definitions, you should not have to change
-# anything below.
-#
-
-import sys
-
# extract just the compound flag names into a list
compoundFlags = []
compoundFlags.extend(compoundFlagMap.keys())
compoundFlags.sort()
-#
-# First generate the header file. This defines the Flag enum
-# and some extern declarations for the .cc file.
-#
-try:
- hhfile = file(hhfilename, 'w')
-except IOError, e:
- sys.exit("can't open %s: %s" % (hhfilename, e))
-
-# file header boilerplate
-print >>hhfile, '''
-/*
- * DO NOT EDIT THIS FILE!
- *
- * Automatically generated from traceflags.py
- */
+allFlags = frozenset(baseFlags + compoundFlags)
-#ifndef __BASE_TRACE_FLAGS_HH__
-#define __BASE_TRACE_FLAGS_HH__
-
-namespace Trace {
-
-enum Flags {
-''',
-
-# Generate the enum. Base flags come first, then compound flags.
-idx = 0
-for flag in baseFlags:
- print >>hhfile, ' %s = %d,' % (flag, idx)
- idx += 1
-
-numBaseFlags = idx
-print >>hhfile, ' NumFlags = %d,' % idx
-
-# put a comment in here to separate base from compound flags
-print >>hhfile, '''
- // The remaining enum values are *not* valid indices for Trace::flags.
- // They are "compound" flags, which correspond to sets of base
- // flags, and are used only by TraceParamContext::setFlags().
-''',
-
-for flag in compoundFlags:
- print >>hhfile, ' %s = %d,' % (flag, idx)
- idx += 1
-
-numCompoundFlags = idx - numBaseFlags
-print >>hhfile, ' NumCompoundFlags = %d' % numCompoundFlags
-
-# trailer boilerplate
-print >>hhfile, '''\
-}; // enum Flags
-
-// Array of strings for SimpleEnumParam
-extern const char *flagStrings[];
-extern const int numFlagStrings;
-
-// Array of arraay pointers: for each compound flag, gives the list of
-// base flags to set. Inidividual flag arrays are terminated by -1.
-extern const Flags *compoundFlags[];
-
-/* namespace Trace */ }
-
-#endif // __BASE_TRACE_FLAGS_HH__
-''',
-
-hhfile.close()
-
-#
-#
-# Print out .cc file with array definitions.
+#############################################################
#
+# Everything below this point generates the appropriate C++
+# declarations and definitions for the trace flags. If you are simply
+# adding or modifying flag definitions, you should not have to change
+# anything below.
#
-try:
- ccfile = file(ccfilename, 'w')
-except OSError, e:
- sys.exit("can't open %s: %s" % (ccfilename, e))
-
-# file header
-print >>ccfile, '''
+def gen_hh(filename):
+ #
+ # First generate the header file. This defines the Flag enum
+ # and some extern declarations for the .cc file.
+ #
+ try:
+ hhfile = file(filename, 'w')
+ except IOError, e:
+ sys.exit("can't open %s: %s" % (hhfilename, e))
+
+ # file header boilerplate
+ print >>hhfile, '''
+ /*
+ * DO NOT EDIT THIS FILE!
+ *
+ * Automatically generated from traceflags.py
+ */
+
+ #ifndef __BASE_TRACE_FLAGS_HH__
+ #define __BASE_TRACE_FLAGS_HH__
+
+ namespace Trace {
+
+ enum Flags {
+ ''',
+
+ # Generate the enum. Base flags come first, then compound flags.
+ idx = 0
+ for flag in baseFlags:
+ print >>hhfile, ' %s = %d,' % (flag, idx)
+ idx += 1
+
+ numBaseFlags = idx
+ print >>hhfile, ' NumFlags = %d,' % idx
+
+ # put a comment in here to separate base from compound flags
+ print >>hhfile, '''
+ // The remaining enum values are *not* valid indices for Trace::flags.
+ // They are "compound" flags, which correspond to sets of base
+ // flags, and are used by changeFlag.
+ ''',
+
+ for flag in compoundFlags:
+ print >>hhfile, ' %s = %d,' % (flag, idx)
+ idx += 1
+
+ numCompoundFlags = idx - numBaseFlags
+ print >>hhfile, ' NumCompoundFlags = %d' % numCompoundFlags
+
+ # trailer boilerplate
+ print >>hhfile, '''\
+ }; // enum Flags
+
+ // Array of strings for SimpleEnumParam
+ extern const char *flagStrings[];
+ extern const int numFlagStrings;
+
+ // Array of arraay pointers: for each compound flag, gives the list of
+ // base flags to set. Inidividual flag arrays are terminated by -1.
+ extern const Flags *compoundFlags[];
+
+ /* namespace Trace */ }
+
+ #endif // __BASE_TRACE_FLAGS_HH__
+ \n''',
+
+ hhfile.close()
+
+def gen_cc(filename):
+ '''Print out .cc file with array definitions.'''
+
+ try:
+ ccfile = file(filename, 'w')
+ except OSError, e:
+ sys.exit("can't open %s: %s" % (ccfilename, e))
+
+ # file header
+ print >>ccfile, '''
/*
* DO NOT EDIT THIS FILE!
*
@@ -297,45 +309,57 @@ const char *Trace::flagStrings[] =
{
''',
-# The string array is used by SimpleEnumParam to map the strings
-# provided by the user to enum values.
-for flag in baseFlags:
- print >>ccfile, ' "%s",' % flag
+ # The string array is used by SimpleEnumParam to map the strings
+ # provided by the user to enum values.
+ for flag in baseFlags:
+ print >>ccfile, ' "%s",' % flag
-for flag in compoundFlags:
- print >>ccfile, ' "%s",' % flag
+ for flag in compoundFlags:
+ print >>ccfile, ' "%s",' % flag
-print >>ccfile, '};\n'
+ print >>ccfile, '};\n'
-numFlagStrings = len(baseFlags) + len(compoundFlags);
+ numFlagStrings = len(baseFlags) + len(compoundFlags);
-print >>ccfile, 'const int Trace::numFlagStrings = %d;' % numFlagStrings
-print >>ccfile
+ print >>ccfile, 'const int Trace::numFlagStrings = %d;' % numFlagStrings
+ print >>ccfile
-#
-# Now define the individual compound flag arrays. There is an array
-# for each compound flag listing the component base flags.
-#
+ #
+ # Now define the individual compound flag arrays. There is an array
+ # for each compound flag listing the component base flags.
+ #
-for flag in compoundFlags:
- flags = compoundFlagMap[flag]
- flags.append('(Flags)-1')
- print >>ccfile, 'static const Flags %sMap[] =' % flag
- print >>ccfile, '{ %s };' % (', '.join(flags))
- print >>ccfile
+ for flag in compoundFlags:
+ flags = compoundFlagMap[flag]
+ flags.append('(Flags)-1')
+ print >>ccfile, 'static const Flags %sMap[] =' % flag
+ print >>ccfile, '{ %s };' % (', '.join(flags))
+ print >>ccfile
-#
-# Finally the compoundFlags[] array maps the compound flags
-# to their individual arrays/
-#
-print >>ccfile, 'const Flags *Trace::compoundFlags[] ='
-print >>ccfile, '{'
+ #
+ # Finally the compoundFlags[] array maps the compound flags
+ # to their individual arrays/
+ #
+ print >>ccfile, 'const Flags *Trace::compoundFlags[] ='
+ print >>ccfile, '{'
+
+ for flag in compoundFlags:
+ print >>ccfile, ' %sMap,' % flag
+
+ # file trailer
+ print >>ccfile, '};'
+
+ ccfile.close()
-for flag in compoundFlags:
- print >>ccfile, ' %sMap,' % flag
+if __name__ == '__main__':
+ # This file generates the header and source files for the flags
+ # that control the tracing facility.
-# file trailer
-print >>ccfile, '};'
+ import sys
-ccfile.close()
+ if len(sys.argv) != 2:
+ print "%s: Need argument (basename of cc/hh files)" % sys.argv[0]
+ sys.exit(1)
+ gen_hh(sys.argv[1] + '.hh')
+ gen_cc(sys.argv[1] + '.cc')
diff --git a/src/base/varargs.hh b/src/base/varargs.hh
new file mode 100644
index 000000000..2ba8c240a
--- /dev/null
+++ b/src/base/varargs.hh
@@ -0,0 +1,292 @@
+/*
+ * Copyright (c) 2006 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Nathan Binkert
+ */
+
+#ifndef __BASE_VARARGS_HH__
+#define __BASE_VARARGS_HH__
+
+#include "base/refcnt.hh"
+
+#define VARARGS_DECLARATION(receiver) \
+ VarArgs::Argument<receiver> a01 = VarArgs::Null(), \
+ VarArgs::Argument<receiver> a02 = VarArgs::Null(), \
+ VarArgs::Argument<receiver> a03 = VarArgs::Null(), \
+ VarArgs::Argument<receiver> a04 = VarArgs::Null(), \
+ VarArgs::Argument<receiver> a05 = VarArgs::Null(), \
+ VarArgs::Argument<receiver> a06 = VarArgs::Null(), \
+ VarArgs::Argument<receiver> a07 = VarArgs::Null(), \
+ VarArgs::Argument<receiver> a08 = VarArgs::Null(), \
+ VarArgs::Argument<receiver> a09 = VarArgs::Null(), \
+ VarArgs::Argument<receiver> a10 = VarArgs::Null(), \
+ VarArgs::Argument<receiver> a11 = VarArgs::Null(), \
+ VarArgs::Argument<receiver> a12 = VarArgs::Null(), \
+ VarArgs::Argument<receiver> a13 = VarArgs::Null(), \
+ VarArgs::Argument<receiver> a14 = VarArgs::Null(), \
+ VarArgs::Argument<receiver> a15 = VarArgs::Null(), \
+ VarArgs::Argument<receiver> a16 = VarArgs::Null()
+
+#define VARARGS_DEFINITION(receiver) \
+ VarArgs::Argument<receiver> a01, \
+ VarArgs::Argument<receiver> a02, \
+ VarArgs::Argument<receiver> a03, \
+ VarArgs::Argument<receiver> a04, \
+ VarArgs::Argument<receiver> a05, \
+ VarArgs::Argument<receiver> a06, \
+ VarArgs::Argument<receiver> a07, \
+ VarArgs::Argument<receiver> a08, \
+ VarArgs::Argument<receiver> a09, \
+ VarArgs::Argument<receiver> a10, \
+ VarArgs::Argument<receiver> a11, \
+ VarArgs::Argument<receiver> a12, \
+ VarArgs::Argument<receiver> a13, \
+ VarArgs::Argument<receiver> a14, \
+ VarArgs::Argument<receiver> a15, \
+ VarArgs::Argument<receiver> a16
+
+#define VARARGS_ALLARGS \
+ a01, a02, a03, a04, a05, a06, a07, a08, \
+ a09, a10, a11, a12, a13, a14, a15, a16
+
+#define VARARGS_ADDARGS(receiver) do { \
+ do { \
+ if (!a01) break; \
+ a01.add_arg(receiver); \
+ if (!a02) break; \
+ a02.add_arg(receiver); \
+ if (!a03) break; \
+ a03.add_arg(receiver); \
+ if (!a04) break; \
+ a04.add_arg(receiver); \
+ if (!a05) break; \
+ a05.add_arg(receiver); \
+ if (!a06) break; \
+ a06.add_arg(receiver); \
+ if (!a07) break; \
+ a07.add_arg(receiver); \
+ if (!a08) break; \
+ a08.add_arg(receiver); \
+ if (!a09) break; \
+ a09.add_arg(receiver); \
+ if (!a10) break; \
+ a10.add_arg(receiver); \
+ if (!a11) break; \
+ a11.add_arg(receiver); \
+ if (!a12) break; \
+ a12.add_arg(receiver); \
+ if (!a13) break; \
+ a13.add_arg(receiver); \
+ if (!a14) break; \
+ a14.add_arg(receiver); \
+ if (!a15) break; \
+ a15.add_arg(receiver); \
+ if (!a16) break; \
+ a16.add_arg(receiver); \
+ } while (0); \
+ receiver.end_args(); \
+} while (0)
+
+namespace VarArgs {
+
+struct Null {};
+
+template <typename T>
+struct Traits
+{
+ enum { enabled = true };
+};
+
+template <>
+struct Traits<Null>
+{
+ enum { enabled = false };
+};
+
+template <class RECV>
+struct Base : public RefCounted
+{
+ virtual void add_arg(RECV &receiver) const = 0;
+};
+
+template <typename T, class RECV>
+struct Any : 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;
+
+ Argument() { }
+ Argument(const Null &null) { }
+ template <typename T>
+ Argument(const T& arg) : Base(new Any<T, RECV>(arg)) { }
+
+ void
+ add_arg(RECV &receiver) const
+ {
+ if (this->data)
+ this->data->add_arg(receiver);
+ }
+};
+
+template<class RECV>
+class List
+{
+ public:
+ typedef Argument<RECV> Argument;
+ typedef std::list<Argument> list;
+ typedef typename list::iterator iterator;
+ typedef typename list::const_iterator const_iterator;
+ typedef typename list::size_type size_type;
+
+ protected:
+ list l;
+
+ public:
+ List() {}
+ List(Argument a01, Argument a02, Argument a03, Argument a04,
+ Argument a05, Argument a06, Argument a07, Argument a08,
+ Argument a09, Argument a10, Argument a11, Argument a12,
+ Argument a13, Argument a14, Argument a15, Argument a16)
+ {
+ if (!a01) return;
+ l.push_back(a01);
+ if (!a02) return;
+ l.push_back(a02);
+ if (!a03) return;
+ l.push_back(a03);
+ if (!a04) return;
+ l.push_back(a04);
+ if (!a05) return;
+ l.push_back(a05);
+ if (!a06) return;
+ l.push_back(a06);
+ if (!a07) return;
+ l.push_back(a07);
+ if (!a08) return;
+ l.push_back(a08);
+ if (!a09) return;
+ l.push_back(a09);
+ if (!a10) return;
+ l.push_back(a10);
+ if (!a11) return;
+ l.push_back(a11);
+ if (!a12) return;
+ l.push_back(a12);
+ if (!a13) return;
+ l.push_back(a13);
+ if (!a14) return;
+ l.push_back(a14);
+ if (!a15) return;
+ l.push_back(a15);
+ if (!a16) return;
+ l.push_back(a16);
+ }
+
+ size_type size() const { return l.size(); }
+ bool empty() const { return l.empty(); }
+
+ iterator begin() { return l.begin(); }
+ const_iterator begin() const { return l.begin(); }
+
+ iterator end() { return l.end(); }
+ const_iterator end() const { return l.end(); }
+
+ void
+ push_back(const Argument &arg)
+ {
+ if (arg)
+ l.push_back(arg);
+ }
+
+ void
+ push_front(const Argument &arg)
+ {
+ if (arg)
+ l.push_front(arg);
+ }
+
+ template <typename T>
+ void
+ push_back(const T &arg)
+ {
+ if (Traits<T>::enabled)
+ l.push_back(arg);
+ }
+
+ template <typename T>
+ void
+ push_front(const T &arg)
+ {
+ if (Traits<T>::enabled)
+ l.push_front(arg);
+ }
+
+ Argument& front() { return l.front(); }
+ const Argument& front() const { return l.front(); }
+ Argument& back() { return l.back(); }
+ const Argument& back() const { return l.back(); }
+
+ void erase(iterator position) { return l.erase(position); }
+ void erase(iterator first, iterator last) { return l.erase(first, last); }
+ void clear() { return l.clear(); }
+ void pop_front() { return l.pop_front(); }
+ void pop_back() { return l.pop_back(); }
+ void reverse() { l.reverse(); }
+
+ /*
+ * Functions specific to variable arguments
+ */
+ void
+ add_args(RECV &recv) const
+ {
+ const_iterator i = l.begin();
+ const_iterator end = l.end();
+ while (i != end) {
+ i->add_arg(recv);
+ ++i;
+ }
+
+ recv.end_args();
+ }
+};
+
+/* end namespace VarArgs */ }
+
+#endif /* __BASE_VARARGS_HH__ */