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
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
00052
00053 FEDBufferPayload::FEDBufferPayload(const std::vector< std::vector<uint8_t> >& channelBuffers)
00054 {
00055
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
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
00070 for (uint8_t iFE = 0; iFE < FEUNITS_PER_FED; iFE++) {
00071 const size_t lengthAtStartOfFEUnit = indexInBuffer;
00072
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
00077 feLengths_.push_back(indexInBuffer-lengthAtStartOfFEUnit);
00078
00079 while (indexInBuffer % 8) appendToBuffer(&indexInBuffer,0);
00080 }
00081 }
00082
00083 const uint8_t* FEDBufferPayload::data() const
00084 {
00085
00086 if (lengthInBytes()) return &data_[0];
00087
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
00148 const uint16_t channelLength = nSamples*2 + 3;
00149 channelBuffer->reserve(channelLength);
00150
00151 channelBuffer->push_back( channelLength & 0xFF );
00152 channelBuffer->push_back( (channelLength & 0xF00) >> 8 );
00153
00154 channelBuffer->push_back(packetCode);
00155
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
00170 if (!channelEnabled) {
00171
00172 channelBuffer->push_back(7);
00173 channelBuffer->push_back(0);
00174
00175 channelBuffer->push_back(PACKET_CODE_ZERO_SUPPRESSED);
00176
00177 channelBuffer->insert(channelBuffer->end(),4,0);
00178 return;
00179 }
00180
00181
00182 channelBuffer->push_back(0xFF); channelBuffer->push_back(0xFF);
00183
00184 channelBuffer->push_back(PACKET_CODE_ZERO_SUPPRESSED);
00185
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
00192 fillClusterData(channelBuffer,data);
00193
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
00205 if (!channelEnabled) {
00206
00207 channelBuffer->push_back(2);
00208 channelBuffer->push_back(0);
00209 return;
00210 }
00211
00212
00213 channelBuffer->push_back(0xFF); channelBuffer->push_back(0xFF);
00214
00215 fillClusterData(channelBuffer,data);
00216
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);
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
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
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
00364 FEDDAQHeader daqHeader(defaultDAQHeader_);
00365 daqHeader.setSourceID(sourceID);
00366
00367 const FEDBufferPayloadCreator payloadPacker(feUnitsEnabled_,channelsEnabled_);
00368 const FEDBufferPayload payload = payloadPacker(getReadoutMode(),data);
00369
00370 for (uint8_t iFE = 0; iFE < FEUNITS_PER_FED; iFE++) {
00371 fedFeHeader->setFEUnitLength(iFE,payload.getFELength(iFE));
00372 }
00373
00374 rawDataObject->resize(bufferSizeInBytes(*fedFeHeader,payload));
00375
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
00387 const size_t lengthInBytes = bufferSizeInBytes(feHeader,payload);
00388 FEDDAQTrailer updatedDAQTrailer(daqTrailer);
00389 updatedDAQTrailer.setEventLengthIn64BitWords(lengthInBytes/8);
00390
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
00402 const uint16_t crc = calculateFEDBufferCRC(pointerToStartOfBuffer,lengthInBytes);
00403 updatedDAQTrailer.setCRC(crc);
00404 memcpy(bufferPointer,updatedDAQTrailer.data(),8);
00405
00406 if (tkSpecialHeader.wasSwapped()) {
00407 for (size_t i = 0; i < 8; i++) {
00408 bufferPointer[i] = bufferPointer[i^4];
00409 }
00410 }
00411 }
00412
00413 }