ChannelData

FEDBufferGenerator

FEDBufferPayload

FEDBufferPayloadCreator

FEDStripData

Macros

Line Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363
#ifndef EventFilter_SiStripRawToDigi_SiStripFEDBufferGenerator_H
#define EventFilter_SiStripRawToDigi_SiStripFEDBufferGenerator_H

#include "EventFilter/SiStripRawToDigi/interface/SiStripFEDBufferComponents.h"
#include "DataFormats/FEDRawData/interface/FEDRawData.h"
#include <vector>
#include <list>
#include <utility>
#include <memory>
#include <cstdint>

namespace sistrip {

  //
  // Class definitions
  //

  class FEDStripData {
  public:
    //class used to represent channel data
    class ChannelData {
    public:
      ChannelData(bool dataIsAlreadyConvertedTo8Bit,
                  const size_t numberOfSamples,
                  const std::pair<uint16_t, uint16_t> medians = std::make_pair<uint16_t>(0, 0));
      //number of samples
      size_t size() const;
      //get common mode medians for first and second APV
      std::pair<uint16_t, uint16_t> getMedians() const;
      //set common mode medians for first and second APV
      void setMedians(const std::pair<uint16_t, uint16_t> values);
      //get the 10bit value to be used for raw modes
      uint16_t getSample(const uint16_t sampleNumber) const;
      //get the 8 bit value to be used for ZS modes, converting it as the FED does if specified in constructor
      uint8_t get8BitSample(const uint16_t sampleNumber, uint16_t nBotBitsToDrop) const;
      uint16_t get10BitSample(const uint16_t sampleNumber) const;
      void setSample(const uint16_t sampleNumber, const uint16_t adcValue);
      //setting value directly is equivalent to get and set Sample but without length check
      uint16_t& operator[](const size_t sampleNumber);
      const uint16_t& operator[](const size_t sampleNumber) const;

    private:
      std::pair<uint16_t, uint16_t> medians_;
      std::vector<uint16_t> data_;
      bool dataIs8Bit_;
    };

    FEDStripData(const std::vector<ChannelData>& data);
    //specify whether the data is already in the 8bit ZS format (only affects what is returned by ChannelData::get8BitSample() if the value if >253)
    //if the data is for scope mode then specify the scope length
    FEDStripData(bool dataIsAlreadyConvertedTo8Bit = true, const size_t samplesPerChannel = STRIPS_PER_FEDCH);
    //access to elements
    ChannelData& operator[](const uint8_t internalFEDChannelNum);
    const ChannelData& operator[](const uint8_t internalFEDChannelNum) const;
    ChannelData& channel(const uint8_t internalFEDChannelNum);
    const ChannelData& channel(const uint8_t internalFEDChannelNum) const;

  private:
    std::vector<ChannelData> data_;
  };

  class FEDBufferPayload {
  public:
    FEDBufferPayload(const std::vector<std::vector<uint8_t> >& channelBuffers);
    //size of payload in bytes
    size_t lengthInBytes() const;
    //returns NULL if payload size is 0, otherwise return a pointer to the payload buffer
    const uint8_t* data() const;
    //size of FE unit payload
    uint16_t getFELength(const uint8_t internalFEUnitNum) const;

  private:
    void appendToBuffer(size_t* pIndexInBuffer, const uint8_t value);
    void appendToBuffer(size_t* pIndexInBuffer,
                        std::vector<uint8_t>::const_iterator start,
                        std::vector<uint8_t>::const_iterator finish);
    std::vector<uint8_t> data_;
    std::vector<uint16_t> feLengths_;
  };

  class FEDBufferPayloadCreator {
  public:
    //specify which FE units and channels should have data generated for them
    //If an FE unit is disabled then the channel is as well. The whole FE payload will be missing.
    //If a channel is disabled then it is considered to have all zeros in the data but will be present in the data
    FEDBufferPayloadCreator(const std::vector<bool>& enabledFEUnits, const std::vector<bool>& enabledChannels);
    //create the payload for a particular mode
    FEDBufferPayload createPayload(FEDReadoutMode mode, uint8_t packetCode, const FEDStripData& data) const;
    FEDBufferPayload operator()(FEDReadoutMode mode, uint8_t packetCode, const FEDStripData& data) const;

