CMS 3D CMS Logo

RawDataUnpacker.cc
Go to the documentation of this file.
1 /****************************************************************************
2 *
3 * This is a part of TOTEM offline software.
4 * Authors:
5 * Jan Kašpar (jan.kaspar@gmail.com)
6 * Nicola Minafra
7 *
8 ****************************************************************************/
9 
13 
14 //----------------------------------------------------------------------------------------------------
15 
16 using namespace std;
17 using namespace edm;
18 using namespace ctpps;
19 
20 //----------------------------------------------------------------------------------------------------
21 
22 RawDataUnpacker::RawDataUnpacker(const edm::ParameterSet& iConfig) :
23  verbosity(iConfig.getUntrackedParameter<unsigned int>("verbosity", 0))
24 {}
25 
26 //----------------------------------------------------------------------------------------------------
27 
28 int RawDataUnpacker::run(int fedId, const FEDRawData &data, vector<TotemFEDInfo> &fedInfoColl, SimpleVFATFrameCollection &coll) const
29 {
30  unsigned int size_in_words = data.size() / 8; // bytes -> words
31  if (size_in_words < 2)
32  {
33  if (verbosity)
34  LogWarning("Totem") << "Error in RawDataUnpacker::run > " <<
35  "Data in FED " << fedId << " too short (size = " << size_in_words << " words).";
36  return 1;
37  }
38 
39  fedInfoColl.push_back(TotemFEDInfo(fedId));
40 
41  return processOptoRxFrame((const word *) data.data(), size_in_words, fedInfoColl.back(), &coll);
42 }
43 
44 //----------------------------------------------------------------------------------------------------
45 
46 int RawDataUnpacker::processOptoRxFrame(const word *buf, unsigned int frameSize, TotemFEDInfo &fedInfo, SimpleVFATFrameCollection *fc) const
47 {
48  // get OptoRx metadata
49  unsigned long long head = buf[0];
50  unsigned long long foot = buf[frameSize-1];
51 
52  fedInfo.setHeader(head);
53  fedInfo.setFooter(foot);
54 
55  unsigned int boe = (head >> 60) & 0xF;
56  unsigned int h0 = (head >> 0) & 0xF;
57 
58  unsigned long lv1 = (head >> 32) & 0xFFFFFF;
59  unsigned long bx = (head >> 20) & 0xFFF;
60  unsigned int optoRxId = (head >> 8) & 0xFFF;
61  unsigned int fov = (head >> 4) & 0xF;
62 
63  unsigned int eoe = (foot >> 60) & 0xF;
64  unsigned int f0 = (foot >> 0) & 0xF;
65  unsigned int fSize = (foot >> 32) & 0x3FF;
66 
67  // check header and footer structure
68  if (boe != 5 || h0 != 0 || eoe != 10 || f0 != 0 || fSize != frameSize)
69  {
70  if (verbosity)
71  LogWarning("Totem") << "Error in RawDataUnpacker::processOptoRxFrame > " << "Wrong structure of OptoRx header/footer: "
72  << "BOE=" << boe << ", H0=" << h0 << ", EOE=" << eoe << ", F0=" << f0
73  << ", size (OptoRx)=" << fSize << ", size (DATE)=" << frameSize
74  << ". OptoRxID=" << optoRxId << ". Skipping frame." << endl;
75  return 0;
76  }
77 
78  LogDebug( "Totem" ) << "RawDataUnpacker::processOptoRxFrame: "
79  << "OptoRxId = " << optoRxId << ", BX = " << bx << ", LV1 = " << lv1 << ", frameSize = " << frameSize;
80 
82  {
83  processOptoRxFrameSampic(buf, frameSize, fedInfo, fc);
84  return 0;
85  }
86 
87  // parallel or serial transmission?
88  switch (fov) {
89  case 1:
90  return processOptoRxFrameSerial(buf, frameSize, fc);
91  case 2:
92  case 3:
93  return processOptoRxFrameParallel(buf, frameSize, fedInfo, fc);
94  default: break;
95  }
96 
97  if (verbosity)
98  LogWarning("Totem") << "Error in RawDataUnpacker::processOptoRxFrame > " << "Unknown FOV = " << fov << endl;
99 
100  return 0;
101 }
102 
103 //----------------------------------------------------------------------------------------------------
104 
105 int RawDataUnpacker::processOptoRxFrameSerial(const word *buf, unsigned int frameSize, SimpleVFATFrameCollection *fc) const
106 {
107  // get OptoRx metadata
108  unsigned int optoRxId = (buf[0] >> 8) & 0xFFF;
109 
110  // get number of subframes
111  unsigned int subFrames = (frameSize - 2) / 194;
112 
113  // process all sub-frames
114  unsigned int errorCounter = 0;
115  for (unsigned int r = 0; r < subFrames; ++r)
116  {
117  for (unsigned int c = 0; c < 4; ++c)
118  {
119  unsigned int head = (buf[1 + 194 * r] >> (16 * c)) & 0xFFFF;
120  unsigned int foot = (buf[194 + 194 * r] >> (16 * c)) & 0xFFFF;
121 
122  LogDebug( "Totem" )
123  << "r = " << r << ", c = " << c << ": "
124  << "S = " << ( head & 0x1 ) << ", BOF = " << ( head >> 12 ) << ", EOF = " << ( foot >> 12 )
125  << ", ID = " << ( ( head >> 8 ) & 0xF ) << ", ID' = " << ( ( foot >> 8) & 0xF );
126 
127  // stop if this GOH is NOT active
128  if ((head & 0x1) == 0)
129  continue;
130 
131  LogDebug( "Totem" )
132  << "Header active (" << head << " -> " << ( head & 0x1 ) << ").";
133 
134  // check structure
135  if (head >> 12 != 0x4 || foot >> 12 != 0xB || ((head >> 8) & 0xF) != ((foot >> 8) & 0xF))
136  {
137  std::ostringstream oss;
138  if (head >> 12 != 0x4)
139  oss << "\n\tHeader is not 0x4 as expected (0x" << std::hex << head << ").";
140  if (foot >> 12 != 0xB)
141  oss << "\n\tFooter is not 0xB as expected (0x" << std::hex << foot << ").";
142  if (((head >> 8) & 0xF) != ((foot >> 8) & 0xF))
143  oss << "\n\tIncompatible GOH IDs in header (0x" << std::hex << ( ( head >> 8 ) & 0xF ) << ") and footer (0x" << std::hex << ( ( foot >> 8 ) & 0xF ) << ").";
144 
145  if (verbosity)
146  LogWarning("Totem") << "Error in RawDataUnpacker::processOptoRxFrame > " << "Wrong payload structure (in GOH block row " << r <<
147  " and column " << c << ") in OptoRx frame ID " << optoRxId << ". GOH block omitted." << oss.str() << endl;
148 
149  errorCounter++;
150  continue;
151  }
152 
153  // allocate memory for VFAT frames
154  unsigned int goh = (head >> 8) & 0xF;
155  vector<VFATFrame::word*> dataPtrs;
156  for (unsigned int fi = 0; fi < 16; fi++)
157  {
158  TotemFramePosition fp(0, 0, optoRxId, goh, fi);
159  dataPtrs.push_back( fc->InsertEmptyFrame(fp)->getData() );
160  }
161 
162  LogDebug( "Totem" )
163  << "transposing GOH block at prefix: " << ( optoRxId*192+goh*16 ) << ", dataPtrs = " << dataPtrs;
164 
165  // deserialization
166  for (int i = 0; i < 192; i++)
167  {
168  int iword = 11 - i / 16; // number of current word (11...0)
169  int ibit = 15 - i % 16; // number of current bit (15...0)
170  unsigned int w = (buf[i + 2 + 194 * r] >> (16 * c)) & 0xFFFF;
171 
172  // Fill the current bit of the current word of all VFAT frames
173  for (int idx = 0; idx < 16; idx++)
174  {
175  if (w & (1 << idx))
176  dataPtrs[idx][iword] |= (1 << ibit);
177  }
178  }
179  }
180  }
181 
182  return errorCounter;
183 }
184 
185 //----------------------------------------------------------------------------------------------------
186 
187 int RawDataUnpacker::processOptoRxFrameParallel(const word *buf, unsigned int frameSize, TotemFEDInfo &fedInfo, SimpleVFATFrameCollection *fc) const
188 {
189  // get OptoRx metadata
190  unsigned long long head = buf[0];
191  unsigned int optoRxId = (head >> 8) & 0xFFF;
192 
193  // recast data as buffer or 16bit words, skip header
194  const uint16_t *payload = (const uint16_t *) (buf + 1);
195 
196  // read in OrbitCounter block
197  const uint32_t *ocPtr = (const uint32_t *) payload;
198  fedInfo.setOrbitCounter(*ocPtr);
199  payload += 2;
200 
201  // size in 16bit words, without header, footer and orbit counter block
202  unsigned int nWords = (frameSize-2) * 4 - 2;
203 
204  // process all VFAT data
205  for (unsigned int offset = 0; offset < nWords;)
206  {
207  unsigned int wordsProcessed = processVFATDataParallel(payload + offset, nWords, optoRxId, fc);
208  offset += wordsProcessed;
209  }
210 
211  return 0;
212 }
213 
214 //----------------------------------------------------------------------------------------------------
215 
216 int RawDataUnpacker::processVFATDataParallel(const uint16_t *buf, unsigned int maxWords, unsigned int optoRxId, SimpleVFATFrameCollection *fc) const
217 {
218  // start counting processed words
219  unsigned int wordsProcessed = 1;
220 
221  // padding word? skip it
222  if (buf[0] == 0xFFFF)
223  return wordsProcessed;
224 
225  // check header flag
226  unsigned int hFlag = (buf[0] >> 8) & 0xFF;
227  if (hFlag != vmCluster && hFlag != vmRaw && hFlag != vmDiamondCompact)
228  {
229  if (verbosity)
230  LogWarning("Totem") << "Error in RawDataUnpacker::processVFATDataParallel > "
231  << "Unknown header flag " << hFlag << ". Skipping this word." << endl;
232  return wordsProcessed;
233  }
234 
235  // compile frame position
236  // NOTE: DAQ group uses terms GOH and fiber in the other way
237  unsigned int gohIdx = (buf[0] >> 4) & 0xF;
238  unsigned int fiberIdx = (buf[0] >> 0) & 0xF;
239  TotemFramePosition fp(0, 0, optoRxId, gohIdx, fiberIdx);
240 
241  // prepare temporary VFAT frame
242  VFATFrame f;
243  VFATFrame::word *fd = f.getData();
244 
245  // copy footprint, BC, EC, Flags, ID, if they exist
246  uint8_t presenceFlags = 0;
247 
248  if (((buf[wordsProcessed] >> 12) & 0xF) == 0xA) // BC
249  {
250  presenceFlags |= 0x1;
251  fd[11] = buf[wordsProcessed];
252  wordsProcessed++;
253  }
254 
255  if (((buf[wordsProcessed] >> 12) & 0xF) == 0xC) // EC, flags
256  {
257  presenceFlags |= 0x2;
258  fd[10] = buf[wordsProcessed];
259  wordsProcessed++;
260  }
261 
262  if (((buf[wordsProcessed] >> 12) & 0xF) == 0xE) // ID
263  {
264  presenceFlags |= 0x4;
265  fd[9] = buf[wordsProcessed];
266  wordsProcessed++;
267  }
268 
269  // save offset where channel data start
270  unsigned int dataOffset = wordsProcessed;
271 
272  // find trailer
273  switch (hFlag) {
274  case vmCluster: {
275  unsigned int nCl = 0;
276  while ( (buf[wordsProcessed + nCl] >> 12) != 0xF && ( wordsProcessed + nCl < maxWords ) ) nCl++;
277  wordsProcessed += nCl;
278  } break;
279  case vmRaw:
280  wordsProcessed += 9;
281  break;
282  case vmDiamondCompact: {
283  wordsProcessed--;
284  while ( (buf[wordsProcessed] & 0xFFF0)!= 0xF000 && ( wordsProcessed < maxWords ) ) wordsProcessed++;
285  } break;
286  }
287 
288  // process trailer
289  unsigned int tSig = buf[wordsProcessed] >> 12;
290  unsigned int tErrFlags = (buf[wordsProcessed] >> 8) & 0xF;
291  unsigned int tSize = buf[wordsProcessed] & 0xFF;
292 
293  f.setDAQErrorFlags(tErrFlags);
294 
295  // consistency checks
296  bool skipFrame = false;
297  stringstream ess;
298 
299  if (tSig != 0xF)
300  {
301  if (verbosity)
302  ess << " Wrong trailer signature (" << tSig << ")." << endl;
303  skipFrame = true;
304  }
305 
306  if (tErrFlags != 0)
307  {
308  if (verbosity)
309  ess << " Error flags not zero (" << tErrFlags << ")." << endl;
310  skipFrame = true;
311  }
312 
313  wordsProcessed++;
314 
315  if (tSize != wordsProcessed)
316  {
317  if (verbosity)
318  ess << " Trailer size (" << tSize << ") does not match with words processed (" << wordsProcessed << ")." << endl;
319  skipFrame = true;
320  }
321 
322  if (skipFrame)
323  {
324  if (verbosity)
325  LogWarning("Totem") << "Error in RawDataUnpacker::processVFATDataParallel > Frame at " << fp
326  << " has the following problems and will be skipped.\n" << endl << ess.rdbuf();
327 
328  return wordsProcessed;
329  }
330 
331  // get channel data - cluster mode
332  if (hFlag == vmCluster)
333  {
334  for (unsigned int nCl = 0; (buf[dataOffset + nCl] >> 12) != 0xF && ( dataOffset + nCl < maxWords ); ++nCl)
335  {
336  const uint16_t &w = buf[dataOffset + nCl];
337  unsigned int upperBlock = w >> 8;
338  unsigned int clSize = upperBlock & 0x7F;
339  unsigned int clPos = (w >> 0) & 0xFF;
340 
341  // special case: upperBlock=0xD0 => numberOfClusters
342  if (upperBlock == 0xD0)
343  {
344  presenceFlags |= 0x10;
345  f.setNumberOfClusters(clPos);
346  continue;
347  }
348 
349  // special case: size=0 means chip full
350  if (clSize == 0)
351  clSize = 128;
352 
353  // activate channels
354  // convention - range <pos, pos-size+1>
355  signed int chMax = clPos;
356  signed int chMin = clPos - clSize + 1;
357  if (chMax < 0 || chMax > 127 || chMin < 0 || chMin > 127 || chMin > chMax)
358  {
359  if (verbosity)
360  LogWarning("Totem") << "Error in RawDataUnpacker::processVFATDataParallel > "
361  << "Invalid cluster (pos=" << clPos
362  << ", size=" << clSize << ", min=" << chMin << ", max=" << chMax << ") at " << fp
363  <<". Skipping this cluster." << endl;
364  continue;
365  }
366 
367  for (signed int ch = chMin; ch <= chMax; ch++)
368  {
369  unsigned int wi = ch / 16;
370  unsigned int bi = ch % 16;
371  fd[wi + 1] |= (1 << bi);
372  }
373  }
374  }
375 
376  // get channel data and CRC - raw mode
377  if (hFlag == vmRaw)
378  {
379  for (unsigned int i = 0; i < 8; i++)
380  fd[8 - i] = buf[dataOffset + i];
381 
382  // copy CRC
383  presenceFlags |= 0x8;
384  fd[0] = buf[dataOffset + 8];
385  }
386 
387  // get channel data for diamond compact mode
388  if (hFlag == vmDiamondCompact)
389  {
390  for (unsigned int i = 1; (buf[i+1] & 0xFFF0)!= 0xF000 && ( i+1 < maxWords ); i++) {
391  if ( ( buf[i] & 0xF000 ) == VFAT_HEADER_OF_EC ) {
392  // Event Counter word is found
393  fd[10] = buf[i];
394  continue;
395  }
396  switch ( buf[i] & 0xF800 ) {
398  // word 2 of the diamond VFAT frame is found
399  fd[1] = buf[i + 1];
400  fd[2] = buf[i];
401  break;
403  // word 3 of the diamond VFAT frame is found
404  fd[3] = buf[i];
405  fd[4] = buf[i - 1];
406  break;
408  // word 5 of the diamond VFAT frame is found
409  fd[5] = buf[i];
410  fd[6] = buf[i - 1];
411  break;
413  // word 7 of the diamond VFAT frame is found
414  fd[7] = buf[i];
415  fd[8] = buf[i - 1];
416  break;
417  default:
418  break;
419  }
420  presenceFlags |= 0x8;
421  }
422  }
423 
424  // save frame to output
425  f.setPresenceFlags(presenceFlags);
426  fc->Insert(fp, f);
427 
428  return wordsProcessed;
429 }
430 
431 //----------------------------------------------------------------------------------------------------
432 
433 int RawDataUnpacker::processOptoRxFrameSampic(const word *buf, unsigned int frameSize, TotemFEDInfo &fedInfo, SimpleVFATFrameCollection *fc) const
434 {
435  unsigned int optoRxId = (buf[0] >> 8) & 0xFFF;
436 
437  LogDebug( "RawDataUnpacker::processOptoRxFrameSampic" )
438  << "Processing sampic frame: OptoRx " << optoRxId << " framesize: " << frameSize;
439 
440  unsigned int orbitCounterVFATFrameWords = 6;
441  unsigned int sizeofVFATPayload = 12;
442 
443  const VFATFrame::word *VFATFrameWordPtr = (const VFATFrame::word *) buf;
444  VFATFrameWordPtr += orbitCounterVFATFrameWords - 1;
445 
446  LogDebug( "RawDataUnpacker::processOptoRxFrameSampic" )
447  << "Framesize: " << frameSize << "\tframes: " << frameSize/(sizeofVFATPayload+2);
448 
449  unsigned int nWords = (frameSize-2) * 4 - 2;
450 
451  for (unsigned int i=1; i*(sizeofVFATPayload+2)<nWords; ++i) {
452  // compile frame position
453  // NOTE: DAQ group uses terms GOH and fiber in the other way
454  unsigned int fiberIdx = (*(++VFATFrameWordPtr)) & 0xF;
455  unsigned int gohIdx = (*VFATFrameWordPtr >> 4) & 0xF;
456  TotemFramePosition fp(0, 0, optoRxId, gohIdx, fiberIdx);
457 
458  LogDebug( "RawDataUnpacker::processOptoRxFrameSampic" )
459  << "OptoRx: " << optoRxId << " Goh: " << gohIdx << " Idx: " << fiberIdx;
460 
461  // prepare temporary VFAT frame
462  VFATFrame frame(++VFATFrameWordPtr);
463  VFATFrameWordPtr += sizeofVFATPayload;
464 
465  if ( *(VFATFrameWordPtr) != 0xf00e ) {
466  edm::LogError( "RawDataUnpacker::processOptoRxFrameSampic" )
467  << "Wrong trailer " << *VFATFrameWordPtr;
468  continue;
469  }
470  // save frame to output
471  frame.setPresenceFlags(1);
472  fc->Insert(fp, frame);
473 
474  LogDebug( "RawDataUnpacker::processOptoRxFrameSampic" )
475  << "Trailer: " << std::hex << *VFATFrameWordPtr;
476  }
477 
478  return 0;
479 }
480 
#define LogDebug(id)
OptoRx headers and footers.
Definition: TotemFEDInfo.h:17
int processVFATDataParallel(const uint16_t *buf, unsigned int maxWords, unsigned int OptoRxId, SimpleVFATFrameCollection *fc) const
Process data from one VFAT in parallel (new) format.
int processOptoRxFrameParallel(const word *buffer, unsigned int frameSize, TotemFEDInfo &fedInfo, SimpleVFATFrameCollection *fc) const
Process one Opto-Rx frame in parallel (new) format.
static constexpr unsigned int VFAT_DIAMOND_HEADER_OF_WORD_7
VFATFrame::word * getData()
Definition: VFATFrame.h:40
const double w
Definition: UKUtility.cc:23
int processOptoRxFrame(const word *buf, unsigned int frameSize, TotemFEDInfo &fedInfo, SimpleVFATFrameCollection *fc) const
Process one Opto-Rx (or LoneG) frame.
int run(int fedId, const FEDRawData &data, std::vector< TotemFEDInfo > &fedInfoColl, SimpleVFATFrameCollection &coll) const
Unpack data from FED with fedId into `coll&#39; collection.
static constexpr unsigned int VFAT_DIAMOND_HEADER_OF_WORD_2
uint16_t word
Definition: VFATFrame.h:22
int processOptoRxFrameSampic(const word *buffer, unsigned int frameSize, TotemFEDInfo &fedInfo, SimpleVFATFrameCollection *fc) const
Process one Opto-Rx frame that contains SAMPIC frames.
static constexpr unsigned int VFAT_HEADER_OF_EC
size_t size() const
Lenght of the data buffer in bytes.
Definition: FEDRawData.h:47
static constexpr unsigned int VFAT_DIAMOND_HEADER_OF_WORD_3
int processOptoRxFrameSerial(const word *buffer, unsigned int frameSize, SimpleVFATFrameCollection *fc) const
Process one Opto-Rx frame in serial (old) format.
static constexpr unsigned int VFAT_DIAMOND_HEADER_OF_WORD_5
void setOrbitCounter(uint32_t _oc)
Definition: TotemFEDInfo.h:35
void setFooter(uint64_t _f)
Definition: TotemFEDInfo.h:38
double f[11][100]
VFATFrame * InsertEmptyFrame(TotemFramePosition index)
inserts an empty (default) frame to the given position and returns pointer to the frame ...
JetCorrectorParametersCollection coll
Definition: classes.h:10
void setPresenceFlags(uint8_t v)
Sets presence flags.
Definition: VFATFrame.h:82
void setDAQErrorFlags(uint8_t v)
Sets DAQ error flags.
Definition: VFATFrame.h:118
HLT enums.
char data[epos_bytes_allocation]
Definition: EPOS_Wrapper.h:82
const unsigned char * data() const
Return a const pointer to the beginning of the data buffer.
Definition: FEDRawData.cc:28
void setHeader(uint64_t _h)
Definition: TotemFEDInfo.h:27
void Insert(const TotemFramePosition &index, const VFATFrame &frame)
void setNumberOfClusters(uint8_t v)
Definition: VFATFrame.h:123