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 
163  LogDebug( "Totem" ).log( [&] (auto& l) {
164  l << "transposing GOH block at prefix: " << ( optoRxId*192+goh*16 ) << ", dataPtrs = ";
165  for(auto p: dataPtrs) {
166  l<< p<<" ";
167  }
168  });
169  // deserialization
170  for (int i = 0; i < 192; i++)
171  {
172  int iword = 11 - i / 16; // number of current word (11...0)
173  int ibit = 15 - i % 16; // number of current bit (15...0)
174  unsigned int w = (buf[i + 2 + 194 * r] >> (16 * c)) & 0xFFFF;
175 
176  // Fill the current bit of the current word of all VFAT frames
177  for (int idx = 0; idx < 16; idx++)
178  {
179  if (w & (1 << idx))
180  dataPtrs[idx][iword] |= (1 << ibit);
181  }
182  }
183  }
184  }
185 
186  return errorCounter;
187 }
188 
189 //----------------------------------------------------------------------------------------------------
190 
191 int RawDataUnpacker::processOptoRxFrameParallel(const word *buf, unsigned int frameSize, TotemFEDInfo &fedInfo, SimpleVFATFrameCollection *fc) const
192 {
193  // get OptoRx metadata
194  unsigned long long head = buf[0];
195  unsigned int optoRxId = (head >> 8) & 0xFFF;
196 
197  // recast data as buffer or 16bit words, skip header
198  const uint16_t *payload = (const uint16_t *) (buf + 1);
199 
200  // read in OrbitCounter block
201  const uint32_t *ocPtr = (const uint32_t *) payload;
202  fedInfo.setOrbitCounter(*ocPtr);
203  payload += 2;
204 
205  // size in 16bit words, without header, footer and orbit counter block
206  unsigned int nWords = (frameSize-2) * 4 - 2;
207 
208  // process all VFAT data
209  for (unsigned int offset = 0; offset < nWords;)
210  {
211  unsigned int wordsProcessed = processVFATDataParallel(payload + offset, nWords, optoRxId, fc);
212  offset += wordsProcessed;
213  }
214 
215  return 0;
216 }
217 
218 //----------------------------------------------------------------------------------------------------
219 
220 int RawDataUnpacker::processVFATDataParallel(const uint16_t *buf, unsigned int maxWords, unsigned int optoRxId, SimpleVFATFrameCollection *fc) const
221 {
222  // start counting processed words
223  unsigned int wordsProcessed = 1;
224 
225  // padding word? skip it
226  if (buf[0] == 0xFFFF)
227  return wordsProcessed;
228 
229  // check header flag
230  unsigned int hFlag = (buf[0] >> 8) & 0xFF;
231  if (hFlag != vmCluster && hFlag != vmRaw && hFlag != vmDiamondCompact)
232  {
233  if (verbosity)
234  LogWarning("Totem") << "Error in RawDataUnpacker::processVFATDataParallel > "
235  << "Unknown header flag " << hFlag << ". Skipping this word." << endl;
236  return wordsProcessed;
237  }
238 
239  // compile frame position
240  // NOTE: DAQ group uses terms GOH and fiber in the other way
241  unsigned int gohIdx = (buf[0] >> 4) & 0xF;
242  unsigned int fiberIdx = (buf[0] >> 0) & 0xF;
243  TotemFramePosition fp(0, 0, optoRxId, gohIdx, fiberIdx);
244 
245  // prepare temporary VFAT frame
246  VFATFrame f;
247  VFATFrame::word *fd = f.getData();
248 
249  // copy footprint, BC, EC, Flags, ID, if they exist
250  uint8_t presenceFlags = 0;
251 
252  if (((buf[wordsProcessed] >> 12) & 0xF) == 0xA) // BC
253  {
254  presenceFlags |= 0x1;
255  fd[11] = buf[wordsProcessed];
256  wordsProcessed++;
257  }
258 
259  if (((buf[wordsProcessed] >> 12) & 0xF) == 0xC) // EC, flags
260  {
261  presenceFlags |= 0x2;
262  fd[10] = buf[wordsProcessed];
263  wordsProcessed++;
264  }
265 
266  if (((buf[wordsProcessed] >> 12) & 0xF) == 0xE) // ID
267  {
268  presenceFlags |= 0x4;
269  fd[9] = buf[wordsProcessed];
270  wordsProcessed++;
271  }
272 
273  // save offset where channel data start
274  unsigned int dataOffset = wordsProcessed;
275 
276  // find trailer
277  switch (hFlag) {
278  case vmCluster: {
279  unsigned int nCl = 0;
280  while ( (buf[wordsProcessed + nCl] >> 12) != 0xF && ( wordsProcessed + nCl < maxWords ) ) nCl++;
281  wordsProcessed += nCl;
282  } break;
283  case vmRaw:
284  wordsProcessed += 9;
285  break;
286  case vmDiamondCompact: {
287  wordsProcessed--;
288  while ( (buf[wordsProcessed] & 0xFFF0)!= 0xF000 && ( wordsProcessed < maxWords ) ) wordsProcessed++;
289  } break;
290  }
291 
292  // process trailer
293  unsigned int tSig = buf[wordsProcessed] >> 12;
294  unsigned int tErrFlags = (buf[wordsProcessed] >> 8) & 0xF;
295  unsigned int tSize = buf[wordsProcessed] & 0xFF;
296 
297  f.setDAQErrorFlags(tErrFlags);
298 
299  // consistency checks
300  bool skipFrame = false;
301  stringstream ess;
302 
303  if (tSig != 0xF)
304  {
305  if (verbosity)
306  ess << " Wrong trailer signature (" << tSig << ")." << endl;
307  skipFrame = true;
308  }
309 
310  if (tErrFlags != 0)
311  {
312  if (verbosity)
313  ess << " Error flags not zero (" << tErrFlags << ")." << endl;
314  skipFrame = true;
315  }
316 
317  wordsProcessed++;
318 
319  if (tSize != wordsProcessed)
320  {
321  if (verbosity)
322  ess << " Trailer size (" << tSize << ") does not match with words processed (" << wordsProcessed << ")." << endl;
323  skipFrame = true;
324  }
325 
326  if (skipFrame)
327  {
328  if (verbosity)
329  LogWarning("Totem") << "Error in RawDataUnpacker::processVFATDataParallel > Frame at " << fp
330  << " has the following problems and will be skipped.\n" << endl << ess.rdbuf();
331 
332  return wordsProcessed;
333  }
334 
335  // get channel data - cluster mode
336  if (hFlag == vmCluster)
337  {
338  for (unsigned int nCl = 0; (buf[dataOffset + nCl] >> 12) != 0xF && ( dataOffset + nCl < maxWords ); ++nCl)
339  {
340  const uint16_t &w = buf[dataOffset + nCl];
341  unsigned int upperBlock = w >> 8;
342  unsigned int clSize = upperBlock & 0x7F;
343  unsigned int clPos = (w >> 0) & 0xFF;
344 
345  // special case: upperBlock=0xD0 => numberOfClusters
346  if (upperBlock == 0xD0)
347  {
348  presenceFlags |= 0x10;
349  f.setNumberOfClusters(clPos);
350  continue;
351  }
352 
353  // special case: size=0 means chip full
354  if (clSize == 0)
355  clSize = 128;
356 
357  // activate channels
358  // convention - range <pos, pos-size+1>
359  signed int chMax = clPos;
360  signed int chMin = clPos - clSize + 1;
361  if (chMax < 0 || chMax > 127 || chMin < 0 || chMin > 127 || chMin > chMax)
362  {
363  if (verbosity)
364  LogWarning("Totem") << "Error in RawDataUnpacker::processVFATDataParallel > "
365  << "Invalid cluster (pos=" << clPos
366  << ", size=" << clSize << ", min=" << chMin << ", max=" << chMax << ") at " << fp
367  <<". Skipping this cluster." << endl;
368  continue;
369  }
370 
371  for (signed int ch = chMin; ch <= chMax; ch++)
372  {
373  unsigned int wi = ch / 16;
374  unsigned int bi = ch % 16;
375  fd[wi + 1] |= (1 << bi);
376  }
377  }
378  }
379 
380  // get channel data and CRC - raw mode
381  if (hFlag == vmRaw)
382  {
383  for (unsigned int i = 0; i < 8; i++)
384  fd[8 - i] = buf[dataOffset + i];
385 
386  // copy CRC
387  presenceFlags |= 0x8;
388  fd[0] = buf[dataOffset + 8];
389  }
390 
391  // get channel data for diamond compact mode
392  if (hFlag == vmDiamondCompact)
393  {
394  for (unsigned int i = 1; (buf[i+1] & 0xFFF0)!= 0xF000 && ( i+1 < maxWords ); i++) {
395  if ( ( buf[i] & 0xF000 ) == VFAT_HEADER_OF_EC ) {
396  // Event Counter word is found
397  fd[10] = buf[i];
398  continue;
399  }
400  switch ( buf[i] & 0xF800 ) {
402  // word 2 of the diamond VFAT frame is found
403  fd[1] = buf[i + 1];
404  fd[2] = buf[i];
405  break;
407  // word 3 of the diamond VFAT frame is found
408  fd[3] = buf[i];
409  fd[4] = buf[i - 1];
410  break;
412  // word 5 of the diamond VFAT frame is found
413  fd[5] = buf[i];
414  fd[6] = buf[i - 1];
415  break;
417  // word 7 of the diamond VFAT frame is found
418  fd[7] = buf[i];
419  fd[8] = buf[i - 1];
420  break;
421  default:
422  break;
423  }
424  presenceFlags |= 0x8;
425  }
426  }
427 
428  // save frame to output
429  f.setPresenceFlags(presenceFlags);
430  fc->Insert(fp, f);
431 
432  return wordsProcessed;
433 }
434 
435 //----------------------------------------------------------------------------------------------------
436 
437 int RawDataUnpacker::processOptoRxFrameSampic(const word *buf, unsigned int frameSize, TotemFEDInfo &fedInfo, SimpleVFATFrameCollection *fc) const
438 {
439  unsigned int optoRxId = (buf[0] >> 8) & 0xFFF;
440 
441  LogDebug( "RawDataUnpacker::processOptoRxFrameSampic" )
442  << "Processing sampic frame: OptoRx " << optoRxId << " framesize: " << frameSize;
443 
444  unsigned int orbitCounterVFATFrameWords = 6;
445  unsigned int sizeofVFATPayload = 12;
446 
447  const VFATFrame::word *VFATFrameWordPtr = (const VFATFrame::word *) buf;
448  VFATFrameWordPtr += orbitCounterVFATFrameWords - 1;
449 
450  LogDebug( "RawDataUnpacker::processOptoRxFrameSampic" )
451  << "Framesize: " << frameSize << "\tframes: " << frameSize/(sizeofVFATPayload+2);
452 
453  unsigned int nWords = (frameSize-2) * 4 - 2;
454 
455  for (unsigned int i=1; i*(sizeofVFATPayload+2)<nWords; ++i) {
456  // compile frame position
457  // NOTE: DAQ group uses terms GOH and fiber in the other way
458  unsigned int fiberIdx = (*(++VFATFrameWordPtr)) & 0xF;
459  unsigned int gohIdx = (*VFATFrameWordPtr >> 4) & 0xF;
460  TotemFramePosition fp(0, 0, optoRxId, gohIdx, fiberIdx);
461 
462  LogDebug( "RawDataUnpacker::processOptoRxFrameSampic" )
463  << "OptoRx: " << optoRxId << " Goh: " << gohIdx << " Idx: " << fiberIdx;
464 
465  // prepare temporary VFAT frame
466  VFATFrame frame(++VFATFrameWordPtr);
467  VFATFrameWordPtr += sizeofVFATPayload;
468 
469  if ( *(VFATFrameWordPtr) != 0xf00e ) {
470  edm::LogError( "RawDataUnpacker::processOptoRxFrameSampic" )
471  << "Wrong trailer " << *VFATFrameWordPtr;
472  continue;
473  }
474  // save frame to output
475  frame.setPresenceFlags(1);
476  fc->Insert(fp, frame);
477 
478  LogDebug( "RawDataUnpacker::processOptoRxFrameSampic" )
479  << "Trailer: " << std::hex << *VFATFrameWordPtr;
480  }
481 
482  return 0;
483 }
484 
#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