Back to home page

Project CMSSW displayed by LXR

 
 

    


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

0001 #include "EventFilter/Phase2TrackerRawToDigi/interface/Phase2TrackerFEDBuffer.h"
0002 #include "EventFilter/Phase2TrackerRawToDigi/interface/utils.h"
0003 #include "FWCore/Utilities/interface/Exception.h"
0004 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0005 
0006 namespace Phase2Tracker {
0007 
0008   // implementation of Phase2TrackerFEDBuffer
0009   Phase2TrackerFEDBuffer::Phase2TrackerFEDBuffer(const uint8_t* fedBuffer, const size_t fedBufferSize)
0010       : buffer_(fedBuffer), bufferSize_(fedBufferSize) {
0011     LogTrace("Phase2TrackerFEDBuffer") << "content of buffer with size: " << int(fedBufferSize) << std::endl;
0012     for (size_t i = 0; i < fedBufferSize; i += 8) {
0013       uint64_t word = read64(i, buffer_);
0014       LogTrace("Phase2TrackerFEDBuffer") << " word " << std::setfill(' ') << std::setw(2) << i / 8 << " | " << std::hex
0015                                          << std::setw(16) << std::setfill('0') << word << std::dec << std::endl;
0016     }
0017     LogTrace("Phase2TrackerFEDBuffer") << std::endl;
0018 
0019     // reserve all channels (should be 16x16 in our case)
0020     channels_.reserve(MAX_FE_PER_FED * MAX_CBC_PER_FE);
0021     // first 64 bits word is for DAQ header
0022     daqHeader_ = FEDDAQHeader(buffer_);
0023     // last 64 bit word is daq trailer
0024     daqTrailer_ = FEDDAQTrailer(buffer_ + bufferSize_ - 8);
0025     // tracker header follows daq header
0026     trackerHeader_ = Phase2TrackerFEDHeader(buffer_ + 8);
0027     // get pointer to payload
0028     payloadPointer_ = getPointerToPayload();
0029     // fill list of Phase2TrackerFEDChannels and get pointers to trigger and comissioning data
0030     findChannels();
0031   }
0032 
0033   Phase2TrackerFEDBuffer::~Phase2TrackerFEDBuffer() {}
0034 
0035   void Phase2TrackerFEDBuffer::findChannels() {
0036     // each FED can be connectd to up to 16 frontends (read from header)
0037     // each fronted can be connected to up to 16 CBC
0038     // in raw mode, a header of 16bits tells which CBC are activated on this FE
0039     // in ZS mode, one byte is used to tell how many clusters are present in the current CBC
0040     // one channel corresponds to one CBC chip, undependently of the mode
0041 
0042     // offset of beginning of current channel
0043     size_t offsetBeginningOfChannel = 0;
0044 
0045     // iterate over all FEs to see if they are active
0046     std::vector<bool>::iterator FE_it;
0047     std::vector<bool> status = trackerHeader_.frontendStatus();
0048 
0049     if (readoutMode() == READOUT_MODE_PROC_RAW) {
0050       for (FE_it = status.begin(); FE_it < status.end(); FE_it++) {
0051         // if the current fronted is on, fill channels and advance pointer to end of channel
0052         if (*FE_it) {
0053           // read first FEDCH_PER_FEUNIT bits to know which CBC are on
0054           uint16_t cbc_status = static_cast<uint16_t>(*(payloadPointer_ + (offsetBeginningOfChannel ^ 7)) << 8);
0055           cbc_status += static_cast<uint16_t>(*(payloadPointer_ + ((offsetBeginningOfChannel + 1) ^ 7)));
0056 
0057           // advance pointer by FEDCH_PER_FEUNIT bits
0058           offsetBeginningOfChannel += MAX_CBC_PER_FE / 8;
0059           for (int i = 0; i < MAX_CBC_PER_FE; i++) {
0060             // if CBC is ON, fill channel and advance pointer. else, push back empty channel
0061             if ((cbc_status >> i) & 0x1) {
0062               // Warning: STRIPS_PADDING+STRIPS_PER_CBC should always be an entire number of bytes
0063               channels_.push_back(Phase2TrackerFEDChannel(
0064                   payloadPointer_, offsetBeginningOfChannel, (STRIPS_PADDING + STRIPS_PER_CBC) / 8));
0065               offsetBeginningOfChannel += (STRIPS_PADDING + STRIPS_PER_CBC) / 8;
0066             } else {
0067               channels_.push_back(Phase2TrackerFEDChannel(nullptr, 0, 0));
0068             }
0069           }
0070         } else {
0071           // else fill with FEDCH_PER_FEUNIT null channels, don't advance the channel pointer
0072           channels_.insert(channels_.end(), size_t(MAX_CBC_PER_FE), Phase2TrackerFEDChannel(payloadPointer_, 0, 0));
0073         }
0074       }
0075     } else if (readoutMode() == READOUT_MODE_ZERO_SUPPRESSED) {
0076       for (FE_it = status.begin(); FE_it < status.end(); FE_it++) {
0077         if (*FE_it) {
0078           for (int i = 0; i < MAX_CBC_PER_FE; i++) {
0079             // read first byte to get number of clusters and skip it
0080             uint8_t n_clusters = static_cast<uint8_t>(*(payloadPointer_ + offsetBeginningOfChannel));
0081             offsetBeginningOfChannel += 1;
0082             // each channel contains 2 bytes per cluster
0083             channels_.push_back(Phase2TrackerFEDChannel(payloadPointer_, offsetBeginningOfChannel, 2 * n_clusters));
0084             // skip clusters
0085             offsetBeginningOfChannel += 2 * n_clusters;
0086           }
0087         } else {
0088           // else fill with FEDCH_PER_FEUNIT null channels, don't advance the channel pointer
0089           channels_.insert(channels_.end(), size_t(MAX_CBC_PER_FE), Phase2TrackerFEDChannel(payloadPointer_, 0, 0));
0090         }
0091       }
0092     } else {
0093       // TODO: throw exception for unrecognised readout mode
0094       // check done at Phase2TrackerFEDHeader::readoutMode()
0095     }
0096     // round the offset to the next 64 bits word
0097     int words64 = (offsetBeginningOfChannel + 8 - 1) / 8;  // size in 64 bit
0098     int payloadSize = words64 * 8;                         // size in bytes
0099     triggerPointer_ = payloadPointer_ + payloadSize;
0100 
0101     // get diff size in bytes:
0102     // fedBufferSize - (DAQHeader+TrackHeader+PayloadSize+TriggerSize+DAQTrailer)
0103     int bufferDiff = bufferSize_ - 8 - trackerHeader_.getTrackerHeaderSize() - payloadSize - TRIGGER_SIZE - 8;
0104 
0105     // check if condition data is supposed to be there:
0106     if (trackerHeader_.getConditionData()) {
0107       condDataPointer_ = triggerPointer_ + TRIGGER_SIZE;
0108       // diff must be equal to condition data size
0109       if (bufferDiff <= 0) {
0110         std::ostringstream ss;
0111         ss << "[Phase2Tracker::Phase2TrackerFEDBuffer::" << __func__ << "] "
0112            << "\n";
0113         ss << "FED Buffer Size does not match data => missing condition data? : "
0114            << "\n";
0115         ss << "Expected Buffer Size " << bufferSize_ << " bytes"
0116            << "\n";
0117         ss << "Computed Buffer Size " << bufferSize_ + bufferDiff << " bytes"
0118            << "\n";
0119         throw cms::Exception("Phase2TrackerFEDBuffer") << ss.str();
0120       }
0121     } else {
0122       // put a null pointer to indicate lack of condition data
0123       condDataPointer_ = nullptr;
0124       // check buffer size :
0125       if (bufferDiff != 0) {
0126         std::ostringstream ss;
0127         ss << "[Phase2Tracker::Phase2TrackerFEDBuffer::" << __func__ << "] "
0128            << "\n";
0129         ss << "FED Buffer Size does not match data => corrupted buffer? : "
0130            << "\n";
0131         ss << "Expected Buffer Size " << bufferSize_ << " bytes"
0132            << "\n";
0133         ss << "Computed Buffer Size " << bufferSize_ + bufferDiff << " bytes"
0134            << "\n";
0135         throw cms::Exception("Phase2TrackerFEDBuffer") << ss.str();
0136       }
0137     }
0138   }
0139 
0140   std::map<uint32_t, uint32_t> Phase2TrackerFEDBuffer::conditionData() const {
0141     std::map<uint32_t, uint32_t> cdata;
0142     // check if there is condition data
0143     if (condDataPointer_) {
0144       const uint8_t* pointer = condDataPointer_;
0145       const uint8_t* stop = buffer_ + bufferSize_ - 8;
0146       // first read the size
0147       uint32_t size = 0;
0148       // somehow the size is not inverted
0149       //for (int i=0;i<4;++i) size += *(pointer-4+(i^7)) << (i*8);
0150       size = *reinterpret_cast<const uint32_t*>(pointer);
0151       LogTrace("Phase2TrackerFEDBuffer") << "Condition Data size = " << size << std::endl;
0152       pointer += 8;
0153       // now the conditions
0154       while (pointer < stop) {
0155         // somehow the data is not inverted
0156         uint32_t data = 0;
0157         //for (int i = 0, j=3 ; i<4; i++,j--)
0158         //{ data += (*(pointer+i) << j*8); }
0159         data = *reinterpret_cast<const uint32_t*>(pointer);
0160         pointer += 4;
0161 
0162         uint32_t key = 0;
0163         for (int i = 0, j = 3; i < 4; i++, j--) {
0164           key += (*(pointer + i) << j * 8);
0165         }
0166         pointer += 4;
0167 
0168         cdata[key] = data;
0169       }
0170       // final check: cdata size == size
0171       if (cdata.size() != size) {
0172         std::ostringstream ss;
0173         ss << "[Phase2Tracker::Phase2TrackerFEDBuffer::" << __func__ << "] "
0174            << "\n";
0175         ss << "Number of condition data does not match the announced value!"
0176            << "\n";
0177         ss << "Expected condition data Size " << size << " entries"
0178            << "\n";
0179         ss << "Computed condition data Size " << cdata.size() << " entries"
0180            << "\n";
0181         throw cms::Exception("Phase2TrackerFEDBuffer") << ss.str();
0182       }
0183     }
0184     // REMOVE THIS : inject fake cond data for tests
0185     /*
0186       cdata[0x0011] = 0x0001;
0187       cdata[0x0012] = 0x0002;
0188       */
0189     // add trigger data
0190     cdata[0x0B0000FF] = (TRIGGER_SIZE > 0) ? (*triggerPointer_) : 0x00000000;
0191     return cdata;
0192   }
0193 
0194   FEDReadoutMode Phase2TrackerFEDBuffer::readoutMode() const { return trackerHeader_.getReadoutMode(); }
0195 
0196 }  // namespace Phase2Tracker