  private:
    //fill vector with channel data
    void fillChannelBuffer(std::vector<uint8_t>* channelBuffer,
                           FEDReadoutMode mode,
                           uint8_t packetCode,
                           const FEDStripData::ChannelData& data,
                           const bool channelEnabled) const;
    //fill the vector with channel data for raw mode
    void fillRawChannelBuffer(std::vector<uint8_t>* channelBuffer,
                              const uint8_t packetCode,
                              const FEDStripData::ChannelData& data,
                              const bool channelEnabled,
                              const bool reorderData) const;
    //fill the vector with channel data for zero suppressed modes
    void fillZeroSuppressedChannelBuffer(std::vector<uint8_t>* channelBuffer,
                                         const uint8_t packetCode,
                                         const FEDStripData::ChannelData& data,
                                         const bool channelEnabled) const;
    void fillZeroSuppressedLiteChannelBuffer(std::vector<uint8_t>* channelBuffer,
                                             const FEDStripData::ChannelData& data,
                                             const bool channelEnabled,
                                             const FEDReadoutMode mode) const;
    void fillPreMixRawChannelBuffer(std::vector<uint8_t>* channelBuffer,
                                    const FEDStripData::ChannelData& data,
                                    const bool channelEnabled) const;
    //add the ZS cluster data for the channel to the end of the vector
    void fillClusterData(std::vector<uint8_t>* channelBuffer,
                         uint8_t packetCode,
                         const FEDStripData::ChannelData& data,
                         const FEDReadoutMode mode) const;
    void fillClusterDataPreMixMode(std::vector<uint8_t>* channelBuffer, const FEDStripData::ChannelData& data) const;
    std::vector<bool> feUnitsEnabled_;
    std::vector<bool> channelsEnabled_;
  };

  class FEDBufferGenerator {
  public:
    //constructor in which you can specify the defaults for some parameters
    FEDBufferGenerator(const uint32_t l1ID = 0,
                       const uint16_t bxID = 0,
                       const std::vector<bool>& feUnitsEnabled = std::vector<bool>(FEUNITS_PER_FED, true),
                       const std::vector<bool>& channelsEnabled = std::vector<bool>(FEDCH_PER_FED, true),
                       const FEDReadoutMode readoutMode = READOUT_MODE_ZERO_SUPPRESSED,
                       const FEDHeaderType headerType = HEADER_TYPE_FULL_DEBUG,
                       const FEDBufferFormat bufferFormat = BUFFER_FORMAT_OLD_SLINK,
                       const FEDDAQEventType evtType = DAQ_EVENT_TYPE_PHYSICS);
    //methods to get and set the defaults
    uint32_t getL1ID() const;
    uint16_t getBXID() const;
    FEDReadoutMode getReadoutMode() const;
    FEDHeaderType getHeaderType() const;
    FEDBufferFormat getBufferFormat() const;
    FEDDAQEventType getDAQEventType() const;
    FEDBufferGenerator& setL1ID(const uint32_t newL1ID);
    FEDBufferGenerator& setBXID(const uint16_t newBXID);
    FEDBufferGenerator& setReadoutMode(const FEDReadoutMode newReadoutMode);
    FEDBufferGenerator& setHeaderType(const FEDHeaderType newHeaderType);
    FEDBufferGenerator& setBufferFormat(const FEDBufferFormat newBufferFormat);
    FEDBufferGenerator& setDAQEventType(const FEDDAQEventType newDAQEventType);
    //disabled FE units produce no data at all
    //disabled channels have headers but data is all zeros (raw modes) or have no clusters (ZS)
    bool getFEUnitEnabled(const uint8_t internalFEUnitNumber) const;
    bool getChannelEnabled(const uint8_t internalFEDChannelNumber) const;
    FEDBufferGenerator& setFEUnitEnable(const uint8_t internalFEUnitNumber, const bool enabled);
    FEDBufferGenerator& setChannelEnable(const uint8_t internalFEDChannelNumber, const bool enabled);
    FEDBufferGenerator& setFEUnitEnables(const std::vector<bool>& feUnitsEnabled);
    FEDBufferGenerator& setChannelEnables(const std::vector<bool>& channelsEnabled);
    //make finer changes to defaults for parts of buffer
    //setting source ID in DAQ header and length and CRC in DAQ trailer has no effect since they are set when buffer is built
    FEDDAQHeader& daqHeader();
    FEDDAQTrailer& daqTrailer();
    TrackerSpecialHeader& trackerSpecialHeader();
    FEDFEHeader& feHeader();
    //method to generate buffer
    //unspecified parameters use defaults set by constructor or setters
    //FEDRawData object will be resized to fit buffer and filled
    void generateBuffer(FEDRawData* rawDataObject,
                        const FEDStripData& data,
                        uint16_t sourceID,
                        uint8_t packetCode) const;

