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