CMS 3D CMS Logo

SiStripFEDBuffer.h

Go to the documentation of this file.
00001 #ifndef EventFilter_SiStripRawToDigi_SiStripFEDBuffer_H
00002 #define EventFilter_SiStripRawToDigi_SiStripFEDBuffer_H
00003 
00004 #include "boost/cstdint.hpp"
00005 #include <string>
00006 #include <vector>
00007 #include <memory>
00008 #include <ostream>
00009 #include "DataFormats/SiStripCommon/interface/ConstantsForHardwareSystems.h"
00010 #include "EventFilter/SiStripRawToDigi/interface/SiStripFEDBufferComponents.h"
00011 
00012 namespace sistrip {
00013 
00014   //
00015   // Class definitions
00016   //
00017 
00018   class FEDBufferBase
00019     {
00020     public:
00021       FEDBufferBase(const uint8_t* fedBuffer, size_t fedBufferSize, bool allowUnrecognizedFormat = false);
00022       virtual ~FEDBufferBase();
00023       //dump buffer to stream
00024       void dump(std::ostream& os) const { printHex(orderedBuffer_,bufferSize_,os); }
00025       //dump original buffer before word swapping
00026       void dumpOriginalBuffer(std::ostream& os) const { printHex(originalBuffer_,bufferSize_,os); }
00027       virtual void print(std::ostream& os) const;
00028       //calculate the CRC from the buffer
00029       uint16_t calcCRC() const;
00030   
00031       //methods to get parts of the buffer
00032       FEDDAQHeader daqHeader() const { return daqHeader_; }
00033       FEDDAQTrailer daqTrailer() const { return daqTrailer_; }
00034       size_t bufferSize() const { return bufferSize_; }
00035       TrackerSpecialHeader trackerSpecialHeader() const { return specialHeader_; }
00036       //methods to get info from DAQ header
00037       FEDDAQEventType daqEventType() const { return daqHeader_.eventType(); }
00038       uint32_t daqLvl1ID() const { return daqHeader_.l1ID(); }
00039       uint16_t daqBXID() const { return daqHeader_.bxID(); }
00040       uint16_t daqSourceID() const { return daqHeader_.sourceID(); }
00041       uint16_t sourceID() const { return daqSourceID(); }
00042       //methods to get info from DAQ trailer
00043       uint32_t daqEventLengthIn64bitWords() const { return daqTrailer_.eventLengthIn64BitWords(); }
00044       uint32_t daqEventLengthInBytes() const { return daqTrailer_.eventLengthInBytes(); }
00045       uint16_t daqCRC() const { return daqTrailer_.crc(); }
00046       FEDTTSBits daqTTSState() const { return daqTrailer_.ttsBits(); }
00047       //methods to get info from the tracker special header
00048       FEDBufferFormat bufferFormat() const { return specialHeader_.bufferFormat(); }
00049       FEDHeaderType headerType() const { return specialHeader_.headerType(); }
00050       FEDReadoutMode readoutMode() const { return specialHeader_.readoutMode(); }
00051       FEDDataType dataType() const { return specialHeader_.dataType(); }
00052       uint8_t apveAddress() const { return specialHeader_.apveAddress(); }
00053       bool majorityAddressErrorForFEUnit(uint8_t internalFEUnitNum) const { return specialHeader_.majorityAddressErrorForFEUnit(internalFEUnitNum); }
00054       bool feEnabled(uint8_t internalFEUnitNum) const { return specialHeader_.feEnabled(internalFEUnitNum); }
00055       uint8_t nFEUnitsEnabled() const;
00056       bool feOverflow(uint8_t internalFEUnitNum) const { return specialHeader_.feOverflow(internalFEUnitNum); }
00057       FEDStatusRegister fedStatusRegister() const { return specialHeader_.fedStatusRegister(); }
00058   
00059       //summary checks
00060       //check that tracker special header is valid (does not check for FE unit errors indicated in special header)
00061       bool doTrackerSpecialHeaderChecks() const;
00062       //check for errors in DAQ heaqder and trailer (not including bad CRC)
00063       bool doDAQHeaderAndTrailerChecks() const;
00064       //do both
00065       virtual bool doChecks() const;
00066       //print the result of all detailed checks
00067       virtual std::string checkSummary() const;
00068   
00069       //detailed checks
00070       bool checkCRC() const { return ( checkNoSlinkCRCError() && (calcCRC()==daqCRC()) ); }
00071       bool checkMajorityAddresses() const;
00072       //methods to check tracker special header
00073       bool checkBufferFormat() const { return (bufferFormat() != BUFFER_FORMAT_INVALID); }
00074       bool checkHeaderType() const { return (headerType() != HEADER_TYPE_INVALID); }
00075       bool checkReadoutMode() const { return (readoutMode() != READOUT_MODE_INVALID); }
00076       bool checkAPVEAddressValid() const { return (apveAddress() <= APV_MAX_ADDRESS); }
00077       bool checkNoFEOverflows() const { return !specialHeader_.feOverflowRegister(); }
00078       //methods to check daq header and trailer
00079       bool checkNoSlinkCRCError() const { return !daqTrailer_.slinkCRCError(); }
00080       bool checkNoSLinkTransmissionError() const { return !daqTrailer_.slinkTransmissionError(); }
00081       bool checkSourceIDs() const;
00082       bool checkNoUnexpectedSourceID() const { return !daqTrailer_.badFEDID(); }
00083       bool checkNoExtraHeadersOrTrailers() const { return ( (daqHeader_.boeNibble() == 0x5) && (daqTrailer_.eoeNibble() == 0xA) ); }
00084       bool checkLengthFromTrailer() const { return (bufferSize() == daqEventLengthInBytes()); }
00085     protected:
00086       const uint8_t* getPointerToDataAfterTrackerSpecialHeader() const
00087         { return orderedBuffer_+16; }
00088       uint8_t* getPointerToDataAfterTrackerSpecialHeader();
00089       const uint8_t* getPointerToByteAfterEndOfPayload() const
00090         { return orderedBuffer_+bufferSize_-8; }
00091       uint8_t* getPointerToByteAfterEndOfPayload();
00092     private:
00093       const uint8_t* originalBuffer_;
00094       const uint8_t* orderedBuffer_;
00095       const size_t bufferSize_;
00096       FEDDAQHeader daqHeader_;
00097       FEDDAQTrailer daqTrailer_;
00098       TrackerSpecialHeader specialHeader_;
00099     };
00100 
00101   class FEDZSChannelUnpacker;
00102   class FEDRawChannelUnpacker;
00103 
00104   class FEDChannel
00105     {
00106     public:
00107       FEDChannel(const uint8_t* data, size_t offset);
00108       uint16_t length() const { return length_; }
00109       uint8_t packetCode() const { return data_[(offset_+2)^7]; }
00110     private:
00111       friend class FEDBuffer;
00112       friend class FEDZSChannelUnpacker;
00113       friend class FEDRawChannelUnpacker;
00114       const uint8_t* data() const { return data_; }
00115       size_t offset() const { return offset_; }
00116       const uint8_t* data_;
00117       uint16_t length_;
00118       size_t offset_;
00119     };
00120 
00121   class FEDBuffer : public FEDBufferBase
00122     {
00123     public:
00124       //construct from buffer
00125       //if allowBadBuffer is set to true then exceptions will not be thrown if the channel lengths do not make sense or the event format is not recognized
00126       FEDBuffer(const uint8_t* fedBuffer, size_t fedBufferSize, bool allowBadBuffer = false);
00127       virtual ~FEDBuffer();
00128       virtual void print(std::ostream& os) const;
00129       const FEDFEHeader* feHeader() const { return feHeader_.get(); }
00130       //check that a FE unit is enabled, has a good majority address and, if in full debug mode, that it is present
00131       bool feGood(uint8_t internalFEUnitNum) const { return ( !majorityAddressErrorForFEUnit(internalFEUnitNum) && !feOverflow(internalFEUnitNum) && fePresent(internalFEUnitNum) ); }
00132       //check that channel is on enabled FE Unit and has no errors
00133       bool channelGood(uint8_t internalFEDChannelNum) const;
00134       bool channelGood(uint8_t internalFEUnitNum, uint8_t internalChannelNum) const
00135         { return channelGood(internalFEDChannelNum(internalFEUnitNum,internalChannelNum)); }
00136       //return channel object for channel
00137       const FEDChannel& channel(uint8_t internalFEDChannelNum) const { return channels_[internalFEDChannelNum]; }
00138       const FEDChannel& channel(uint8_t internalFEUnitNum, uint8_t internalChannelNum) const
00139         { return channel(internalFEDChannelNum(internalFEUnitNum,internalChannelNum)); }
00140 
00141       //functions to check buffer. All return true if there is no problem.
00142       //minimum checks to do before using buffer
00143       virtual bool doChecks() const;
00144   
00145       //additional checks to check for corrupt buffers
00146       //check channel lengths fit inside to buffer length
00147       bool checkChannelLengths() const;
00148       //check that channel lengths add up to buffer length (this does the previous check as well)
00149       bool checkChannelLengthsMatchBufferLength() const;
00150       //check channel packet codes match readout mode
00151       bool checkChannelPacketCodes() const;
00152       //check FE unit lengths in FULL DEBUG header match the lengths of their channels
00153       bool checkFEUnitLengths() const;
00154       //check FE unit APV addresses in FULL DEBUG header are equal to the APVe address if the majority was good
00155       bool checkFEUnitAPVAddresses() const;
00156       //do all corrupt buffer checks
00157       virtual bool doCorruptBufferChecks() const;
00158   
00159       //check that there are no errors in channel, APV or FEUnit status bits
00160       //these are done by channelGood(). Channels with bad status bits may be disabled so bad status bits do not usually indicate an error
00161       bool checkStatusBits(uint8_t internalFEDChannelNum) const { return feHeader_->checkChannelStatusBits(internalFEDChannelNum); }
00162       bool checkStatusBits(uint8_t internalFEUnitNum, uint8_t internalChannelNum) const
00163         { return checkStatusBits(internalFEDChannelNum(internalFEUnitNum,internalChannelNum)); }
00164       //same but for all channels on enabled FE units
00165       bool checkAllChannelStatusBits() const;
00166   
00167       //print a summary of all checks
00168       virtual std::string checkSummary() const;
00169     private:
00170       bool fePresent(uint8_t internalFEUnitNum) const { return fePresent_[internalFEUnitNum]; }
00171       uint8_t nFEUnitsPresent() const;
00172       void findChannels();
00173       uint8_t getCorrectPacketCode() const;
00174       uint16_t calculateFEUnitLength(uint8_t internalFEUnitNumber) const;
00175       std::vector<FEDChannel> channels_;
00176       std::auto_ptr<FEDFEHeader> feHeader_;
00177       uint8_t* payloadPointer_;
00178       uint16_t payloadLength_;
00179       uint8_t lastValidChannel_;
00180       bool fePresent_[FEUNITS_PER_FED];
00181     };
00182 
00183   class FEDZSChannelUnpacker
00184     {
00185     public:
00186       static FEDZSChannelUnpacker zeroSuppressedModeUnpacker(const FEDChannel& channel);
00187       static FEDZSChannelUnpacker zeroSuppressedLiteModeUnpacker(const FEDChannel& channel);
00188       FEDZSChannelUnpacker() : data_(NULL), valuesLeftInCluster_(0), valuesLeftAfterThisCluster_(0) { }
00189       uint8_t strip() const { return currentStrip_; }
00190       uint8_t adc() const { return data_[currentOffset_^7]; }
00191       bool hasData() const { return (valuesLeftAfterThisCluster_ || valuesLeftInCluster_); }
00192       FEDZSChannelUnpacker& operator ++ ();
00193       FEDZSChannelUnpacker& operator ++ (int) { ++(*this); return *this; }
00194     private:
00195       //pointer to begining of FED or FE data, offset of start of channel payload in data and length of channel payload
00196       FEDZSChannelUnpacker(const uint8_t* payload, size_t channelPayloadOffset,int16_t channelPayloadLength);
00197       void readNewClusterInfo();
00198       static void throwBadChannelLength(uint16_t length);
00199       void throwBadClusterLength();
00200       const uint8_t* data_;
00201       size_t currentOffset_;
00202       uint8_t currentStrip_;
00203       uint8_t valuesLeftInCluster_;
00204       int16_t valuesLeftAfterThisCluster_;
00205     };
00206 
00207   class FEDRawChannelUnpacker
00208     {
00209     public:
00210       static FEDRawChannelUnpacker scopeModeUnpacker(const FEDChannel& channel) { return FEDRawChannelUnpacker(channel); }
00211       static FEDRawChannelUnpacker virginRawModeUnpacker(const FEDChannel& channel) { return FEDRawChannelUnpacker(channel); }
00212       static FEDRawChannelUnpacker procRawModeUnpacker(const FEDChannel& channel) { return FEDRawChannelUnpacker(channel); }
00213       FEDRawChannelUnpacker(const FEDChannel& channel);
00214       uint8_t strip() const { return currentStrip_; }
00215       uint16_t adc() const { return ( data_[currentOffset_^7] + ((data_[(currentOffset_+1)^7]&0x03)<<8) ); }
00216       bool hasData() const { return valuesLeft_; }
00217       FEDRawChannelUnpacker& operator ++ ();
00218       FEDRawChannelUnpacker& operator ++ (int) { ++(*this); return *this; }
00219     private:
00220       static void throwBadChannelLength(uint16_t length);
00221       const uint8_t* data_;
00222       size_t currentOffset_;
00223       uint8_t currentStrip_;
00224       uint8_t valuesLeft_;
00225     };
00226 
00227   //
00228   // Inline function definitions
00229   //
00230 
00231   inline std::ostream& operator << (std::ostream& os, const FEDBufferBase& obj) { obj.print(os); os << obj.checkSummary(); return os; }
00232 
00233   //FEDBuffer
00234 
00235   inline bool FEDBuffer::channelGood(uint8_t internalFEDChannelNum) const
00236     {
00237       return ( (internalFEDChannelNum <= lastValidChannel_) &&
00238                feGood(internalFEDChannelNum/FEDCH_PER_FEUNIT) &&
00239                checkStatusBits(internalFEDChannelNum) );
00240     }
00241 
00242   //FEDBufferBase
00243 
00244   inline bool FEDBufferBase::doTrackerSpecialHeaderChecks() const
00245     {
00246       return ( checkBufferFormat() &&
00247                checkHeaderType() &&
00248                checkReadoutMode() &&
00249                checkAPVEAddressValid() &&
00250                checkNoFEOverflows() ); 
00251     }
00252 
00253   inline bool FEDBufferBase::doDAQHeaderAndTrailerChecks() const
00254     {
00255       return ( checkNoSLinkTransmissionError() &&
00256                checkSourceIDs() &&
00257                checkNoUnexpectedSourceID() &&
00258                checkNoExtraHeadersOrTrailers() &&
00259                checkLengthFromTrailer() );
00260     }
00261 
00262   //re-use the const method by using static and const casts to avoid code duplication
00263   inline uint8_t* FEDBufferBase::getPointerToDataAfterTrackerSpecialHeader()
00264     {
00265       const FEDBufferBase* constThis = static_cast<const FEDBufferBase*>(this);
00266       const uint8_t* constPointer = constThis->getPointerToDataAfterTrackerSpecialHeader();
00267       return const_cast<uint8_t*>(constPointer);
00268     }
00269 
00270   inline uint8_t* FEDBufferBase::getPointerToByteAfterEndOfPayload()
00271     {
00272       const FEDBufferBase* constThis = static_cast<const FEDBufferBase*>(this);
00273       const uint8_t* constPointer = constThis->getPointerToByteAfterEndOfPayload();
00274       return const_cast<uint8_t*>(constPointer);
00275     }
00276 
00277   //FEDChannel
00278 
00279   inline FEDChannel::FEDChannel(const uint8_t* data, size_t offset)
00280     : data_(data),
00281     offset_(offset)
00282     {
00283       length_ = ( data_[(offset_)^7] + (data_[(offset_+1)^7] << 8) );
00284     }
00285 
00286   //FEDRawChannelUnpacker
00287 
00288   inline FEDRawChannelUnpacker::FEDRawChannelUnpacker(const FEDChannel& channel)
00289     : data_(channel.data()),
00290     currentOffset_(channel.offset()+3),
00291     currentStrip_(0),
00292     valuesLeft_((channel.length()-3)/2)
00293     {
00294       if ((channel.length()-3)%2) throwBadChannelLength(channel.length());
00295     }
00296 
00297   inline FEDRawChannelUnpacker& FEDRawChannelUnpacker::operator ++ ()
00298     {
00299       currentOffset_ += 2;
00300       currentStrip_++;
00301       valuesLeft_--;
00302       return (*this);
00303     }
00304 
00305   //FEDZSChannelUnpacker
00306 
00307   inline FEDZSChannelUnpacker::FEDZSChannelUnpacker(const uint8_t* payload, size_t channelPayloadOffset,int16_t channelPayloadLength)
00308     : data_(payload),
00309     currentOffset_(channelPayloadOffset),
00310     currentStrip_(0),
00311     valuesLeftInCluster_(0),
00312     valuesLeftAfterThisCluster_(channelPayloadLength)
00313     {
00314       readNewClusterInfo();
00315     }
00316 
00317   inline void FEDZSChannelUnpacker::readNewClusterInfo()
00318     {
00319       if (valuesLeftAfterThisCluster_) {
00320         currentStrip_ = data_[(currentOffset_++)^7];
00321         valuesLeftInCluster_ = data_[(currentOffset_++)^7]-1;
00322         valuesLeftAfterThisCluster_ -= valuesLeftInCluster_+3;
00323         if (valuesLeftAfterThisCluster_ < 0) throwBadClusterLength();
00324       }
00325     }
00326 
00327   inline FEDZSChannelUnpacker& FEDZSChannelUnpacker::operator ++ ()
00328     {
00329       if (valuesLeftInCluster_) {
00330         currentStrip_++;
00331         currentOffset_++;
00332         valuesLeftInCluster_--;
00333       } else {
00334         currentOffset_++;
00335         readNewClusterInfo();
00336       }
00337       return (*this);
00338     }
00339 
00340   inline FEDZSChannelUnpacker FEDZSChannelUnpacker::zeroSuppressedModeUnpacker(const FEDChannel& channel)
00341     {
00342       uint16_t length = channel.length();
00343       if (length & 0xF000) throwBadChannelLength(length);
00344       FEDZSChannelUnpacker result(channel.data(),channel.offset()+7,length-7);
00345       return result;
00346     }
00347 
00348   inline FEDZSChannelUnpacker FEDZSChannelUnpacker::zeroSuppressedLiteModeUnpacker(const FEDChannel& channel)
00349     {
00350       uint16_t length = channel.length();
00351       if (length & 0xF000) throwBadChannelLength(length);
00352       FEDZSChannelUnpacker result(channel.data(),channel.offset()+2,length-2);
00353       return result;
00354     }
00355 
00356 }
00357 
00358 #endif //ndef EventFilter_SiStripRawToDigi_SiStripFEDBuffer_H

Generated on Tue Jun 9 17:34:50 2009 for CMSSW by  doxygen 1.5.4