X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fbase%2Fbitfield.hh;h=664093fa27fc96145ce16448afadf3264c7c3eee;hb=5de3b2b6f0723b36873047dae20714a0b46e4aee;hp=69cce22459aa11014958ef6c78a39d176ce27e72;hpb=55614caecca476a12ef711b8b6e459fee19028b9;p=gem5.git diff --git a/src/base/bitfield.hh b/src/base/bitfield.hh index 69cce2245..664093fa2 100644 --- a/src/base/bitfield.hh +++ b/src/base/bitfield.hh @@ -58,6 +58,17 @@ bits(T val, int first, int last) return (val >> last) & mask(nbits); } +/** + * Extract the bit from this position from 'val' and right justify it. + */ +template +inline +T +bits(T val, int bit) +{ + return bits(val, bit, bit); +} + /** * Mask off the given bits in place like bits() but without shifting. * msb = 63, lsb = 0 @@ -96,8 +107,20 @@ inline T insertBits(T val, int first, int last, B bit_val) { + T t_bit_val = bit_val; T bmask = mask(first - last + 1) << last; - return ((bit_val << last) & bmask) | (val & ~bmask); + return ((t_bit_val << last) & bmask) | (val & ~bmask); +} + +/** + * Overloaded for access to only one bit in value + */ +template +inline +T +insertBits(T val, int bit, B bit_val) +{ + return insertBits(val, bit, bit, bit_val); } /** @@ -112,6 +135,14 @@ replaceBits(T& val, int first, int last, B bit_val) val = insertBits(val, first, last, bit_val); } +/** Overloaded function to allow to access only 1 bit*/ +template +inline +void +replaceBits(T& val, int bit, B bit_val) +{ + val = insertBits(val, bit, bit, bit_val); +} /** * Returns the bit position of the MSB that is set in the input */ @@ -130,273 +161,4 @@ findMsbSet(uint64_t val) { 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 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 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 - class Bitfield : public BitfieldBase - { - 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 - class BitfieldRO : public Bitfield - { - private: - uint64_t - operator=(const uint64_t _data); - }; - - //Similar to the above, but only allows writing. - template - class BitfieldWO : public Bitfield - { - private: - operator uint64_t () const; - - public: - using Bitfield::operator=; - }; - }; - - //This class contains all the "regular" bitfield classes. It is inherited - //by all BitUnions which give them access to those types. - template - 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 - class SignedBitfield : public BitfieldBase - { - public: - operator int64_t () const - { - return sext(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 - class SignedBitfieldRO : public SignedBitfield - { - private: - int64_t - operator=(const int64_t _data); - }; - - //Similar to the above, but only allows writing. - template - class SignedBitfieldWO : public SignedBitfield - { - private: - operator int64_t () const; - - public: - int64_t operator=(const int64_t _data) - { - *((SignedBitfield *)this) = _data; - return _data; - } - }; - }; - - template - class BitfieldTypes : public RegularBitfieldTypes, - public SignedBitfieldTypes - {}; - - //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 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 \ - { \ - 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 __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__