Cut class for the filtering of ESD V0s (Boris Hippolyte <hippolyt@in2p3.fr>)
[u/mrichter/AliRoot.git] / MUON / AliMUONRawStreamTrackerHP.cxx
CommitLineData
e3a2b9c9 1/**************************************************************************
2 * This file is property of and copyright by the ALICE HLT Project *
3 * All rights reserved. *
4 * *
5 * Primary Authors: *
6 * Artur Szostak <artursz@iafrica.com> *
7 * *
8 * Permission to use, copy, modify and distribute this software and its *
9 * documentation strictly for non-commercial purposes is hereby granted *
10 * without fee, provided that the above copyright notice appears in all *
11 * copies and that both the copyright notice and this permission notice *
12 * appear in the supporting documentation. The authors make no claims *
13 * about the suitability of this software for any purpose. It is *
14 * provided "as is" without express or implied warranty. *
15 **************************************************************************/
16
17/* $Id$*/
18
19///
20/// \file AliMUONRawStreamTrackerHP.cxx
21/// \author Artur Szostak <artursz@iafrica.com>
22/// \date 29-11-2007
23/// \brief Implementation of the the high performance decoder AliMUONRawStreamTrackerHP.
24///
25
26//-----------------------------------------------------------------------------
27/// \ingroup raw
28/// \class AliMUONRawStreamTrackerHP
29/// \brief A high performance stream decoder for muon tracking DDL streams.
30///
31/// This is the raw stream class which interfaces between the high performance
32/// core decoder and the AliRawReader class.
33/// To gain the most out of the decoder, the Next() method which returns batches
34/// of decoded digit / channel information should be used. That is:
35/// \code
8a0dae7c 36/// const AliBusPatch* Next();
e3a2b9c9 37/// \endcode
38///
8a0dae7c 39/// This decoder tries to implement as similar an interface as possible to
40/// AliMUONRawStreamTracker where possible. However certain constructs which
41/// would slow us down too much are avoided.
42///
e3a2b9c9 43/// \author Artur Szostak <artursz@iafrica.com>
44//-----------------------------------------------------------------------------
45
46#include "AliMUONRawStreamTrackerHP.h"
47#include "AliRawReader.h"
48#include "AliLog.h"
49#include <cassert>
8a0dae7c 50#include <iostream>
51#include <iomanip>
52using std::cout;
53using std::endl;
54using std::hex;
55using std::dec;
e3a2b9c9 56
57/// \cond CLASSIMP
58ClassImp(AliMUONRawStreamTrackerHP)
59/// \endcond
60
61
62AliMUONRawStreamTrackerHP::AliMUONRawStreamTrackerHP() :
63 AliMUONVRawStreamTracker(),
64 fDecoder(),
65 fDDL(0),
e3a2b9c9 66 fBufferSize(8192),
67 fBuffer(new UChar_t[8192]),
8a0dae7c 68 fCurrentBusPatch(NULL),
69 fCurrentData(NULL),
70 fEndOfData(NULL),
71 fHadError(kFALSE),
72 fDone(kFALSE)
e3a2b9c9 73{
74 ///
75 /// Default constructor.
76 ///
8a0dae7c 77
78 // Must set this flag to get all information about parity errors though
79 // the OnData method. OnError gets them either way.
80 fDecoder.ExitOnError(false);
81 fDecoder.SendDataOnParityError(true);
82
83 fDecoder.GetHandler().SetMaxStructs(
84 fDecoder.MaxBlocks(),
85 fDecoder.MaxDSPs(),
86 fDecoder.MaxBusPatches()
87 );
88
89 fDecoder.GetHandler().SetRawStream(this);
e3a2b9c9 90}
91
92
93AliMUONRawStreamTrackerHP::AliMUONRawStreamTrackerHP(AliRawReader* rawReader) :
94 AliMUONVRawStreamTracker(rawReader),
95 fDecoder(),
96 fDDL(0),
e3a2b9c9 97 fBufferSize(8192),
98 fBuffer(new UChar_t[8192]),
8a0dae7c 99 fCurrentBusPatch(NULL),
100 fCurrentData(NULL),
101 fEndOfData(NULL),
102 fHadError(kFALSE),
103 fDone(kFALSE)
e3a2b9c9 104{
105 ///
106 /// Constructor with AliRawReader as argument.
107 ///
108
8a0dae7c 109 // Must set this flag to get all information about parity errors though
110 // the OnData method. OnError gets them either way.
111 fDecoder.ExitOnError(false);
112 fDecoder.SendDataOnParityError(true);
113
114 fDecoder.GetHandler().SetMaxStructs(
115 fDecoder.MaxBlocks(),
116 fDecoder.MaxDSPs(),
117 fDecoder.MaxBusPatches()
118 );
119
e3a2b9c9 120 fDecoder.GetHandler().SetRawStream(this);
121}
122
123
124AliMUONRawStreamTrackerHP::~AliMUONRawStreamTrackerHP()
125{
126 ///
127 /// Default destructor.
128 ///
129
130 if (fBuffer != NULL)
131 {
132 delete [] fBuffer;
133 }
134}
135
136
137void AliMUONRawStreamTrackerHP::First()
138{
139 /// Initialise or reset the iterator.
140 /// The first DDL will be found and decoded.
141
142 assert( GetReader() != NULL );
143
144 fDDL = 0;
8a0dae7c 145 fDone = kFALSE;
e3a2b9c9 146 NextDDL();
147}
148
149
150Bool_t AliMUONRawStreamTrackerHP::NextDDL()
151{
152 /// Reading the next tracker DDL and decode the payload with the
153 /// high performance decoder.
154 /// \return kTRUE if the next DDL was successfully read and kFALSE otherwise.
155
156 assert( GetReader() != NULL );
157
1788245f 158 // Better to reset these pointers.
159 fCurrentBusPatch = NULL;
160 fCurrentData = NULL;
161 fEndOfData = NULL;
162
8a0dae7c 163 while (fDDL < GetMaxDDL())
e3a2b9c9 164 {
165 GetReader()->Reset();
166 GetReader()->Select("MUONTRK", fDDL, fDDL); // Select the DDL file to be read.
167 if (GetReader()->ReadHeader()) break;
168 AliDebug(3, Form("Skipping DDL %d which does not seem to be there", fDDL+1));
169 fDDL++;
170 }
8a0dae7c 171
172 // If we reach the end of the DDL list for this event then reset the
1788245f 173 // DDL counter, mark the iteration as done and exit.
8a0dae7c 174 if (fDDL >= GetMaxDDL())
175 {
176 fDDL = 0;
177 fDone = kTRUE;
178 return kFALSE;
179 }
180 else
181 {
182 fDone = kFALSE;
183 }
184
e3a2b9c9 185 AliDebug(3, Form("DDL Number %d\n", fDDL));
186
187 Int_t dataSize = GetReader()->GetDataSize(); // in bytes
188 // Check if we have enough buffer space already in fBuffer. If we do then
189 // just continue reading otherwise we need to resize the buffer.
190 if (fBufferSize < dataSize)
191 {
192 if (fBuffer != NULL)
193 {
194 delete [] fBuffer;
195 fBuffer = NULL;
196 fBufferSize = 0;
197 }
198 try
199 {
200 fBuffer = new UChar_t[dataSize];
201 fBufferSize = dataSize;
202 }
203 catch (const std::bad_alloc&)
204 {
205 AliError("Could not allocate more buffer space. Cannot decode DDL.");
206 return kFALSE;
207 }
208 }
209
210 if (not GetReader()->ReadNext(fBuffer, dataSize))
211 {
212 return kFALSE;
213 }
214
215#ifndef R__BYTESWAP
ab0129ae 216 Swap(reinterpret_cast<UInt_t*>(fBuffer), dataSize / sizeof(UInt_t)); // Swap needed for mac power pc.
e3a2b9c9 217#endif
218
219 bool result = false;
220 try
221 {
222 // Since we might allocate memory inside OnNewBuffer in the event
223 // handler we need to trap any memory allocation exception to be robust.
224 result = fDecoder.Decode(fBuffer, dataSize);
8a0dae7c 225 fHadError = (result == true ? kFALSE : kTRUE);
e3a2b9c9 226 }
227 catch (const std::bad_alloc&)
228 {
229 AliError("Could not allocate more buffer space. Cannot decode DDL.");
230 return kFALSE;
231 }
8a0dae7c 232
233 // Update the current bus patch pointers.
234 fCurrentBusPatch = fDecoder.GetHandler().FirstBusPatch();
235 if (fCurrentBusPatch != fDecoder.GetHandler().EndOfBusPatch())
236 {
237 fCurrentData = fCurrentBusPatch->GetData();
238 fEndOfData = fCurrentData + fCurrentBusPatch->GetDataCount();
239 }
240 else
241 {
242 // If the DDL did not have any bus patches then mark both fCurrentData
243 // and fEndOfData as NULL so that in Next() we are forced to find the
244 // first non empty DDL.
245 fCurrentData = fEndOfData = NULL;
246 }
247
e3a2b9c9 248 fDDL++; // Remember to increment index to next DDL.
29ee96d8 249 return kTRUE;
e3a2b9c9 250}
251
252
253Bool_t AliMUONRawStreamTrackerHP::IsDone() const
254{
255 /// Indicates whether the iteration is finished or not.
256 /// \return kTRUE if we already read all the digits and kFALSE if not.
257
8a0dae7c 258 return fDone;
e3a2b9c9 259}
260
261
262Bool_t AliMUONRawStreamTrackerHP::Next(
263 Int_t& busPatchId, UShort_t& manuId, UChar_t& manuChannel,
264 UShort_t& adc
265 )
266{
267 /// Advance one step in the iteration. Returns false if finished.
268 /// [out] \param busPatchId This is filled with the bus patch ID of the digit.
269 /// [out] \param manuId This is filled with the MANU ID of the digit.
270 /// [out] \param manuChannel This is filled with the MANU channel ID of the digit.
271 /// [out] \param adc This is filled with the ADC signal value of the digit.
272 /// \return kTRUE if we read another digit and kFALSE if we have read all the
273 /// digits already, i.e. at the end of the iteration.
274
1788245f 275 if (fCurrentData == NULL) return kFALSE;
276
8a0dae7c 277retry:
278 // Check if we still have data to be returned for the current bus patch.
279 if (fCurrentData != fEndOfData)
e3a2b9c9 280 {
8a0dae7c 281 busPatchId = fCurrentBusPatch->GetBusPatchId();
282 AliMUONTrackerDDLDecoderEventHandler::UnpackADC(*fCurrentData, manuId, manuChannel, adc);
283 fCurrentData++;
e3a2b9c9 284 return kTRUE;
285 }
286 else
287 {
8a0dae7c 288 // We hit the end of the current bus patch so check if we have any more
289 // bus patches to process for the current DDL. If we do, then increment
290 // the current bus patch, make sure it is not the last one and then try
291 // reading the first element again.
292 if (fCurrentBusPatch != fDecoder.GetHandler().EndOfBusPatch())
e3a2b9c9 293 {
8a0dae7c 294 fCurrentBusPatch++;
295 if (fCurrentBusPatch != fDecoder.GetHandler().EndOfBusPatch())
e3a2b9c9 296 {
8a0dae7c 297 fCurrentData = fCurrentBusPatch->GetData();
298 fEndOfData = fCurrentData + fCurrentBusPatch->GetDataCount();
299 goto retry;
e3a2b9c9 300 }
301 }
8a0dae7c 302
303 // This was the last bus patch in the DDL so read in the next one and
304 // try reading the first data element again.
305 // Note: fCurrentBusPatch is set inside NextDDL().
306 if (NextDDL()) goto retry;
e3a2b9c9 307 }
308 return kFALSE;
309}
310
311
8a0dae7c 312void AliMUONRawStreamTrackerHP::SetMaxBlock(Int_t blk)
e3a2b9c9 313{
8a0dae7c 314 /// Set maximum number of blocks per DDL allowed.
315 fDecoder.MaxBlocks( (UInt_t) blk );
e3a2b9c9 316
8a0dae7c 317 fDecoder.GetHandler().SetMaxStructs(
318 fDecoder.MaxBlocks(),
319 fDecoder.MaxDSPs(),
320 fDecoder.MaxBusPatches()
321 );
322}
323
324
325void AliMUONRawStreamTrackerHP::SetMaxDsp(Int_t dsp)
326{
327 /// Set maximum number of Dsp per block allowed.
328 fDecoder.MaxDSPs( (UInt_t) dsp );
329
330 fDecoder.GetHandler().SetMaxStructs(
331 fDecoder.MaxBlocks(),
332 fDecoder.MaxDSPs(),
333 fDecoder.MaxBusPatches()
334 );
335}
336
337
338void AliMUONRawStreamTrackerHP::SetMaxBus(Int_t bus)
339{
340 /// Set maximum number of Buspatch per Dsp allowed.
341 fDecoder.MaxBusPatches( (UInt_t) bus );
342
343 fDecoder.GetHandler().SetMaxStructs(
344 fDecoder.MaxBlocks(),
345 fDecoder.MaxDSPs(),
346 fDecoder.MaxBusPatches()
347 );
348}
349
350///////////////////////////////////////////////////////////////////////////////
351
352void AliMUONRawStreamTrackerHP::AliBlockHeader::Print() const
353{
354 /// Print header to screen.
355
356 cout << "CRT info" << endl;
357 if (fHeader == NULL)
e3a2b9c9 358 {
8a0dae7c 359 cout << "Header is NULL" << endl;
360 return;
361 }
362 cout << "DataKey: 0x" << hex << fHeader->fDataKey << dec << endl;
363 cout << "TotalLength: " << fHeader->fTotalLength << endl;
364 cout << "Length: " << fHeader->fLength << endl;
365 cout << "DspId: " << fHeader->fDSPId << endl;
366 cout << "L0Trigger: " << fHeader->fL0Trigger << endl;
367 cout << "MiniEventId: " << fHeader->fMiniEventId<< endl;
368 cout << "EventId1: " << fHeader->fEventId1 << endl;
369 cout << "EventId2: " << fHeader->fEventId2 << endl;
370}
371
372
373void AliMUONRawStreamTrackerHP::AliDspHeader::Print() const
374{
375 /// Print header to screen.
376
377 cout << "FRT info" << endl;
378 if (fHeader == NULL)
379 {
380 cout << "Header is NULL" << endl;
381 return;
382 }
383 cout << "DataKey: 0x" << hex << fHeader->fDataKey << dec << endl;
384 cout << "TotalLength: " << fHeader->fTotalLength << endl;
385 cout << "Length : " << fHeader->fLength << endl;
386 cout << "DspId: " << fHeader->fDSPId << endl;
387 cout << "BlkL1ATrigger: " << fHeader->fBlkL1ATrigger << endl;
388 cout << "MiniEventId: " << fHeader->fMiniEventId << endl;
389 cout << "L1ATrigger: " << fHeader->fL1ATrigger << endl;
390 cout << "L1RTrigger: " << fHeader->fL1RTrigger << endl;
391 cout << "PaddingWord: " << fHeader->fPaddingWord << endl;
392 cout << "ErrorWord: " << fHeader->fErrorWord << endl;
393}
394
395
396void AliMUONRawStreamTrackerHP::AliBusPatch::Print(const Option_t* opt) const
397{
398 /// Print header to screen.
399 cout << "Bus patch info" << endl;
400 if (fHeader == NULL)
401 {
402 cout << "Header is NULL" << endl;
403 return;
404 }
405 cout << "DataKey: 0x" << hex << fHeader->fDataKey << dec << endl;
406 cout << "fTotalLength: " << fHeader->fTotalLength << endl;
407 cout << "fLength: " << fHeader->fLength << endl;
408 cout << "fBusPatchId: " << fHeader->fBusPatchId << endl;
409
410 if (TString(opt).Contains("all"))
411 {
412 for (UInt_t i = 0; i < fHeader->fLength; ++i)
413 cout << "Data["<< i << "] = " << fData[i] << endl;
e3a2b9c9 414 }
e3a2b9c9 415}
416
417///////////////////////////////////////////////////////////////////////////////
418
419AliMUONRawStreamTrackerHP::AliDecoderEventHandler::AliDecoderEventHandler() :
e3a2b9c9 420 fRawStream(NULL),
8a0dae7c 421 fBufferStart(NULL),
422 fBlockCount(0),
423 fBlocks(NULL),
424 fDSPs(NULL),
425 fBusPatches(NULL),
426 fEndOfBusPatches(NULL),
427 fMaxChannels(8192),
428 fParityOk(new Bool_t[8192]),
429 fCurrentBlock(NULL),
430 fCurrentDSP(NULL),
431 fCurrentBusPatch(NULL),
432 fCurrentParityOkFlag(NULL),
433 fParityErrors(0),
434 fGlitchErrors(0),
435 fPaddingErrors(0),
436 fWarnings(kTRUE)
e3a2b9c9 437{
8a0dae7c 438 /// Default constructor initialises the internal parity flags buffer to
439 /// store 8192 elements. This array will grow dynamically if needed.
e3a2b9c9 440}
441
442
443AliMUONRawStreamTrackerHP::AliDecoderEventHandler::~AliDecoderEventHandler()
444{
445 /// Default destructor cleans up the allocated memory.
446
8a0dae7c 447 if (fParityOk != NULL) delete [] fParityOk;
448 if (fBlocks != NULL) delete [] fBlocks;
449 if (fDSPs != NULL) delete [] fDSPs;
450 if (fBusPatches != NULL) delete [] fBusPatches;
451}
452
453
454void AliMUONRawStreamTrackerHP::AliDecoderEventHandler::SetMaxStructs(
455 UInt_t maxBlocks, UInt_t maxDsps, UInt_t maxBusPatches
456 )
457{
458 /// Sets the maximum number of structures allowed.
459
460 // Start by clearing the current arrays.
461 if (fBlocks != NULL)
462 {
463 delete [] fBlocks;
464 fBlocks = NULL;
465 }
466 if (fDSPs != NULL)
e3a2b9c9 467 {
8a0dae7c 468 delete [] fDSPs;
469 fDSPs = NULL;
e3a2b9c9 470 }
8a0dae7c 471 if (fBusPatches != NULL)
472 {
473 delete [] fBusPatches;
474 fBusPatches = NULL;
475 }
476 fCurrentBlock = NULL;
477 fCurrentDSP = NULL;
478 fCurrentBusPatch = NULL;
479
480 // Allocate new memory.
481 fBlocks = new AliBlockHeader[maxBlocks];
482 fDSPs = new AliDspHeader[maxBlocks*maxDsps];
483 fBusPatches = new AliBusPatch[maxBlocks*maxDsps*maxBusPatches];
1788245f 484 fEndOfBusPatches = fBusPatches;
e3a2b9c9 485}
486
8a0dae7c 487
e3a2b9c9 488void AliMUONRawStreamTrackerHP::AliDecoderEventHandler::OnNewBuffer(
489 const void* buffer, UInt_t bufferSize
490 )
491{
492 /// This is called by the high performance decoder when a new DDL payload
493 /// is about to be decoded.
494 /// \param buffer The pointer to the buffer storing the DDL payload.
495 /// \param bufferSize The size of the buffer in bytes.
496
8a0dae7c 497 assert( fRawStream != NULL );
498
e3a2b9c9 499 // remember the start of the buffer to be used in OnError.
500 fBufferStart = buffer;
8a0dae7c 501
502 // Reset error counters.
503 fParityErrors = 0;
504 fGlitchErrors = 0;
505 fPaddingErrors = 0;
506
507 // Check if we will have enough space in the fParityOk array.
e3a2b9c9 508 // If we do not then we need to resize the array.
509 // bufferSize / sizeof(UInt_t) will be a safe over estimate of the
510 // number of channels that we will find.
8a0dae7c 511 UInt_t maxChannelsPossible = bufferSize / sizeof(UInt_t);
512 if (maxChannelsPossible > fMaxChannels)
e3a2b9c9 513 {
8a0dae7c 514 if (fParityOk != NULL)
e3a2b9c9 515 {
8a0dae7c 516 delete [] fParityOk;
517 fParityOk = NULL;
e3a2b9c9 518 fMaxChannels = 0;
519 }
8a0dae7c 520 fParityOk = new Bool_t[maxChannelsPossible];
521 fMaxChannels = maxChannelsPossible;
e3a2b9c9 522 }
e3a2b9c9 523
8a0dae7c 524 // Reset the current pointers which will be used to track where we need to
525 // fill fBlocks, fDSPs, fBusPatches and the parity flag. We have to subtract
526 // one space because we will increment the pointer the first time in the
527 // OnNewXZY methods.
528 fCurrentBlock = fBlocks-1;
529 fCurrentDSP = fDSPs-1;
530 fCurrentBusPatch = fBusPatches-1;
531 fCurrentParityOkFlag = fParityOk-1;
532 fBlockCount = 0;
e3a2b9c9 533}
534
535
536void AliMUONRawStreamTrackerHP::AliDecoderEventHandler::OnError(
537 ErrorCode error, const void* location
538 )
539{
540 /// This is called by the high performance decoder when a error occurs
541 /// when trying to decode the DDL payload. This indicates corruption in
542 /// the data. This method converts the error code to a descriptive message
1788245f 543 /// and logs this with the raw reader.
e3a2b9c9 544 /// \param error The error code indicating the problem.
545 /// \param location A pointer to the location within the DDL payload buffer
546 /// being decoded where the problem with the data was found.
547
548 assert( fRawStream != NULL );
549 assert( fRawStream->GetReader() != NULL );
550
8a0dae7c 551 Char_t* message = NULL;
552 UInt_t word = 0;
553
e3a2b9c9 554 switch (error)
555 {
8a0dae7c 556 case kGlitchFound:
1788245f 557 fGlitchErrors++;
8a0dae7c 558 message = Form(
559 "Glitch error detected in DSP %d, skipping event ",
560 fCurrentBlock->GetDspId()
561 );
562 fRawStream->GetReader()->AddMajorErrorLog(error, message);
563 break;
564
e3a2b9c9 565 case kBadPaddingWord:
1788245f 566 fPaddingErrors++;
8a0dae7c 567 // We subtract 1 from the current numbers of blocks, DSPs
568 // and bus patches to get the indices.
569 message = Form(
570 "Padding word error for iBlock %d, iDsp %d, iBus %d\n",
571 fBlockCount-1,
572 fCurrentBlock->GetDspCount()-1,
573 fCurrentDSP->GetBusPatchCount()-1
574 );
575 fRawStream->GetReader()->AddMinorErrorLog(error, message);
576 break;
577
e3a2b9c9 578 case kParityError:
1788245f 579 fParityErrors++;
8a0dae7c 580 // location points to the incorrect data word and
581 // fCurrentBusPatch->GetData() returns a pointer to the start of
582 // bus patches data, so the difference divided by 4 gives the 32
583 // bit word number.
584 word = ((unsigned long)location - (unsigned long)fCurrentBusPatch->GetData())
585 / sizeof(UInt_t);
586 message = Form(
587 "Parity error in word %d for manuId %d and channel %d in buspatch %d\n",
588 word,
589 fCurrentBusPatch->GetManuId(word),
590 fCurrentBusPatch->GetChannelId(word),
591 fCurrentBusPatch->GetBusPatchId()
592 );
593 fRawStream->GetReader()->AddMinorErrorLog(error, message);
e3a2b9c9 594 break;
8a0dae7c 595
e3a2b9c9 596 default:
8a0dae7c 597 message = Form(
598 "%s (At byte %d in DDL.)",
599 ErrorCodeToMessage(error),
29ee96d8 600 (unsigned long)location - (unsigned long)fBufferStart + sizeof(AliRawDataHeader)
8a0dae7c 601 );
602 fRawStream->GetReader()->AddMajorErrorLog(error, message);
e3a2b9c9 603 break;
604 }
8a0dae7c 605
606 if (fWarnings)
607 {
608 AliWarningGeneral(
609 "AliMUONRawStreamTrackerHP::AliDecoderEventHandler",
610 message
611 );
612 }
e3a2b9c9 613}
614