ALIROOT-5420 Changes for CDH v3
[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"
586dda01 47#include "AliMUONTrackerDDLDecoder.h"
481d8064 48#include "AliMUONDspHeader.h"
49#include "AliMUONBlockHeader.h"
50#include "AliMUONBusStruct.h"
51#include "AliMUONDDLTracker.h"
64c2397e 52#include "AliMUONLogger.h"
e3a2b9c9 53#include "AliRawReader.h"
54#include "AliLog.h"
64c2397e 55#include "AliDAQ.h"
e3a2b9c9 56#include <cassert>
8a0dae7c 57#include <iostream>
8a0dae7c 58using std::cout;
59using std::endl;
60using std::hex;
61using std::dec;
e3a2b9c9 62
63/// \cond CLASSIMP
64ClassImp(AliMUONRawStreamTrackerHP)
65/// \endcond
66
b6f591ae 67const Int_t AliMUONRawStreamTrackerHP::fgkMaxDDL = 20;
e3a2b9c9 68
69AliMUONRawStreamTrackerHP::AliMUONRawStreamTrackerHP() :
b6f591ae 70 TObject(),
64c2397e 71 fRawReader(NULL),
72 fLogger(NULL),
73 fDetailLevel(kMediumErrorDetail),
74 fEnableMUONErrorLogger(kFALSE),
75 fEnableRawReaderErrorLogger(kFALSE),
76 fWarnings(kTRUE),
e3a2b9c9 77 fDecoder(),
78 fDDL(0),
e3a2b9c9 79 fBufferSize(8192),
80 fBuffer(new UChar_t[8192]),
586dda01 81 fkCurrentBusPatch(NULL),
82 fkCurrentData(NULL),
83 fkEndOfData(NULL),
8a0dae7c 84 fHadError(kFALSE),
481d8064 85 fDone(kFALSE),
b6f591ae 86 fDDLObject(NULL),
74585128 87 fTotalNumberOfGlitchErrors(0),
88 fTotalNumberOfParityErrors(0),
89 fTotalNumberOfPaddingErrors(0),
90 fTotalNumberOfTokenLostErrors(0)
e3a2b9c9 91{
92 ///
93 /// Default constructor.
94 ///
8a0dae7c 95
96 // Must set this flag to get all information about parity errors though
97 // the OnData method. OnError gets them either way.
98 fDecoder.ExitOnError(false);
99 fDecoder.SendDataOnParityError(true);
100
101 fDecoder.GetHandler().SetMaxStructs(
102 fDecoder.MaxBlocks(),
103 fDecoder.MaxDSPs(),
104 fDecoder.MaxBusPatches()
105 );
64c2397e 106
107 fDecoder.GetHandler().SetRawStream(this);
e3a2b9c9 108}
109
110
111AliMUONRawStreamTrackerHP::AliMUONRawStreamTrackerHP(AliRawReader* rawReader) :
74585128 112 TObject(),
64c2397e 113 fRawReader(rawReader),
114 fLogger(NULL),
115 fDetailLevel(kMediumErrorDetail),
116 fEnableMUONErrorLogger(kFALSE),
117 fEnableRawReaderErrorLogger(kFALSE),
118 fWarnings(kTRUE),
e3a2b9c9 119 fDecoder(),
120 fDDL(0),
e3a2b9c9 121 fBufferSize(8192),
122 fBuffer(new UChar_t[8192]),
586dda01 123 fkCurrentBusPatch(NULL),
124 fkCurrentData(NULL),
125 fkEndOfData(NULL),
8a0dae7c 126 fHadError(kFALSE),
481d8064 127 fDone(kFALSE),
74585128 128 fDDLObject(NULL),
129 fTotalNumberOfGlitchErrors(0),
130 fTotalNumberOfParityErrors(0),
131 fTotalNumberOfPaddingErrors(0),
132 fTotalNumberOfTokenLostErrors(0)
e3a2b9c9 133{
134 ///
135 /// Constructor with AliRawReader as argument.
136 ///
137
8a0dae7c 138 // Must set this flag to get all information about parity errors though
139 // the OnData method. OnError gets them either way.
140 fDecoder.ExitOnError(false);
141 fDecoder.SendDataOnParityError(true);
142
143 fDecoder.GetHandler().SetMaxStructs(
144 fDecoder.MaxBlocks(),
145 fDecoder.MaxDSPs(),
146 fDecoder.MaxBusPatches()
147 );
74585128 148
64c2397e 149 fDecoder.GetHandler().SetRawStream(this);
e3a2b9c9 150}
151
152
153AliMUONRawStreamTrackerHP::~AliMUONRawStreamTrackerHP()
154{
155 ///
156 /// Default destructor.
157 ///
158
159 if (fBuffer != NULL)
160 {
161 delete [] fBuffer;
162 }
481d8064 163 if (fDDLObject != NULL)
164 {
165 delete fDDLObject;
166 }
e3a2b9c9 167}
168
169
170void AliMUONRawStreamTrackerHP::First()
171{
172 /// Initialise or reset the iterator.
173 /// The first DDL will be found and decoded.
174
175 assert( GetReader() != NULL );
176
177 fDDL = 0;
8a0dae7c 178 fDone = kFALSE;
e3a2b9c9 179 NextDDL();
74585128 180 fTotalNumberOfGlitchErrors = 0;
181 fTotalNumberOfPaddingErrors = 0;
182 fTotalNumberOfParityErrors = 0;
183 fTotalNumberOfTokenLostErrors = 0;
e3a2b9c9 184}
185
186
187Bool_t AliMUONRawStreamTrackerHP::NextDDL()
188{
189 /// Reading the next tracker DDL and decode the payload with the
190 /// high performance decoder.
191 /// \return kTRUE if the next DDL was successfully read and kFALSE otherwise.
192
193 assert( GetReader() != NULL );
194
481d8064 195 // The temporary object if generated in GetDDLTracker, is now stale,
196 // so delete it.
197 if (fDDLObject != NULL)
198 {
199 delete fDDLObject;
200 fDDLObject = NULL;
201 }
202
1788245f 203 // Better to reset these pointers.
586dda01 204 fkCurrentBusPatch = NULL;
205 fkCurrentData = NULL;
206 fkEndOfData = NULL;
1788245f 207
8a0dae7c 208 while (fDDL < GetMaxDDL())
e3a2b9c9 209 {
210 GetReader()->Reset();
211 GetReader()->Select("MUONTRK", fDDL, fDDL); // Select the DDL file to be read.
212 if (GetReader()->ReadHeader()) break;
213 AliDebug(3, Form("Skipping DDL %d which does not seem to be there", fDDL+1));
214 fDDL++;
215 }
8a0dae7c 216
217 // If we reach the end of the DDL list for this event then reset the
1788245f 218 // DDL counter, mark the iteration as done and exit.
8a0dae7c 219 if (fDDL >= GetMaxDDL())
220 {
221 fDDL = 0;
222 fDone = kTRUE;
223 return kFALSE;
224 }
225 else
226 {
227 fDone = kFALSE;
228 }
229
e3a2b9c9 230 AliDebug(3, Form("DDL Number %d\n", fDDL));
231
232 Int_t dataSize = GetReader()->GetDataSize(); // in bytes
233 // Check if we have enough buffer space already in fBuffer. If we do then
234 // just continue reading otherwise we need to resize the buffer.
235 if (fBufferSize < dataSize)
236 {
237 if (fBuffer != NULL)
238 {
239 delete [] fBuffer;
240 fBuffer = NULL;
241 fBufferSize = 0;
242 }
243 try
244 {
245 fBuffer = new UChar_t[dataSize];
246 fBufferSize = dataSize;
247 }
248 catch (const std::bad_alloc&)
249 {
250 AliError("Could not allocate more buffer space. Cannot decode DDL.");
251 return kFALSE;
252 }
253 }
254
255 if (not GetReader()->ReadNext(fBuffer, dataSize))
256 {
257 return kFALSE;
258 }
259
260#ifndef R__BYTESWAP
ab0129ae 261 Swap(reinterpret_cast<UInt_t*>(fBuffer), dataSize / sizeof(UInt_t)); // Swap needed for mac power pc.
e3a2b9c9 262#endif
263
a5f5f349 264 fDDL++; // Remember to increment index to next DDL before the calls to
265 // fDecoder.Decode since the callback methods of the decoder will
266 // use AliMUONRawStreamTrackerHP::GetDDL()
267
e3a2b9c9 268 bool result = false;
269 try
270 {
271 // Since we might allocate memory inside OnNewBuffer in the event
272 // handler we need to trap any memory allocation exception to be robust.
273 result = fDecoder.Decode(fBuffer, dataSize);
8a0dae7c 274 fHadError = (result == true ? kFALSE : kTRUE);
74585128 275 fTotalNumberOfGlitchErrors += fDecoder.GetHandler().GlitchErrorCount();
276 fTotalNumberOfParityErrors += fDecoder.GetHandler().ParityErrorCount();
b6f591ae 277 fTotalNumberOfPaddingErrors += fDecoder.GetHandler().PaddingErrorCount();
74585128 278 fTotalNumberOfTokenLostErrors += fDecoder.GetHandler().TokenLostCount();
e3a2b9c9 279 }
280 catch (const std::bad_alloc&)
281 {
282 AliError("Could not allocate more buffer space. Cannot decode DDL.");
283 return kFALSE;
284 }
8a0dae7c 285
286 // Update the current bus patch pointers.
586dda01 287 fkCurrentBusPatch = fDecoder.GetHandler().FirstBusPatch();
288 if (fkCurrentBusPatch != fDecoder.GetHandler().EndOfBusPatch())
8a0dae7c 289 {
586dda01 290 fkCurrentData = fkCurrentBusPatch->GetData();
291 fkEndOfData = fkCurrentData + fkCurrentBusPatch->GetDataCount();
8a0dae7c 292 }
293 else
294 {
295 // If the DDL did not have any bus patches then mark both fCurrentData
296 // and fEndOfData as NULL so that in Next() we are forced to find the
297 // first non empty DDL.
586dda01 298 fkCurrentData = fkEndOfData = NULL;
8a0dae7c 299 }
300
29ee96d8 301 return kTRUE;
e3a2b9c9 302}
303
304
305Bool_t AliMUONRawStreamTrackerHP::IsDone() const
306{
307 /// Indicates whether the iteration is finished or not.
308 /// \return kTRUE if we already read all the digits and kFALSE if not.
309
8a0dae7c 310 return fDone;
e3a2b9c9 311}
312
313
b6f591ae 314Bool_t AliMUONRawStreamTrackerHP::Next(Int_t& busPatchId,
315 UShort_t& manuId,
316 UChar_t& manuChannel,
317 UShort_t& adc,
318 Bool_t skipParityErrors)
e3a2b9c9 319{
320 /// Advance one step in the iteration. Returns false if finished.
321 /// [out] \param busPatchId This is filled with the bus patch ID of the digit.
322 /// [out] \param manuId This is filled with the MANU ID of the digit.
323 /// [out] \param manuChannel This is filled with the MANU channel ID of the digit.
324 /// [out] \param adc This is filled with the ADC signal value of the digit.
74585128 325 /// [in] \param skipParityErrors If this is kTRUE, we'll skip the buspatches that
326 /// have some parity errors
e3a2b9c9 327 /// \return kTRUE if we read another digit and kFALSE if we have read all the
328 /// digits already, i.e. at the end of the iteration.
329
586dda01 330 if (fkCurrentData == NULL) return kFALSE;
1788245f 331
8a0dae7c 332retry:
333 // Check if we still have data to be returned for the current bus patch.
586dda01 334 if (fkCurrentData != fkEndOfData)
e3a2b9c9 335 {
586dda01 336 busPatchId = fkCurrentBusPatch->GetBusPatchId();
337 AliMUONTrackerDDLDecoderEventHandler::UnpackADC(*fkCurrentData, manuId, manuChannel, adc);
338 fkCurrentData++;
e3a2b9c9 339 return kTRUE;
340 }
341 else
342 {
8a0dae7c 343 // We hit the end of the current bus patch so check if we have any more
344 // bus patches to process for the current DDL. If we do, then increment
345 // the current bus patch, make sure it is not the last one and then try
346 // reading the first element again.
586dda01 347 if (fkCurrentBusPatch != fDecoder.GetHandler().EndOfBusPatch())
e3a2b9c9 348 {
586dda01 349 fkCurrentBusPatch++;
350 if (fkCurrentBusPatch != fDecoder.GetHandler().EndOfBusPatch())
e3a2b9c9 351 {
586dda01 352 fkCurrentData = fkCurrentBusPatch->GetData();
353 fkEndOfData = fkCurrentData + fkCurrentBusPatch->GetDataCount();
74585128 354 if ( skipParityErrors )
355 {
356 Bool_t ok(kTRUE);
357 for ( Int_t i = 0; i < fkCurrentBusPatch->GetLength() && ok; ++ i )
358 {
359 ok = fkCurrentBusPatch->IsParityOk(i);
360 }
361 if (!ok) fkCurrentData = fkEndOfData;
362 }
8a0dae7c 363 goto retry;
e3a2b9c9 364 }
365 }
8a0dae7c 366
367 // This was the last bus patch in the DDL so read in the next one and
368 // try reading the first data element again.
369 // Note: fCurrentBusPatch is set inside NextDDL().
370 if (NextDDL()) goto retry;
e3a2b9c9 371 }
372 return kFALSE;
373}
374
375
481d8064 376AliMUONDDLTracker* AliMUONRawStreamTrackerHP::GetDDLTracker() const
377{
378 /// Construct and return a pointer to the DDL payload object.
379 /// \return Pointer to internally constructed AliMUONDDLTracker object.
380 /// The object is owned by this class and should not be deleted
381 /// by the caller.
382 ///
383 /// \note This method should not be used just to gain access to the DDL
384 /// payload, unless there is a good reason to have the AliMUONDDLTracker
385 /// object. For example, if you want to modify the data and then save it
386 /// to another DDL stream. Otherwise it can be an order of magnitude
387 /// faster to access the DDL headers and data with the GetBlockHeader,
388 /// GetDspHeader and GetBusPatch methods for example.
389 /// Refer to the MUONRawStreamTracker.C macro to see how to use the fast
390 /// decoder interface optimally.
391
392 if (fDDLObject != NULL) return fDDLObject;
393
394 fDDLObject = new AliMUONDDLTracker;
395 for (Int_t iBlock = 0; iBlock < (Int_t)GetBlockCount(); iBlock++)
396 {
397 AliMUONBlockHeader blockHeader;
398 AliMUONDspHeader dspHeader;
399 AliMUONBusStruct busPatch;
400
401 const AliBlockHeader* bh = GetBlockHeader(iBlock);
402 // Copy block header and add it to the DDL object.
403 memcpy(blockHeader.GetHeader(), bh->GetHeader(), sizeof(AliMUONBlockHeaderStruct));
404 fDDLObject->AddBlkHeader(blockHeader);
405
406 for (Int_t iDsp = 0; iDsp < (Int_t)bh->GetDspCount(); iDsp++)
407 {
408 const AliDspHeader* dh = bh->GetDspHeader(iDsp);
409 // Copy DSP header and add it to the DDL object.
410 memcpy(dspHeader.GetHeader(), dh->GetHeader(), sizeof(AliMUONDSPHeaderStruct));
411 fDDLObject->AddDspHeader(dspHeader, iBlock);
412
413 const AliBusPatch* bp = dh->GetFirstBusPatch();
414 while (bp != NULL)
415 {
416 // Copy bus patch header, data and add everything into DDL object.
417 memcpy(busPatch.GetHeader(), bp->GetHeader(), sizeof(AliMUONBusPatchHeaderStruct));
418 busPatch.SetAlloc(bp->GetLength());
419 memcpy(busPatch.GetData(), bp->GetData(), bp->GetDataCount()*sizeof(UInt_t));
420 busPatch.SetBlockId(iBlock);
421 busPatch.SetDspId(iDsp);
422 fDDLObject->AddBusPatch(busPatch, iBlock, iDsp);
423 bp = bp->Next();
424 }
425 }
426 }
427
428 return fDDLObject;
429}
430
431
8a0dae7c 432void AliMUONRawStreamTrackerHP::SetMaxBlock(Int_t blk)
e3a2b9c9 433{
8a0dae7c 434 /// Set maximum number of blocks per DDL allowed.
435 fDecoder.MaxBlocks( (UInt_t) blk );
e3a2b9c9 436
8a0dae7c 437 fDecoder.GetHandler().SetMaxStructs(
438 fDecoder.MaxBlocks(),
439 fDecoder.MaxDSPs(),
440 fDecoder.MaxBusPatches()
441 );
442}
443
444
445void AliMUONRawStreamTrackerHP::SetMaxDsp(Int_t dsp)
446{
447 /// Set maximum number of Dsp per block allowed.
448 fDecoder.MaxDSPs( (UInt_t) dsp );
449
450 fDecoder.GetHandler().SetMaxStructs(
451 fDecoder.MaxBlocks(),
452 fDecoder.MaxDSPs(),
453 fDecoder.MaxBusPatches()
454 );
455}
456
457
458void AliMUONRawStreamTrackerHP::SetMaxBus(Int_t bus)
459{
460 /// Set maximum number of Buspatch per Dsp allowed.
461 fDecoder.MaxBusPatches( (UInt_t) bus );
462
463 fDecoder.GetHandler().SetMaxStructs(
464 fDecoder.MaxBlocks(),
465 fDecoder.MaxDSPs(),
466 fDecoder.MaxBusPatches()
467 );
468}
469
470///////////////////////////////////////////////////////////////////////////////
471
472void AliMUONRawStreamTrackerHP::AliBlockHeader::Print() const
473{
474 /// Print header to screen.
475
476 cout << "CRT info" << endl;
477 if (fHeader == NULL)
e3a2b9c9 478 {
8a0dae7c 479 cout << "Header is NULL" << endl;
480 return;
481 }
482 cout << "DataKey: 0x" << hex << fHeader->fDataKey << dec << endl;
483 cout << "TotalLength: " << fHeader->fTotalLength << endl;
484 cout << "Length: " << fHeader->fLength << endl;
485 cout << "DspId: " << fHeader->fDSPId << endl;
486 cout << "L0Trigger: " << fHeader->fL0Trigger << endl;
487 cout << "MiniEventId: " << fHeader->fMiniEventId<< endl;
488 cout << "EventId1: " << fHeader->fEventId1 << endl;
489 cout << "EventId2: " << fHeader->fEventId2 << endl;
490}
491
492
493void AliMUONRawStreamTrackerHP::AliDspHeader::Print() const
494{
495 /// Print header to screen.
496
497 cout << "FRT info" << endl;
498 if (fHeader == NULL)
499 {
500 cout << "Header is NULL" << endl;
501 return;
502 }
503 cout << "DataKey: 0x" << hex << fHeader->fDataKey << dec << endl;
504 cout << "TotalLength: " << fHeader->fTotalLength << endl;
505 cout << "Length : " << fHeader->fLength << endl;
506 cout << "DspId: " << fHeader->fDSPId << endl;
507 cout << "BlkL1ATrigger: " << fHeader->fBlkL1ATrigger << endl;
508 cout << "MiniEventId: " << fHeader->fMiniEventId << endl;
509 cout << "L1ATrigger: " << fHeader->fL1ATrigger << endl;
510 cout << "L1RTrigger: " << fHeader->fL1RTrigger << endl;
511 cout << "PaddingWord: " << fHeader->fPaddingWord << endl;
512 cout << "ErrorWord: " << fHeader->fErrorWord << endl;
513}
514
515
516void AliMUONRawStreamTrackerHP::AliBusPatch::Print(const Option_t* opt) const
517{
518 /// Print header to screen.
519 cout << "Bus patch info" << endl;
520 if (fHeader == NULL)
521 {
522 cout << "Header is NULL" << endl;
523 return;
524 }
525 cout << "DataKey: 0x" << hex << fHeader->fDataKey << dec << endl;
526 cout << "fTotalLength: " << fHeader->fTotalLength << endl;
527 cout << "fLength: " << fHeader->fLength << endl;
528 cout << "fBusPatchId: " << fHeader->fBusPatchId << endl;
529
530 if (TString(opt).Contains("all"))
531 {
532 for (UInt_t i = 0; i < fHeader->fLength; ++i)
533 cout << "Data["<< i << "] = " << fData[i] << endl;
e3a2b9c9 534 }
e3a2b9c9 535}
536
537///////////////////////////////////////////////////////////////////////////////
538
539AliMUONRawStreamTrackerHP::AliDecoderEventHandler::AliDecoderEventHandler() :
64c2397e 540 fRawStream(NULL),
8a0dae7c 541 fBufferStart(NULL),
542 fBlockCount(0),
543 fBlocks(NULL),
544 fDSPs(NULL),
545 fBusPatches(NULL),
546 fEndOfBusPatches(NULL),
547 fMaxChannels(8192),
548 fParityOk(new Bool_t[8192]),
549 fCurrentBlock(NULL),
550 fCurrentDSP(NULL),
551 fCurrentBusPatch(NULL),
552 fCurrentParityOkFlag(NULL),
553 fParityErrors(0),
554 fGlitchErrors(0),
555 fPaddingErrors(0),
74585128 556 fTokenLostErrors(0),
74585128 557 fMaxBlocks(),
558 fMaxDsps(),
559 fMaxBusPatches()
e3a2b9c9 560{
8a0dae7c 561 /// Default constructor initialises the internal parity flags buffer to
562 /// store 8192 elements. This array will grow dynamically if needed.
e3a2b9c9 563}
564
565
566AliMUONRawStreamTrackerHP::AliDecoderEventHandler::~AliDecoderEventHandler()
567{
568 /// Default destructor cleans up the allocated memory.
569
8a0dae7c 570 if (fParityOk != NULL) delete [] fParityOk;
571 if (fBlocks != NULL) delete [] fBlocks;
572 if (fDSPs != NULL) delete [] fDSPs;
573 if (fBusPatches != NULL) delete [] fBusPatches;
574}
575
576
577void AliMUONRawStreamTrackerHP::AliDecoderEventHandler::SetMaxStructs(
578 UInt_t maxBlocks, UInt_t maxDsps, UInt_t maxBusPatches
579 )
580{
581 /// Sets the maximum number of structures allowed.
582
583 // Start by clearing the current arrays.
584 if (fBlocks != NULL)
585 {
586 delete [] fBlocks;
587 fBlocks = NULL;
588 }
589 if (fDSPs != NULL)
e3a2b9c9 590 {
8a0dae7c 591 delete [] fDSPs;
592 fDSPs = NULL;
e3a2b9c9 593 }
8a0dae7c 594 if (fBusPatches != NULL)
595 {
596 delete [] fBusPatches;
597 fBusPatches = NULL;
598 }
599 fCurrentBlock = NULL;
600 fCurrentDSP = NULL;
601 fCurrentBusPatch = NULL;
602
603 // Allocate new memory.
604 fBlocks = new AliBlockHeader[maxBlocks];
605 fDSPs = new AliDspHeader[maxBlocks*maxDsps];
606 fBusPatches = new AliBusPatch[maxBlocks*maxDsps*maxBusPatches];
1788245f 607 fEndOfBusPatches = fBusPatches;
b6f591ae 608
74585128 609 fMaxBlocks = maxBlocks;
610 fMaxDsps = maxDsps;
611 fMaxBusPatches = maxBusPatches;
e3a2b9c9 612}
613
8a0dae7c 614
e3a2b9c9 615void AliMUONRawStreamTrackerHP::AliDecoderEventHandler::OnNewBuffer(
616 const void* buffer, UInt_t bufferSize
617 )
618{
619 /// This is called by the high performance decoder when a new DDL payload
620 /// is about to be decoded.
621 /// \param buffer The pointer to the buffer storing the DDL payload.
622 /// \param bufferSize The size of the buffer in bytes.
623
624 // remember the start of the buffer to be used in OnError.
625 fBufferStart = buffer;
8a0dae7c 626
627 // Reset error counters.
628 fParityErrors = 0;
629 fGlitchErrors = 0;
630 fPaddingErrors = 0;
74585128 631 fTokenLostErrors = 0;
8a0dae7c 632
633 // Check if we will have enough space in the fParityOk array.
e3a2b9c9 634 // If we do not then we need to resize the array.
635 // bufferSize / sizeof(UInt_t) will be a safe over estimate of the
636 // number of channels that we will find.
8a0dae7c 637 UInt_t maxChannelsPossible = bufferSize / sizeof(UInt_t);
638 if (maxChannelsPossible > fMaxChannels)
e3a2b9c9 639 {
8a0dae7c 640 if (fParityOk != NULL)
e3a2b9c9 641 {
8a0dae7c 642 delete [] fParityOk;
643 fParityOk = NULL;
e3a2b9c9 644 fMaxChannels = 0;
645 }
8a0dae7c 646 fParityOk = new Bool_t[maxChannelsPossible];
647 fMaxChannels = maxChannelsPossible;
e3a2b9c9 648 }
e3a2b9c9 649
8a0dae7c 650 // Reset the current pointers which will be used to track where we need to
651 // fill fBlocks, fDSPs, fBusPatches and the parity flag. We have to subtract
652 // one space because we will increment the pointer the first time in the
653 // OnNewXZY methods.
654 fCurrentBlock = fBlocks-1;
655 fCurrentDSP = fDSPs-1;
656 fCurrentBusPatch = fBusPatches-1;
657 fCurrentParityOkFlag = fParityOk-1;
658 fBlockCount = 0;
e3a2b9c9 659}
660
661
64c2397e 662void AliMUONRawStreamTrackerHP::Swap(UInt_t* buffer, Int_t size) const
663{
664 // swap from little to big endian
665
666 typedef struct {
667 UInt_t b1:8; ///< first byte word
668 UInt_t b2:8; ///< second byte word
669 UInt_t b3:8; ///< third byte word
670 UInt_t b4:8; ///< fourth byte word
671 } RawWord;
672
673 RawWord* word, temp;
674 word = (RawWord*) buffer;
675
676 for (Int_t i = 0; i < size; i++)
677 {
678 temp = *(((RawWord*)buffer)+i);
679 word->b1 = temp.b4;
680 word->b2 = temp.b3;
681 word->b3 = temp.b2;
682 word->b4 = temp.b1;
683 word++;
684 }
685}
686
687
e3a2b9c9 688void AliMUONRawStreamTrackerHP::AliDecoderEventHandler::OnError(
689 ErrorCode error, const void* location
690 )
691{
692 /// This is called by the high performance decoder when a error occurs
693 /// when trying to decode the DDL payload. This indicates corruption in
694 /// the data. This method converts the error code to a descriptive message
64c2397e 695 /// and logs this with the logger object.
e3a2b9c9 696 /// \param error The error code indicating the problem.
697 /// \param location A pointer to the location within the DDL payload buffer
698 /// being decoded where the problem with the data was found.
e3a2b9c9 699
64c2397e 700 assert(fRawStream != NULL);
701
702 const char* message = NULL;
8a0dae7c 703 UInt_t word = 0;
64c2397e 704 bool logAsMajorError = true;
705
706 // Build the detailed part of the error message if high detail selected.
707 const char* detail = "";
708 if (fRawStream->GetLoggingDetailLevel() == kHighErrorDetail)
709 {
710 bool blockPtrOk = fBlockCount > 0;
711 bool dspPtrOk = blockPtrOk ? fCurrentBlock->GetDspCount() > 0 : false;
712 bool buspatchPtrOk = dspPtrOk ? fCurrentDSP->GetBusPatchCount() > 0 : false;
713 // We subtract 1 from the current numbers of blocks, DSPs
714 // and bus patches to get the iBlock, iDsp and iBus indices.
715 detail = Form(
1130977f 716 "At byte %lu in DDL %d, event %d, iBlock %d, iDsp %d [DSP ID: %d (0x%X)],"
64c2397e 717 " iBus %d [bus patch ID: %d (0x%X)].",
718 (unsigned long)location - (unsigned long)fBufferStart + sizeof(AliRawDataHeader),
719 AliDAQ::DdlID("MUONTRK", fRawStream->GetDDL()),
720 fRawStream->GetReader()->GetEventIndex(),
721 int(fBlockCount)-1,
722 blockPtrOk ? int(fCurrentBlock->GetDspCount())-1 : -1,
723 blockPtrOk ? fCurrentBlock->GetDspId() : -1,
724 blockPtrOk ? fCurrentBlock->GetDspId() : -1,
725 dspPtrOk ? int(fCurrentDSP->GetBusPatchCount())-1 : -1,
726 buspatchPtrOk ? fCurrentBusPatch->GetBusPatchId() : -1,
727 buspatchPtrOk ? fCurrentBusPatch->GetBusPatchId() : -1
728 );
729 }
730
731 // Build the log message.
e3a2b9c9 732 switch (error)
733 {
8a0dae7c 734 case kGlitchFound:
1788245f 735 fGlitchErrors++;
64c2397e 736 switch (fRawStream->GetLoggingDetailLevel())
737 {
738 case kLowErrorDetail:
739 message = "Glitch error detected.";
740 break;
741 case kMediumErrorDetail:
742 message = Form(
743 "Glitch error detected in DSP %d (0x%X), skipping event.",
744 fCurrentBlock->GetDspId(), fCurrentBlock->GetDspId()
745 );
746 break;
747 case kHighErrorDetail:
748 default:
749 message = Form("%s %s", ErrorCodeToMessage(error), detail);
750 break;
751 }
752 logAsMajorError = true;
8a0dae7c 753 break;
754
e3a2b9c9 755 case kBadPaddingWord:
1788245f 756 fPaddingErrors++;
64c2397e 757 switch (fRawStream->GetLoggingDetailLevel())
758 {
759 case kLowErrorDetail:
760 message = "Padding word error detected.";
761 break;
762 case kMediumErrorDetail:
763 // We subtract 1 from the current numbers of blocks, DSPs
764 // and bus patches to get the indices.
765 message = Form(
766 "Padding word error for iBlock %d, iDsp %d, iBus %d.",
767 fBlockCount-1,
768 fCurrentBlock->GetDspCount()-1,
769 fCurrentDSP->GetBusPatchCount()-1
770 );
771 break;
772 case kHighErrorDetail:
773 default:
774 message = Form("%s %s", ErrorCodeToMessage(error), detail);
775 break;
776 }
777 logAsMajorError = false;
8a0dae7c 778 break;
779
e3a2b9c9 780 case kParityError:
1788245f 781 fParityErrors++;
64c2397e 782 switch (fRawStream->GetLoggingDetailLevel())
783 {
784 case kLowErrorDetail:
785 message = "Parity error detected.";
786 break;
787 case kMediumErrorDetail:
788 message = Form(
789 "Parity error in buspatch %d (0x%X).",
790 fCurrentBusPatch->GetBusPatchId(),
791 fCurrentBusPatch->GetBusPatchId()
792 );
793 break;
794 case kHighErrorDetail:
795 default:
796 // location points to the incorrect data word and
797 // fCurrentBusPatch->GetData() returns a pointer to the start of
798 // bus patches data, so the difference divided by 4 gives the 32
799 // bit word number.
24efe4e6 800 word = (reinterpret_cast<size_t>(location) - reinterpret_cast<size_t>(fCurrentBusPatch->GetData()))
8a0dae7c 801 / sizeof(UInt_t);
64c2397e 802 message = Form(
803 "Parity error in word %d for manuId %d and channel %d in buspatch %d. %s",
804 word,
805 fCurrentBusPatch->GetManuId(word),
806 fCurrentBusPatch->GetChannelId(word),
807 fCurrentBusPatch->GetBusPatchId(),
808 detail
809 );
810 break;
811 }
812 logAsMajorError = false;
e3a2b9c9 813 break;
74585128 814
815 case kTokenLost:
816 fTokenLostErrors++;
64c2397e 817 switch (fRawStream->GetLoggingDetailLevel())
818 {
819 case kLowErrorDetail:
820 message = "Lost token error detected.";
821 break;
822 case kMediumErrorDetail:
823 word = *reinterpret_cast<const UInt_t*>(location);
824 message = Form(
f2e6387f 825 "Lost token error detected with address 0x%X of DDL %d and code %d.",
826 ((word & 0xFFFF0000)),
a5f5f349 827 fRawStream->GetDDL(),
64c2397e 828 (word & 0xF)
829 );
830 break;
831 case kHighErrorDetail:
832 default:
833 word = *reinterpret_cast<const UInt_t*>(location);
834 message = Form(
835 "Lost token error detected with address 0x%X and code %d. %s",
f2e6387f 836 ((word & 0xFFFF0000)),
64c2397e 837 (word & 0xF),
838 detail
839 );
64c2397e 840 break;
841 }
842 logAsMajorError = false;
74585128 843 break;
8a0dae7c 844
e3a2b9c9 845 default:
64c2397e 846 switch (fRawStream->GetLoggingDetailLevel())
847 {
848 case kLowErrorDetail:
849 message = ErrorCodeToMessage(error);
850 break;
851 case kMediumErrorDetail:
852 message = Form(
1130977f 853 "%s (At byte %lu)",
64c2397e 854 ErrorCodeToMessage(error),
855 (unsigned long)location - (unsigned long)fBufferStart + sizeof(AliRawDataHeader)
856 );
857 break;
858 case kHighErrorDetail:
859 default:
860 message = Form(
861 "%s Error code: %d (%s). %s",
862 ErrorCodeToMessage(error),
863 error, ErrorCodeToString(error),
864 detail
865 );
866 break;
867 }
868 logAsMajorError = true;
e3a2b9c9 869 break;
870 }
64c2397e 871
872 // Now log the error message depending on the logging flags set.
873 if (fRawStream->IsRawReaderErrorLoggerEnabled())
874 {
875 if (logAsMajorError)
876 fRawStream->GetReader()->AddMajorErrorLog(Int_t(error), message);
877 else
878 fRawStream->GetReader()->AddMinorErrorLog(Int_t(error), message);
879 }
880 if (fRawStream->IsMUONErrorLoggerEnabled())
881 {
882 AliMUONLogger* logger = fRawStream->GetMUONErrorLogger();
883 if (logger != NULL)
884 {
885 logger->Log(message);
886 }
887 else
888 {
889 AliErrorGeneral(
890 "AliMUONRawStreamTrackerHP::AliDecoderEventHandler",
891 "Enabled logging to AliMUONLogger, but the logger object"
892 " was not set with SetMUONErrorLogger()."
893 );
894 }
895 }
896 if (fRawStream->IsWarningsEnabled())
8a0dae7c 897 {
898 AliWarningGeneral(
899 "AliMUONRawStreamTrackerHP::AliDecoderEventHandler",
900 message
901 );
902 }
e3a2b9c9 903}
904