X-Git-Url: http://git.uio.no/git/?a=blobdiff_plain;f=MUON%2FAliMUONRawStreamTrackerHP.h;h=9f9be0dbe8b0614eaa838ab26a23a429667ea909;hb=0a918d8d80e9900008464c3bb616f57b0c154abf;hp=f4fbc8e0567473afa03b5ea0fcb3b4447678b0d4;hpb=e3a2b9c9edb56742c252e886eaabd26f6f96b597;p=u%2Fmrichter%2FAliRoot.git diff --git a/MUON/AliMUONRawStreamTrackerHP.h b/MUON/AliMUONRawStreamTrackerHP.h index f4fbc8e0567..9f9be0dbe8b 100644 --- a/MUON/AliMUONRawStreamTrackerHP.h +++ b/MUON/AliMUONRawStreamTrackerHP.h @@ -13,12 +13,30 @@ /// \brief Declaration of the high performance decoder for muon trigger chamber raw streams. /// -#include "AliMUONVRawStreamTracker.h" +#ifndef ROOT_TObject +# include "TObject.h" +#endif #include "AliMUONTrackerDDLDecoder.h" -class AliMUONRawStreamTrackerHP : public AliMUONVRawStreamTracker +#include + +class AliMUONDDLTracker; +class AliRawReader; +class AliMUONLogger; + +class AliMUONRawStreamTrackerHP : public TObject { public: + class AliDspHeader; + class AliBusPatch; + + /// Values indicating the logging detail level to use for error messages. + enum EDetailLevel + { + kLowErrorDetail, /// Logs minimal information in the error messages. + kMediumErrorDetail, /// Logs a medium level of detail in the error messages. + kHighErrorDetail /// Logs maximum information in the error messages. + }; /// Default constructor. AliMUONRawStreamTrackerHP(); @@ -29,7 +47,11 @@ public: /// Default destructor. virtual ~AliMUONRawStreamTrackerHP(); - // The following public methods are all inherited from AliMUONVRawStreamTracker: + /// Get object for reading the raw data + virtual AliRawReader* GetReader() { return fRawReader; } + + /// Set the raw reader + void SetReader(AliRawReader* reader) { fRawReader = reader; } /// Initialize iterator virtual void First(); @@ -39,18 +61,24 @@ public: /// Whether the iteration is finished or not virtual Bool_t IsDone() const; - - /// Nothing is actually done in the AddErrorMessage method because we log - /// the error messages as we find them in AliDecoderEventHandler::OnError(). - virtual void AddErrorMessage() {}; + + /// Advance one step in the iteration. Returns false if finished. + virtual Bool_t Next(Int_t& busPatchId, + UShort_t& manuId, UChar_t& manuChannel, + UShort_t& adc) { return Next(busPatchId,manuId,manuChannel,adc,kTRUE); } /// Advance one step in the iteration. Returns false if finished. virtual Bool_t Next(Int_t& busPatchId, - UShort_t& manuId, UChar_t& manuChannel, - UShort_t& adc); + UShort_t& manuId, + UChar_t& manuChannel, + UShort_t& adc, + Bool_t skipParityErrors); + + /// Construct and return a pointer to the DDL payload object. + virtual AliMUONDDLTracker* GetDDLTracker() const; /// Returns the next batch of decoded channel data. - virtual UInt_t Next(const AliChannelInfo*& channels); + const AliBusPatch* Next(); /// Return maximum number of blocks per DDL allowed. virtual Int_t GetMaxBlock() const { return (Int_t) fDecoder.MaxBlocks(); } @@ -60,17 +88,503 @@ public: virtual Int_t GetMaxBus() const { return (Int_t) fDecoder.MaxBusPatches(); } /// Set maximum number of blocks per DDL allowed. - virtual void SetMaxBlock(Int_t blk) { fDecoder.MaxBlocks( (UInt_t) blk ); } + virtual void SetMaxBlock(Int_t blk); /// Set maximum number of Dsp per block allowed. - virtual void SetMaxDsp(Int_t dsp) { fDecoder.MaxDSPs( (UInt_t) dsp ); } + virtual void SetMaxDsp(Int_t dsp); /// Set maximum number of Buspatch per Dsp allowed. - virtual void SetMaxBus(Int_t bus) { fDecoder.MaxBusPatches( (UInt_t) bus ); } + virtual void SetMaxBus(Int_t bus); - /// Return number of the current DDL. + /// Return number of the current DDL being processed in the range [0..19] or -1 if no DDL set. virtual Int_t GetDDL() const { return fDDL - 1; } /// check error/Warning presence virtual Bool_t IsErrorMessage() const { return fHadError; } + + /// Get number of parity errors in the DDL last decoded. + Int_t GetParityErrors() const + { + return (Int_t) fDecoder.GetHandler().ParityErrorCount(); + } + + /// Get number of glitch errors in the DDL last decoded. + Int_t GetGlitchErrors() const + { + return (Int_t) fDecoder.GetHandler().GlitchErrorCount(); + } + + /// Get number of padding word errors in the DDL last decoded. + Int_t GetPaddingErrors() const + { + return (Int_t) fDecoder.GetHandler().PaddingErrorCount(); + } + + /// Get number of token lost errors in the DDL last decoded. + Int_t GetTokenLostErrors() const + { + return (Int_t) fDecoder.GetHandler().TokenLostCount(); + } + + /// Set warnings flag to disable warnings on data errors. + void DisableWarnings() { fWarnings = kFALSE; } + /// Set warnings flag to enable warnings on data errors. + void EnableWarnings() { fWarnings = kTRUE; } + + /// Returns the flag indicating if we should generate a warning for errors. + Bool_t IsWarningsEnabled() const { return fWarnings; } + + /// Returns the "try to recover from errors" flag. + Bool_t TryRecover() const { return Bool_t(fDecoder.TryRecover()); } + + /// Sets the "try to recover from errors" flag. + /// i.e. should the decoder try to recover from errors found in the + /// payload headers. + void TryRecover(Bool_t value) { fDecoder.TryRecover(bool(value)); } + + /// Returns the auto-detect trailer words flag. + Bool_t AutoDetectTrailer() const { return Bool_t(fDecoder.AutoDetectTrailer()); } + + /// Sets the auto-detect trailer words flag. + /// When set to true the decoder will try to detect if the end of DDL + /// keys are in the trailer words or not. These are generated by the + /// detector but not the older versions of AliRoot simulations. + void AutoDetectTrailer(Bool_t value) { fDecoder.AutoDetectTrailer(bool(value)); } + + /// Returns the flag indicating if the data is expected to have the + /// end of DDL keys in the trailer. This flag is ignored if AutoDetectTrailer() + /// was set to true. + Bool_t CheckForTrailer() const { return Bool_t(fDecoder.CheckForTrailer()); } + + /// Sets the flag indicating if the trailer words should contain the + /// end of DDL key. + void CheckForTrailer(Bool_t value) { fDecoder.CheckForTrailer(bool(value)); } + + /// Light weight interface class to the block header data. + class AliBlockHeader + { + public: + /// Default constructor. + AliBlockHeader( + AliDspHeader* dspArray = NULL, + const AliMUONBlockHeaderStruct* header = NULL + ) + : fNext(NULL), fDspCount(0), fFirstDsp(dspArray), fHeader(header) + { + } + + /// Implement shallow copying in the copy constructor. + AliBlockHeader(const AliBlockHeader& o) : + fNext(o.fNext), fDspCount(o.fDspCount), fFirstDsp(o.fFirstDsp), fHeader(o.fHeader) + { + } + + /// Implement shallow copying in the assignment operator. + AliBlockHeader& operator = (const AliBlockHeader& object) + { + memcpy(this, &object, sizeof(AliBlockHeader)); + return *this; + } + + /// Default destructor. + ~AliBlockHeader() {}; + + /// Return data key word for CRT header + Int_t GetDataKey() const {assert(fHeader != NULL); return fHeader->fDataKey;} + /// Return total length of block structure (w/o padding word) + Int_t GetTotalLength() const {assert(fHeader != NULL); return fHeader->fTotalLength;} + /// Return length of raw data + Int_t GetLength() const {assert(fHeader != NULL); return fHeader->fLength;} + /// Return Dsp id + Int_t GetDspId() const {assert(fHeader != NULL); return fHeader->fDSPId;} + /// Return L0 trigger word + Int_t GetL0Trigger() const {assert(fHeader != NULL); return fHeader->fL0Trigger;} + /// Return Bunch Crossing for mini-event id (see TDR chapter 8) + Int_t GetMiniEventId() const {assert(fHeader != NULL); return fHeader->fMiniEventId;} + /// Return Event Id in bunch crossing + Int_t GetEventId1() const {assert(fHeader != NULL); return fHeader->fEventId1;} + /// Return Event Id in orbit number + Int_t GetEventId2() const {assert(fHeader != NULL); return fHeader->fEventId2;} + + /// Return the header's raw data. + const AliMUONBlockHeaderStruct* GetHeader() const {return fHeader;} + + /// Return the next block header. + const AliBlockHeader* Next() const { return fNext; } + + /// Returns the first AliDspHeader class in this block. + const AliDspHeader* GetFirstDspHeader() const { return fFirstDsp; } + + /// Returns the number of DSPs within this block. + UInt_t GetDspCount() const { return fDspCount; } + + /// Return the i'th DSP in this block. + const AliDspHeader* GetDspHeader(UInt_t i) const + { + return i < fDspCount ? GetFirstDspHeader() + i : NULL; + } + + /// Sets the next block header. + void SetNext(const AliBlockHeader* next) { fNext = next; } + + /// Increments the DSP count. + void IncDspCount() { fDspCount++; }; + + /// Print the contents of the header to screen. + void Print() const; + + private: + + const AliBlockHeader* fNext; ///< Pointer to next block. + UInt_t fDspCount; ///< The number of AliDspHeader objects found in the array pointed to by fFirstDsp. + const AliDspHeader* fFirstDsp; ///< The first DSP associated with this block. + const AliMUONBlockHeaderStruct* fHeader; ///< Pointer to header in DDL payload. + }; + + /// Light weight interface class to the DSP header data. + class AliDspHeader + { + public: + /// Default constructor. + AliDspHeader( + const AliBlockHeader* block = NULL, + const AliBusPatch* busPatchArray = NULL, + const AliMUONDSPHeaderStruct* header = NULL + ) : + fBlock(block), fNext(NULL), fBusPatchCount(0), + fFirstBusPatch(busPatchArray), fHeader(header) + { + } + + /// Implement shallow copying in the copy constructor. + AliDspHeader(const AliDspHeader& o) : + fBlock(o.fBlock), fNext(o.fNext), fBusPatchCount(o.fBusPatchCount), + fFirstBusPatch(o.fFirstBusPatch), fHeader(o.fHeader) + { + } + + /// Implement shallow copying in the assignment operator. + AliDspHeader& operator = (const AliDspHeader& object) + { + memcpy(this, &object, sizeof(AliDspHeader)); + return *this; + } + + /// Default destructor. + ~AliDspHeader() {}; + + /// Return Data key word for FRT header + Int_t GetDataKey() const {assert(fHeader != NULL); return fHeader->fDataKey;} + /// Return total length of block structure + Int_t GetTotalLength() const {assert(fHeader != NULL); return fHeader->fTotalLength;} + /// Return length of raw data + Int_t GetLength() const {assert(fHeader != NULL); return fHeader->fLength;} + /// Return Dsp id + Int_t GetDspId() const {assert(fHeader != NULL); return fHeader->fDSPId;} + /// Return L1 accept in Block Structure (CRT) + Int_t GetBlkL1ATrigger() const {assert(fHeader != NULL); return fHeader->fBlkL1ATrigger;} + /// Return Mini Event Id in bunch crossing + Int_t GetMiniEventId() const {assert(fHeader != NULL); return fHeader->fMiniEventId;} + /// Return Number of L1 accept in DSP Structure (FRT) + Int_t GetL1ATrigger() const {assert(fHeader != NULL); return fHeader->fL1ATrigger;} + /// Return Number of L1 reject in DSP Structure (FRT) + Int_t GetL1RTrigger() const {assert(fHeader != NULL); return fHeader->fL1RTrigger;} + /// Return padding dummy word for 64 bits transfer + UInt_t GetPaddingWord() const {assert(fHeader != NULL); return fHeader->fPaddingWord;} + /// Return Error word + Int_t GetErrorWord() const {assert(fHeader != NULL); return fHeader->fErrorWord;} + + /// Return raw data of header + const AliMUONDSPHeaderStruct* GetHeader() const { return fHeader; } + + /// Return the parent block header. + const AliBlockHeader* GetBlockHeader() const { return fBlock; } + + /// Return the next DSP header. + const AliDspHeader* Next() const { return fNext; } + + /// Returns the first AliBusPatch class in this DSP. + const AliBusPatch* GetFirstBusPatch() const { return fFirstBusPatch; } + + /// Returns the number of bus patches within this DSP. + UInt_t GetBusPatchCount() const { return fBusPatchCount; } + + /// Return the i'th bus patch in this DSP. + const AliBusPatch* GetBusPatch(UInt_t i) const + { + return i < fBusPatchCount ? GetFirstBusPatch() + i : NULL; + } + + /// Sets the next DSP header. + void SetNext(const AliDspHeader* next) { fNext = next; } + + /// Increments the bus patch count. + void IncBusPatchCount() { fBusPatchCount++; }; + + /// Print the contents of the header to screen. + void Print() const; + + private: + + const AliBlockHeader* fBlock; ///< Pointer to parent block structure. + const AliDspHeader* fNext; ///< Pointer to next DSP. + UInt_t fBusPatchCount; ///< The number of AliDspHeader objects found in the array pointed to by fFirstBusPatch + const AliBusPatch* fFirstBusPatch; ///< The first bus patch of this DSP. + const AliMUONDSPHeaderStruct* fHeader; ///< Pointer to header in DDL payload. + }; + + /// Light weight interface class to the bus patch data. + class AliBusPatch + { + public: + /// Default constructor. + AliBusPatch( + const AliDspHeader* dsp = NULL, + const AliMUONBusPatchHeaderStruct* header = NULL, + const UInt_t* data = NULL, + const Bool_t* parityOk = NULL + ) : + fDSP(dsp), + fNext(NULL), + fHeader(header), + fData(data), + fParityOk(parityOk) + { + } + + /// Implement shallow copying in the copy constructor. + AliBusPatch(const AliBusPatch& o) : + fDSP(o.fDSP), + fNext(o.fNext), + fHeader(o.fHeader), + fData(o.fData), + fParityOk(o.fParityOk) + { + } + + /// Implement shallow copying in the assignment operator. + AliBusPatch& operator = (const AliBusPatch& object) + { + memcpy(this, &object, sizeof(AliBusPatch)); + return *this; + } + + /// Default destructor. + ~AliBusPatch() {}; + + /// Return Data key word for bus patch header. + Int_t GetDataKey() const {assert(fHeader != NULL); return fHeader->fDataKey;} + /// Return total length of buspatch structure + Int_t GetTotalLength() const {assert(fHeader != NULL); return fHeader->fTotalLength;} + /// Return length of raw data + Int_t GetLength() const {assert(fHeader != NULL); return fHeader->fLength;} + /// Return bus patch id + Int_t GetBusPatchId() const {assert(fHeader != NULL); return fHeader->fBusPatchId;} + + /// Return raw data of header + const AliMUONBusPatchHeaderStruct* GetHeader() const {return fHeader;} + /// Return raw digit data + const UInt_t* GetData() const {return fData;} + /// Returns the number of raw data words within this bus patch. + UInt_t GetDataCount() const { return (UInt_t)GetLength(); } + + /// Returns the parity bit of the n'th raw data word. + Char_t GetParity(UInt_t n) const + { + assert( fHeader != NULL && n < fHeader->fLength ); + return (Char_t)(fData[n] >> 31) & 0x1; + } + + /// Returns the MANU ID of the n'th raw data word. + UShort_t GetManuId(UInt_t n) const + { + assert( fHeader != NULL && n < fHeader->fLength ); + return (UShort_t)(fData[n] >> 18) & 0x7FF; + } + + /// Returns the channel ID of the n'th raw data word. + UChar_t GetChannelId(UInt_t n) const + { + assert( fHeader != NULL && n < fHeader->fLength ); + return (Char_t)(fData[n] >> 12) & 0x3F; + } + + /// Returns the charge/signal of the n'th raw data word. + UShort_t GetCharge(UInt_t n) const + { + assert( fHeader != NULL && n < fHeader->fLength ); + return (UShort_t)(fData[n] & 0xFFF); + } + + /// Returns the n'th raw data word. + UInt_t GetData(UInt_t n) const + { + assert( fHeader != NULL && n < fHeader->fLength ); + return fData[n]; + } + + /// Returns kTRUE if the parity of the n'th raw data word is OK + /// and kFALSE otherwise. + Bool_t IsParityOk(UInt_t n) const + { + assert( fHeader != NULL && n < fHeader->fLength ); + return fParityOk[n]; + } + + /// Unpacks and returns the fields of the n'th raw data word. kTRUE + /// is returned if the data word's parity was OK and kFALSE otherwise. + Bool_t GetData(UInt_t n, UShort_t& manuId, UChar_t& channelId, UShort_t& adc) const + { + assert( fHeader != NULL && n < fHeader->fLength ); + AliMUONTrackerDDLDecoderEventHandler::UnpackADC(fData[n], manuId, channelId, adc); + return fParityOk[n]; + } + + /// Return the parent block header. + const AliDspHeader* GetDspHeader() const { return fDSP; } + + /// Return the next bus patch header. + const AliBusPatch* Next() const { return fNext; } + + /// Sets the next bus patch. + void SetNext(const AliBusPatch* next) { fNext = next; } + + /// Print the contents of the bus patch to screen. + void Print(const Option_t* opt = "") const; + + private: + + const AliDspHeader* fDSP; ///< The DSP this bus patch belongs to. + const AliBusPatch* fNext; ///< Next bus patch object in the DSP. + const AliMUONBusPatchHeaderStruct* fHeader; ///< Pointer to bus patch in DDL payload. + const UInt_t* fData; ///< Pointer to the bus patch data. + const Bool_t* fParityOk; ///< Array of flags indicating if the parity of the given data word in fData is good or not. + }; + + /// Return the number of blocks in the DDL payload. + UInt_t GetBlockCount() const + { + return fDecoder.GetHandler().BlockCount(); + } + + /// Return the first block header. + const AliBlockHeader* GetFirstBlockHeader() const + { + return fDecoder.GetHandler().BlockHeader(0); + } + + /// Return the i'th block header or NULL if not found. + const AliBlockHeader* GetBlockHeader(UInt_t i) const + { + return fDecoder.GetHandler().BlockHeader(i); + } + + /// Returns the number of DSPs for the given block number. + UInt_t GetDspCount(UInt_t block) const + { + const AliBlockHeader* b = GetBlockHeader(block); + return b != NULL ? b->GetDspCount() : 0; + } + + /// Returns the i'th DSP header for the given block number or NULL if not found. + const AliDspHeader* GetDspHeader(UInt_t block, UInt_t i) const + { + const AliBlockHeader* b = GetBlockHeader(block); + return b != NULL ? b->GetDspHeader(i) : NULL; + } + + /// Returns the number of bus patches for the given block and dsp number. + UInt_t GetBusPatchCount(UInt_t block, UInt_t dsp) const + { + const AliDspHeader* d = GetDspHeader(block, dsp); + return d != NULL ? d->GetBusPatchCount() : 0; + } + + /// Returns the i'th bus patch for the given block and dsp. + const AliBusPatch* GetBusPatch(UInt_t block, UInt_t dsp, UInt_t i) const + { + const AliDspHeader* d = GetDspHeader(block, dsp); + return d != NULL ? d->GetBusPatch(i) : NULL; + } + + /// Returns the current bus patch being decoded or NULL if none found. + const AliBusPatch* CurrentBusPatch() const + { + return (fkCurrentBusPatch != fDecoder.GetHandler().EndOfBusPatch()) ? + fkCurrentBusPatch : NULL; + } + + /// Returns the current DSP being decoded or NULL if none found. + const AliDspHeader* CurrentDspHeader() const + { + const AliBusPatch* busPatch = CurrentBusPatch(); + return (busPatch != NULL) ? busPatch->GetDspHeader() : NULL; + } + + /// Returns the current block header being decoded or NULL if none found. + const AliBlockHeader* CurrentBlockHeader() const + { + const AliDspHeader* dsp = CurrentDspHeader(); + return (dsp != NULL) ? dsp->GetBlockHeader() : NULL; + } + + /// Enable error logging to the raw reader. \note Kept for backward compatibility. + virtual void EnabbleErrorLogger() { EnableRawReaderErrorLogger(); } + + /// Enable error info logging to AliMUONLogger. + void EnableMUONErrorLogger() { fEnableMUONErrorLogger = kTRUE; } + + /// Disable logging to AliMUONLogger. + void DisableMUONErrorLogger() { fEnableMUONErrorLogger = kFALSE; } + + /// Enable error info logging to raw reader. + void EnableRawReaderErrorLogger() { fEnableRawReaderErrorLogger = kTRUE; } + + /// Disable logging to the raw reader. + void DisableRawReaderErrorLogger() { fEnableRawReaderErrorLogger = kFALSE; } + + /// Check if the AliMUONLogger is enabled for error logging. + Bool_t IsMUONErrorLoggerEnabled() const { return fEnableMUONErrorLogger; } + + /// Check if the AliMUONLogger is enabled for error logging. + Bool_t IsRawReaderErrorLoggerEnabled() const { return fEnableRawReaderErrorLogger; } + + /// Returns the logger object. (constant version) + const AliMUONLogger* GetMUONErrorLogger() const { return fLogger; } + + /// Returns the logger object. + AliMUONLogger* GetMUONErrorLogger() { return fLogger; } + + /// Sets the logger object to use. Ownership of the logger object remains with the caller. + void SetMUONErrorLogger(AliMUONLogger* logger) { fLogger = logger; } + + /// Returns the level of detail used in the error messages. + EDetailLevel GetLoggingDetailLevel() const { return fDetailLevel; } + + /// Sets the level of detail used in the error messages. + void SetLoggingDetailLevel(EDetailLevel level) { fDetailLevel = level; } + + /// Number of glitch errors since First() was called + UInt_t NumberOfGlitchErrors() const { return fTotalNumberOfGlitchErrors; } + + /// Number of padding errors since First() was called + UInt_t NumberOfPaddingErrors() const { return fTotalNumberOfPaddingErrors; } + + /// Number of parity errors since First() was called + UInt_t NumberOfParityErrors() const { return fTotalNumberOfParityErrors; } + + /// Number of token lost errors since First() was called + UInt_t NumberOfTokenLostErrors() const { return fTotalNumberOfTokenLostErrors; } + + /// Whether we got glitch errors or not + Bool_t HasGlitchError() const { return NumberOfGlitchErrors() > 0; } + + /// Whether we got padding errors or not + Bool_t HasPaddingError() const { return NumberOfPaddingErrors() > 0; } + + /// Whether we got parity errors or not + Bool_t HasParityError() const { return NumberOfParityErrors() > 0; } + + /// Whether we got token lost errors or not + Bool_t HasTokenLostError() const { return NumberOfTokenLostErrors() > 0; } private: @@ -80,11 +594,15 @@ private: /// Not implemented AliMUONRawStreamTrackerHP& operator = (const AliMUONRawStreamTrackerHP& stream); + /// Return max number of tracker DDLs + Int_t GetMaxDDL() const { return fgkMaxDDL; } + + /// swap method for Power PC + virtual void Swap(UInt_t* buffer, Int_t size) const; + /// This is the custom event handler (callback interface) class which /// unpacks raw data words and fills an internal buffer with decoded digits /// as they are decoded by the high performance decoder. - /// Any errors are logged to the parent AliMUONVRawStreamTracker, so one - /// must set this pointer appropriately before decoding and DDL payload. class AliDecoderEventHandler : public AliMUONTrackerDDLDecoderEventHandler { public: @@ -94,25 +612,68 @@ private: /// Default destructor. virtual ~AliDecoderEventHandler(); + /// Sets the internal arrays based on the maximum number of structures allowed. + void SetMaxStructs(UInt_t maxBlocks, UInt_t maxDsps, UInt_t maxBusPatches); + /// Sets the raw stream object which should be the parent of this class. - void SetRawStream(AliMUONVRawStreamTracker* rawStream) { fRawStream = rawStream; } + void SetRawStream(AliMUONRawStreamTrackerHP* rawStream) { fRawStream = rawStream; } - /// Return the number of channels in the buffer returned by Channels(). - UInt_t ChannelCount() const { return fChannelCount; } + /// Return the number of blocks found in the payload. + UInt_t BlockCount() const { return fBlockCount; }; - /// Return the buffer of decoded channel data. - const AliChannelInfo* Channels() const { return fChannelBuffer; } + /// Return the i'th block structure. + const AliBlockHeader* BlockHeader(UInt_t i) const + { + return i < fBlockCount ? &fBlocks[i] : NULL; + } + + /// Return the first bus patch decoded. + const AliBusPatch* FirstBusPatch() const { return fBusPatches; } + + /// Returns the marker to the end of bus patches. i.e. one position past the last bus patch. + const AliBusPatch* EndOfBusPatch() const { return fEndOfBusPatches; } + + /// Returns the number of parity errors found in the DDL. + UInt_t ParityErrorCount() const { return fParityErrors; } + /// Returns the number of glitch errors found in the DDL. + UInt_t GlitchErrorCount() const { return fGlitchErrors; } + /// Returns the number of padding errors found in the DDL. + UInt_t PaddingErrorCount() const { return fPaddingErrors; } + /// Returns the number of token lost errors found in the DDL. + UInt_t TokenLostCount() const { return fTokenLostErrors; } // The following methods are inherited from AliMUONTrackerDDLDecoderEventHandler: /// New buffer handler. void OnNewBuffer(const void* buffer, UInt_t bufferSize); + + /// End of buffer handler marks the end of bus patches. + void OnEndOfBuffer(const void* /*buffer*/, UInt_t /*bufferSize*/) + { + fEndOfBusPatches = fCurrentBusPatch+1; + } + + /// New block handler is called by the decoder whenever a new block + /// structure is found. We just mark the new block and increment the + /// internal counter. + void OnNewBlock(const AliMUONBlockHeaderStruct* header, const void* /*data*/); + + /// New DSP handler is called by the decoder whenever a new DSP + /// structure is found. We just mark the DSP and increment the + /// appropriate counters. + void OnNewDSP(const AliMUONDSPHeaderStruct* header, const void* /*data*/); /// New bus patch handler. + /// This is called by the high performance decoder when a new bus patch + /// is found within the DDL payload. void OnNewBusPatch(const AliMUONBusPatchHeaderStruct* header, const void* data); /// Raw data word handler. - void OnData(UInt_t data); + void OnData(UInt_t /*data*/, bool parityError) + { + assert( fCurrentParityOkFlag < fParityOk + fMaxChannels ); + *(++fCurrentParityOkFlag) = Bool_t(not parityError); + } /// Error handler. void OnError(ErrorCode error, const void* location); @@ -125,22 +686,120 @@ private: /// Not implemented AliDecoderEventHandler& operator = (const AliDecoderEventHandler& /*obj*/); - Int_t fBusPatchId; //!< The bus patch ID of the current bus patch being decoded. - UInt_t fChannelCount; //!< Number of elements in fChannelBuffer. - UInt_t fMaxChannels; //!< Maximum number of elements that can be stored in fChannelBuffer. - AliChannelInfo* fChannelBuffer; //!< Buffer of decoded channel structures. - AliMUONVRawStreamTracker* fRawStream; //!< Pointer to the parent raw stream object. + AliMUONRawStreamTrackerHP* fRawStream; //!< Pointer to the parent raw stream object. const void* fBufferStart; //!< Pointer to the start of the current DDL payload buffer. + UInt_t fBlockCount; //!< Number of blocks filled in fBlocks. + AliBlockHeader* fBlocks; //!< Array of blocks. [0..fMaxBlocks-1] + AliDspHeader* fDSPs; //!< Array of DSPs. [0..fMaxDsps*fMaxBlocks-1] + AliBusPatch* fBusPatches; //!< Array of bus patches. [0..fMaxBusPatches*fMaxDsps*fMaxBlocks-1] + AliBusPatch* fEndOfBusPatches; //!< Marks the last bus patch. + UInt_t fMaxChannels; //!< Maximum number of elements that can be stored in fParityOk. + Bool_t* fParityOk; //!< Array of flags for indicating if the parity is good for a raw data word. + AliBlockHeader* fCurrentBlock; //!< Current block in fBlocks. + AliDspHeader* fCurrentDSP; //!< Current DSP in fDSPs. + AliBusPatch* fCurrentBusPatch; //!< Current bus patch in fBusPatches. + Bool_t* fCurrentParityOkFlag; //!< Current parity flag to be set in fParityOk. + UInt_t fParityErrors; //!< Number of parity errors found in DDL. + UInt_t fGlitchErrors; //!< Number of glitch errors found in DDL. + UInt_t fPaddingErrors; //!< Number of padding errors found in DDL. + UInt_t fTokenLostErrors; //!< Number of token lost errors found in DDL. + UInt_t fMaxBlocks; //!< max number of blocks + UInt_t fMaxDsps; //!< max number of dsps per block + UInt_t fMaxBusPatches; //!< max number of buspatches per dsp }; - + + AliRawReader* fRawReader; //!< Pointer to the raw reader + AliMUONLogger* fLogger; //!< Logger object to store error messages. + EDetailLevel fDetailLevel; //!< The logging detail level used in the error messages generated in OnError. + Bool_t fEnableMUONErrorLogger; //!< whether or not we log errors to AliMUONLogger + Bool_t fEnableRawReaderErrorLogger; //!< whether or not we log errors to the raw reader. + Bool_t fWarnings; //!< Flag indicating if we should generate a warning for errors. AliMUONTrackerDDLDecoder fDecoder; //!< The decoder for the DDL payload. Int_t fDDL; //!< The current DDL number being handled. - UInt_t fCurrentChannel; //!< The current channel to return by Next(). Int_t fBufferSize; //!< This is the buffer size in bytes of fBuffer. UChar_t* fBuffer; //!< This is the buffer in which we store the DDL payload read from AliRawReader. + const AliBusPatch* fkCurrentBusPatch; //!< The current bus patch being handled by Next(). + const UInt_t* fkCurrentData; //!< The current data word to return by Next(). + const UInt_t* fkEndOfData; //!< The last data word in the current bus patch. Bool_t fHadError; //!< Flag indicating if there was a decoding error or not. + Bool_t fDone; //!< Flag indicating if the iteration is done or not. + mutable AliMUONDDLTracker* fDDLObject; //!< Temporary DDL object used by GetDDLTracker() for caching. + UInt_t fTotalNumberOfGlitchErrors; //!< number of glitch errors since First() was called + UInt_t fTotalNumberOfParityErrors; //!< number of parity errors since First() was called + UInt_t fTotalNumberOfPaddingErrors; //!< number of padding errors since First() was called + UInt_t fTotalNumberOfTokenLostErrors; //!< number of token lost errors since First() was called + + static const Int_t fgkMaxDDL; //!< max number of tracker DDLs ClassDef(AliMUONRawStreamTrackerHP, 0) // High performance decoder for reading MUON raw digits from tracking chamber DDL data. }; +//////////////////////////////////////////////////////////////////////////////// + +inline const AliMUONRawStreamTrackerHP::AliBusPatch* AliMUONRawStreamTrackerHP::Next() +{ + /// Returns the next batch of decoded channel data. + if (fkCurrentBusPatch == NULL) return NULL; + do { + if (fkCurrentBusPatch != fDecoder.GetHandler().EndOfBusPatch()) + return fkCurrentBusPatch++; + } while (NextDDL()); + return NULL; +} + +inline void AliMUONRawStreamTrackerHP::AliDecoderEventHandler::OnNewBlock( + const AliMUONBlockHeaderStruct* header, const void* /*data*/ + ) +{ + /// New block handler is called by the decoder whenever a new block + /// structure is found. We just mark the new block and increment the + /// internal counter. + + assert( header != NULL ); + assert( fBlockCount < fMaxBlocks ); + // Link the block unless it is the first one. + if (fBlockCount > 0) fCurrentBlock->SetNext(fCurrentBlock+1); + *(++fCurrentBlock) = AliBlockHeader(fCurrentDSP+1, header); + fBlockCount++; +} + +inline void AliMUONRawStreamTrackerHP::AliDecoderEventHandler::OnNewDSP( + const AliMUONDSPHeaderStruct* header, const void* /*data*/ + ) +{ + /// New DSP handler is called by the decoder whenever a new DSP + /// structure is found. We just mark the DSP and increment the + /// appropriate counters. + + assert( header != NULL ); + assert( fCurrentBlock->GetDspCount() < fMaxDsps ); + // Link the DSP unless it is the first one. + if (fCurrentBlock->GetDspCount() > 0) fCurrentDSP->SetNext(fCurrentDSP+1); + *(++fCurrentDSP) = AliDspHeader(fCurrentBlock, fCurrentBusPatch+1, header); + fCurrentBlock->IncDspCount(); +} + +inline void AliMUONRawStreamTrackerHP::AliDecoderEventHandler::OnNewBusPatch( + const AliMUONBusPatchHeaderStruct* header, const void* data + ) +{ + /// New bus patch handler. + /// This is called by the high performance decoder when a new bus patch + /// is found within the DDL payload. + + assert( header != NULL ); + assert( data != NULL ); + assert( fCurrentDSP->GetBusPatchCount() < fMaxBusPatches ); + // Link the bus patch unless it is the first one. + if (fCurrentDSP->GetBusPatchCount() > 0) fCurrentBusPatch->SetNext(fCurrentBusPatch+1); + *(++fCurrentBusPatch) = AliBusPatch( + fCurrentDSP, + header, + reinterpret_cast(data), + fCurrentParityOkFlag+1 + ); + fCurrentDSP->IncBusPatchCount(); +} + #endif // ALIMUONRAWSTREAMTRACKERHP_H +