diff options
Diffstat (limited to 'src/base')
-rw-r--r-- | src/base/SConscript | 24 | ||||
-rw-r--r-- | src/base/bigint.hh | 14 | ||||
-rw-r--r-- | src/base/bitfield.hh | 284 | ||||
-rw-r--r-- | src/base/cprintf.hh | 6 | ||||
-rw-r--r-- | src/base/traceflags.py | 15 |
5 files changed, 312 insertions, 31 deletions
diff --git a/src/base/SConscript b/src/base/SConscript index 788aa3e6f..6fc140145 100644 --- a/src/base/SConscript +++ b/src/base/SConscript @@ -30,10 +30,26 @@ 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') +def make_cc(target, source, env): + assert(len(source) == 1) + assert(len(target) == 1) + + traceflags = {} + execfile(str(source[0]), traceflags) + func = traceflags['gen_cc'] + func(str(target[0])) + +def make_hh(target, source, env): + assert(len(source) == 1) + assert(len(target) == 1) + + traceflags = {} + execfile(str(source[0]), traceflags) + func = traceflags['gen_hh'] + func(str(target[0])) + +env.Command('traceflags.hh', 'traceflags.py', make_hh) +env.Command('traceflags.cc', 'traceflags.py', make_cc) Source('annotate.cc') Source('bigint.cc') diff --git a/src/base/bigint.hh b/src/base/bigint.hh index ed48c67fe..d60684231 100644 --- a/src/base/bigint.hh +++ b/src/base/bigint.hh @@ -28,6 +28,8 @@ * Authors: Ali Saidi */ +#include "base/misc.hh" + #include <iostream> #ifndef __BASE_BIGINT_HH__ @@ -49,6 +51,12 @@ struct m5_twin64_t { b = x; return *this; } + + operator uint64_t() + { + panic("Tried to cram a twin64_t into an integer!\n"); + return a; + } }; struct m5_twin32_t { @@ -67,6 +75,12 @@ struct m5_twin32_t { b = x; return *this; } + + operator uint32_t() + { + panic("Tried to cram a twin32_t into an integer!\n"); + return a; + } }; diff --git a/src/base/bitfield.hh b/src/base/bitfield.hh index 83b9138b4..69cce2245 100644 --- a/src/base/bitfield.hh +++ b/src/base/bitfield.hh @@ -121,20 +121,282 @@ 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; + 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.hh b/src/base/cprintf.hh index 7f8e33367..cff73a228 100644 --- a/src/base/cprintf.hh +++ b/src/base/cprintf.hh @@ -143,20 +143,20 @@ ccprintf(std::ostream &stream, const std::string &format, inline void ccprintf(std::ostream &stream, const std::string &format, CPRINTF_DECLARATION) { - ccprintf(stream, format, VARARGS_ALLARGS); + ccprintf(stream, format.c_str(), VARARGS_ALLARGS); } inline void cprintf(const std::string &format, CPRINTF_DECLARATION) { - ccprintf(std::cout, format, VARARGS_ALLARGS); + ccprintf(std::cout, format.c_str(), VARARGS_ALLARGS); } inline std::string csprintf(const std::string &format, CPRINTF_DECLARATION) { std::stringstream stream; - ccprintf(stream, format, VARARGS_ALLARGS); + ccprintf(stream, format.c_str(), VARARGS_ALLARGS); return stream.str(); } diff --git a/src/base/traceflags.py b/src/base/traceflags.py index cb17d98d3..6b241c410 100644 --- a/src/base/traceflags.py +++ b/src/base/traceflags.py @@ -116,6 +116,7 @@ baseFlags = [ 'ISP', 'IdeCtrl', 'IdeDisk', + 'Iob', 'Interrupt', 'LLSC', 'LSQ', @@ -136,6 +137,7 @@ baseFlags = [ 'PciConfigAll', 'Pipeline', 'Printf', + 'Predecoder', 'Quiesce', 'ROB', 'Regs', @@ -348,16 +350,3 @@ const char *Trace::flagStrings[] = print >>ccfile, '};' ccfile.close() - -if __name__ == '__main__': - # 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) - - gen_hh(sys.argv[1] + '.hh') - gen_cc(sys.argv[1] + '.cc') |