  private:
    //method to fill buffer at pointer from pre generated components (only the length and CRC will be changed)
    //at least bufferSizeInBytes(feHeader,payload) must have already been allocated
    static void fillBuffer(uint8_t* pointerToStartOfBuffer,
                           const FEDDAQHeader& daqHeader,
                           const FEDDAQTrailer& daqTrailer,
                           const TrackerSpecialHeader& tkSpecialHeader,
                           const FEDFEHeader& feHeader,
                           const FEDBufferPayload& payload);
    //returns required size of buffer from given components
    static size_t bufferSizeInBytes(const FEDFEHeader& feHeader, const FEDBufferPayload& payload);
    //used to store default values
    FEDDAQHeader defaultDAQHeader_;
    FEDDAQTrailer defaultDAQTrailer_;
    TrackerSpecialHeader defaultTrackerSpecialHeader_;
    std::unique_ptr<FEDFEHeader> defaultFEHeader_;
    std::vector<bool> feUnitsEnabled_;
    std::vector<bool> channelsEnabled_;
  };

  //
  // Inline function definitions
  //

  //FEDStripData

  inline FEDStripData::FEDStripData(const std::vector<ChannelData>& data) : data_(data) {}

  //re-use const method
  inline FEDStripData::ChannelData& FEDStripData::channel(const uint8_t internalFEDChannelNum) {
    return const_cast<FEDStripData::ChannelData&>(std::as_const(*this).channel(internalFEDChannelNum));
  }

  inline FEDStripData::ChannelData& FEDStripData::operator[](const uint8_t internalFEDChannelNum) {
    return channel(internalFEDChannelNum);
  }

  inline const FEDStripData::ChannelData& FEDStripData::operator[](const uint8_t internalFEDChannelNum) const {
    return channel(internalFEDChannelNum);
  }

  inline FEDStripData::ChannelData::ChannelData(bool dataIsAlreadyConvertedTo8Bit,
                                                const size_t numberOfSamples,
                                                const std::pair<uint16_t, uint16_t> medians)
      : medians_(medians), data_(numberOfSamples, 0), dataIs8Bit_(dataIsAlreadyConvertedTo8Bit) {}

  inline size_t FEDStripData::ChannelData::size() const { return data_.size(); }

  inline const uint16_t& FEDStripData::ChannelData::operator[](const size_t sampleNumber) const {
    return data_[sampleNumber];
  }

  //re-use const method
  inline uint16_t& FEDStripData::ChannelData::operator[](const size_t sampleNumber) {
    return const_cast<uint16_t&>(std::as_const(*this)[sampleNumber]);
  }

  inline uint16_t FEDStripData::ChannelData::getSample(const uint16_t sampleNumber) const {
    //try {
    //  return data_.at(sampleNumber);
    //} catch (const std::out_of_range&) {
    //  std::ostringstream ss;
    //  ss << "Sample index out of range. "
    //     << "Requesting sample " << sampleNumber
    //     << " when channel has only " << data_.size() << " samples.";
    //  throw cms::Exception("FEDBufferGenerator") << ss.str();
    //}
    return data_[sampleNumber];
  }

  inline uint8_t FEDStripData::ChannelData::get8BitSample(const uint16_t sampleNumber, uint16_t nBotBitsToDrop) const {
    uint16_t sample = getSample(sampleNumber) >> nBotBitsToDrop;
    if (dataIs8Bit_) {
      return (0xFF & sample);
    } else {
      if (sample < 0xFE)
        return sample;
      else if (sample == 0x3FF)
        return 0xFF;
      else
        return 0xFE;
    }
  }

  inline uint16_t FEDStripData::ChannelData::get10BitSample(const uint16_t sampleNumber) const {
    if (dataIs8Bit_) {
      return (0xFF & getSample(sampleNumber));
    } else {
      const uint16_t sample = getSample(sampleNumber);
      if (sample < 0x3FF)
        return sample;
      else
        return 0x3FF;
    }
  }

  inline std::pair<uint16_t, uint16_t> FEDStripData::ChannelData::getMedians() const { return medians_; }

  inline void FEDStripData::ChannelData::setMedians(const std::pair<uint16_t, uint16_t> values) { medians_ = values; }

