1 /**************************************************************************
2 * This file is property of and copyright by the ALICE HLT Project *
3 * All rights reserved. *
6 * Artur Szostak <artursz@iafrica.com> *
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 **************************************************************************/
20 /// \file AliMUONRawStreamTrackerHP.cxx
21 /// \author Artur Szostak <artursz@iafrica.com>
23 /// \brief Implementation of the the high performance decoder AliMUONRawStreamTrackerHP.
26 //-----------------------------------------------------------------------------
28 /// \class AliMUONRawStreamTrackerHP
29 /// \brief A high performance stream decoder for muon tracking DDL streams.
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:
36 /// const AliBusPatch* Next();
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.
43 /// \author Artur Szostak <artursz@iafrica.com>
44 //-----------------------------------------------------------------------------
46 #include "AliMUONRawStreamTrackerHP.h"
47 #include "AliRawReader.h"
58 ClassImp(AliMUONRawStreamTrackerHP)
62 AliMUONRawStreamTrackerHP::AliMUONRawStreamTrackerHP() :
63 AliMUONVRawStreamTracker(),
67 fBuffer(new UChar_t[8192]),
68 fCurrentBusPatch(NULL),
75 /// Default constructor.
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);
83 fDecoder.GetHandler().SetMaxStructs(
86 fDecoder.MaxBusPatches()
89 fDecoder.GetHandler().SetRawStream(this);
93 AliMUONRawStreamTrackerHP::AliMUONRawStreamTrackerHP(AliRawReader* rawReader) :
94 AliMUONVRawStreamTracker(rawReader),
98 fBuffer(new UChar_t[8192]),
99 fCurrentBusPatch(NULL),
106 /// Constructor with AliRawReader as argument.
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);
114 fDecoder.GetHandler().SetMaxStructs(
115 fDecoder.MaxBlocks(),
117 fDecoder.MaxBusPatches()
120 fDecoder.GetHandler().SetRawStream(this);
124 AliMUONRawStreamTrackerHP::~AliMUONRawStreamTrackerHP()
127 /// Default destructor.
137 void AliMUONRawStreamTrackerHP::First()
139 /// Initialise or reset the iterator.
140 /// The first DDL will be found and decoded.
142 assert( GetReader() != NULL );
150 Bool_t AliMUONRawStreamTrackerHP::NextDDL()
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.
156 assert( GetReader() != NULL );
158 while (fDDL < GetMaxDDL())
160 GetReader()->Reset();
161 GetReader()->Select("MUONTRK", fDDL, fDDL); // Select the DDL file to be read.
162 if (GetReader()->ReadHeader()) break;
163 AliDebug(3, Form("Skipping DDL %d which does not seem to be there", fDDL+1));
167 // If we reach the end of the DDL list for this event then reset the
168 // DDL counter, mark the iteration as done and
169 if (fDDL >= GetMaxDDL())
180 AliDebug(3, Form("DDL Number %d\n", fDDL));
182 Int_t dataSize = GetReader()->GetDataSize(); // in bytes
183 // Check if we have enough buffer space already in fBuffer. If we do then
184 // just continue reading otherwise we need to resize the buffer.
185 if (fBufferSize < dataSize)
195 fBuffer = new UChar_t[dataSize];
196 fBufferSize = dataSize;
198 catch (const std::bad_alloc&)
200 AliError("Could not allocate more buffer space. Cannot decode DDL.");
205 if (not GetReader()->ReadNext(fBuffer, dataSize))
211 Swap(reinterpret_cast<UInt_t*>(fBuffer), dataSize / sizeof(UInt_t)); // Swap needed for mac power pc.
217 // Since we might allocate memory inside OnNewBuffer in the event
218 // handler we need to trap any memory allocation exception to be robust.
219 result = fDecoder.Decode(fBuffer, dataSize);
220 fHadError = (result == true ? kFALSE : kTRUE);
222 catch (const std::bad_alloc&)
224 AliError("Could not allocate more buffer space. Cannot decode DDL.");
228 // Update the current bus patch pointers.
229 fCurrentBusPatch = fDecoder.GetHandler().FirstBusPatch();
230 if (fCurrentBusPatch != fDecoder.GetHandler().EndOfBusPatch())
232 fCurrentData = fCurrentBusPatch->GetData();
233 fEndOfData = fCurrentData + fCurrentBusPatch->GetDataCount();
237 // If the DDL did not have any bus patches then mark both fCurrentData
238 // and fEndOfData as NULL so that in Next() we are forced to find the
239 // first non empty DDL.
240 fCurrentData = fEndOfData = NULL;
243 fDDL++; // Remember to increment index to next DDL.
248 Bool_t AliMUONRawStreamTrackerHP::IsDone() const
250 /// Indicates whether the iteration is finished or not.
251 /// \return kTRUE if we already read all the digits and kFALSE if not.
257 Bool_t AliMUONRawStreamTrackerHP::Next(
258 Int_t& busPatchId, UShort_t& manuId, UChar_t& manuChannel,
262 /// Advance one step in the iteration. Returns false if finished.
263 /// [out] \param busPatchId This is filled with the bus patch ID of the digit.
264 /// [out] \param manuId This is filled with the MANU ID of the digit.
265 /// [out] \param manuChannel This is filled with the MANU channel ID of the digit.
266 /// [out] \param adc This is filled with the ADC signal value of the digit.
267 /// \return kTRUE if we read another digit and kFALSE if we have read all the
268 /// digits already, i.e. at the end of the iteration.
271 // Check if we still have data to be returned for the current bus patch.
272 if (fCurrentData != fEndOfData)
274 busPatchId = fCurrentBusPatch->GetBusPatchId();
275 AliMUONTrackerDDLDecoderEventHandler::UnpackADC(*fCurrentData, manuId, manuChannel, adc);
281 // We hit the end of the current bus patch so check if we have any more
282 // bus patches to process for the current DDL. If we do, then increment
283 // the current bus patch, make sure it is not the last one and then try
284 // reading the first element again.
285 if (fCurrentBusPatch != fDecoder.GetHandler().EndOfBusPatch())
288 if (fCurrentBusPatch != fDecoder.GetHandler().EndOfBusPatch())
290 fCurrentData = fCurrentBusPatch->GetData();
291 fEndOfData = fCurrentData + fCurrentBusPatch->GetDataCount();
296 // This was the last bus patch in the DDL so read in the next one and
297 // try reading the first data element again.
298 // Note: fCurrentBusPatch is set inside NextDDL().
299 if (NextDDL()) goto retry;
305 void AliMUONRawStreamTrackerHP::SetMaxBlock(Int_t blk)
307 /// Set maximum number of blocks per DDL allowed.
308 fDecoder.MaxBlocks( (UInt_t) blk );
310 fDecoder.GetHandler().SetMaxStructs(
311 fDecoder.MaxBlocks(),
313 fDecoder.MaxBusPatches()
318 void AliMUONRawStreamTrackerHP::SetMaxDsp(Int_t dsp)
320 /// Set maximum number of Dsp per block allowed.
321 fDecoder.MaxDSPs( (UInt_t) dsp );
323 fDecoder.GetHandler().SetMaxStructs(
324 fDecoder.MaxBlocks(),
326 fDecoder.MaxBusPatches()
331 void AliMUONRawStreamTrackerHP::SetMaxBus(Int_t bus)
333 /// Set maximum number of Buspatch per Dsp allowed.
334 fDecoder.MaxBusPatches( (UInt_t) bus );
336 fDecoder.GetHandler().SetMaxStructs(
337 fDecoder.MaxBlocks(),
339 fDecoder.MaxBusPatches()
343 ///////////////////////////////////////////////////////////////////////////////
345 void AliMUONRawStreamTrackerHP::AliBlockHeader::Print() const
347 /// Print header to screen.
349 cout << "CRT info" << endl;
352 cout << "Header is NULL" << endl;
355 cout << "DataKey: 0x" << hex << fHeader->fDataKey << dec << endl;
356 cout << "TotalLength: " << fHeader->fTotalLength << endl;
357 cout << "Length: " << fHeader->fLength << endl;
358 cout << "DspId: " << fHeader->fDSPId << endl;
359 cout << "L0Trigger: " << fHeader->fL0Trigger << endl;
360 cout << "MiniEventId: " << fHeader->fMiniEventId<< endl;
361 cout << "EventId1: " << fHeader->fEventId1 << endl;
362 cout << "EventId2: " << fHeader->fEventId2 << endl;
366 void AliMUONRawStreamTrackerHP::AliDspHeader::Print() const
368 /// Print header to screen.
370 cout << "FRT info" << endl;
373 cout << "Header is NULL" << endl;
376 cout << "DataKey: 0x" << hex << fHeader->fDataKey << dec << endl;
377 cout << "TotalLength: " << fHeader->fTotalLength << endl;
378 cout << "Length : " << fHeader->fLength << endl;
379 cout << "DspId: " << fHeader->fDSPId << endl;
380 cout << "BlkL1ATrigger: " << fHeader->fBlkL1ATrigger << endl;
381 cout << "MiniEventId: " << fHeader->fMiniEventId << endl;
382 cout << "L1ATrigger: " << fHeader->fL1ATrigger << endl;
383 cout << "L1RTrigger: " << fHeader->fL1RTrigger << endl;
384 cout << "PaddingWord: " << fHeader->fPaddingWord << endl;
385 cout << "ErrorWord: " << fHeader->fErrorWord << endl;
389 void AliMUONRawStreamTrackerHP::AliBusPatch::Print(const Option_t* opt) const
391 /// Print header to screen.
392 cout << "Bus patch info" << endl;
395 cout << "Header is NULL" << endl;
398 cout << "DataKey: 0x" << hex << fHeader->fDataKey << dec << endl;
399 cout << "fTotalLength: " << fHeader->fTotalLength << endl;
400 cout << "fLength: " << fHeader->fLength << endl;
401 cout << "fBusPatchId: " << fHeader->fBusPatchId << endl;
403 if (TString(opt).Contains("all"))
405 for (UInt_t i = 0; i < fHeader->fLength; ++i)
406 cout << "Data["<< i << "] = " << fData[i] << endl;
410 ///////////////////////////////////////////////////////////////////////////////
412 AliMUONRawStreamTrackerHP::AliDecoderEventHandler::AliDecoderEventHandler() :
419 fEndOfBusPatches(NULL),
421 fParityOk(new Bool_t[8192]),
424 fCurrentBusPatch(NULL),
425 fCurrentParityOkFlag(NULL),
431 /// Default constructor initialises the internal parity flags buffer to
432 /// store 8192 elements. This array will grow dynamically if needed.
436 AliMUONRawStreamTrackerHP::AliDecoderEventHandler::~AliDecoderEventHandler()
438 /// Default destructor cleans up the allocated memory.
440 if (fParityOk != NULL) delete [] fParityOk;
441 if (fBlocks != NULL) delete [] fBlocks;
442 if (fDSPs != NULL) delete [] fDSPs;
443 if (fBusPatches != NULL) delete [] fBusPatches;
447 void AliMUONRawStreamTrackerHP::AliDecoderEventHandler::SetMaxStructs(
448 UInt_t maxBlocks, UInt_t maxDsps, UInt_t maxBusPatches
451 /// Sets the maximum number of structures allowed.
453 // Start by clearing the current arrays.
464 if (fBusPatches != NULL)
466 delete [] fBusPatches;
469 fCurrentBlock = NULL;
471 fCurrentBusPatch = NULL;
473 // Allocate new memory.
474 fBlocks = new AliBlockHeader[maxBlocks];
475 fDSPs = new AliDspHeader[maxBlocks*maxDsps];
476 fBusPatches = new AliBusPatch[maxBlocks*maxDsps*maxBusPatches];
477 fEndOfBusPatches = fEndOfBusPatches;
481 void AliMUONRawStreamTrackerHP::AliDecoderEventHandler::OnNewBuffer(
482 const void* buffer, UInt_t bufferSize
485 /// This is called by the high performance decoder when a new DDL payload
486 /// is about to be decoded.
487 /// \param buffer The pointer to the buffer storing the DDL payload.
488 /// \param bufferSize The size of the buffer in bytes.
490 assert( fRawStream != NULL );
492 // remember the start of the buffer to be used in OnError.
493 fBufferStart = buffer;
495 // Reset error counters.
500 // Check if we will have enough space in the fParityOk array.
501 // If we do not then we need to resize the array.
502 // bufferSize / sizeof(UInt_t) will be a safe over estimate of the
503 // number of channels that we will find.
504 UInt_t maxChannelsPossible = bufferSize / sizeof(UInt_t);
505 if (maxChannelsPossible > fMaxChannels)
507 if (fParityOk != NULL)
513 fParityOk = new Bool_t[maxChannelsPossible];
514 fMaxChannels = maxChannelsPossible;
517 // Reset the current pointers which will be used to track where we need to
518 // fill fBlocks, fDSPs, fBusPatches and the parity flag. We have to subtract
519 // one space because we will increment the pointer the first time in the
521 fCurrentBlock = fBlocks-1;
522 fCurrentDSP = fDSPs-1;
523 fCurrentBusPatch = fBusPatches-1;
524 fCurrentParityOkFlag = fParityOk-1;
529 void AliMUONRawStreamTrackerHP::AliDecoderEventHandler::OnError(
530 ErrorCode error, const void* location
533 /// This is called by the high performance decoder when a error occurs
534 /// when trying to decode the DDL payload. This indicates corruption in
535 /// the data. This method converts the error code to a descriptive message
536 /// and log this with the raw reader.
537 /// \param error The error code indicating the problem.
538 /// \param location A pointer to the location within the DDL payload buffer
539 /// being decoded where the problem with the data was found.
541 assert( fRawStream != NULL );
542 assert( fRawStream->GetReader() != NULL );
544 Char_t* message = NULL;
551 "Glitch error detected in DSP %d, skipping event ",
552 fCurrentBlock->GetDspId()
554 fRawStream->GetReader()->AddMajorErrorLog(error, message);
557 case kBadPaddingWord:
558 // We subtract 1 from the current numbers of blocks, DSPs
559 // and bus patches to get the indices.
561 "Padding word error for iBlock %d, iDsp %d, iBus %d\n",
563 fCurrentBlock->GetDspCount()-1,
564 fCurrentDSP->GetBusPatchCount()-1
566 fRawStream->GetReader()->AddMinorErrorLog(error, message);
570 // location points to the incorrect data word and
571 // fCurrentBusPatch->GetData() returns a pointer to the start of
572 // bus patches data, so the difference divided by 4 gives the 32
574 word = ((unsigned long)location - (unsigned long)fCurrentBusPatch->GetData())
577 "Parity error in word %d for manuId %d and channel %d in buspatch %d\n",
579 fCurrentBusPatch->GetManuId(word),
580 fCurrentBusPatch->GetChannelId(word),
581 fCurrentBusPatch->GetBusPatchId()
583 fRawStream->GetReader()->AddMinorErrorLog(error, message);
588 "%s (At byte %d in DDL.)",
589 ErrorCodeToMessage(error),
590 (unsigned long)location - (unsigned long)fBufferStart
592 fRawStream->GetReader()->AddMajorErrorLog(error, message);
599 "AliMUONRawStreamTrackerHP::AliDecoderEventHandler",