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