  //FEDBufferPayload

  inline size_t FEDBufferPayload::lengthInBytes() const { return data_.size(); }

  inline void FEDBufferPayload::appendToBuffer(size_t* pIndexInBuffer, const uint8_t value) {
    data_[((*pIndexInBuffer)++) ^ 7] = value;
  }

  inline void FEDBufferPayload::appendToBuffer(size_t* pIndexInBuffer,
                                               std::vector<uint8_t>::const_iterator start,
                                               std::vector<uint8_t>::const_iterator finish) {
    for (std::vector<uint8_t>::const_iterator iVal = start; iVal != finish; iVal++) {
      appendToBuffer(pIndexInBuffer, *iVal);
    }
  }

  //FEDBufferPayloadCreator

  inline FEDBufferPayloadCreator::FEDBufferPayloadCreator(const std::vector<bool>& feUnitsEnabled,
                                                          const std::vector<bool>& channelsEnabled)
      : feUnitsEnabled_(feUnitsEnabled), channelsEnabled_(channelsEnabled) {}

  inline FEDBufferPayload FEDBufferPayloadCreator::operator()(FEDReadoutMode mode,
                                                              uint8_t packetCode,
                                                              const FEDStripData& data) const {
    return createPayload(mode, packetCode, data);
  }

  //FEDBufferGenerator

  inline uint32_t FEDBufferGenerator::getL1ID() const { return defaultDAQHeader_.l1ID(); }

  inline uint16_t FEDBufferGenerator::getBXID() const { return defaultDAQHeader_.bxID(); }

  inline FEDReadoutMode FEDBufferGenerator::getReadoutMode() const {
    return defaultTrackerSpecialHeader_.readoutMode();
  }

  inline FEDHeaderType FEDBufferGenerator::getHeaderType() const { return defaultTrackerSpecialHeader_.headerType(); }

  inline FEDBufferFormat FEDBufferGenerator::getBufferFormat() const {
    return defaultTrackerSpecialHeader_.bufferFormat();
  }

  inline FEDDAQEventType FEDBufferGenerator::getDAQEventType() const { return defaultDAQHeader_.eventType(); }

  inline FEDBufferGenerator& FEDBufferGenerator::setL1ID(const uint32_t newL1ID) {
    defaultDAQHeader_.setL1ID(newL1ID);
    return *this;
  }

  inline FEDBufferGenerator& FEDBufferGenerator::setBXID(const uint16_t newBXID) {
    defaultDAQHeader_.setBXID(newBXID);
    return *this;
  }

  inline FEDBufferGenerator& FEDBufferGenerator::setReadoutMode(const FEDReadoutMode newReadoutMode) {
    defaultTrackerSpecialHeader_.setReadoutMode(newReadoutMode);
    return *this;
  }

  inline FEDBufferGenerator& FEDBufferGenerator::setHeaderType(const FEDHeaderType newHeaderType) {
    defaultTrackerSpecialHeader_.setHeaderType(newHeaderType);
    return *this;
  }

  inline FEDBufferGenerator& FEDBufferGenerator::setBufferFormat(const FEDBufferFormat newBufferFormat) {
    defaultTrackerSpecialHeader_.setBufferFormat(newBufferFormat);
    return *this;
  }

  inline FEDBufferGenerator& FEDBufferGenerator::setDAQEventType(const FEDDAQEventType newDAQEventType) {
    defaultDAQHeader_.setEventType(newDAQEventType);
    return *this;
  }

  inline FEDDAQHeader& FEDBufferGenerator::daqHeader() { return defaultDAQHeader_; }

  inline FEDDAQTrailer& FEDBufferGenerator::daqTrailer() { return defaultDAQTrailer_; }

  inline TrackerSpecialHeader& FEDBufferGenerator::trackerSpecialHeader() { return defaultTrackerSpecialHeader_; }

  inline FEDFEHeader& FEDBufferGenerator::feHeader() { return *defaultFEHeader_; }

  inline size_t FEDBufferGenerator::bufferSizeInBytes(const FEDFEHeader& feHeader, const FEDBufferPayload& payload) {
    //FE header + payload + tracker special header + daq header + daq trailer
    return feHeader.lengthInBytes() + payload.lengthInBytes() + 8 + 8 + 8;
  }

}  // namespace sistrip

#endif  //ndef EventFilter_SiStripRawToDigi_FEDBufferGenerator_H