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
#include "EventFilter/CSCTFRawToDigi/src/CSCTFEvent.h"
#include "EventFilter/CSCTFRawToDigi/src/CSCSPHeader.h"
#include <cstring>
#include <stdexcept>

unsigned int CSCTFEvent::unpack(const unsigned short *buf, unsigned int length) {
  // Clean up
  nRecords = 0;
  bzero(sp, sizeof(sp));

  // Make sure that we are running right platform (can't imagine opposite)
  if (sizeof(unsigned long long) != 8 || sizeof(unsigned short) != 2)
    throw std::runtime_error(std::string("Wrong platform: sizeof(unsigned long long)!=8 || sizeof(unsigned short)!=2"));

  // Type of coruptions
  unsigned long coruptions = 0;

  // Combine 64-bit ddu word for simlicity and efficiency
  const unsigned long long *dduWord = reinterpret_cast<const unsigned long long *>(buf);
  unsigned long long word_1 = 0, word_2 = 0;
  // 'length' counts ddu words now
  length /= sizeof(unsigned long long) / sizeof(unsigned short);
  // Set of markers
  bool spHeader = false, spTrailer = false;
  unsigned long spWordCount = 0, spWordCountExpected = 0;

  // Run through the buffer and check its structure
  unsigned int index = 0;
  while (index < length) {
    word_1 = word_2;          // delay by 1 DDU word
    word_2 = dduWord[index];  // current DDU word

    if (spHeader && !spTrailer)
      spWordCount++;

    if ((word_1 & 0xF000F000F000F000LL) == 0x9000900090009000LL &&
        (word_2 & 0xF000F000F000F000LL) == 0xA000A000A000A000LL) {
      if (spHeader) {
        coruptions |= MISSING_TRAILER;
        break;
      }
      spHeader = true;
      spTrailer = false;
      // number of 64-bit words between header and trailer
      spWordCount = 0;
      spWordCountExpected = 0;
      // need header to calculate expected word count
      CSCSPHeader header;
      const unsigned short *spWord = reinterpret_cast<const unsigned short *>(&dduWord[index - 1]);
      // we are here because we have a header => we are safe from crash instantiating one
      header.unpack(spWord);

      // Counter block exists only in format version 4.3 and higher
      if (header.format_version() && !header.empty()) {
        if (length > index + 1) {
          spWord += 4;
        } else {
          coruptions |= OUT_OF_BUFFER;
          break;
        }
      }

      // Calculate expected record length (internal variable 'shift' counts 16-bit words)
      for (unsigned short tbin = 0, shift = 0; tbin < header.nTBINs() && !header.empty(); tbin++) {
        // check if didn't pass end of event, keep in mind that 'length', 'index', and 'spWordCountExpected' counts 64-bit words
        if (length <= index + spWordCountExpected + 2) {
          coruptions |= OUT_OF_BUFFER;
          break;
        } else {
          // In the format version >=5.3 with zero_supression
          if (header.format_version() >= 3 && header.suppression()) {
            //  we seek the loop index untill it matches the current non-empty tbin
            if (((spWord[shift + 7] >> 8) & 0x7) != tbin + 1)
              continue;
            //  otherwise there may be no more non-empty tbins and we ran into the trailer
            if ((spWord[shift + 0] & 0xF000) == 0xF000 && (spWord[shift + 1] & 0xF000) == 0xF000 &&
                (spWord[shift + 2] & 0xF000) == 0xF000 && (spWord[shift + 3] & 0xF000) == 0xF000 &&
                (spWord[shift + 4] & 0xF000) == 0xE000 && (spWord[shift + 5] & 0xF000) == 0xE000 &&
                (spWord[shift + 6] & 0xF000) == 0xE000 && (spWord[shift + 7] & 0xF000) == 0xE000)
              break;
          }

          // Data Block Header always exists if we got so far
          spWordCountExpected += 2;
          // 15 ME data blocks
          for (unsigned int me_block = 0; me_block < 15; me_block++)
            if (header.active() & (1 << (me_block / 3)) &&
                (!header.suppression() || spWord[shift + 0] & (1 << me_block)))
              spWordCountExpected += 1;
          // 2 MB data blocks
          for (unsigned int mb_block = 0; mb_block < 2; mb_block++)
            if (header.active() & 0x20 && (!header.suppression() || spWord[shift + 1] & (1 << (mb_block + 12))))
              spWordCountExpected += 1;
          // 3 SP data blocks
          for (unsigned int sp_block = 0; sp_block < 3; sp_block++)
            if (header.active() & 0x40 && (!header.suppression() || spWord[shift + 1] & (0xF << (sp_block * 4))))
              spWordCountExpected += 1;

          // multiply by 4 because 'shift' is a 16-bit array index and 'spWordCountExpected' conuts 64-bit words
          shift = spWordCountExpected * 4;
        }
      }

      // Counter block exists only in format version 4.3 and higher
      if (header.format_version() && !header.empty())
        spWordCountExpected += 1;

      if (coruptions & OUT_OF_BUFFER)
        break;
    }

    //if( !spHeader && spTrailer ) coruptions |= NONSENSE; ///???

    if ((word_1 & 0xF000F000F000F000LL) == 0xF000F000F000F000LL &&
        (word_2 & 0xF000F000F000F000LL) == 0xE000E000E000E000LL) {
      if (spTrailer) {
        coruptions |= MISSING_HEADER;
        break;
      }
      spHeader = false;
      spTrailer = true;

      if (spWordCount != spWordCountExpected + 2) {
        coruptions |= WORD_COUNT;
        break;
      }
      // main unpacking
      const unsigned short *spWord = reinterpret_cast<const unsigned short *>(&dduWord[index - spWordCount - 1]);
      if (nRecords < 12) {
        if (sp[nRecords++].unpack(spWord))
          coruptions |= NONSENSE;
      } else {
        coruptions |= CONFIGURATION;
        break;
      }
    }

    index++;
  }

  return coruptions;
}