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 
11 
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  #ifdef DEBUG
79  printf(">> RawDataUnpacker::ProcessOptoRxFrame > OptoRxId = %u, BX = %lu, LV1 = %lu, frameSize = %u, subFrames = %u)\n",
80  OptoRxId, BX, LV1, frameSize, subFrames);
81  #endif
82 
83  // parallel or serial transmission?
84  switch (FOV) {
85  case 1:
86  return ProcessOptoRxFrameSerial(buf, frameSize, fc);
87  case 2:
88  case 3:
89  return ProcessOptoRxFrameParallel(buf, frameSize, fedInfo, fc);
90  default: break;
91  }
92 
93  if (verbosity)
94  LogWarning("Totem") << "Error in RawDataUnpacker::ProcessOptoRxFrame > " << "Unknown FOV = " << FOV << endl;
95 
96  return 0;
97 }
98 
99 //----------------------------------------------------------------------------------------------------
100 
101 int RawDataUnpacker::ProcessOptoRxFrameSerial(const word *buf, unsigned int frameSize, SimpleVFATFrameCollection *fc) const
102 {
103  // get OptoRx metadata
104  unsigned int OptoRxId = (buf[0] >> 8) & 0xFFF;
105 
106  // get number of subframes
107  unsigned int subFrames = (frameSize - 2) / 194;
108 
109  // process all sub-frames
110  unsigned int errorCounter = 0;
111  for (unsigned int r = 0; r < subFrames; ++r)
112  {
113  for (unsigned int c = 0; c < 4; ++c)
114  {
115  unsigned int head = (buf[1 + 194 * r] >> (16 * c)) & 0xFFFF;
116  unsigned int foot = (buf[194 + 194 * r] >> (16 * c)) & 0xFFFF;
117 
118  #ifdef DEBUG
119  printf(">>>> r = %i, c = %i: S = %i, BOF = %i, EOF = %i, ID = %i, ID' = %i\n", r, c, head & 0x1, head >> 12, foot >> 12, (head >> 8) & 0xF, (foot >> 8) & 0xF);
120  #endif
121 
122  // stop if this GOH is NOT active
123  if ((head & 0x1) == 0)
124  continue;
125 
126  #ifdef DEBUG
127  printf("\tHeader active (%04x -> %x).\n", head, head & 0x1);
128  #endif
129 
130  // check structure
131  if (head >> 12 != 0x4 || foot >> 12 != 0xB || ((head >> 8) & 0xF) != ((foot >> 8) & 0xF))
132  {
133  char ss[500];
134  if (head >> 12 != 0x4)
135  sprintf(ss, "\n\tHeader is not 0x4 as expected (%x).", head);
136  if (foot >> 12 != 0xB)
137  sprintf(ss, "\n\tFooter is not 0xB as expected (%x).", foot);
138  if (((head >> 8) & 0xF) != ((foot >> 8) & 0xF))
139  sprintf(ss, "\n\tIncompatible GOH IDs in header (%x) and footer (%x).", ((head >> 8) & 0xF),
140  ((foot >> 8) & 0xF));
141 
142  if (verbosity)
143  LogWarning("Totem") << "Error in RawDataUnpacker::ProcessOptoRxFrame > " << "Wrong payload structure (in GOH block row " << r <<
144  " and column " << c << ") in OptoRx frame ID " << OptoRxId << ". GOH block omitted." << ss << endl;
145 
146  errorCounter++;
147  continue;
148  }
149 
150  // allocate memory for VFAT frames
151  unsigned int goh = (head >> 8) & 0xF;
152  vector<VFATFrame::word*> dataPtrs;
153  for (unsigned int fi = 0; fi < 16; fi++)
154  {
155  TotemFramePosition fp(0, 0, OptoRxId, goh, fi);
156  dataPtrs.push_back( fc->InsertEmptyFrame(fp)->getData() );
157  }
158 
159  #ifdef DEBUG
160  printf(">>>> transposing GOH block at prefix: %i, dataPtrs = %p\n", OptoRxId*192 + goh*16, dataPtrs);
161  #endif
162 
163  // deserialization
164  for (int i = 0; i < 192; i++)
165  {
166  int iword = 11 - i / 16; // number of current word (11...0)
167  int ibit = 15 - i % 16; // number of current bit (15...0)
168  unsigned int w = (buf[i + 2 + 194 * r] >> (16 * c)) & 0xFFFF;
169 
170  // Fill the current bit of the current word of all VFAT frames
171  for (int idx = 0; idx < 16; idx++)
172  {
173  if (w & (1 << idx))
174  dataPtrs[idx][iword] |= (1 << ibit);
175  }
176  }
177  }
178  }
179 
180  return errorCounter;
181 }
182 
183 //----------------------------------------------------------------------------------------------------
184 
185 int RawDataUnpacker::ProcessOptoRxFrameParallel(const word *buf, unsigned int frameSize, TotemFEDInfo &fedInfo, SimpleVFATFrameCollection *fc) const
186 {
187  // get OptoRx metadata
188  unsigned long long head = buf[0];
189  unsigned int OptoRxId = (head >> 8) & 0xFFF;
190 
191  // recast data as buffer or 16bit words, skip header
192  const uint16_t *payload = (const uint16_t *) (buf + 1);
193 
194  // read in OrbitCounter block
195  const uint32_t *ocPtr = (const uint32_t *) payload;
196  fedInfo.setOrbitCounter(*ocPtr);
197  payload += 2;
198 
199  // size in 16bit words, without header, footer and orbit counter block
200  unsigned int nWords = (frameSize-2) * 4 - 2;
201 
202  // process all VFAT data
203  for (unsigned int offset = 0; offset < nWords;)
204  {
205  unsigned int wordsProcessed = ProcessVFATDataParallel(payload + offset, nWords, OptoRxId, fc);
206  offset += wordsProcessed;
207  }
208 
209  return 0;
210 }
211 
212 //----------------------------------------------------------------------------------------------------
213 
214 int RawDataUnpacker::ProcessVFATDataParallel(const uint16_t *buf, unsigned int maxWords, unsigned int OptoRxId, SimpleVFATFrameCollection *fc) const
215 {
216  // start counting processed words
217  unsigned int wordsProcessed = 1;
218 
219  // padding word? skip it
220  if (buf[0] == 0xFFFF)
221  return wordsProcessed;
222 
223  // check header flag
224  unsigned int hFlag = (buf[0] >> 8) & 0xFF;
225  if (hFlag != vmCluster && hFlag != vmRaw && hFlag != vmDiamondCompact)
226  {
227  if (verbosity)
228  LogWarning("Totem") << "Error in RawDataUnpacker::ProcessVFATDataParallel > "
229  << "Unknown header flag " << hFlag << ". Skipping this word." << endl;
230  return wordsProcessed;
231  }
232 
233  // compile frame position
234  // NOTE: DAQ group uses terms GOH and fiber in the other way
235  unsigned int gohIdx = (buf[0] >> 4) & 0xF;
236  unsigned int fiberIdx = (buf[0] >> 0) & 0xF;
237  TotemFramePosition fp(0, 0, OptoRxId, gohIdx, fiberIdx);
238 
239  // prepare temporary VFAT frame
240  VFATFrame f;
241  VFATFrame::word *fd = f.getData();
242 
243  // copy footprint, BC, EC, Flags, ID, if they exist
244  uint8_t presenceFlags = 0;
245 
246  if (((buf[wordsProcessed] >> 12) & 0xF) == 0xA) // BC
247  {
248  presenceFlags |= 0x1;
249  fd[11] = buf[wordsProcessed];
250  wordsProcessed++;
251  }
252 
253  if (((buf[wordsProcessed] >> 12) & 0xF) == 0xC) // EC, flags
254  {
255  presenceFlags |= 0x2;
256  fd[10] = buf[wordsProcessed];
257  wordsProcessed++;
258  }
259 
260  if (((buf[wordsProcessed] >> 12) & 0xF) == 0xE) // ID
261  {
262  presenceFlags |= 0x4;
263  fd[9] = buf[wordsProcessed];
264  wordsProcessed++;
265  }
266 
267  // save offset where channel data start
268  unsigned int dataOffset = wordsProcessed;
269 
270  // find trailer
271  switch (hFlag) {
272  case vmCluster: {
273  unsigned int nCl = 0;
274  while ( (buf[wordsProcessed + nCl] >> 12) != 0xF && ( wordsProcessed + nCl < maxWords ) ) nCl++;
275  wordsProcessed += nCl;
276  } break;
277  case vmRaw:
278  wordsProcessed += 9;
279  break;
280  case vmDiamondCompact: {
281  wordsProcessed--;
282  while ( (buf[wordsProcessed] & 0xFFF0)!= 0xF000 && ( wordsProcessed < maxWords ) ) wordsProcessed++;
283  } break;
284  }
285 
286  // process trailer
287  unsigned int tSig = buf[wordsProcessed] >> 12;
288  unsigned int tErrFlags = (buf[wordsProcessed] >> 8) & 0xF;
289  unsigned int tSize = buf[wordsProcessed] & 0xFF;
290 
291  f.setDAQErrorFlags(tErrFlags);
292 
293  // consistency checks
294  bool skipFrame = false;
295  stringstream ess;
296 
297  if (tSig != 0xF)
298  {
299  if (verbosity)
300  ess << " Wrong trailer signature (" << tSig << ")." << endl;
301  skipFrame = true;
302  }
303 
304  if (tErrFlags != 0)
305  {
306  if (verbosity)
307  ess << " Error flags not zero (" << tErrFlags << ")." << endl;
308  skipFrame = true;
309  }
310 
311  wordsProcessed++;
312 
313  if (tSize != wordsProcessed)
314  {
315  if (verbosity)
316  ess << " Trailer size (" << tSize << ") does not match with words processed (" << wordsProcessed << ")." << endl;
317  skipFrame = true;
318  }
319 
320  if (skipFrame)
321  {
322  if (verbosity)
323  LogWarning("Totem") << "Error in RawDataUnpacker::ProcessVFATDataParallel > Frame at " << fp
324  << " has the following problems and will be skipped.\n" << endl << ess.rdbuf();
325 
326  return wordsProcessed;
327  }
328 
329  // get channel data - cluster mode
330  if (hFlag == vmCluster)
331  {
332  for (unsigned int nCl = 0; (buf[dataOffset + nCl] >> 12) != 0xF && ( dataOffset + nCl < maxWords ); ++nCl)
333  {
334  const uint16_t &w = buf[dataOffset + nCl];
335  unsigned int upperBlock = w >> 8;
336  unsigned int clSize = upperBlock & 0x7F;
337  unsigned int clPos = (w >> 0) & 0xFF;
338 
339  // special case: upperBlock=0xD0 => numberOfClusters
340  if (upperBlock == 0xD0)
341  {
342  presenceFlags |= 0x10;
343  f.setNumberOfClusters(clPos);
344  continue;
345  }
346 
347  // special case: size=0 means chip full
348  if (clSize == 0)
349  clSize = 128;
350 
351  // activate channels
352  // convention - range <pos, pos-size+1>
353  signed int chMax = clPos;
354  signed int chMin = clPos - clSize + 1;
355  if (chMax < 0 || chMax > 127 || chMin < 0 || chMin > 127 || chMin > chMax)
356  {
357  if (verbosity)
358  LogWarning("Totem") << "Error in RawDataUnpacker::ProcessVFATDataParallel > "
359  << "Invalid cluster (pos=" << clPos
360  << ", size=" << clSize << ", min=" << chMin << ", max=" << chMax << ") at " << fp
361  <<". Skipping this cluster." << endl;
362  continue;
363  }
364 
365  for (signed int ch = chMin; ch <= chMax; ch++)
366  {
367  unsigned int wi = ch / 16;
368  unsigned int bi = ch % 16;
369  fd[wi + 1] |= (1 << bi);
370  }
371  }
372  }
373 
374  // get channel data and CRC - raw mode
375  if (hFlag == vmRaw)
376  {
377  for (unsigned int i = 0; i < 8; i++)
378  fd[8 - i] = buf[dataOffset + i];
379 
380  // copy CRC
381  presenceFlags |= 0x8;
382  fd[0] = buf[dataOffset + 8];
383  }
384 
385  // get channel data for diamond compact mode
386  if (hFlag == vmDiamondCompact)
387  {
388  for (unsigned int i = 1; (buf[i+1] & 0xFFF0)!= 0xF000 && ( i+1 < maxWords ); i++) {
389  if ( ( buf[i] & 0xF000 ) == VFAT_HEADER_OF_EC ) {
390  // Event Counter word is found
391  fd[10] = buf[i];
392  continue;
393  }
394  switch ( buf[i] & 0xF800 ) {
396  // word 2 of the diamond VFAT frame is found
397  fd[1] = buf[i + 1];
398  fd[2] = buf[i];
399  break;
401  // word 3 of the diamond VFAT frame is found
402  fd[3] = buf[i];
403  fd[4] = buf[i - 1];
404  break;
406  // word 5 of the diamond VFAT frame is found
407  fd[5] = buf[i];
408  fd[6] = buf[i - 1];
409  break;
411  // word 7 of the diamond VFAT frame is found
412  fd[7] = buf[i];
413  fd[8] = buf[i - 1];
414  break;
415  default:
416  break;
417  }
418  presenceFlags |= 0x8;
419  }
420  }
421 
422  // save frame to output
423  f.setPresenceFlags(presenceFlags);
424  fc->Insert(fp, f);
425 
426  return wordsProcessed;
427 }
OptoRx headers and footers.
Definition: TotemFEDInfo.h:15
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.
static constexpr unsigned int VFAT_DIAMOND_HEADER_OF_WORD_2
uint16_t word
Definition: VFATFrame.h:22
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
payload
payload postfix for testing
static constexpr unsigned int VFAT_DIAMOND_HEADER_OF_WORD_5
int ProcessOptoRxFrameSerial(const word *buffer, unsigned int frameSize, SimpleVFATFrameCollection *fc) const
Process one Opto-Rx frame in serial (old) format.
void setOrbitCounter(uint32_t _oc)
Definition: TotemFEDInfo.h:33
int ProcessVFATDataParallel(const uint16_t *buf, unsigned int maxWords, unsigned int OptoRxId, SimpleVFATFrameCollection *fc) const
Process data from one VFAT in parallel (new) format.
void setFooter(uint64_t _f)
Definition: TotemFEDInfo.h:36
double f[11][100]
VFATFrame * InsertEmptyFrame(TotemFramePosition index)
inserts an empty (default) frame to the given position and returns pointer to the frame ...
int ProcessOptoRxFrameParallel(const word *buffer, unsigned int frameSize, TotemFEDInfo &fedInfo, SimpleVFATFrameCollection *fc) const
Process one Opto-Rx frame in parallel (new) format.
JetCorrectorParametersCollection coll
Definition: classes.h:10
void setPresenceFlags(uint8_t v)
Sets presence flags.
Definition: VFATFrame.h:77
void setDAQErrorFlags(uint8_t v)
Sets DAQ error flags.
Definition: VFATFrame.h:113
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:25
void Insert(const TotemFramePosition &index, const VFATFrame &frame)
void setNumberOfClusters(uint8_t v)
Definition: VFATFrame.h:118
int Run(int fedId, const FEDRawData &data, std::vector< TotemFEDInfo > &fedInfoColl, SimpleVFATFrameCollection &coll) const
Unpack data from FED with fedId into `coll&#39; collection.