Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 12:10:52

0001 #ifndef UCTCTP7RawData5BX_hh
0002 #define UCTCTP7RawData5BX_hh
0003 
0004 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0005 #include "FWCore/MessageLogger/interface/MessageDrop.h"
0006 
0007 class UCTCTP7RawData5BX {
0008 public:
0009   enum CaloType { EBEE = 0, HBHE, HF };
0010 
0011   // read-only constructor
0012   UCTCTP7RawData5BX(const uint32_t* d) : myDataPtr(d) {
0013     if (myDataPtr == nullptr) {
0014       edm::LogError("UCTCTP7RawData5BX") << "You gave me a nullptr :<";
0015     }
0016   }
0017   // read-write constructor, caller must allocate 192*5*sizeof(uint32_t) bytes
0018   UCTCTP7RawData5BX(uint32_t* d) : myDataPtr(d), myDataWritePtr(d) {
0019     if (myDataPtr == nullptr) {
0020       edm::LogError("UCTCTP7RawData5BX") << "You gave me a nullptr :<";
0021     }
0022   }
0023 
0024   // No copy constructor and equality operator are needed
0025   UCTCTP7RawData5BX(const UCTCTP7RawData5BX&) = delete;
0026   const UCTCTP7RawData5BX& operator=(const UCTCTP7RawData5BX& i) = delete;
0027 
0028   virtual ~UCTCTP7RawData5BX() { ; }
0029 
0030   // Access functions for convenience
0031 
0032   const uint32_t* dataPtr() const { return myDataPtr; }
0033 
0034   uint32_t sof() { return myDataPtr[0]; }
0035 
0036   size_t getIndex(CaloType cType, bool negativeEta, uint32_t cEta, uint32_t iPhi, uint32_t BX_n) {
0037     size_t index = 0;
0038     if (cType == EBEE || cType == HBHE) {
0039       if (iPhi > 3) {
0040         edm::LogError("UCTCTP7RawData5BX") << "Incorrect iPhi; iPhi = " << iPhi << "; should be in [0,3]";
0041         return index;
0042       }
0043       if (cEta < 1 || cEta > 28) {
0044         edm::LogError("UCTCTP7RawData5BX") << "Incorrect caloEta; cEta = " << cEta << "; should be in [1-28]";
0045         return index;
0046       }
0047       // ECAL/HB+HE fragment size is 3 32-bit words
0048       // Each fragment covers 2 eta and 4 phi towers
0049       // All four phi towers are in one 32-bit word
0050       // Even and odd eta are in neighboring 32-bit words
0051       // Now each fragment contains 5 BX instead of just 1
0052       // Here BX_n = 0, 1, 2, 3, 4, where 2 is nominal
0053       index = (((cEta - 1) / 2) * (3 + 3) * 5 + ((cEta - 1) % 2)) + 3 * BX_n;
0054       // But, towers are arranged in a peculiar order for firmware
0055       // convenience - the index needs to be computing with these
0056       // if statements.  This is brittle code that one should be
0057       // very careful with.
0058       if (negativeEta) {
0059         // Add offset for 6 ECAL and 6 HCAL fragments
0060         index += (6 * (3 + 3)) * 5;
0061       } else {
0062         if (cEta > 12) {
0063           // Add offset for 14 ECAL, 14 HB+HE and 2 HF fragments
0064           // Note that first six are included in the definition of
0065           // the variable - index
0066           // Note also that HF fragments are larger at 4 32-bit words
0067           index += ((14 * (3 + 3) + (2 * 4))) * 5;
0068         }
0069       }
0070       // Data starts with ECAL towers so offset by 3 additional 32-bit words
0071       if (cType == HBHE)
0072         index += 3 * 5;
0073     } else if (cType == HF) {
0074       if (iPhi > 1) {
0075         edm::LogError("UCTCTP7RawData5BX") << "HF iPhi should be 0 or 1 (for a , b) - invalid iPhi  = " << iPhi;
0076         return index;
0077       }
0078       if (cEta < 30 || cEta > 41) {
0079         edm::LogError("UCTCTP7RawData5BX") << "HF cEta should be between 30 and 41 - invalid cEta = " << cEta;
0080         return index;
0081       }
0082       if (negativeEta) {
0083         if (iPhi == 0) {
0084           // Offset by 6 positive eta and 14 negative eta EBEE/HBHE fragments (each 3 32-bit words)
0085           // There are four HF cEta towers packed in each 32-bit word
0086           // Add additional offset of 1 for (34-37) and 2 for (38-41)
0087           index = 20 * (3 + 3) * 5 + ((cEta - 30) / 4) + 4 * BX_n;
0088         } else {
0089           // Additional HF a fragment offset for HF b channel
0090           index = 20 * (3 + 3) * 5 + 1 * 4 * 5 + ((cEta - 30) / 4) + 4 * BX_n;
0091         }
0092       } else {
0093         if (iPhi == 0) {
0094           // Offset by all EBEE/HBHE and two HF fragments (4 32-bit words)
0095           index = 2 * 14 * (3 + 3) * 5 + 2 * 4 * 5 + ((cEta - 30) / 4) + 4 * BX_n;
0096         } else {
0097           // Additional HF a fragment offset for HF b channel
0098           index = 2 * 14 * (3 + 3) * 5 + 3 * 4 * 5 + ((cEta - 30) / 4) + 4 * BX_n;
0099         }
0100       }
0101     } else {
0102       edm::LogError("UCTCTP7RawData5BX") << "Unknown CaloType " << cType;
0103       return index;
0104     }
0105     if (index >= 192 * 5) {
0106       edm::LogError("UCTCTP7RawData5BX") << "Managed to calculate an out-of-bounds index, buyer beware";
0107     }
0108     return index;
0109   }
0110 
0111   size_t getFeatureIndex(CaloType cType, bool negativeEta, uint32_t cEta, uint32_t iPhi, uint32_t BX_n) {
0112     // Get index into the data words for the tower
0113     size_t index = getIndex(cType, negativeEta, cEta, iPhi, BX_n);
0114     if (cType == EBEE || cType == HBHE) {
0115       // Two 32-bit words contain ET, so we should offset the index to
0116       // to the feature and link status bits
0117       if (((cEta - 1) % 2) == 0) {
0118         // [index] is offset to ET of first four towers (0 - 3)
0119         // [index + 2] is where the feature and link status bits are
0120         index += 2;
0121       } else {
0122         // In this case [index] is offset to ET of second four towers (4 - 7)
0123         // [index + 1] is where the feature and link status bits are
0124         index += 1;
0125       }
0126     } else if (cType == HF) {
0127       // HF Fragment has different structure than EBEE and HBHE fragments
0128       // First three 32-bit words have ETs for 11 objects (yes, 11 not 12)
0129       // cEta = 40 / 41 are double in eta and flop bettween a and b HF fragments
0130       // Further the remaining upper byte of the third word actually has feature
0131       // bits.  This feature index will point to the 4th 32-bit word.  It is
0132       // expected that the top byte from 3rd 32-bit word will be patched in within
0133       // the feature bit access function.
0134       // Since there are three instead of if block as above for EBEE, HBHE
0135       // I wrote here a more compact implementation of index computation.
0136       index += (3 - ((cEta - 30) / 4));
0137       if (index == 0) {
0138         // Since we sticth index-1, zero is also illegal
0139         edm::LogError("UCTCTP7RawData5BX") << "Managed to calculate an out-of-bounds index, buyer beware";
0140       }
0141     } else {
0142       // Unknown calotype error already generated in getIndex()
0143       return 0;
0144     }
0145     if (index >= 192 * 5) {
0146       edm::LogError("UCTCTP7RawData5BX") << "Managed to calculate an out-of-bounds index, buyer beware";
0147     }
0148     return index;
0149   }
0150 
0151   void setET(CaloType cType, bool negativeEta, uint32_t cEta, uint32_t iPhi, uint32_t et, uint32_t BX_n) {
0152     if (myDataWritePtr == nullptr) {
0153       edm::LogError("UCTCTP7RawData5BX") << "I was made in read-only mode";
0154       return;
0155     }
0156     size_t index = getIndex(cType, negativeEta, cEta, iPhi, BX_n);
0157     uint32_t& data = myDataWritePtr[index];
0158     if (cType == HF) {
0159       // Pick out the correct 8-bits for the iEta chosen
0160       // Note that cEta = 41 is special, it only occurs for iPhi == 1 and shares cEta = 40 position
0161       if (cEta == 41) {
0162         data |= (et & 0xFF) << 16;
0163       } else {
0164         data |= (et & 0xFF) << (((cEta - 30) % 4) * 8);
0165       }
0166     } else {
0167       // Pick out the correct 8-bits for the iPhi chosen
0168       data |= (et & 0xFF) << (iPhi * 8);
0169     }
0170   }
0171 
0172   uint32_t getET(CaloType cType, bool negativeEta, uint32_t cEta, uint32_t iPhi, uint32_t BX_n) {
0173     size_t index = getIndex(cType, negativeEta, cEta, iPhi, BX_n);
0174     const uint32_t data = myDataPtr[index];
0175     uint32_t et = 0xDEADBEEF;
0176     if (cType == HF) {
0177       // Pick out the correct 8-bits for the iEta chosen
0178       // Note that cEta = 41 is special, it only occurs for iPhi == 1 and shares cEta = 40 position
0179       if (cEta == 41)
0180         et = ((data >> 16) & 0xFF);
0181       else
0182         et = ((data >> ((cEta - 30) % 4) * 8) & 0xFF);
0183     } else {
0184       // Pick out the correct 8-bits for the iPhi chosen
0185       et = ((data >> (iPhi * 8)) & 0xFF);
0186     }
0187     return et;
0188   }
0189 
0190   void setFB(CaloType cType, bool negativeEta, uint32_t cEta, uint32_t iPhi, uint32_t fb, uint32_t BX_n) {
0191     if (myDataWritePtr == nullptr) {
0192       edm::LogError("UCTCTP7RawData5BX") << "I was made in read-only mode";
0193       return;
0194     }
0195     if (cType == HF) {
0196       setHFFeatureBits(negativeEta, cEta, iPhi, fb, BX_n);
0197     } else {
0198       size_t index = getFeatureIndex(cType, negativeEta, cEta, iPhi, BX_n);
0199       uint32_t& data = myDataWritePtr[index];
0200 
0201       uint32_t tower = iPhi;
0202       if (((cEta - 1) % 2) == 1) {
0203         tower += 4;
0204       }
0205       data |= (fb & 0x1) << tower;
0206     }
0207   }
0208 
0209   uint32_t getFB(CaloType cType, bool negativeEta, uint32_t cEta, uint32_t iPhi, uint32_t BX_n) {
0210     size_t index = getFeatureIndex(cType, negativeEta, cEta, iPhi, BX_n);
0211     const uint32_t data = myDataPtr[index];
0212     uint32_t fb = 0;
0213     if (cType == HF) {
0214       fb = getHFFeatureBits(negativeEta, cEta, iPhi, BX_n);
0215     } else {
0216       // Pick out the correct bit for the tower chosen
0217       uint32_t tower = iPhi;
0218       if (((cEta - 1) % 2) == 1) {
0219         tower += 4;
0220       }
0221       fb = ((data & (0x1 << tower)) != 0) ? 1 : 0;
0222     }
0223     return fb;
0224   }
0225 
0226   void setHFFeatureBits(bool negativeEta, uint32_t cEta, uint32_t iPhi, uint32_t fb, uint32_t BX_n) {
0227     if (myDataWritePtr == nullptr) {
0228       edm::LogError("UCTCTP7RawData5BX") << "I was made in read-only mode";
0229       return;
0230     }
0231     size_t index = getFeatureIndex(HF, negativeEta, cEta, iPhi, BX_n);
0232     uint32_t shift = (cEta - 30) * 2;
0233     if (cEta == 41)
0234       shift = 20;  // 41 occurs on b-fiber but shares the position of 40
0235     if (shift >= 8) {
0236       uint32_t& data = myDataWritePtr[index];
0237       data |= (fb & 0x3) << (shift - 8);
0238     } else {
0239       uint32_t& data = myDataWritePtr[index - 1];
0240       data |= (fb & 0x3) << (shift + 24);
0241     }
0242   }
0243 
0244   uint32_t getHFFeatureBits(bool negativeEta, uint32_t cEta, uint32_t iPhi, uint32_t BX_n) {
0245     size_t index = getFeatureIndex(HF, negativeEta, cEta, iPhi, BX_n);
0246     // Stitch together the top 8 bits from previous 32-bit word and bottom 14 bits from this word
0247     const uint32_t data = ((myDataPtr[index] & 0x3FFF) << 8) + (myDataPtr[index - 1] >> 24);
0248     uint32_t shift = (cEta - 30) * 2;
0249     if (cEta == 41)
0250       shift = 20;  // 41 occurs on b-fiber but shares the position of 40
0251     return ((data >> shift) & 0x3);
0252   }
0253 
0254   uint32_t getLinkStatus(CaloType cType, bool negativeEta, uint32_t cEta, uint32_t iPhi, uint32_t BX_n) {
0255     size_t index = getFeatureIndex(cType, negativeEta, cEta, iPhi, BX_n);
0256     const uint32_t data = myDataPtr[index];
0257     return (data >> 16);
0258   }
0259 
0260   size_t getSummaryIndex(bool negativeEta, uint32_t region, uint32_t BX_n) {
0261     size_t index = 2 * 14 * (3 + 3) * 5 + 4 * 4 * 5 + (region / 2) + 4 * BX_n;
0262     if (negativeEta)
0263       index += 4 * 5;
0264     if (index >= 192 * 5) {
0265       edm::LogError("UCTCTP7RawData5BX") << "Managed to calculate an out-of-bounds index, buyer beware";
0266     }
0267     return index;
0268   }
0269 
0270   void setRegionSummary(bool negativeEta, uint32_t region, uint32_t regionData, uint32_t BX_n) {
0271     if (myDataWritePtr == nullptr) {
0272       edm::LogError("UCTCTP7RawData5BX") << "I was made in read-only mode";
0273       return;
0274     }
0275     size_t index = getSummaryIndex(negativeEta, region, BX_n);
0276     uint32_t& data = myDataWritePtr[index];
0277     data |= (regionData & 0xFFFF) << (16 * (region % 2));
0278   }
0279 
0280   uint32_t getRegionSummary(bool negativeEta, uint32_t region, uint32_t BX_n) {
0281     size_t index = getSummaryIndex(negativeEta, region, BX_n);
0282     const uint32_t data = myDataPtr[index];
0283     return ((data >> (16 * (region % 2))) & 0xFFFF);
0284   }
0285 
0286   uint32_t getRegionET(bool negativeEta, uint32_t region, uint32_t BX_n) {
0287     return (getRegionSummary(negativeEta, region, BX_n) & 0x3FF);
0288   }
0289 
0290   bool getRegionEGVeto(bool negativeEta, uint32_t region, uint32_t BX_n) {
0291     return (getRegionSummary(negativeEta, region, BX_n) & 0x0400);
0292   }
0293 
0294   bool getRegionTauVeto(bool negativeEta, uint32_t region, uint32_t BX_n) {
0295     return (getRegionSummary(negativeEta, region, BX_n) & 0x0800);
0296   }
0297 
0298   uint32_t getRegionHitLocation(bool negativeEta, uint32_t region, uint32_t BX_n) {
0299     return ((getRegionSummary(negativeEta, region, BX_n) & 0xF000) >> 12);
0300   }
0301 
0302   bool isTowerMasked(CaloType cType, bool negativeEta, uint32_t cEta, uint32_t iPhi, uint32_t BX_n) {
0303     uint32_t linkStatus = getLinkStatus(cType, negativeEta, cEta, iPhi, BX_n);
0304     uint32_t tower = iPhi;
0305     if ((cEta % 2) == 0)
0306       tower += 4;
0307     if (cType == HF) {
0308       tower = (cEta - 30);
0309       if (cEta == 41)
0310         tower = 10;
0311     }
0312     return ((linkStatus & (0x1 << tower)) != 0);
0313   }
0314 
0315   bool isLinkMisaligned(CaloType cType, bool negativeEta, uint32_t cEta, uint32_t iPhi, uint32_t BX_n) {
0316     uint32_t linkStatus = getLinkStatus(cType, negativeEta, cEta, iPhi, BX_n);
0317     if (cType == EBEE && (cEta == 17 || cEta == 21)) {
0318       return ((linkStatus & 0x00000100) != 0);
0319     }
0320     return ((linkStatus & 0x00001000) != 0);
0321   }
0322 
0323   bool isLinkInError(CaloType cType, bool negativeEta, uint32_t cEta, uint32_t iPhi, uint32_t BX_n) {
0324     uint32_t linkStatus = getLinkStatus(cType, negativeEta, cEta, iPhi, BX_n);
0325     if (cType == EBEE && (cEta == 17 || cEta == 21)) {
0326       return ((linkStatus & 0x00000200) != 0);
0327     }
0328     return ((linkStatus & 0x00002000) != 0);
0329   }
0330 
0331   bool isLinkDown(CaloType cType, bool negativeEta, uint32_t cEta, uint32_t iPhi, uint32_t BX_n) {
0332     uint32_t linkStatus = getLinkStatus(cType, negativeEta, cEta, iPhi, BX_n);
0333     if (cType == EBEE && (cEta == 17 || cEta == 21)) {
0334       return ((linkStatus & 0x00000400) != 0);
0335     }
0336     return ((linkStatus & 0x00004000) != 0);
0337   }
0338 
0339   bool isLinkMasked(CaloType cType, bool negativeEta, uint32_t cEta, uint32_t iPhi, uint32_t BX_n) {
0340     uint32_t linkStatus = getLinkStatus(cType, negativeEta, cEta, iPhi, BX_n);
0341     if (cType == EBEE && (cEta == 17 || cEta == 21)) {
0342       return ((linkStatus & 0x00000800) != 0);
0343     }
0344     return ((linkStatus & 0x00008000) != 0);
0345   }
0346 
0347 private:
0348   // Pointer to contiguous array of 192*5 values
0349   // We assume instantiator of this class will gurantee that fact
0350   const uint32_t* myDataPtr;
0351   // == myDataPtr unless read-only
0352   uint32_t* myDataWritePtr = nullptr;
0353 };
0354 
0355 #endif