X-Git-Url: http://git.uio.no/git/?a=blobdiff_plain;f=MUON%2FAliMUONRawStreamTrackerHP.cxx;h=16862c2276887d885056d2aaeff01a9fe71c574d;hb=8e5db053220202db87da44e2abf1bba86c54ed13;hp=352d241f9b5b928942610e6d2a0162b4e653ad21;hpb=ab0129aef998cccf7cd5de1abb3c2a8923d0a80a;p=u%2Fmrichter%2FAliRoot.git diff --git a/MUON/AliMUONRawStreamTrackerHP.cxx b/MUON/AliMUONRawStreamTrackerHP.cxx index 352d241f9b5..16862c22768 100644 --- a/MUON/AliMUONRawStreamTrackerHP.cxx +++ b/MUON/AliMUONRawStreamTrackerHP.cxx @@ -44,11 +44,17 @@ //----------------------------------------------------------------------------- #include "AliMUONRawStreamTrackerHP.h" +#include "AliMUONTrackerDDLDecoder.h" +#include "AliMUONDspHeader.h" +#include "AliMUONBlockHeader.h" +#include "AliMUONBusStruct.h" +#include "AliMUONDDLTracker.h" +#include "AliMUONLogger.h" #include "AliRawReader.h" #include "AliLog.h" +#include "AliDAQ.h" #include #include -#include using std::cout; using std::endl; using std::hex; @@ -58,18 +64,30 @@ using std::dec; ClassImp(AliMUONRawStreamTrackerHP) /// \endcond +const Int_t AliMUONRawStreamTrackerHP::fgkMaxDDL = 20; AliMUONRawStreamTrackerHP::AliMUONRawStreamTrackerHP() : - AliMUONVRawStreamTracker(), + TObject(), + fRawReader(NULL), + fLogger(NULL), + fDetailLevel(kMediumErrorDetail), + fEnableMUONErrorLogger(kFALSE), + fEnableRawReaderErrorLogger(kFALSE), + fWarnings(kTRUE), fDecoder(), fDDL(0), fBufferSize(8192), fBuffer(new UChar_t[8192]), - fCurrentBusPatch(NULL), - fCurrentData(NULL), - fEndOfData(NULL), + fkCurrentBusPatch(NULL), + fkCurrentData(NULL), + fkEndOfData(NULL), fHadError(kFALSE), - fDone(kFALSE) + fDone(kFALSE), + fDDLObject(NULL), + fTotalNumberOfGlitchErrors(0), + fTotalNumberOfParityErrors(0), + fTotalNumberOfPaddingErrors(0), + fTotalNumberOfTokenLostErrors(0) { /// /// Default constructor. @@ -85,22 +103,33 @@ AliMUONRawStreamTrackerHP::AliMUONRawStreamTrackerHP() : fDecoder.MaxDSPs(), fDecoder.MaxBusPatches() ); - + fDecoder.GetHandler().SetRawStream(this); } AliMUONRawStreamTrackerHP::AliMUONRawStreamTrackerHP(AliRawReader* rawReader) : - AliMUONVRawStreamTracker(rawReader), + TObject(), + fRawReader(rawReader), + fLogger(NULL), + fDetailLevel(kMediumErrorDetail), + fEnableMUONErrorLogger(kFALSE), + fEnableRawReaderErrorLogger(kFALSE), + fWarnings(kTRUE), fDecoder(), fDDL(0), fBufferSize(8192), fBuffer(new UChar_t[8192]), - fCurrentBusPatch(NULL), - fCurrentData(NULL), - fEndOfData(NULL), + fkCurrentBusPatch(NULL), + fkCurrentData(NULL), + fkEndOfData(NULL), fHadError(kFALSE), - fDone(kFALSE) + fDone(kFALSE), + fDDLObject(NULL), + fTotalNumberOfGlitchErrors(0), + fTotalNumberOfParityErrors(0), + fTotalNumberOfPaddingErrors(0), + fTotalNumberOfTokenLostErrors(0) { /// /// Constructor with AliRawReader as argument. @@ -131,6 +160,10 @@ AliMUONRawStreamTrackerHP::~AliMUONRawStreamTrackerHP() { delete [] fBuffer; } + if (fDDLObject != NULL) + { + delete fDDLObject; + } } @@ -144,6 +177,10 @@ void AliMUONRawStreamTrackerHP::First() fDDL = 0; fDone = kFALSE; NextDDL(); + fTotalNumberOfGlitchErrors = 0; + fTotalNumberOfPaddingErrors = 0; + fTotalNumberOfParityErrors = 0; + fTotalNumberOfTokenLostErrors = 0; } @@ -155,6 +192,19 @@ Bool_t AliMUONRawStreamTrackerHP::NextDDL() assert( GetReader() != NULL ); + // The temporary object if generated in GetDDLTracker, is now stale, + // so delete it. + if (fDDLObject != NULL) + { + delete fDDLObject; + fDDLObject = NULL; + } + + // Better to reset these pointers. + fkCurrentBusPatch = NULL; + fkCurrentData = NULL; + fkEndOfData = NULL; + while (fDDL < GetMaxDDL()) { GetReader()->Reset(); @@ -165,7 +215,7 @@ Bool_t AliMUONRawStreamTrackerHP::NextDDL() } // If we reach the end of the DDL list for this event then reset the - // DDL counter, mark the iteration as done and + // DDL counter, mark the iteration as done and exit. if (fDDL >= GetMaxDDL()) { fDDL = 0; @@ -218,6 +268,10 @@ Bool_t AliMUONRawStreamTrackerHP::NextDDL() // handler we need to trap any memory allocation exception to be robust. result = fDecoder.Decode(fBuffer, dataSize); fHadError = (result == true ? kFALSE : kTRUE); + fTotalNumberOfGlitchErrors += fDecoder.GetHandler().GlitchErrorCount(); + fTotalNumberOfParityErrors += fDecoder.GetHandler().ParityErrorCount(); + fTotalNumberOfPaddingErrors += fDecoder.GetHandler().PaddingErrorCount(); + fTotalNumberOfTokenLostErrors += fDecoder.GetHandler().TokenLostCount(); } catch (const std::bad_alloc&) { @@ -226,22 +280,22 @@ Bool_t AliMUONRawStreamTrackerHP::NextDDL() } // Update the current bus patch pointers. - fCurrentBusPatch = fDecoder.GetHandler().FirstBusPatch(); - if (fCurrentBusPatch != fDecoder.GetHandler().EndOfBusPatch()) + fkCurrentBusPatch = fDecoder.GetHandler().FirstBusPatch(); + if (fkCurrentBusPatch != fDecoder.GetHandler().EndOfBusPatch()) { - fCurrentData = fCurrentBusPatch->GetData(); - fEndOfData = fCurrentData + fCurrentBusPatch->GetDataCount(); + fkCurrentData = fkCurrentBusPatch->GetData(); + fkEndOfData = fkCurrentData + fkCurrentBusPatch->GetDataCount(); } else { // If the DDL did not have any bus patches then mark both fCurrentData // and fEndOfData as NULL so that in Next() we are forced to find the // first non empty DDL. - fCurrentData = fEndOfData = NULL; + fkCurrentData = fkEndOfData = NULL; } fDDL++; // Remember to increment index to next DDL. - return result; + return kTRUE; } @@ -254,26 +308,31 @@ Bool_t AliMUONRawStreamTrackerHP::IsDone() const } -Bool_t AliMUONRawStreamTrackerHP::Next( - Int_t& busPatchId, UShort_t& manuId, UChar_t& manuChannel, - UShort_t& adc - ) +Bool_t AliMUONRawStreamTrackerHP::Next(Int_t& busPatchId, + UShort_t& manuId, + UChar_t& manuChannel, + UShort_t& adc, + Bool_t skipParityErrors) { /// Advance one step in the iteration. Returns false if finished. /// [out] \param busPatchId This is filled with the bus patch ID of the digit. /// [out] \param manuId This is filled with the MANU ID of the digit. /// [out] \param manuChannel This is filled with the MANU channel ID of the digit. /// [out] \param adc This is filled with the ADC signal value of the digit. + /// [in] \param skipParityErrors If this is kTRUE, we'll skip the buspatches that + /// have some parity errors /// \return kTRUE if we read another digit and kFALSE if we have read all the /// digits already, i.e. at the end of the iteration. + if (fkCurrentData == NULL) return kFALSE; + retry: // Check if we still have data to be returned for the current bus patch. - if (fCurrentData != fEndOfData) + if (fkCurrentData != fkEndOfData) { - busPatchId = fCurrentBusPatch->GetBusPatchId(); - AliMUONTrackerDDLDecoderEventHandler::UnpackADC(*fCurrentData, manuId, manuChannel, adc); - fCurrentData++; + busPatchId = fkCurrentBusPatch->GetBusPatchId(); + AliMUONTrackerDDLDecoderEventHandler::UnpackADC(*fkCurrentData, manuId, manuChannel, adc); + fkCurrentData++; return kTRUE; } else @@ -282,13 +341,22 @@ retry: // bus patches to process for the current DDL. If we do, then increment // the current bus patch, make sure it is not the last one and then try // reading the first element again. - if (fCurrentBusPatch != fDecoder.GetHandler().EndOfBusPatch()) + if (fkCurrentBusPatch != fDecoder.GetHandler().EndOfBusPatch()) { - fCurrentBusPatch++; - if (fCurrentBusPatch != fDecoder.GetHandler().EndOfBusPatch()) + fkCurrentBusPatch++; + if (fkCurrentBusPatch != fDecoder.GetHandler().EndOfBusPatch()) { - fCurrentData = fCurrentBusPatch->GetData(); - fEndOfData = fCurrentData + fCurrentBusPatch->GetDataCount(); + fkCurrentData = fkCurrentBusPatch->GetData(); + fkEndOfData = fkCurrentData + fkCurrentBusPatch->GetDataCount(); + if ( skipParityErrors ) + { + Bool_t ok(kTRUE); + for ( Int_t i = 0; i < fkCurrentBusPatch->GetLength() && ok; ++ i ) + { + ok = fkCurrentBusPatch->IsParityOk(i); + } + if (!ok) fkCurrentData = fkEndOfData; + } goto retry; } } @@ -302,6 +370,62 @@ retry: } +AliMUONDDLTracker* AliMUONRawStreamTrackerHP::GetDDLTracker() const +{ + /// Construct and return a pointer to the DDL payload object. + /// \return Pointer to internally constructed AliMUONDDLTracker object. + /// The object is owned by this class and should not be deleted + /// by the caller. + /// + /// \note This method should not be used just to gain access to the DDL + /// payload, unless there is a good reason to have the AliMUONDDLTracker + /// object. For example, if you want to modify the data and then save it + /// to another DDL stream. Otherwise it can be an order of magnitude + /// faster to access the DDL headers and data with the GetBlockHeader, + /// GetDspHeader and GetBusPatch methods for example. + /// Refer to the MUONRawStreamTracker.C macro to see how to use the fast + /// decoder interface optimally. + + if (fDDLObject != NULL) return fDDLObject; + + fDDLObject = new AliMUONDDLTracker; + for (Int_t iBlock = 0; iBlock < (Int_t)GetBlockCount(); iBlock++) + { + AliMUONBlockHeader blockHeader; + AliMUONDspHeader dspHeader; + AliMUONBusStruct busPatch; + + const AliBlockHeader* bh = GetBlockHeader(iBlock); + // Copy block header and add it to the DDL object. + memcpy(blockHeader.GetHeader(), bh->GetHeader(), sizeof(AliMUONBlockHeaderStruct)); + fDDLObject->AddBlkHeader(blockHeader); + + for (Int_t iDsp = 0; iDsp < (Int_t)bh->GetDspCount(); iDsp++) + { + const AliDspHeader* dh = bh->GetDspHeader(iDsp); + // Copy DSP header and add it to the DDL object. + memcpy(dspHeader.GetHeader(), dh->GetHeader(), sizeof(AliMUONDSPHeaderStruct)); + fDDLObject->AddDspHeader(dspHeader, iBlock); + + const AliBusPatch* bp = dh->GetFirstBusPatch(); + while (bp != NULL) + { + // Copy bus patch header, data and add everything into DDL object. + memcpy(busPatch.GetHeader(), bp->GetHeader(), sizeof(AliMUONBusPatchHeaderStruct)); + busPatch.SetAlloc(bp->GetLength()); + memcpy(busPatch.GetData(), bp->GetData(), bp->GetDataCount()*sizeof(UInt_t)); + busPatch.SetBlockId(iBlock); + busPatch.SetDspId(iDsp); + fDDLObject->AddBusPatch(busPatch, iBlock, iDsp); + bp = bp->Next(); + } + } + } + + return fDDLObject; +} + + void AliMUONRawStreamTrackerHP::SetMaxBlock(Int_t blk) { /// Set maximum number of blocks per DDL allowed. @@ -426,7 +550,10 @@ AliMUONRawStreamTrackerHP::AliDecoderEventHandler::AliDecoderEventHandler() : fParityErrors(0), fGlitchErrors(0), fPaddingErrors(0), - fWarnings(kTRUE) + fTokenLostErrors(0), + fMaxBlocks(), + fMaxDsps(), + fMaxBusPatches() { /// Default constructor initialises the internal parity flags buffer to /// store 8192 elements. This array will grow dynamically if needed. @@ -474,7 +601,11 @@ void AliMUONRawStreamTrackerHP::AliDecoderEventHandler::SetMaxStructs( fBlocks = new AliBlockHeader[maxBlocks]; fDSPs = new AliDspHeader[maxBlocks*maxDsps]; fBusPatches = new AliBusPatch[maxBlocks*maxDsps*maxBusPatches]; - fEndOfBusPatches = fEndOfBusPatches; + fEndOfBusPatches = fBusPatches; + + fMaxBlocks = maxBlocks; + fMaxDsps = maxDsps; + fMaxBusPatches = maxBusPatches; } @@ -487,8 +618,6 @@ void AliMUONRawStreamTrackerHP::AliDecoderEventHandler::OnNewBuffer( /// \param buffer The pointer to the buffer storing the DDL payload. /// \param bufferSize The size of the buffer in bytes. - assert( fRawStream != NULL ); - // remember the start of the buffer to be used in OnError. fBufferStart = buffer; @@ -496,6 +625,7 @@ void AliMUONRawStreamTrackerHP::AliDecoderEventHandler::OnNewBuffer( fParityErrors = 0; fGlitchErrors = 0; fPaddingErrors = 0; + fTokenLostErrors = 0; // Check if we will have enough space in the fParityOk array. // If we do not then we need to resize the array. @@ -526,6 +656,32 @@ void AliMUONRawStreamTrackerHP::AliDecoderEventHandler::OnNewBuffer( } +void AliMUONRawStreamTrackerHP::Swap(UInt_t* buffer, Int_t size) const +{ + // swap from little to big endian + + typedef struct { + UInt_t b1:8; ///< first byte word + UInt_t b2:8; ///< second byte word + UInt_t b3:8; ///< third byte word + UInt_t b4:8; ///< fourth byte word + } RawWord; + + RawWord* word, temp; + word = (RawWord*) buffer; + + for (Int_t i = 0; i < size; i++) + { + temp = *(((RawWord*)buffer)+i); + word->b1 = temp.b4; + word->b2 = temp.b3; + word->b3 = temp.b2; + word->b4 = temp.b1; + word++; + } +} + + void AliMUONRawStreamTrackerHP::AliDecoderEventHandler::OnError( ErrorCode error, const void* location ) @@ -533,67 +689,209 @@ void AliMUONRawStreamTrackerHP::AliDecoderEventHandler::OnError( /// This is called by the high performance decoder when a error occurs /// when trying to decode the DDL payload. This indicates corruption in /// the data. This method converts the error code to a descriptive message - /// and log this with the raw reader. + /// and logs this with the logger object. /// \param error The error code indicating the problem. /// \param location A pointer to the location within the DDL payload buffer /// being decoded where the problem with the data was found. - - assert( fRawStream != NULL ); - assert( fRawStream->GetReader() != NULL ); - Char_t* message = NULL; + assert(fRawStream != NULL); + + const char* message = NULL; UInt_t word = 0; - + bool logAsMajorError = true; + + // Build the detailed part of the error message if high detail selected. + const char* detail = ""; + if (fRawStream->GetLoggingDetailLevel() == kHighErrorDetail) + { + bool blockPtrOk = fBlockCount > 0; + bool dspPtrOk = blockPtrOk ? fCurrentBlock->GetDspCount() > 0 : false; + bool buspatchPtrOk = dspPtrOk ? fCurrentDSP->GetBusPatchCount() > 0 : false; + // We subtract 1 from the current numbers of blocks, DSPs + // and bus patches to get the iBlock, iDsp and iBus indices. + detail = Form( + "At byte %d in DDL %d, event %d, iBlock %d, iDsp %d [DSP ID: %d (0x%X)]," + " iBus %d [bus patch ID: %d (0x%X)].", + (unsigned long)location - (unsigned long)fBufferStart + sizeof(AliRawDataHeader), + AliDAQ::DdlID("MUONTRK", fRawStream->GetDDL()), + fRawStream->GetReader()->GetEventIndex(), + int(fBlockCount)-1, + blockPtrOk ? int(fCurrentBlock->GetDspCount())-1 : -1, + blockPtrOk ? fCurrentBlock->GetDspId() : -1, + blockPtrOk ? fCurrentBlock->GetDspId() : -1, + dspPtrOk ? int(fCurrentDSP->GetBusPatchCount())-1 : -1, + buspatchPtrOk ? fCurrentBusPatch->GetBusPatchId() : -1, + buspatchPtrOk ? fCurrentBusPatch->GetBusPatchId() : -1 + ); + } + + // Build the log message. switch (error) { case kGlitchFound: - message = Form( - "Glitch error detected in DSP %d, skipping event ", - fCurrentBlock->GetDspId() - ); - fRawStream->GetReader()->AddMajorErrorLog(error, message); + fGlitchErrors++; + switch (fRawStream->GetLoggingDetailLevel()) + { + case kLowErrorDetail: + message = "Glitch error detected."; + break; + case kMediumErrorDetail: + message = Form( + "Glitch error detected in DSP %d (0x%X), skipping event.", + fCurrentBlock->GetDspId(), fCurrentBlock->GetDspId() + ); + break; + case kHighErrorDetail: + default: + message = Form("%s %s", ErrorCodeToMessage(error), detail); + break; + } + logAsMajorError = true; break; case kBadPaddingWord: - // We subtract 1 from the current numbers of blocks, DSPs - // and bus patches to get the indices. - message = Form( - "Padding word error for iBlock %d, iDsp %d, iBus %d\n", - fBlockCount-1, - fCurrentBlock->GetDspCount()-1, - fCurrentDSP->GetBusPatchCount()-1 - ); - fRawStream->GetReader()->AddMinorErrorLog(error, message); + fPaddingErrors++; + switch (fRawStream->GetLoggingDetailLevel()) + { + case kLowErrorDetail: + message = "Padding word error detected."; + break; + case kMediumErrorDetail: + // We subtract 1 from the current numbers of blocks, DSPs + // and bus patches to get the indices. + message = Form( + "Padding word error for iBlock %d, iDsp %d, iBus %d.", + fBlockCount-1, + fCurrentBlock->GetDspCount()-1, + fCurrentDSP->GetBusPatchCount()-1 + ); + break; + case kHighErrorDetail: + default: + message = Form("%s %s", ErrorCodeToMessage(error), detail); + break; + } + logAsMajorError = false; break; case kParityError: - // location points to the incorrect data word and - // fCurrentBusPatch->GetData() returns a pointer to the start of - // bus patches data, so the difference divided by 4 gives the 32 - // bit word number. - word = ((unsigned long)location - (unsigned long)fCurrentBusPatch->GetData()) + fParityErrors++; + switch (fRawStream->GetLoggingDetailLevel()) + { + case kLowErrorDetail: + message = "Parity error detected."; + break; + case kMediumErrorDetail: + message = Form( + "Parity error in buspatch %d (0x%X).", + fCurrentBusPatch->GetBusPatchId(), + fCurrentBusPatch->GetBusPatchId() + ); + break; + case kHighErrorDetail: + default: + // location points to the incorrect data word and + // fCurrentBusPatch->GetData() returns a pointer to the start of + // bus patches data, so the difference divided by 4 gives the 32 + // bit word number. + word = ((unsigned long)location - (unsigned long)fCurrentBusPatch->GetData()) / sizeof(UInt_t); - message = Form( - "Parity error in word %d for manuId %d and channel %d in buspatch %d\n", - word, - fCurrentBusPatch->GetManuId(word), - fCurrentBusPatch->GetChannelId(word), - fCurrentBusPatch->GetBusPatchId() - ); - fRawStream->GetReader()->AddMinorErrorLog(error, message); + message = Form( + "Parity error in word %d for manuId %d and channel %d in buspatch %d. %s", + word, + fCurrentBusPatch->GetManuId(word), + fCurrentBusPatch->GetChannelId(word), + fCurrentBusPatch->GetBusPatchId(), + detail + ); + break; + } + logAsMajorError = false; + break; + + case kTokenLost: + fTokenLostErrors++; + switch (fRawStream->GetLoggingDetailLevel()) + { + case kLowErrorDetail: + message = "Lost token error detected."; + break; + case kMediumErrorDetail: + word = *reinterpret_cast(location); + message = Form( + "Lost token error detected in DSP 0x%X of DDL %d and code %d.", + ((word & 0xFFFF0000) >> 16), + fRawStream->GetDDL(), + (word & 0xF) + ); + break; + case kHighErrorDetail: + default: + word = *reinterpret_cast(location); + message = Form( + "Lost token error detected with address 0x%X and code %d. %s", + ((word & 0xFFFF0000) >> 16), + (word & 0xF), + detail + ); + message = Form("Lost token error detected. %s.", detail); + break; + } + logAsMajorError = false; break; default: - message = Form( - "%s (At byte %d in DDL.)", - ErrorCodeToMessage(error), - (unsigned long)location - (unsigned long)fBufferStart - ); - fRawStream->GetReader()->AddMajorErrorLog(error, message); + switch (fRawStream->GetLoggingDetailLevel()) + { + case kLowErrorDetail: + message = ErrorCodeToMessage(error); + break; + case kMediumErrorDetail: + message = Form( + "%s (At byte %d)", + ErrorCodeToMessage(error), + (unsigned long)location - (unsigned long)fBufferStart + sizeof(AliRawDataHeader) + ); + break; + case kHighErrorDetail: + default: + message = Form( + "%s Error code: %d (%s). %s", + ErrorCodeToMessage(error), + error, ErrorCodeToString(error), + detail + ); + break; + } + logAsMajorError = true; break; } - - if (fWarnings) + + // Now log the error message depending on the logging flags set. + if (fRawStream->IsRawReaderErrorLoggerEnabled()) + { + if (logAsMajorError) + fRawStream->GetReader()->AddMajorErrorLog(Int_t(error), message); + else + fRawStream->GetReader()->AddMinorErrorLog(Int_t(error), message); + } + if (fRawStream->IsMUONErrorLoggerEnabled()) + { + AliMUONLogger* logger = fRawStream->GetMUONErrorLogger(); + if (logger != NULL) + { + logger->Log(message); + } + else + { + AliErrorGeneral( + "AliMUONRawStreamTrackerHP::AliDecoderEventHandler", + "Enabled logging to AliMUONLogger, but the logger object" + " was not set with SetMUONErrorLogger()." + ); + } + } + if (fRawStream->IsWarningsEnabled()) { AliWarningGeneral( "AliMUONRawStreamTrackerHP::AliDecoderEventHandler",