Back to home page

Project CMSSW displayed by LXR

 
 

    


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

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