/// To gain the most out of the decoder, the Next() method which returns batches
/// of decoded digit / channel information should be used. That is:
/// \code
-/// UInt_t Next(const AliChannelInfo*& channels);
+/// const AliBusPatch* Next();
/// \endcode
///
+/// This decoder tries to implement as similar an interface as possible to
+/// AliMUONRawStreamTracker where possible. However certain constructs which
+/// would slow us down too much are avoided.
+///
/// \author Artur Szostak <artursz@iafrica.com>
//-----------------------------------------------------------------------------
#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 <cassert>
+#include <iostream>
+using std::cout;
+using std::endl;
+using std::hex;
+using std::dec;
/// \cond CLASSIMP
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),
- fCurrentChannel(0),
fBufferSize(8192),
fBuffer(new UChar_t[8192]),
- fHadError(kFALSE)
+ fkCurrentBusPatch(NULL),
+ fkCurrentData(NULL),
+ fkEndOfData(NULL),
+ fHadError(kFALSE),
+ fDone(kFALSE),
+ fDDLObject(NULL),
+ fTotalNumberOfGlitchErrors(0),
+ fTotalNumberOfParityErrors(0),
+ fTotalNumberOfPaddingErrors(0),
+ fTotalNumberOfTokenLostErrors(0)
{
///
/// Default constructor.
///
+
+ // Must set this flag to get all information about parity errors though
+ // the OnData method. OnError gets them either way.
+ fDecoder.ExitOnError(false);
+ fDecoder.SendDataOnParityError(true);
+
+ fDecoder.GetHandler().SetMaxStructs(
+ fDecoder.MaxBlocks(),
+ 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),
- fCurrentChannel(0),
fBufferSize(8192),
fBuffer(new UChar_t[8192]),
- fHadError(kFALSE)
+ fkCurrentBusPatch(NULL),
+ fkCurrentData(NULL),
+ fkEndOfData(NULL),
+ fHadError(kFALSE),
+ fDone(kFALSE),
+ fDDLObject(NULL),
+ fTotalNumberOfGlitchErrors(0),
+ fTotalNumberOfParityErrors(0),
+ fTotalNumberOfPaddingErrors(0),
+ fTotalNumberOfTokenLostErrors(0)
{
///
/// Constructor with AliRawReader as argument.
///
+ // Must set this flag to get all information about parity errors though
+ // the OnData method. OnError gets them either way.
+ fDecoder.ExitOnError(false);
+ fDecoder.SendDataOnParityError(true);
+
+ fDecoder.GetHandler().SetMaxStructs(
+ fDecoder.MaxBlocks(),
+ fDecoder.MaxDSPs(),
+ fDecoder.MaxBusPatches()
+ );
+
fDecoder.GetHandler().SetRawStream(this);
}
{
delete [] fBuffer;
}
+ if (fDDLObject != NULL)
+ {
+ delete fDDLObject;
+ }
}
assert( GetReader() != NULL );
fDDL = 0;
+ fDone = kFALSE;
NextDDL();
+ fTotalNumberOfGlitchErrors = 0;
+ fTotalNumberOfPaddingErrors = 0;
+ fTotalNumberOfParityErrors = 0;
+ fTotalNumberOfTokenLostErrors = 0;
}
assert( GetReader() != NULL );
- if (IsDone()) return kFALSE;
+ // The temporary object if generated in GetDDLTracker, is now stale,
+ // so delete it.
+ if (fDDLObject != NULL)
+ {
+ delete fDDLObject;
+ fDDLObject = NULL;
+ }
- do
+ // Better to reset these pointers.
+ fkCurrentBusPatch = NULL;
+ fkCurrentData = NULL;
+ fkEndOfData = NULL;
+
+ while (fDDL < GetMaxDDL())
{
GetReader()->Reset();
GetReader()->Select("MUONTRK", fDDL, fDDL); // Select the DDL file to be read.
AliDebug(3, Form("Skipping DDL %d which does not seem to be there", fDDL+1));
fDDL++;
}
- while (fDDL < GetMaxDDL());
-
+
+ // If we reach the end of the DDL list for this event then reset the
+ // DDL counter, mark the iteration as done and exit.
+ if (fDDL >= GetMaxDDL())
+ {
+ fDDL = 0;
+ fDone = kTRUE;
+ return kFALSE;
+ }
+ else
+ {
+ fDone = kFALSE;
+ }
+
AliDebug(3, Form("DDL Number %d\n", fDDL));
Int_t dataSize = GetReader()->GetDataSize(); // in bytes
}
#ifndef R__BYTESWAP
- Swap(fBuffer, dataSize); // Swap needed for mac power pc.
+ Swap(reinterpret_cast<UInt_t*>(fBuffer), dataSize / sizeof(UInt_t)); // Swap needed for mac power pc.
#endif
+ fDDL++; // Remember to increment index to next DDL before the calls to
+ // fDecoder.Decode since the callback methods of the decoder will
+ // use AliMUONRawStreamTrackerHP::GetDDL()
+
bool result = false;
try
{
// Since we might allocate memory inside OnNewBuffer in the event
// 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&)
{
AliError("Could not allocate more buffer space. Cannot decode DDL.");
return kFALSE;
}
-
- fCurrentChannel = 0;
- fDDL++; // Remember to increment index to next DDL.
- return result;
+
+ // Update the current bus patch pointers.
+ fkCurrentBusPatch = fDecoder.GetHandler().FirstBusPatch();
+ if (fkCurrentBusPatch != fDecoder.GetHandler().EndOfBusPatch())
+ {
+ 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.
+ fkCurrentData = fkEndOfData = NULL;
+ }
+
+ return kTRUE;
}
/// Indicates whether the iteration is finished or not.
/// \return kTRUE if we already read all the digits and kFALSE if not.
- return fDDL == GetMaxDDL();
+ return fDone;
}
-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 (fCurrentChannel < fDecoder.GetHandler().ChannelCount())
+ if (fkCurrentData == NULL) return kFALSE;
+
+retry:
+ // Check if we still have data to be returned for the current bus patch.
+ if (fkCurrentData != fkEndOfData)
{
- const AliChannelInfo& channel = fDecoder.GetHandler().Channels()[fCurrentChannel];
- busPatchId = channel.BusPatchId();
- manuId = channel.ManuId();
- manuChannel = channel.ChannelId();
- adc = channel.ADC();
- fCurrentChannel++;
+ busPatchId = fkCurrentBusPatch->GetBusPatchId();
+ AliMUONTrackerDDLDecoderEventHandler::UnpackADC(*fkCurrentData, manuId, manuChannel, adc);
+ fkCurrentData++;
return kTRUE;
}
else
{
- if (NextDDL())
+ // We hit the end of the current bus patch so check if we have any more
+ // 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 (fkCurrentBusPatch != fDecoder.GetHandler().EndOfBusPatch())
{
- if (fCurrentChannel < fDecoder.GetHandler().ChannelCount())
+ fkCurrentBusPatch++;
+ if (fkCurrentBusPatch != fDecoder.GetHandler().EndOfBusPatch())
{
- const AliChannelInfo& channel = fDecoder.GetHandler().Channels()[fCurrentChannel];
- busPatchId = channel.BusPatchId();
- manuId = channel.ManuId();
- manuChannel = channel.ChannelId();
- adc = channel.ADC();
- fCurrentChannel++;
- return kTRUE;
+ 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;
}
}
+
+ // This was the last bus patch in the DDL so read in the next one and
+ // try reading the first data element again.
+ // Note: fCurrentBusPatch is set inside NextDDL().
+ if (NextDDL()) goto retry;
}
return kFALSE;
}
-UInt_t AliMUONRawStreamTrackerHP::Next(const AliChannelInfo*& channels)
+AliMUONDDLTracker* AliMUONRawStreamTrackerHP::GetDDLTracker() const
{
- /// Returns the next batch of decoded channel data.
- /// [out] \param channels This is filled with a pointer to an array of
- /// channels / digits that were decoded. This method does not
- /// modify 'channels' if zero is returned.
- /// \return The number of elements in the array pointed to by 'channels'
- /// is returned. If zero is returned then there are no more channels to read.
-
- // Check if we are already at the end of the channels array. If so then we
- // need to fetch the next non empty DDL.
- if (fCurrentChannel >= fDecoder.GetHandler().ChannelCount())
+ /// 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++)
{
- do
+ 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++)
{
- if (not NextDDL()) return 0;
+ 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();
+ }
}
- // Make sure to keep going even for empty DDL payloads:
- while (fDecoder.GetHandler().ChannelCount() == 0);
}
- channels = fDecoder.GetHandler().Channels() + fCurrentChannel;
- return fDecoder.GetHandler().ChannelCount() - fCurrentChannel;
+
+ return fDDLObject;
+}
+
+
+void AliMUONRawStreamTrackerHP::SetMaxBlock(Int_t blk)
+{
+ /// Set maximum number of blocks per DDL allowed.
+ fDecoder.MaxBlocks( (UInt_t) blk );
+
+ fDecoder.GetHandler().SetMaxStructs(
+ fDecoder.MaxBlocks(),
+ fDecoder.MaxDSPs(),
+ fDecoder.MaxBusPatches()
+ );
+}
+
+
+void AliMUONRawStreamTrackerHP::SetMaxDsp(Int_t dsp)
+{
+ /// Set maximum number of Dsp per block allowed.
+ fDecoder.MaxDSPs( (UInt_t) dsp );
+
+ fDecoder.GetHandler().SetMaxStructs(
+ fDecoder.MaxBlocks(),
+ fDecoder.MaxDSPs(),
+ fDecoder.MaxBusPatches()
+ );
+}
+
+
+void AliMUONRawStreamTrackerHP::SetMaxBus(Int_t bus)
+{
+ /// Set maximum number of Buspatch per Dsp allowed.
+ fDecoder.MaxBusPatches( (UInt_t) bus );
+
+ fDecoder.GetHandler().SetMaxStructs(
+ fDecoder.MaxBlocks(),
+ fDecoder.MaxDSPs(),
+ fDecoder.MaxBusPatches()
+ );
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void AliMUONRawStreamTrackerHP::AliBlockHeader::Print() const
+{
+ /// Print header to screen.
+
+ cout << "CRT info" << endl;
+ if (fHeader == NULL)
+ {
+ cout << "Header is NULL" << endl;
+ return;
+ }
+ cout << "DataKey: 0x" << hex << fHeader->fDataKey << dec << endl;
+ cout << "TotalLength: " << fHeader->fTotalLength << endl;
+ cout << "Length: " << fHeader->fLength << endl;
+ cout << "DspId: " << fHeader->fDSPId << endl;
+ cout << "L0Trigger: " << fHeader->fL0Trigger << endl;
+ cout << "MiniEventId: " << fHeader->fMiniEventId<< endl;
+ cout << "EventId1: " << fHeader->fEventId1 << endl;
+ cout << "EventId2: " << fHeader->fEventId2 << endl;
+}
+
+
+void AliMUONRawStreamTrackerHP::AliDspHeader::Print() const
+{
+ /// Print header to screen.
+
+ cout << "FRT info" << endl;
+ if (fHeader == NULL)
+ {
+ cout << "Header is NULL" << endl;
+ return;
+ }
+ cout << "DataKey: 0x" << hex << fHeader->fDataKey << dec << endl;
+ cout << "TotalLength: " << fHeader->fTotalLength << endl;
+ cout << "Length : " << fHeader->fLength << endl;
+ cout << "DspId: " << fHeader->fDSPId << endl;
+ cout << "BlkL1ATrigger: " << fHeader->fBlkL1ATrigger << endl;
+ cout << "MiniEventId: " << fHeader->fMiniEventId << endl;
+ cout << "L1ATrigger: " << fHeader->fL1ATrigger << endl;
+ cout << "L1RTrigger: " << fHeader->fL1RTrigger << endl;
+ cout << "PaddingWord: " << fHeader->fPaddingWord << endl;
+ cout << "ErrorWord: " << fHeader->fErrorWord << endl;
+}
+
+
+void AliMUONRawStreamTrackerHP::AliBusPatch::Print(const Option_t* opt) const
+{
+ /// Print header to screen.
+ cout << "Bus patch info" << endl;
+ if (fHeader == NULL)
+ {
+ cout << "Header is NULL" << endl;
+ return;
+ }
+ cout << "DataKey: 0x" << hex << fHeader->fDataKey << dec << endl;
+ cout << "fTotalLength: " << fHeader->fTotalLength << endl;
+ cout << "fLength: " << fHeader->fLength << endl;
+ cout << "fBusPatchId: " << fHeader->fBusPatchId << endl;
+
+ if (TString(opt).Contains("all"))
+ {
+ for (UInt_t i = 0; i < fHeader->fLength; ++i)
+ cout << "Data["<< i << "] = " << fData[i] << endl;
+ }
}
///////////////////////////////////////////////////////////////////////////////
AliMUONRawStreamTrackerHP::AliDecoderEventHandler::AliDecoderEventHandler() :
- fBusPatchId(0),
- fChannelCount(0),
- fMaxChannels(8192),
- fChannelBuffer(new AliChannelInfo[8192]),
fRawStream(NULL),
- fBufferStart(NULL)
+ fBufferStart(NULL),
+ fBlockCount(0),
+ fBlocks(NULL),
+ fDSPs(NULL),
+ fBusPatches(NULL),
+ fEndOfBusPatches(NULL),
+ fMaxChannels(8192),
+ fParityOk(new Bool_t[8192]),
+ fCurrentBlock(NULL),
+ fCurrentDSP(NULL),
+ fCurrentBusPatch(NULL),
+ fCurrentParityOkFlag(NULL),
+ fParityErrors(0),
+ fGlitchErrors(0),
+ fPaddingErrors(0),
+ fTokenLostErrors(0),
+ fMaxBlocks(),
+ fMaxDsps(),
+ fMaxBusPatches()
{
- /// Default constructor initialises the internal buffer to store decoded
- /// channel / digit data to 8192 elements.
- /// This array will grow dynamically if needed.
+ /// Default constructor initialises the internal parity flags buffer to
+ /// store 8192 elements. This array will grow dynamically if needed.
}
{
/// Default destructor cleans up the allocated memory.
- if (fChannelBuffer != NULL)
+ if (fParityOk != NULL) delete [] fParityOk;
+ if (fBlocks != NULL) delete [] fBlocks;
+ if (fDSPs != NULL) delete [] fDSPs;
+ if (fBusPatches != NULL) delete [] fBusPatches;
+}
+
+
+void AliMUONRawStreamTrackerHP::AliDecoderEventHandler::SetMaxStructs(
+ UInt_t maxBlocks, UInt_t maxDsps, UInt_t maxBusPatches
+ )
+{
+ /// Sets the maximum number of structures allowed.
+
+ // Start by clearing the current arrays.
+ if (fBlocks != NULL)
{
- delete [] fChannelBuffer;
+ delete [] fBlocks;
+ fBlocks = NULL;
}
+ if (fDSPs != NULL)
+ {
+ delete [] fDSPs;
+ fDSPs = NULL;
+ }
+ if (fBusPatches != NULL)
+ {
+ delete [] fBusPatches;
+ fBusPatches = NULL;
+ }
+ fCurrentBlock = NULL;
+ fCurrentDSP = NULL;
+ fCurrentBusPatch = NULL;
+
+ // Allocate new memory.
+ fBlocks = new AliBlockHeader[maxBlocks];
+ fDSPs = new AliDspHeader[maxBlocks*maxDsps];
+ fBusPatches = new AliBusPatch[maxBlocks*maxDsps*maxBusPatches];
+ fEndOfBusPatches = fBusPatches;
+
+ fMaxBlocks = maxBlocks;
+ fMaxDsps = maxDsps;
+ fMaxBusPatches = maxBusPatches;
}
+
void AliMUONRawStreamTrackerHP::AliDecoderEventHandler::OnNewBuffer(
const void* buffer, UInt_t bufferSize
)
// remember the start of the buffer to be used in OnError.
fBufferStart = buffer;
-
- // Reset the number of channels found.
- fChannelCount = 0;
-
- // Check if we will have enough space in the fChannelBuffer array.
+
+ // Reset error counters.
+ 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.
// bufferSize / sizeof(UInt_t) will be a safe over estimate of the
// number of channels that we will find.
- UInt_t maxPossibleChannels = bufferSize / sizeof(UInt_t);
- if (maxPossibleChannels > fMaxChannels)
+ UInt_t maxChannelsPossible = bufferSize / sizeof(UInt_t);
+ if (maxChannelsPossible > fMaxChannels)
{
- if (fChannelBuffer != NULL)
+ if (fParityOk != NULL)
{
- delete [] fChannelBuffer;
- fChannelBuffer = NULL;
+ delete [] fParityOk;
+ fParityOk = NULL;
fMaxChannels = 0;
}
- fChannelBuffer = new AliChannelInfo[maxPossibleChannels];
- fMaxChannels = maxPossibleChannels;
+ fParityOk = new Bool_t[maxChannelsPossible];
+ fMaxChannels = maxChannelsPossible;
}
-}
-
-
-void AliMUONRawStreamTrackerHP::AliDecoderEventHandler::OnNewBusPatch(
- const AliMUONBusPatchHeaderStruct* header, const void* /*data*/
- )
-{
- /// This is called by the high performance decoder when a new bus patch
- /// is found within the DDL payload. All we do is remember the bus patch ID.
- /// \param header The bus patch header structure.
- /// \param data The bus patch data (not used in this method).
- fBusPatchId = header->fBusPatchId;
+ // Reset the current pointers which will be used to track where we need to
+ // fill fBlocks, fDSPs, fBusPatches and the parity flag. We have to subtract
+ // one space because we will increment the pointer the first time in the
+ // OnNewXZY methods.
+ fCurrentBlock = fBlocks-1;
+ fCurrentDSP = fDSPs-1;
+ fCurrentBusPatch = fBusPatches-1;
+ fCurrentParityOkFlag = fParityOk-1;
+ fBlockCount = 0;
}
-void AliMUONRawStreamTrackerHP::AliDecoderEventHandler::OnData(UInt_t data)
+void AliMUONRawStreamTrackerHP::Swap(UInt_t* buffer, Int_t size) const
{
- /// This is called by the high performance decoder when a new bus patch
- /// is found within the DDL payload. All we do is remember the bus patch ID.
- /// \param data The bus patch data (not used in this method).
+ // swap from little to big endian
- assert( fChannelCount < fMaxChannels );
+ 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;
- UShort_t manuId; UChar_t channelId; UShort_t adc;
- UnpackADC(data, manuId, channelId, adc);
- fChannelBuffer[fChannelCount] = AliChannelInfo(fBusPatchId, manuId, channelId, adc);
- fChannelCount++;
+ 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++;
+ }
}
/// 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 );
- const char* msg = ErrorCodeToMessage(error);
- unsigned long pos = (unsigned long)location - (unsigned long)fBufferStart;
+ 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 %lu 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:
+ 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:
+ 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:
- fRawStream->GetReader()->AddMinorErrorLog(error, Form("%s [At byte: %d]", msg, pos));
+ 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 = (reinterpret_cast<size_t>(location) - reinterpret_cast<size_t>(fCurrentBusPatch->GetData()))
+ / sizeof(UInt_t);
+ 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<const UInt_t*>(location);
+ message = Form(
+ "Lost token error detected with address 0x%X of DDL %d and code %d.",
+ ((word & 0xFFFF0000)),
+ fRawStream->GetDDL(),
+ (word & 0xF)
+ );
+ break;
+ case kHighErrorDetail:
+ default:
+ word = *reinterpret_cast<const UInt_t*>(location);
+ message = Form(
+ "Lost token error detected with address 0x%X and code %d. %s",
+ ((word & 0xFFFF0000)),
+ (word & 0xF),
+ detail
+ );
+ break;
+ }
+ logAsMajorError = false;
+ break;
+
default:
- fRawStream->GetReader()->AddMajorErrorLog(error, Form("%s [At byte: %d]", msg, pos));
+ switch (fRawStream->GetLoggingDetailLevel())
+ {
+ case kLowErrorDetail:
+ message = ErrorCodeToMessage(error);
+ break;
+ case kMediumErrorDetail:
+ message = Form(
+ "%s (At byte %lu)",
+ 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;
}
+
+ // 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",
+ message
+ );
+ }
}