Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 12:19:51

0001 #ifndef L1GCTETTYPES_H
0002 #define L1GCTETTYPES_H
0003 
0004 #include <ostream>
0005 #include <cstdint>
0006 
0007 /*!
0008  * \class L1GctTwosComplement
0009  * \brief Definition of signed integer types with overflow
0010  *
0011  * This file defines the template class L1GctTwosComplement. It is used
0012  * to store energy values that are represented in a given number of bits
0013  * in hardware. The type has a built-in overFlow that is set if the value
0014  * to be represented is outside the allowed range for that number of bits.
0015  * This type represents signed integers; unsigned integers are represented
0016  * by L1GctUnsignedInt. Functions are defined to add two values,
0017  * and to copy data into a different number of bits.
0018  *
0019  * this header file contains method definitions because these are template classes
0020  * see http://www.parashift.com/c++-faq-lite/templates.html#faq-35.12
0021  *
0022  * \author Jim Brooke & Greg Heath
0023  * \date May 2006
0024  * 
0025  */
0026 
0027 template <int nBits>
0028 class L1GctTwosComplement {
0029 public:
0030   /// Construct a signed integer with initial value zero
0031   L1GctTwosComplement();
0032   /// Construct a signed integer from raw data, checking for overFlow
0033   L1GctTwosComplement(uint32_t raw);
0034   /// Construct a signed integer, checking for overflow
0035   L1GctTwosComplement(int value);
0036   /// Destructor
0037   ~L1GctTwosComplement() {}
0038 
0039   /// Copy contructor to move data between representations with different numbers of bits
0040   template <int mBits>
0041   L1GctTwosComplement(const L1GctTwosComplement<mBits>& rhs);
0042 
0043   /// reset value and overflow to zero
0044   void reset();
0045 
0046   /// set the raw data
0047   void setRaw(uint32_t raw);
0048 
0049   /// set value from signed int
0050   void setValue(int value);
0051 
0052   /// set the overflow bit
0053   void setOverFlow(bool oflow) { m_overFlow = oflow; }
0054 
0055   /// access raw data
0056   uint32_t raw() const { return m_data; }
0057 
0058   /// access value as signed int
0059   int value() const;
0060 
0061   /// access overflow
0062   bool overFlow() const { return m_overFlow; }
0063 
0064   /// return number of bits
0065   int size() const { return m_nBits; }
0066 
0067   /// add two numbers of the same size
0068   L1GctTwosComplement operator+(const L1GctTwosComplement& rhs) const;
0069 
0070   /// overload unary - (negation) operator
0071   L1GctTwosComplement operator-() const;
0072 
0073   /// overload = operator
0074   L1GctTwosComplement& operator=(int value);
0075 
0076 private:
0077   // number of bits (for overflow checking)
0078   int m_nBits;
0079 
0080   // the raw data
0081   uint32_t m_data;
0082 
0083   // the overflow bit
0084   bool m_overFlow;
0085 
0086   static const int MAX_NBITS = 24;
0087   static const int MAX_VALUE = 1 << (MAX_NBITS - 1);
0088 
0089   // PRIVATE MEMBER FUNCTION
0090   // function to check overflow
0091   void checkOverFlow(uint32_t rawValue, uint32_t& maskValue, bool& overFlow);
0092 };
0093 
0094 template <int nBits>
0095 std::ostream& operator<<(std::ostream& s, const L1GctTwosComplement<nBits>& data);
0096 
0097 // construct with # bits and set to zero
0098 template <int nBits>
0099 L1GctTwosComplement<nBits>::L1GctTwosComplement() {
0100   m_nBits = nBits > 0 && nBits < MAX_NBITS ? nBits : 16;
0101   this->reset();
0102 }
0103 
0104 // construct from # bits and raw data
0105 template <int nBits>
0106 L1GctTwosComplement<nBits>::L1GctTwosComplement(uint32_t raw) {
0107   m_nBits = nBits > 0 && nBits < MAX_NBITS ? nBits : 16;
0108   m_overFlow = false;
0109   this->setRaw(raw);
0110 }
0111 
0112 // construct from # bits and value
0113 template <int nBits>
0114 L1GctTwosComplement<nBits>::L1GctTwosComplement(int value) {
0115   m_nBits = nBits > 0 && nBits < MAX_NBITS ? nBits : 16;
0116   m_overFlow = false;
0117   this->setValue(value);
0118 }
0119 
0120 // copy contructor to move data between
0121 // representations with different numbers of bits
0122 template <int nBits>
0123 template <int mBits>
0124 L1GctTwosComplement<nBits>::L1GctTwosComplement(const L1GctTwosComplement<mBits>& rhs) {
0125   m_nBits = nBits > 0 && nBits < MAX_NBITS ? nBits : 16;
0126   this->setRaw(rhs.raw());
0127   this->setOverFlow(this->overFlow() || rhs.overFlow());
0128 }
0129 
0130 // reset value and overflow to zero
0131 template <int nBits>
0132 void L1GctTwosComplement<nBits>::reset() {
0133   m_data = static_cast<uint32_t>(0);
0134   m_overFlow = false;
0135 }
0136 
0137 // set value from uint32_t
0138 template <int nBits>
0139 void L1GctTwosComplement<nBits>::setRaw(uint32_t raw) {
0140   checkOverFlow(raw, m_data, m_overFlow);
0141 }
0142 
0143 // set value from int
0144 template <int nBits>
0145 void L1GctTwosComplement<nBits>::setValue(int value) {
0146   int chkValue, posValue;
0147   uint32_t raw;
0148 
0149   // Make sure we have an integer in the range MAX_NBITS
0150   chkValue = value;
0151   if (chkValue < -MAX_VALUE) {
0152     chkValue = -MAX_VALUE;
0153     m_overFlow = true;
0154   }
0155   if (chkValue >= MAX_VALUE) {
0156     chkValue = MAX_VALUE - 1;
0157     m_overFlow = true;
0158   }
0159 
0160   // Transform negative values to large positive values
0161   posValue = chkValue < 0 ? chkValue + (1 << MAX_NBITS) : chkValue;
0162   raw = static_cast<uint32_t>(posValue);
0163 
0164   // Use the setRaw method to check overflow for our given size nBits
0165   this->setRaw(raw);
0166 }
0167 
0168 // return value as int
0169 template <int nBits>
0170 int L1GctTwosComplement<nBits>::value() const {
0171   int value, result;
0172   int maxValueInNbits;
0173   maxValueInNbits = 1 << (m_nBits - 1);
0174   value = static_cast<int>(m_data);
0175   result = value < maxValueInNbits ? value : value - (1 << MAX_NBITS);
0176   return result;
0177 }
0178 
0179 // add two numbers
0180 template <int nBits>
0181 L1GctTwosComplement<nBits> L1GctTwosComplement<nBits>::operator+(const L1GctTwosComplement<nBits>& rhs) const {
0182   // temporary variable for storing the result (need to set its size)
0183   L1GctTwosComplement<nBits> temp;
0184   uint32_t sum;
0185   bool ofl;
0186 
0187   // do the addition here
0188   sum = this->raw() + rhs.raw();
0189   ofl = this->overFlow() || rhs.overFlow();
0190 
0191   //fill the temporary argument
0192   temp.setRaw(sum);
0193   temp.setOverFlow(temp.overFlow() || ofl);
0194 
0195   // return the temporary
0196   return temp;
0197 }
0198 
0199 // overload unary - (negation) operator
0200 template <int nBits>
0201 L1GctTwosComplement<nBits> L1GctTwosComplement<nBits>::operator-() const {
0202   L1GctTwosComplement<nBits> temp;
0203   temp.setValue(-this->value());
0204   temp.setOverFlow(temp.overFlow() || this->overFlow());
0205   return temp;
0206 }
0207 
0208 // overload assignment by int
0209 template <int nBits>
0210 L1GctTwosComplement<nBits>& L1GctTwosComplement<nBits>::operator=(int value) {
0211   this->setValue(value);
0212   return *this;
0213 }
0214 
0215 // Here's the check overflow function
0216 template <int nBits>
0217 void L1GctTwosComplement<nBits>::checkOverFlow(uint32_t rawValue, uint32_t& maskValue, bool& overFlow) {
0218   uint32_t signBit = 1 << (m_nBits - 1);
0219   uint32_t signExtendBits = (static_cast<uint32_t>(MAX_VALUE) - signBit) << 1;
0220   // Consider and return only MAX_NBITS least significant bits
0221   uint32_t mskRawValue = rawValue & ((1 << MAX_NBITS) - 1);
0222   uint32_t value;
0223   bool ofl;
0224 
0225   if ((mskRawValue & signBit) == 0) {
0226     value = mskRawValue & ~signExtendBits;
0227   } else {
0228     value = mskRawValue | signExtendBits;
0229   }
0230   ofl = value != mskRawValue;
0231 
0232   maskValue = value;
0233   overFlow = ofl;
0234 }
0235 
0236 // overload ostream<<
0237 template <int nBits>
0238 std::ostream& operator<<(std::ostream& s, const L1GctTwosComplement<nBits>& data) {
0239   s << "L1GctTwosComplement<" << data.size() << "> raw : " << data.raw() << ", "
0240     << "value : " << data.value();
0241   if (data.overFlow()) {
0242     s << " Overflow set! ";
0243   }
0244 
0245   return s;
0246 }
0247 
0248 #endif