Line data Source code
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
36 : /// const AliBusPatch* Next();
37 : /// \endcode
38 : ///
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 : ///
43 : /// \author Artur Szostak <artursz@iafrica.com>
44 : //-----------------------------------------------------------------------------
45 :
46 : #include "AliMUONRawStreamTrackerHP.h"
47 : #include "AliMUONTrackerDDLDecoder.h"
48 : #include "AliMUONDspHeader.h"
49 : #include "AliMUONBlockHeader.h"
50 : #include "AliMUONBusStruct.h"
51 : #include "AliMUONDDLTracker.h"
52 : #include "AliMUONLogger.h"
53 : #include "AliRawReader.h"
54 : #include "AliRawDataHeaderV3.h"
55 : #include "AliLog.h"
56 : #include "AliDAQ.h"
57 : #include <cassert>
58 : #include <iostream>
59 : using std::cout;
60 : using std::endl;
61 : using std::hex;
62 : using std::dec;
63 :
64 : /// \cond CLASSIMP
65 18 : ClassImp(AliMUONRawStreamTrackerHP)
66 : /// \endcond
67 :
68 : const Int_t AliMUONRawStreamTrackerHP::fgkMaxDDL = 20;
69 :
70 : AliMUONRawStreamTrackerHP::AliMUONRawStreamTrackerHP() :
71 9 : TObject(),
72 9 : fRawReader(NULL),
73 9 : fLogger(NULL),
74 9 : fDetailLevel(kMediumErrorDetail),
75 9 : fEnableMUONErrorLogger(kFALSE),
76 9 : fEnableRawReaderErrorLogger(kFALSE),
77 9 : fWarnings(kTRUE),
78 9 : fDecoder(),
79 9 : fDDL(0),
80 9 : fBufferSize(8192),
81 18 : fBuffer(new UChar_t[8192]),
82 9 : fkCurrentBusPatch(NULL),
83 9 : fkCurrentData(NULL),
84 9 : fkEndOfData(NULL),
85 9 : fHadError(kFALSE),
86 9 : fDone(kFALSE),
87 9 : fDDLObject(NULL),
88 9 : fTotalNumberOfGlitchErrors(0),
89 9 : fTotalNumberOfParityErrors(0),
90 9 : fTotalNumberOfPaddingErrors(0),
91 9 : fTotalNumberOfTokenLostErrors(0)
92 45 : {
93 : ///
94 : /// Default constructor.
95 : ///
96 :
97 : // Must set this flag to get all information about parity errors though
98 : // the OnData method. OnError gets them either way.
99 9 : fDecoder.ExitOnError(false);
100 9 : fDecoder.SendDataOnParityError(true);
101 :
102 18 : fDecoder.GetHandler().SetMaxStructs(
103 9 : fDecoder.MaxBlocks(),
104 9 : fDecoder.MaxDSPs(),
105 9 : fDecoder.MaxBusPatches()
106 : );
107 :
108 9 : fDecoder.GetHandler().SetRawStream(this);
109 18 : }
110 :
111 :
112 : AliMUONRawStreamTrackerHP::AliMUONRawStreamTrackerHP(AliRawReader* rawReader) :
113 0 : TObject(),
114 0 : fRawReader(rawReader),
115 0 : fLogger(NULL),
116 0 : fDetailLevel(kMediumErrorDetail),
117 0 : fEnableMUONErrorLogger(kFALSE),
118 0 : fEnableRawReaderErrorLogger(kFALSE),
119 0 : fWarnings(kTRUE),
120 0 : fDecoder(),
121 0 : fDDL(0),
122 0 : fBufferSize(8192),
123 0 : fBuffer(new UChar_t[8192]),
124 0 : fkCurrentBusPatch(NULL),
125 0 : fkCurrentData(NULL),
126 0 : fkEndOfData(NULL),
127 0 : fHadError(kFALSE),
128 0 : fDone(kFALSE),
129 0 : fDDLObject(NULL),
130 0 : fTotalNumberOfGlitchErrors(0),
131 0 : fTotalNumberOfParityErrors(0),
132 0 : fTotalNumberOfPaddingErrors(0),
133 0 : fTotalNumberOfTokenLostErrors(0)
134 0 : {
135 : ///
136 : /// Constructor with AliRawReader as argument.
137 : ///
138 :
139 : // Must set this flag to get all information about parity errors though
140 : // the OnData method. OnError gets them either way.
141 0 : fDecoder.ExitOnError(false);
142 0 : fDecoder.SendDataOnParityError(true);
143 :
144 0 : fDecoder.GetHandler().SetMaxStructs(
145 0 : fDecoder.MaxBlocks(),
146 0 : fDecoder.MaxDSPs(),
147 0 : fDecoder.MaxBusPatches()
148 : );
149 :
150 0 : fDecoder.GetHandler().SetRawStream(this);
151 0 : }
152 :
153 :
154 : AliMUONRawStreamTrackerHP::~AliMUONRawStreamTrackerHP()
155 30 : {
156 : ///
157 : /// Default destructor.
158 : ///
159 :
160 5 : if (fBuffer != NULL)
161 : {
162 10 : delete [] fBuffer;
163 : }
164 5 : if (fDDLObject != NULL)
165 : {
166 0 : delete fDDLObject;
167 : }
168 15 : }
169 :
170 :
171 : void AliMUONRawStreamTrackerHP::First()
172 : {
173 : /// Initialise or reset the iterator.
174 : /// The first DDL will be found and decoded.
175 :
176 8 : assert( GetReader() != NULL );
177 :
178 4 : fDDL = 0;
179 4 : fDone = kFALSE;
180 4 : NextDDL();
181 4 : fTotalNumberOfGlitchErrors = 0;
182 4 : fTotalNumberOfPaddingErrors = 0;
183 4 : fTotalNumberOfParityErrors = 0;
184 4 : fTotalNumberOfTokenLostErrors = 0;
185 4 : }
186 :
187 :
188 : Bool_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 168 : assert( GetReader() != NULL );
195 :
196 : // The temporary object if generated in GetDDLTracker, is now stale,
197 : // so delete it.
198 84 : if (fDDLObject != NULL)
199 : {
200 0 : delete fDDLObject;
201 0 : fDDLObject = NULL;
202 0 : }
203 :
204 : // Better to reset these pointers.
205 84 : fkCurrentBusPatch = NULL;
206 84 : fkCurrentData = NULL;
207 84 : fkEndOfData = NULL;
208 :
209 168 : while (fDDL < GetMaxDDL())
210 : {
211 80 : GetReader()->Reset();
212 80 : GetReader()->Select("MUONTRK", fDDL, fDDL); // Select the DDL file to be read.
213 80 : if (GetReader()->ReadHeader()) break;
214 0 : AliDebug(3, Form("Skipping DDL %d which does not seem to be there", fDDL+1));
215 0 : fDDL++;
216 : }
217 :
218 : // If we reach the end of the DDL list for this event then reset the
219 : // DDL counter, mark the iteration as done and exit.
220 84 : if (fDDL >= GetMaxDDL())
221 : {
222 4 : fDDL = 0;
223 4 : fDone = kTRUE;
224 4 : return kFALSE;
225 : }
226 : else
227 : {
228 80 : fDone = kFALSE;
229 : }
230 :
231 240 : AliDebug(3, Form("DDL Number %d\n", fDDL));
232 :
233 80 : 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 80 : if (fBufferSize < dataSize)
237 : {
238 0 : if (fBuffer != NULL)
239 : {
240 0 : delete [] fBuffer;
241 0 : fBuffer = NULL;
242 0 : fBufferSize = 0;
243 0 : }
244 : try
245 : {
246 0 : fBuffer = new UChar_t[dataSize];
247 0 : fBufferSize = dataSize;
248 0 : }
249 : catch (const std::bad_alloc&)
250 : {
251 0 : AliError("Could not allocate more buffer space. Cannot decode DDL.");
252 : return kFALSE;
253 0 : }
254 0 : }
255 :
256 80 : if (not GetReader()->ReadNext(fBuffer, dataSize))
257 : {
258 0 : return kFALSE;
259 : }
260 :
261 : #ifndef R__BYTESWAP
262 : Swap(reinterpret_cast<UInt_t*>(fBuffer), dataSize / sizeof(UInt_t)); // Swap needed for mac power pc.
263 : #endif
264 :
265 80 : 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 :
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 160 : result = fDecoder.Decode(fBuffer, dataSize);
275 80 : fHadError = (result == true ? kFALSE : kTRUE);
276 80 : fTotalNumberOfGlitchErrors += fDecoder.GetHandler().GlitchErrorCount();
277 80 : fTotalNumberOfParityErrors += fDecoder.GetHandler().ParityErrorCount();
278 80 : fTotalNumberOfPaddingErrors += fDecoder.GetHandler().PaddingErrorCount();
279 80 : fTotalNumberOfTokenLostErrors += fDecoder.GetHandler().TokenLostCount();
280 0 : }
281 : catch (const std::bad_alloc&)
282 : {
283 0 : AliError("Could not allocate more buffer space. Cannot decode DDL.");
284 : return kFALSE;
285 0 : }
286 :
287 : // Update the current bus patch pointers.
288 80 : fkCurrentBusPatch = fDecoder.GetHandler().FirstBusPatch();
289 80 : if (fkCurrentBusPatch != fDecoder.GetHandler().EndOfBusPatch())
290 : {
291 80 : fkCurrentData = fkCurrentBusPatch->GetData();
292 80 : fkEndOfData = fkCurrentData + fkCurrentBusPatch->GetDataCount();
293 80 : }
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.
299 0 : fkCurrentData = fkEndOfData = NULL;
300 : }
301 :
302 80 : return kTRUE;
303 84 : }
304 :
305 :
306 : Bool_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 :
311 0 : return fDone;
312 : }
313 :
314 :
315 : Bool_t AliMUONRawStreamTrackerHP::Next(Int_t& busPatchId,
316 : UShort_t& manuId,
317 : UChar_t& manuChannel,
318 : UShort_t& adc,
319 : Bool_t skipParityErrors)
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.
326 : /// [in] \param skipParityErrors If this is kTRUE, we'll skip the buspatches that
327 : /// have some parity errors
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 :
331 712 : if (fkCurrentData == NULL) return kFALSE;
332 :
333 : retry:
334 : // Check if we still have data to be returned for the current bus patch.
335 8520 : if (fkCurrentData != fkEndOfData)
336 : {
337 4968 : busPatchId = fkCurrentBusPatch->GetBusPatchId();
338 708 : AliMUONTrackerDDLDecoderEventHandler::UnpackADC(*fkCurrentData, manuId, manuChannel, adc);
339 708 : fkCurrentData++;
340 708 : return kTRUE;
341 : }
342 : else
343 : {
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.
348 3552 : if (fkCurrentBusPatch != fDecoder.GetHandler().EndOfBusPatch())
349 : {
350 3552 : fkCurrentBusPatch++;
351 3552 : if (fkCurrentBusPatch != fDecoder.GetHandler().EndOfBusPatch())
352 : {
353 3472 : fkCurrentData = fkCurrentBusPatch->GetData();
354 3472 : fkEndOfData = fkCurrentData + fkCurrentBusPatch->GetDataCount();
355 3472 : if ( skipParityErrors )
356 : {
357 : Bool_t ok(kTRUE);
358 8360 : for ( Int_t i = 0; i < fkCurrentBusPatch->GetLength() && ok; ++ i )
359 : {
360 708 : ok = fkCurrentBusPatch->IsParityOk(i);
361 : }
362 3472 : if (!ok) fkCurrentData = fkEndOfData;
363 3472 : }
364 : goto retry;
365 : }
366 : }
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 80 : if (NextDDL()) goto retry;
372 : }
373 4 : return kFALSE;
374 712 : }
375 :
376 :
377 : AliMUONDDLTracker* 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 0 : if (fDDLObject != NULL) return fDDLObject;
394 :
395 0 : fDDLObject = new AliMUONDDLTracker;
396 0 : for (Int_t iBlock = 0; iBlock < (Int_t)GetBlockCount(); iBlock++)
397 : {
398 0 : AliMUONBlockHeader blockHeader;
399 0 : AliMUONDspHeader dspHeader;
400 0 : AliMUONBusStruct busPatch;
401 :
402 0 : const AliBlockHeader* bh = GetBlockHeader(iBlock);
403 : // Copy block header and add it to the DDL object.
404 0 : memcpy(blockHeader.GetHeader(), bh->GetHeader(), sizeof(AliMUONBlockHeaderStruct));
405 0 : fDDLObject->AddBlkHeader(blockHeader);
406 :
407 0 : for (Int_t iDsp = 0; iDsp < (Int_t)bh->GetDspCount(); iDsp++)
408 : {
409 0 : const AliDspHeader* dh = bh->GetDspHeader(iDsp);
410 : // Copy DSP header and add it to the DDL object.
411 0 : memcpy(dspHeader.GetHeader(), dh->GetHeader(), sizeof(AliMUONDSPHeaderStruct));
412 0 : fDDLObject->AddDspHeader(dspHeader, iBlock);
413 :
414 0 : const AliBusPatch* bp = dh->GetFirstBusPatch();
415 0 : while (bp != NULL)
416 : {
417 : // Copy bus patch header, data and add everything into DDL object.
418 0 : memcpy(busPatch.GetHeader(), bp->GetHeader(), sizeof(AliMUONBusPatchHeaderStruct));
419 0 : busPatch.SetAlloc(bp->GetLength());
420 0 : memcpy(busPatch.GetData(), bp->GetData(), bp->GetDataCount()*sizeof(UInt_t));
421 0 : busPatch.SetBlockId(iBlock);
422 0 : busPatch.SetDspId(iDsp);
423 0 : fDDLObject->AddBusPatch(busPatch, iBlock, iDsp);
424 0 : bp = bp->Next();
425 : }
426 : }
427 0 : }
428 :
429 0 : return fDDLObject;
430 0 : }
431 :
432 :
433 : void AliMUONRawStreamTrackerHP::SetMaxBlock(Int_t blk)
434 : {
435 : /// Set maximum number of blocks per DDL allowed.
436 0 : fDecoder.MaxBlocks( (UInt_t) blk );
437 :
438 0 : fDecoder.GetHandler().SetMaxStructs(
439 0 : fDecoder.MaxBlocks(),
440 0 : fDecoder.MaxDSPs(),
441 0 : fDecoder.MaxBusPatches()
442 : );
443 0 : }
444 :
445 :
446 : void AliMUONRawStreamTrackerHP::SetMaxDsp(Int_t dsp)
447 : {
448 : /// Set maximum number of Dsp per block allowed.
449 0 : fDecoder.MaxDSPs( (UInt_t) dsp );
450 :
451 0 : fDecoder.GetHandler().SetMaxStructs(
452 0 : fDecoder.MaxBlocks(),
453 0 : fDecoder.MaxDSPs(),
454 0 : fDecoder.MaxBusPatches()
455 : );
456 0 : }
457 :
458 :
459 : void AliMUONRawStreamTrackerHP::SetMaxBus(Int_t bus)
460 : {
461 : /// Set maximum number of Buspatch per Dsp allowed.
462 0 : fDecoder.MaxBusPatches( (UInt_t) bus );
463 :
464 0 : fDecoder.GetHandler().SetMaxStructs(
465 0 : fDecoder.MaxBlocks(),
466 0 : fDecoder.MaxDSPs(),
467 0 : fDecoder.MaxBusPatches()
468 : );
469 0 : }
470 :
471 : ///////////////////////////////////////////////////////////////////////////////
472 :
473 : void AliMUONRawStreamTrackerHP::AliBlockHeader::Print() const
474 : {
475 : /// Print header to screen.
476 :
477 0 : cout << "CRT info" << endl;
478 0 : if (fHeader == NULL)
479 : {
480 0 : cout << "Header is NULL" << endl;
481 0 : return;
482 : }
483 0 : cout << "DataKey: 0x" << hex << fHeader->fDataKey << dec << endl;
484 0 : cout << "TotalLength: " << fHeader->fTotalLength << endl;
485 0 : cout << "Length: " << fHeader->fLength << endl;
486 0 : cout << "DspId: " << fHeader->fDSPId << endl;
487 0 : cout << "L0Trigger: " << fHeader->fL0Trigger << endl;
488 0 : cout << "MiniEventId: " << fHeader->fMiniEventId<< endl;
489 0 : cout << "EventId1: " << fHeader->fEventId1 << endl;
490 0 : cout << "EventId2: " << fHeader->fEventId2 << endl;
491 0 : }
492 :
493 :
494 : void AliMUONRawStreamTrackerHP::AliDspHeader::Print() const
495 : {
496 : /// Print header to screen.
497 :
498 0 : cout << "FRT info" << endl;
499 0 : if (fHeader == NULL)
500 : {
501 0 : cout << "Header is NULL" << endl;
502 0 : return;
503 : }
504 0 : cout << "DataKey: 0x" << hex << fHeader->fDataKey << dec << endl;
505 0 : cout << "TotalLength: " << fHeader->fTotalLength << endl;
506 0 : cout << "Length : " << fHeader->fLength << endl;
507 0 : cout << "DspId: " << fHeader->fDSPId << endl;
508 0 : cout << "BlkL1ATrigger: " << fHeader->fBlkL1ATrigger << endl;
509 0 : cout << "MiniEventId: " << fHeader->fMiniEventId << endl;
510 0 : cout << "L1ATrigger: " << fHeader->fL1ATrigger << endl;
511 0 : cout << "L1RTrigger: " << fHeader->fL1RTrigger << endl;
512 0 : cout << "PaddingWord: " << fHeader->fPaddingWord << endl;
513 0 : cout << "ErrorWord: " << fHeader->fErrorWord << endl;
514 0 : }
515 :
516 :
517 : void AliMUONRawStreamTrackerHP::AliBusPatch::Print(const Option_t* opt) const
518 : {
519 : /// Print header to screen.
520 0 : cout << "Bus patch info" << endl;
521 0 : if (fHeader == NULL)
522 : {
523 0 : cout << "Header is NULL" << endl;
524 0 : return;
525 : }
526 0 : cout << "DataKey: 0x" << hex << fHeader->fDataKey << dec << endl;
527 0 : cout << "fTotalLength: " << fHeader->fTotalLength << endl;
528 0 : cout << "fLength: " << fHeader->fLength << endl;
529 0 : cout << "fBusPatchId: " << fHeader->fBusPatchId << endl;
530 :
531 0 : if (TString(opt).Contains("all"))
532 : {
533 0 : for (UInt_t i = 0; i < fHeader->fLength; ++i)
534 0 : cout << "Data["<< i << "] = " << fData[i] << endl;
535 0 : }
536 0 : }
537 :
538 : ///////////////////////////////////////////////////////////////////////////////
539 :
540 9 : AliMUONRawStreamTrackerHP::AliDecoderEventHandler::AliDecoderEventHandler() :
541 9 : fRawStream(NULL),
542 9 : fBufferStart(NULL),
543 9 : fBlockCount(0),
544 9 : fBlocks(NULL),
545 9 : fDSPs(NULL),
546 9 : fBusPatches(NULL),
547 9 : fEndOfBusPatches(NULL),
548 9 : fMaxChannels(8192),
549 18 : fParityOk(new Bool_t[8192]),
550 9 : fCurrentBlock(NULL),
551 9 : fCurrentDSP(NULL),
552 9 : fCurrentBusPatch(NULL),
553 9 : fCurrentParityOkFlag(NULL),
554 9 : fParityErrors(0),
555 9 : fGlitchErrors(0),
556 9 : fPaddingErrors(0),
557 9 : fTokenLostErrors(0),
558 9 : fMaxBlocks(),
559 9 : fMaxDsps(),
560 9 : fMaxBusPatches()
561 45 : {
562 : /// Default constructor initialises the internal parity flags buffer to
563 : /// store 8192 elements. This array will grow dynamically if needed.
564 18 : }
565 :
566 :
567 : AliMUONRawStreamTrackerHP::AliDecoderEventHandler::~AliDecoderEventHandler()
568 20 : {
569 : /// Default destructor cleans up the allocated memory.
570 :
571 15 : if (fParityOk != NULL) delete [] fParityOk;
572 30 : if (fBlocks != NULL) delete [] fBlocks;
573 70 : if (fDSPs != NULL) delete [] fDSPs;
574 270 : if (fBusPatches != NULL) delete [] fBusPatches;
575 10 : }
576 :
577 :
578 : void 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 18 : if (fBlocks != NULL)
586 : {
587 0 : delete [] fBlocks;
588 0 : fBlocks = NULL;
589 0 : }
590 9 : if (fDSPs != NULL)
591 : {
592 0 : delete [] fDSPs;
593 0 : fDSPs = NULL;
594 0 : }
595 9 : if (fBusPatches != NULL)
596 : {
597 0 : delete [] fBusPatches;
598 0 : fBusPatches = NULL;
599 0 : }
600 9 : fCurrentBlock = NULL;
601 9 : fCurrentDSP = NULL;
602 9 : fCurrentBusPatch = NULL;
603 :
604 : // Allocate new memory.
605 63 : fBlocks = new AliBlockHeader[maxBlocks];
606 207 : fDSPs = new AliDspHeader[maxBlocks*maxDsps];
607 927 : fBusPatches = new AliBusPatch[maxBlocks*maxDsps*maxBusPatches];
608 9 : fEndOfBusPatches = fBusPatches;
609 :
610 9 : fMaxBlocks = maxBlocks;
611 9 : fMaxDsps = maxDsps;
612 9 : fMaxBusPatches = maxBusPatches;
613 9 : }
614 :
615 :
616 : void 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 160 : fBufferStart = buffer;
627 :
628 : // Reset error counters.
629 80 : fParityErrors = 0;
630 80 : fGlitchErrors = 0;
631 80 : fPaddingErrors = 0;
632 80 : fTokenLostErrors = 0;
633 :
634 : // Check if we will have enough space in the fParityOk array.
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.
638 80 : UInt_t maxChannelsPossible = bufferSize / sizeof(UInt_t);
639 80 : if (maxChannelsPossible > fMaxChannels)
640 : {
641 0 : if (fParityOk != NULL)
642 : {
643 0 : delete [] fParityOk;
644 0 : fParityOk = NULL;
645 0 : fMaxChannels = 0;
646 0 : }
647 0 : fParityOk = new Bool_t[maxChannelsPossible];
648 0 : fMaxChannels = maxChannelsPossible;
649 0 : }
650 :
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 80 : fCurrentBlock = fBlocks-1;
656 80 : fCurrentDSP = fDSPs-1;
657 80 : fCurrentBusPatch = fBusPatches-1;
658 80 : fCurrentParityOkFlag = fParityOk-1;
659 80 : fBlockCount = 0;
660 80 : }
661 :
662 :
663 : void 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 0 : word = (RawWord*) buffer;
676 :
677 0 : for (Int_t i = 0; i < size; i++)
678 : {
679 0 : temp = *(((RawWord*)buffer)+i);
680 0 : word->b1 = temp.b4;
681 0 : word->b2 = temp.b3;
682 0 : word->b3 = temp.b2;
683 0 : word->b4 = temp.b1;
684 0 : word++;
685 : }
686 0 : }
687 :
688 :
689 : void 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
696 : /// and logs this with the logger object.
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.
700 :
701 0 : assert(fRawStream != NULL);
702 :
703 : const char* message = NULL;
704 : UInt_t word = 0;
705 : bool logAsMajorError = true;
706 :
707 : // Build the detailed part of the error message if high detail selected.
708 : const char* detail = "";
709 0 : if (fRawStream->GetLoggingDetailLevel() == kHighErrorDetail)
710 : {
711 0 : bool blockPtrOk = fBlockCount > 0;
712 0 : bool dspPtrOk = blockPtrOk ? fCurrentBlock->GetDspCount() > 0 : false;
713 0 : 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 0 : detail = Form(
717 : "At byte %lu in DDL %d, event %d, iBlock %d, iDsp %d [DSP ID: %d (0x%X)],"
718 : " iBus %d [bus patch ID: %d (0x%X)].",
719 0 : (unsigned long)location - (unsigned long)fBufferStart + sizeof(AliRawDataHeaderV3),
720 0 : AliDAQ::DdlID("MUONTRK", fRawStream->GetDDL()),
721 0 : fRawStream->GetReader()->GetEventIndex(),
722 0 : int(fBlockCount)-1,
723 0 : blockPtrOk ? int(fCurrentBlock->GetDspCount())-1 : -1,
724 0 : blockPtrOk ? fCurrentBlock->GetDspId() : -1,
725 0 : blockPtrOk ? fCurrentBlock->GetDspId() : -1,
726 0 : dspPtrOk ? int(fCurrentDSP->GetBusPatchCount())-1 : -1,
727 0 : buspatchPtrOk ? fCurrentBusPatch->GetBusPatchId() : -1,
728 0 : buspatchPtrOk ? fCurrentBusPatch->GetBusPatchId() : -1
729 : );
730 0 : }
731 :
732 : // Build the log message.
733 0 : switch (error)
734 : {
735 : case kGlitchFound:
736 0 : fGlitchErrors++;
737 0 : switch (fRawStream->GetLoggingDetailLevel())
738 : {
739 : case kLowErrorDetail:
740 : message = "Glitch error detected.";
741 0 : break;
742 : case kMediumErrorDetail:
743 0 : message = Form(
744 : "Glitch error detected in DSP %d (0x%X), skipping event.",
745 0 : fCurrentBlock->GetDspId(), fCurrentBlock->GetDspId()
746 : );
747 0 : break;
748 : case kHighErrorDetail:
749 : default:
750 0 : message = Form("%s %s", ErrorCodeToMessage(error), detail);
751 0 : break;
752 : }
753 : logAsMajorError = true;
754 0 : break;
755 :
756 : case kBadPaddingWord:
757 0 : fPaddingErrors++;
758 0 : switch (fRawStream->GetLoggingDetailLevel())
759 : {
760 : case kLowErrorDetail:
761 : message = "Padding word error detected.";
762 0 : break;
763 : case kMediumErrorDetail:
764 : // We subtract 1 from the current numbers of blocks, DSPs
765 : // and bus patches to get the indices.
766 0 : message = Form(
767 : "Padding word error for iBlock %d, iDsp %d, iBus %d.",
768 0 : fBlockCount-1,
769 0 : fCurrentBlock->GetDspCount()-1,
770 0 : fCurrentDSP->GetBusPatchCount()-1
771 : );
772 0 : break;
773 : case kHighErrorDetail:
774 : default:
775 0 : message = Form("%s %s", ErrorCodeToMessage(error), detail);
776 0 : break;
777 : }
778 : logAsMajorError = false;
779 0 : break;
780 :
781 : case kParityError:
782 0 : fParityErrors++;
783 0 : switch (fRawStream->GetLoggingDetailLevel())
784 : {
785 : case kLowErrorDetail:
786 : message = "Parity error detected.";
787 0 : break;
788 : case kMediumErrorDetail:
789 0 : message = Form(
790 : "Parity error in buspatch %d (0x%X).",
791 0 : fCurrentBusPatch->GetBusPatchId(),
792 0 : fCurrentBusPatch->GetBusPatchId()
793 : );
794 0 : 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.
801 0 : word = (reinterpret_cast<size_t>(location) - reinterpret_cast<size_t>(fCurrentBusPatch->GetData()))
802 0 : / sizeof(UInt_t);
803 0 : message = Form(
804 : "Parity error in word %d for manuId %d and channel %d in buspatch %d. %s",
805 : word,
806 0 : fCurrentBusPatch->GetManuId(word),
807 0 : fCurrentBusPatch->GetChannelId(word),
808 0 : fCurrentBusPatch->GetBusPatchId(),
809 : detail
810 : );
811 0 : break;
812 : }
813 : logAsMajorError = false;
814 0 : break;
815 :
816 : case kTokenLost:
817 0 : fTokenLostErrors++;
818 0 : switch (fRawStream->GetLoggingDetailLevel())
819 : {
820 : case kLowErrorDetail:
821 : message = "Lost token error detected.";
822 0 : break;
823 : case kMediumErrorDetail:
824 0 : word = *reinterpret_cast<const UInt_t*>(location);
825 0 : message = Form(
826 : "Lost token error detected with address 0x%X of DDL %d and code %d.",
827 0 : ((word & 0xFFFF0000)),
828 0 : fRawStream->GetDDL(),
829 0 : (word & 0xF)
830 : );
831 0 : break;
832 : case kHighErrorDetail:
833 : default:
834 0 : word = *reinterpret_cast<const UInt_t*>(location);
835 0 : message = Form(
836 : "Lost token error detected with address 0x%X and code %d. %s",
837 0 : ((word & 0xFFFF0000)),
838 0 : (word & 0xF),
839 : detail
840 : );
841 0 : break;
842 : }
843 : logAsMajorError = false;
844 0 : break;
845 :
846 : default:
847 0 : switch (fRawStream->GetLoggingDetailLevel())
848 : {
849 : case kLowErrorDetail:
850 0 : message = ErrorCodeToMessage(error);
851 0 : break;
852 : case kMediumErrorDetail:
853 0 : message = Form(
854 : "%s (At byte %lu)",
855 0 : ErrorCodeToMessage(error),
856 0 : (unsigned long)location - (unsigned long)fBufferStart + sizeof(AliRawDataHeaderV3)
857 : );
858 0 : break;
859 : case kHighErrorDetail:
860 : default:
861 0 : message = Form(
862 : "%s Error code: %d (%s). %s",
863 0 : ErrorCodeToMessage(error),
864 0 : error, ErrorCodeToString(error),
865 : detail
866 : );
867 0 : break;
868 : }
869 : logAsMajorError = true;
870 0 : break;
871 : }
872 :
873 : // Now log the error message depending on the logging flags set.
874 0 : if (fRawStream->IsRawReaderErrorLoggerEnabled())
875 : {
876 0 : if (logAsMajorError)
877 0 : fRawStream->GetReader()->AddMajorErrorLog(Int_t(error), message);
878 : else
879 0 : fRawStream->GetReader()->AddMinorErrorLog(Int_t(error), message);
880 : }
881 0 : if (fRawStream->IsMUONErrorLoggerEnabled())
882 : {
883 0 : AliMUONLogger* logger = fRawStream->GetMUONErrorLogger();
884 0 : if (logger != NULL)
885 : {
886 0 : logger->Log(message);
887 0 : }
888 : else
889 : {
890 0 : AliErrorGeneral(
891 : "AliMUONRawStreamTrackerHP::AliDecoderEventHandler",
892 : "Enabled logging to AliMUONLogger, but the logger object"
893 : " was not set with SetMUONErrorLogger()."
894 : );
895 : }
896 0 : }
897 0 : if (fRawStream->IsWarningsEnabled())
898 : {
899 0 : AliWarningGeneral(
900 : "AliMUONRawStreamTrackerHP::AliDecoderEventHandler",
901 : message
902 : );
903 0 : }
904 0 : }
905 :
|