CMS 3D CMS Logo

/data/git/CMSSW_5_3_11_patch5/src/EventFilter/SiStripRawToDigi/src/SiStripFEDBufferGenerator.cc

Go to the documentation of this file.
00001 #include "EventFilter/SiStripRawToDigi/interface/SiStripFEDBufferGenerator.h"
00002 #include "FWCore/Utilities/interface/Exception.h"
00003 #include <cstring>
00004 #include <stdexcept>
00005 
00006 namespace sistrip {
00007   
00008   //FEDStripData
00009   
00010   FEDStripData::FEDStripData(bool dataIsAlreadyConvertedTo8Bit, const size_t samplesPerChannel)
00011     : data_(FEDCH_PER_FED,ChannelData(dataIsAlreadyConvertedTo8Bit,samplesPerChannel))
00012   {
00013     if (samplesPerChannel > SCOPE_MODE_MAX_SCOPE_LENGTH) {
00014       std::ostringstream ss;
00015       ss << "Scope length " << samplesPerChannel << " is too long. "
00016          << "Max scope length is " << SCOPE_MODE_MAX_SCOPE_LENGTH << ".";
00017       throw cms::Exception("FEDBufferGenerator") << ss.str();
00018     }
00019   }
00020   
00021   const FEDStripData::ChannelData& FEDStripData::channel(const uint8_t internalFEDChannelNum) const
00022   {
00023     try {
00024       return data_.at(internalFEDChannelNum);
00025     } catch (const std::out_of_range&) {
00026       std::ostringstream ss;
00027       ss << "Channel index out of range. (" << uint16_t(internalFEDChannelNum) << ") "
00028          << "Index should be in internal numbering scheme (0-95). ";
00029       throw cms::Exception("FEDBufferGenerator") << ss.str();
00030     }
00031   }
00032   
00033   void FEDStripData::ChannelData::setSample(const uint16_t sampleNumber, const uint16_t value)
00034   {
00035     if (value > 0x3FF) {
00036       std::ostringstream ss;
00037       ss << "Sample value (" << value << ") is too large. Maximum allowed is 1023. ";
00038       throw cms::Exception("FEDBufferGenerator") << ss.str();
00039     }
00040     try {
00041       data_.at(sampleNumber) = value;
00042     } catch (const std::out_of_range&) {
00043       std::ostringstream ss;
00044       ss << "Sample index out of range. "
00045          << "Requesting sample " << sampleNumber
00046          << " when channel has only " << data_.size() << " samples.";
00047       throw cms::Exception("FEDBufferGenerator") << ss.str();
00048     }
00049   }
00050   
00051   //FEDBufferPayload
00052   
00053   FEDBufferPayload::FEDBufferPayload(const std::vector< std::vector<uint8_t> >& channelBuffers)
00054   {
00055     //calculate size of buffer and allocate enough memory
00056     uint32_t totalSize = 0;
00057     for (uint8_t iFE = 0; iFE < FEUNITS_PER_FED; iFE++) {
00058       for (uint8_t iCh = 0; iCh < FEDCH_PER_FEUNIT; iCh++) {
00059         totalSize += channelBuffers[iFE*FEDCH_PER_FEUNIT+iCh].size();
00060       }
00061       //if it does not finish on a 64Bit word boundary then take into account padding
00062       if (totalSize%8) {
00063         totalSize = ((totalSize/8) + 1)*8;
00064       }
00065     }
00066     data_.resize(totalSize);
00067     size_t indexInBuffer = 0;
00068     feLengths_.reserve(FEUNITS_PER_FED);
00069     //copy channel data into buffer with padding and update lengths
00070     for (uint8_t iFE = 0; iFE < FEUNITS_PER_FED; iFE++) {
00071       const size_t lengthAtStartOfFEUnit = indexInBuffer;
00072       //insert data for FE unit
00073       for (uint8_t iCh = 0; iCh < FEDCH_PER_FEUNIT; iCh++) {
00074         appendToBuffer(&indexInBuffer,channelBuffers[iFE*FEDCH_PER_FEUNIT+iCh].begin(),channelBuffers[iFE*FEDCH_PER_FEUNIT+iCh].end());
00075       }
00076       //store length
00077       feLengths_.push_back(indexInBuffer-lengthAtStartOfFEUnit);
00078       //add padding
00079       while (indexInBuffer % 8) appendToBuffer(&indexInBuffer,0);
00080     }
00081   }
00082   
00083   const uint8_t* FEDBufferPayload::data() const
00084   {
00085     //vectors are guarenteed to be contiguous
00086     if (lengthInBytes()) return &data_[0];
00087     //return NULL if there is no data yet
00088     else return NULL;
00089   }
00090   
00091   uint16_t FEDBufferPayload::getFELength(const uint8_t internalFEUnitNum) const
00092   {
00093     try{
00094       return feLengths_.at(internalFEUnitNum);
00095     } catch (const std::out_of_range&) {
00096       std::ostringstream ss;
00097       ss << "Invalid FE unit number " << internalFEUnitNum << ". "
00098          << "Number should be in internal numbering scheme (0-7). ";
00099       throw cms::Exception("FEDBufferGenerator") << ss.str();
00100     }
00101   }
00102   
00103   FEDBufferPayload FEDBufferPayloadCreator::createPayload(const FEDReadoutMode mode, const FEDStripData& data) const
00104   {
00105     std::vector< std::vector<uint8_t> > channelBuffers(FEDCH_PER_FED,std::vector<uint8_t>());
00106     for (size_t iCh = 0; iCh < FEDCH_PER_FED; iCh++) {
00107       if (!feUnitsEnabled_[iCh/FEDCH_PER_FEUNIT]) continue;
00108       fillChannelBuffer(&channelBuffers[iCh],mode,data.channel(iCh),channelsEnabled_[iCh]);
00109     }
00110     return FEDBufferPayload(channelBuffers);
00111   }
00112   
00113   void FEDBufferPayloadCreator::fillChannelBuffer(std::vector<uint8_t>* channelBuffer, const FEDReadoutMode mode,
00114                                                  const FEDStripData::ChannelData& data, const bool channelEnabled) const
00115   {
00116     switch (mode) {
00117     case READOUT_MODE_SCOPE:
00118       fillRawChannelBuffer(channelBuffer,PACKET_CODE_SCOPE,data,channelEnabled,false);
00119       break;
00120     case READOUT_MODE_VIRGIN_RAW:
00121       fillRawChannelBuffer(channelBuffer,PACKET_CODE_VIRGIN_RAW,data,channelEnabled,true);
00122       break;
00123     case READOUT_MODE_PROC_RAW:
00124       fillRawChannelBuffer(channelBuffer,PACKET_CODE_PROC_RAW,data,channelEnabled,false);
00125       break;
00126     case READOUT_MODE_ZERO_SUPPRESSED:
00127       fillZeroSuppressedChannelBuffer(channelBuffer,data,channelEnabled);
00128       break;
00129     case READOUT_MODE_ZERO_SUPPRESSED_LITE:
00130       fillZeroSuppressedLiteChannelBuffer(channelBuffer,data,channelEnabled);
00131       break;
00132     default:
00133       std::ostringstream ss;
00134       ss << "Invalid readout mode " << mode;
00135       throw cms::Exception("FEDBufferGenerator") << ss.str();
00136       break;
00137     }
00138   }
00139   
00140   void FEDBufferPayloadCreator::fillRawChannelBuffer(std::vector<uint8_t>* channelBuffer,
00141                                                     const uint8_t packetCode,
00142                                                     const FEDStripData::ChannelData& data,
00143                                                     const bool channelEnabled,
00144                                                     const bool reorderData) const
00145   {
00146     const uint16_t nSamples = data.size();
00147     //2 bytes per sample + packet code + 2 bytes for length
00148     const uint16_t channelLength = nSamples*2 + 3;
00149     channelBuffer->reserve(channelLength);
00150     //length (max length is 0xFFF)
00151     channelBuffer->push_back( channelLength & 0xFF );
00152     channelBuffer->push_back( (channelLength & 0xF00) >> 8 );
00153     //packet code
00154     channelBuffer->push_back(packetCode);
00155     //channel samples
00156     for (uint16_t sampleNumber = 0; sampleNumber < nSamples; sampleNumber++) {
00157       const uint16_t sampleIndex = ( reorderData ? FEDStripOrdering::physicalOrderForStripInChannel(sampleNumber) : sampleNumber );
00158       const uint16_t sampleValue = (channelEnabled ? data.getSample(sampleIndex) : 0);
00159       channelBuffer->push_back(sampleValue & 0xFF);
00160       channelBuffer->push_back((sampleValue & 0x300) >> 8);
00161     }
00162   }
00163   
00164   void FEDBufferPayloadCreator::fillZeroSuppressedChannelBuffer(std::vector<uint8_t>* channelBuffer,
00165                                                                const FEDStripData::ChannelData& data,
00166                                                                const bool channelEnabled) const
00167   {
00168     channelBuffer->reserve(50);
00169     //if channel is disabled then create empty channel header and return
00170     if (!channelEnabled) {
00171       //min length 7
00172       channelBuffer->push_back(7);
00173       channelBuffer->push_back(0);
00174       //packet code
00175       channelBuffer->push_back(PACKET_CODE_ZERO_SUPPRESSED);
00176       //4 bytes of medians
00177       channelBuffer->insert(channelBuffer->end(),4,0);
00178       return;
00179     }
00180     //if channel is not empty
00181     //add space for channel length
00182     channelBuffer->push_back(0xFF); channelBuffer->push_back(0xFF);
00183     //packet code
00184     channelBuffer->push_back(PACKET_CODE_ZERO_SUPPRESSED);
00185     //add medians
00186     const std::pair<uint16_t,uint16_t> medians = data.getMedians();
00187     channelBuffer->push_back(medians.first & 0xFF);
00188     channelBuffer->push_back((medians.first & 0x300) >> 8);
00189     channelBuffer->push_back(medians.second & 0xFF);
00190     channelBuffer->push_back((medians.second & 0x300) >> 8);
00191     //clusters
00192     fillClusterData(channelBuffer,data);
00193     //set length
00194     const uint16_t length = channelBuffer->size();
00195     (*channelBuffer)[0] = (length & 0xFF);
00196     (*channelBuffer)[1] = ((length & 0x300) >> 8);
00197   }
00198   
00199   void FEDBufferPayloadCreator::fillZeroSuppressedLiteChannelBuffer(std::vector<uint8_t>* channelBuffer,
00200                                                                    const FEDStripData::ChannelData& data,
00201                                                                    const bool channelEnabled) const
00202   {
00203     channelBuffer->reserve(50);
00204     //if channel is disabled then create empty channel header and return
00205     if (!channelEnabled) {
00206       //min length 2
00207       channelBuffer->push_back(2);
00208       channelBuffer->push_back(0);
00209       return;
00210     }
00211     //if channel is not empty
00212     //add space for channel length
00213     channelBuffer->push_back(0xFF); channelBuffer->push_back(0xFF);
00214     //clusters
00215     fillClusterData(channelBuffer,data);
00216     //set length
00217     const uint16_t length = channelBuffer->size();
00218     (*channelBuffer)[0] = (length & 0xFF);
00219     (*channelBuffer)[1] = ((length & 0x300) >> 8);
00220   }
00221   
00222   void FEDBufferPayloadCreator::fillClusterData(std::vector<uint8_t>* channelBuffer, const FEDStripData::ChannelData& data) const
00223   {
00224     uint16_t clusterSize = 0;
00225     const uint16_t nSamples = data.size();
00226     for( uint16_t strip = 0; strip < nSamples; ++strip) {
00227       const uint8_t adc = data.get8BitSample(strip);
00228 
00229       if(adc) {
00230         if( clusterSize==0 || strip == STRIPS_PER_APV ) { 
00231           if(clusterSize) { 
00232             *(channelBuffer->end() - clusterSize - 1) = clusterSize ; 
00233             clusterSize = 0; 
00234           }
00235           channelBuffer->push_back(strip); 
00236           channelBuffer->push_back(0); //clustersize      
00237         }
00238         channelBuffer->push_back(adc);
00239         ++clusterSize;
00240       }
00241 
00242       else if(clusterSize) { 
00243         *(channelBuffer->end() - clusterSize - 1) = clusterSize ; 
00244         clusterSize = 0; 
00245       }
00246     }
00247     if(clusterSize) *(channelBuffer->end() - clusterSize - 1) = clusterSize ;
00248   }
00249 
00250   //FEDBufferGenerator
00251   
00252   FEDBufferGenerator::FEDBufferGenerator(const uint32_t l1ID, const uint16_t bxID,
00253                                          const std::vector<bool>& feUnitsEnabled, const std::vector<bool>& channelsEnabled,
00254                                          const FEDReadoutMode readoutMode, const FEDHeaderType headerType, const FEDBufferFormat bufferFormat,
00255                                          const FEDDAQEventType evtType, const FEDDataType dataType)
00256     : defaultDAQHeader_(l1ID,bxID,0,evtType),
00257       defaultDAQTrailer_(0,0),
00258       defaultTrackerSpecialHeader_(bufferFormat,readoutMode,headerType,dataType),
00259       defaultFEHeader_(FEDFEHeader::newFEHeader(headerType)),
00260       feUnitsEnabled_(feUnitsEnabled),
00261       channelsEnabled_(channelsEnabled)
00262   {
00263     if (!defaultFEHeader_.get()) {
00264       std::ostringstream ss;
00265       ss << "Bad header format: " << headerType;
00266       throw cms::Exception("FEDBufferGenerator") << ss.str();
00267     }
00268   }
00269   
00270   bool FEDBufferGenerator::getFEUnitEnabled(const uint8_t internalFEUnitNumber) const
00271   {
00272     try {
00273       return feUnitsEnabled_.at(internalFEUnitNumber);
00274     } catch (const std::out_of_range&) {
00275       std::ostringstream ss;
00276       ss << "Invalid FE unit number " << internalFEUnitNumber << ". Should be in internal numbering scheme (0-7)";
00277       throw cms::Exception("FEDBufferGenerator") << ss.str();
00278     }
00279   }
00280   
00281   bool FEDBufferGenerator::getChannelEnabled(const uint8_t internalFEDChannelNumber) const
00282   {
00283     try {
00284       return channelsEnabled_.at(internalFEDChannelNumber);
00285     } catch (const std::out_of_range&) {
00286       
00287       std::ostringstream ss;
00288       ss << "Invalid channel number " << internalFEDChannelNumber << ". "
00289          << "Should be in internal numbering scheme (0-95)";
00290       throw cms::Exception("FEDBufferGenerator") << ss.str();
00291     }
00292   }
00293   
00294   FEDBufferGenerator& FEDBufferGenerator::setFEUnitEnable(const uint8_t internalFEUnitNumber, const bool enabled)
00295   {
00296     try {
00297       feUnitsEnabled_.at(internalFEUnitNumber) = enabled;
00298     } catch (const std::out_of_range&) {
00299       std::ostringstream ss;
00300       ss << "Invalid FE unit number " << internalFEUnitNumber << ". "
00301          << "Should be in internal numbering scheme (0-7)";
00302       throw cms::Exception("FEDBufferGenerator") << ss.str();
00303     }
00304     return *this;
00305   }
00306   
00307   FEDBufferGenerator& FEDBufferGenerator::setChannelEnable(const uint8_t internalFEDChannelNumber, const bool enabled)
00308   {
00309     try {
00310       channelsEnabled_.at(internalFEDChannelNumber) = enabled;
00311     } catch (const std::out_of_range&) {
00312       std::ostringstream ss;
00313       ss << "Invalid channel number " << internalFEDChannelNumber << ". "
00314          <<"Should be in internal numbering scheme (0-95)";
00315       throw cms::Exception("FEDBufferGenerator") << ss.str();
00316     }
00317     return *this;
00318   }
00319   
00320   FEDBufferGenerator& FEDBufferGenerator::setFEUnitEnables(const std::vector<bool>& feUnitEnables)
00321   {
00322     if (feUnitEnables.size() != FEUNITS_PER_FED) {
00323       std::ostringstream ss;
00324       ss << "Setting FE enable vector with vector which is the wrong size. Size is " << feUnitEnables.size()
00325          << " it must be " << FEUNITS_PER_FED << "." << std::endl;
00326       throw cms::Exception("FEDBufferGenerator") << ss.str();
00327     }
00328     feUnitsEnabled_ = feUnitEnables;
00329     return *this;
00330   }
00331   
00332   FEDBufferGenerator& FEDBufferGenerator::setChannelEnables(const std::vector<bool>& channelEnables)
00333   {
00334     if (channelEnables.size() != FEDCH_PER_FED) {
00335       std::ostringstream ss;
00336       ss << "Setting FED channel enable vector with vector which is the wrong size. Size is " << channelEnables.size()
00337          << " it must be " << FEDCH_PER_FED << "." << std::endl;
00338       throw cms::Exception("FEDBufferGenerator") << ss.str();
00339     }
00340     channelsEnabled_ = channelEnables;
00341     return *this;
00342   }
00343   
00344   void FEDBufferGenerator::generateBuffer(FEDRawData* rawDataObject, const FEDStripData& data, const uint16_t sourceID) const
00345   {
00346     //deal with disabled FE units and channels properly (FE enables, status bits)
00347     TrackerSpecialHeader tkSpecialHeader(defaultTrackerSpecialHeader_);
00348     std::auto_ptr<FEDFEHeader> fedFeHeader(defaultFEHeader_->clone());
00349     for (uint8_t iFE = 0; iFE < FEUNITS_PER_FED; iFE++) {
00350       const bool enabled = feUnitsEnabled_[iFE];
00351       tkSpecialHeader.setFEEnableForFEUnit(iFE,enabled);
00352       if (!enabled) {
00353         for (uint8_t iFEUnitChannel = 0; iFEUnitChannel < FEDCH_PER_FEUNIT; iFEUnitChannel++) {
00354           fedFeHeader->setChannelStatus(iFE,iFEUnitChannel,FEDChannelStatus(0));
00355         }
00356       }
00357     }
00358     for (uint8_t iCh = 0; iCh < FEDCH_PER_FED; iCh++) {
00359       if (!channelsEnabled_[iCh]) {
00360         fedFeHeader->setChannelStatus(iCh,FEDChannelStatus(0));
00361       }
00362     }
00363     //set the source ID
00364     FEDDAQHeader daqHeader(defaultDAQHeader_);
00365     daqHeader.setSourceID(sourceID);
00366     //build payload
00367     const FEDBufferPayloadCreator payloadPacker(feUnitsEnabled_,channelsEnabled_);
00368     const FEDBufferPayload payload = payloadPacker(getReadoutMode(),data);
00369     //fill FE lengths
00370     for (uint8_t iFE = 0; iFE < FEUNITS_PER_FED; iFE++) {
00371       fedFeHeader->setFEUnitLength(iFE,payload.getFELength(iFE));
00372     }
00373     //resize buffer
00374     rawDataObject->resize(bufferSizeInBytes(*fedFeHeader,payload));
00375     //fill buffer
00376     fillBuffer(rawDataObject->data(),daqHeader,defaultDAQTrailer_,tkSpecialHeader,*fedFeHeader,payload);
00377   }
00378   
00379   void FEDBufferGenerator::fillBuffer(uint8_t* pointerToStartOfBuffer,
00380                                       const FEDDAQHeader& daqHeader,
00381                                       const FEDDAQTrailer& daqTrailer,
00382                                       const TrackerSpecialHeader& tkSpecialHeader,
00383                                       const FEDFEHeader& feHeader,
00384                                       const FEDBufferPayload& payload)
00385   {
00386     //set the length in the DAQ trailer
00387     const size_t lengthInBytes = bufferSizeInBytes(feHeader,payload);
00388     FEDDAQTrailer updatedDAQTrailer(daqTrailer);
00389     updatedDAQTrailer.setEventLengthIn64BitWords(lengthInBytes/8);
00390     //copy pieces into buffer in order
00391     uint8_t* bufferPointer = pointerToStartOfBuffer;
00392     memcpy(bufferPointer,daqHeader.data(),8);
00393     bufferPointer += 8;
00394     memcpy(bufferPointer,tkSpecialHeader.data(),8);
00395     bufferPointer += 8;
00396     memcpy(bufferPointer,feHeader.data(),feHeader.lengthInBytes());
00397     bufferPointer += feHeader.lengthInBytes();
00398     memcpy(bufferPointer,payload.data(),payload.lengthInBytes());
00399     bufferPointer += payload.lengthInBytes();
00400     memcpy(bufferPointer,updatedDAQTrailer.data(),8);
00401     //update CRC
00402     const uint16_t crc = calculateFEDBufferCRC(pointerToStartOfBuffer,lengthInBytes);
00403     updatedDAQTrailer.setCRC(crc);
00404     memcpy(bufferPointer,updatedDAQTrailer.data(),8);
00405     //word swap if necessary
00406     if (tkSpecialHeader.wasSwapped()) {
00407       for (size_t i = 0; i < 8; i++) {
00408         bufferPointer[i] = bufferPointer[i^4];
00409       }
00410     }
00411   }
00412   
00413 }