assert( GetReader() != NULL );
+ // Better to reset these pointers.
+ fCurrentBusPatch = NULL;
+ fCurrentData = NULL;
+ fEndOfData = NULL;
+
while (fDDL < GetMaxDDL())
{
GetReader()->Reset();
}
// 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;
/// \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 (fCurrentData == NULL) return kFALSE;
+
retry:
// Check if we still have data to be returned for the current bus patch.
if (fCurrentData != fEndOfData)
fBlocks = new AliBlockHeader[maxBlocks];
fDSPs = new AliDspHeader[maxBlocks*maxDsps];
fBusPatches = new AliBusPatch[maxBlocks*maxDsps*maxBusPatches];
- fEndOfBusPatches = fEndOfBusPatches;
+ fEndOfBusPatches = fBusPatches;
}
/// 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 raw reader.
/// \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.
switch (error)
{
case kGlitchFound:
+ fGlitchErrors++;
message = Form(
"Glitch error detected in DSP %d, skipping event ",
fCurrentBlock->GetDspId()
break;
case kBadPaddingWord:
+ fPaddingErrors++;
// We subtract 1 from the current numbers of blocks, DSPs
// and bus patches to get the indices.
message = Form(
break;
case kParityError:
+ fParityErrors++;
// 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
Int_t fDDL; //!< The current DDL number being handled.
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* fCurrentBusPatch; //!< The current data word to return by Next().
+ const AliBusPatch* fCurrentBusPatch; //!< The current bus patch being handled by Next().
const UInt_t* fCurrentData; //!< The current data word to return by Next().
const UInt_t* fEndOfData; //!< The last data word in the current bus patch.
Bool_t fHadError; //!< Flag indicating if there was a decoding error or not.
inline const AliMUONRawStreamTrackerHP::AliBusPatch* AliMUONRawStreamTrackerHP::Next()
{
/// Returns the next batch of decoded channel data.
+ if (fCurrentBusPatch == NULL) return NULL;
do {
if (fCurrentBusPatch != fDecoder.GetHandler().EndOfBusPatch())
return fCurrentBusPatch++;
//___________________________________________
AliMUONRawStreamTrigger::AliMUONRawStreamTrigger()
-: AliMUONRawStream(),
+: AliMUONVRawStreamTrigger(),
fPayload(new AliMUONPayloadTrigger()),
fCurrentDDL(0x0),
fCurrentDDLIndex(fgkMaxDDL),
//_________________________________________________________________
AliMUONRawStreamTrigger::AliMUONRawStreamTrigger(AliRawReader* rawReader)
- : AliMUONRawStream(rawReader),
+ : AliMUONVRawStreamTrigger(rawReader),
fPayload(new AliMUONPayloadTrigger()),
fCurrentDDL(0x0),
fCurrentDDLIndex(fgkMaxDDL),
#include <TObject.h>
#include "AliMUONPayloadTrigger.h"
-#include "AliMUONRawStream.h"
+#include "AliMUONVRawStreamTrigger.h"
class TArrayS;
class AliRawReader;
class AliMUONRegkHeader;
class AliMUONLocalStruct;
-class AliMUONRawStreamTrigger: public AliMUONRawStream {
+class AliMUONRawStreamTrigger: public AliMUONVRawStreamTrigger {
public :
AliMUONRawStreamTrigger();
AliMUONRawStreamTrigger(AliRawReader* rawReader);
--- /dev/null
+/**************************************************************************
+ * This file is property of and copyright by the ALICE HLT Project *
+ * All rights reserved. *
+ * *
+ * Primary Authors: *
+ * Artur Szostak <artursz@iafrica.com> *
+ * *
+ * Permission to use, copy, modify and distribute this software and its *
+ * documentation strictly for non-commercial purposes is hereby granted *
+ * without fee, provided that the above copyright notice appears in all *
+ * copies and that both the copyright notice and this permission notice *
+ * appear in the supporting documentation. The authors make no claims *
+ * about the suitability of this software for any purpose. It is *
+ * provided "as is" without express or implied warranty. *
+ **************************************************************************/
+
+/* $Id$ */
+
+/// \class AliMUONRawStreamTriggerHP
+///
+/// Implementation of a streamer interface to the high performance trigger decoder.
+/// This is the raw stream class which interfaces between the high performance
+/// core decoder for MUON trigger chambers and the AliRawReader class.
+/// To gain the most out of the decoder, the Next() method should be used,
+/// for example:
+/// \code
+/// AliMUONRawStreamTriggerHP* rawStream; // assume initialised
+/// const AliMUONRawStreamTriggerHP::AliLocalStruct* localStruct;
+/// while ((localStruct = rawStream->Next()) != NULL)
+/// {
+/// // Do something with localStruct here.
+/// }
+/// \endcode
+///
+/// This decoder tries to implement as similar an interface as possible to
+/// AliMUONRawStreamTrigger where possible. However certain constructs which
+/// would slow us down too much are avoided.
+///
+/// \author Artur Szostak <artursz@iafrica.com>
+
+#include "AliMUONRawStreamTriggerHP.h"
+#include "AliRawReader.h"
+#include "AliLog.h"
+#include <cassert>
+#include <iostream>
+#include <iomanip>
+using std::cout;
+using std::endl;
+using std::hex;
+using std::dec;
+
+/// \cond CLASSIMP
+ClassImp(AliMUONRawStreamTriggerHP)
+/// \endcond
+
+const Int_t AliMUONRawStreamTriggerHP::fgkMaxDDL = 2;
+
+
+AliMUONRawStreamTriggerHP::AliMUONRawStreamTriggerHP() :
+ AliMUONVRawStreamTrigger(),
+ fDecoder(),
+ fDDL(0),
+ fBufferSize(8192),
+ fBuffer(new UChar_t[8192]),
+ fCurrentLocalStruct(NULL),
+ fHadError(kFALSE),
+ fDone(kFALSE)
+{
+ ///
+ /// Default constructor.
+ ///
+
+ fDecoder.ExitOnError(false);
+
+ fDecoder.GetHandler().SetMaxStructs(
+ fDecoder.MaxRegionals(),
+ fDecoder.MaxLocals()
+ );
+
+ fDecoder.GetHandler().SetRawStream(this);
+}
+
+
+AliMUONRawStreamTriggerHP::AliMUONRawStreamTriggerHP(AliRawReader* rawReader) :
+ AliMUONVRawStreamTrigger(rawReader),
+ fDecoder(),
+ fDDL(0),
+ fBufferSize(8192),
+ fBuffer(new UChar_t[8192]),
+ fCurrentLocalStruct(NULL),
+ fHadError(kFALSE),
+ fDone(kFALSE)
+{
+ ///
+ /// Constructor with AliRawReader as argument.
+ ///
+
+ fDecoder.ExitOnError(false);
+
+ fDecoder.GetHandler().SetMaxStructs(
+ fDecoder.MaxRegionals(),
+ fDecoder.MaxLocals()
+ );
+
+ fDecoder.GetHandler().SetRawStream(this);
+}
+
+
+AliMUONRawStreamTriggerHP::~AliMUONRawStreamTriggerHP()
+{
+ ///
+ /// Default destructor which cleans up the memory allocated.
+ ///
+
+ if (fBuffer != NULL)
+ {
+ delete [] fBuffer;
+ }
+}
+
+
+void AliMUONRawStreamTriggerHP::First()
+{
+ /// Initialise or reset the iterator.
+ /// The first DDL will be found and decoded.
+
+ assert( GetReader() != NULL );
+
+ fDDL = 0;
+ fDone = kFALSE;
+ NextDDL();
+}
+
+
+Bool_t AliMUONRawStreamTriggerHP::NextDDL()
+{
+ /// Read in the next trigger DDL and decode the payload with the
+ /// high performance decoder.
+ /// \return kTRUE if the next DDL was successfully read and kFALSE
+ /// otherwise.
+
+ assert( GetReader() != NULL );
+
+ fCurrentLocalStruct = NULL;
+
+ while (fDDL < GetMaxDDL())
+ {
+ GetReader()->Reset();
+ GetReader()->Select("MUONTRG", fDDL, fDDL); // Select the DDL file to be read.
+ if (GetReader()->ReadHeader()) break;
+ AliDebug(3, Form("Skipping DDL %d which does not seem to be there", fDDL+1));
+ fDDL++;
+ }
+
+ // 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
+ // Check if we have enough buffer space already in fBuffer. If we do then
+ // just continue reading otherwise we need to resize the buffer.
+ if (fBufferSize < dataSize)
+ {
+ if (fBuffer != NULL)
+ {
+ delete [] fBuffer;
+ fBuffer = NULL;
+ fBufferSize = 0;
+ }
+ try
+ {
+ fBuffer = new UChar_t[dataSize];
+ fBufferSize = dataSize;
+ }
+ catch (const std::bad_alloc&)
+ {
+ AliError("Could not allocate more buffer space. Cannot decode DDL.");
+ return kFALSE;
+ }
+ }
+
+ if (not GetReader()->ReadNext(fBuffer, dataSize))
+ {
+ return kFALSE;
+ }
+
+#ifndef R__BYTESWAP
+ Swap(reinterpret_cast<UInt_t*>(fBuffer), dataSize / sizeof(UInt_t)); // Swap needed for mac power pc.
+#endif
+
+ 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);
+ }
+ catch (const std::bad_alloc&)
+ {
+ AliError("Could not allocate more buffer space. Cannot decode DDL.");
+ return kFALSE;
+ }
+
+ // Update the current local structure pointer.
+ fCurrentLocalStruct = fDecoder.GetHandler().FirstLocalStruct();
+
+ fDDL++; // Remember to increment index to next DDL.
+ return kTRUE;
+}
+
+
+Bool_t AliMUONRawStreamTriggerHP::IsDone() const
+{
+ /// Indicates whether the iteration is finished or not.
+ /// \return kTRUE if we already read all the digits and kFALSE if not.
+
+ return fDone;
+}
+
+
+Bool_t AliMUONRawStreamTriggerHP::Next(
+ UChar_t& id, UChar_t& dec, Bool_t& trigY,
+ UChar_t& yPos, UChar_t& sXDev, UChar_t& xDev,
+ UChar_t& xPos, Bool_t& triggerY, Bool_t& triggerX,
+ TArrayS& xPattern, TArrayS& yPattern
+ )
+{
+ const AliLocalStruct* localStruct = Next();
+ if (localStruct == NULL) return kFALSE;
+
+ id = localStruct->GetId();
+ dec = localStruct->GetDec();
+ trigY = localStruct->GetTrigY();
+ yPos = localStruct->GetYPos();
+ sXDev = localStruct->GetSXDev();
+ xDev = localStruct->GetXDev();
+ xPos = localStruct->GetXPos();
+
+ triggerX = localStruct->GetTriggerX();
+ triggerY = localStruct->GetTriggerY();
+
+ localStruct->GetXPattern(xPattern);
+ localStruct->GetYPattern(yPattern);
+
+ return kTRUE;
+}
+
+
+void AliMUONRawStreamTriggerHP::SetMaxRegAllowed(Int_t reg)
+{
+ /// Set the maximum allowed number of regional cards in the DDL.
+
+ fDecoder.MaxRegionals( (UInt_t) reg );
+
+ fDecoder.GetHandler().SetMaxStructs(
+ fDecoder.MaxRegionals(),
+ fDecoder.MaxLocals()
+ );
+}
+
+
+void AliMUONRawStreamTriggerHP::SetMaxLoc(Int_t loc)
+{
+ /// Sets the maximum number of local cards in the DDL.
+
+ fDecoder.MaxLocals( (UInt_t) loc );
+
+ fDecoder.GetHandler().SetMaxStructs(
+ fDecoder.MaxRegionals(),
+ fDecoder.MaxLocals()
+ );
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void AliMUONRawStreamTriggerHP::AliHeader::Print() const
+{
+ /// Print DARC header, global header and global scalars to screen.
+
+ cout << "===== DARC info =====" << endl;
+ cout << "Header bits : 0x" << hex << fDarcHeader << dec << endl;
+ if (fDarcScalars != NULL)
+ {
+ cout << "L0R : " << fDarcScalars->fL0R << " (0x"
+ << hex << fDarcScalars->fL0R << dec << ")" << endl;
+ cout << "L1P : " << fDarcScalars->fL1P << " (0x"
+ << hex << fDarcScalars->fL1P << dec << ")" << endl;
+ cout << "L1S : " << fDarcScalars->fL1S << " (0x"
+ << hex << fDarcScalars->fL1S << dec << ")" << endl;
+ cout << "L2A : " << fDarcScalars->fL2A << " (0x"
+ << hex << fDarcScalars->fL2A << dec << ")" << endl;
+ cout << "L2R : " << fDarcScalars->fL2R << " (0x"
+ << hex << fDarcScalars->fL2R << dec << ")" << endl;
+ cout << "Clock : " << fDarcScalars->fClk << " (0x"
+ << hex << fDarcScalars->fClk << dec << ")" << endl;
+ cout << "Hold : " << fDarcScalars->fHold << " (0x"
+ << hex << fDarcScalars->fHold << dec << ")" << endl;
+ cout << "Spare : " << fDarcScalars->fSpare << " (0x"
+ << hex << fDarcScalars->fSpare << dec << ")" << endl;
+ }
+ else
+ {
+ cout << "Scalars == NULL" << endl;
+ }
+
+ cout << "===== Global info =====" << endl;
+ for (int i = 0; i < 4; i++)
+ {
+ cout << "Input[" << i << "] : " << fGlobalHeader->fInput[i] << " (0x"
+ << hex << fGlobalHeader->fInput[i] << dec << ")" << endl;
+ }
+ cout << "Output : " << fGlobalHeader->fOutput << " (0x"
+ << hex << fGlobalHeader->fOutput << dec << ")" << endl;
+ if (fGlobalScalars != NULL)
+ {
+ cout << "L0 : " << fGlobalScalars->fL0 << " (0x"
+ << hex << fGlobalScalars->fL0 << dec << ")" << endl;
+ cout << "Clock : " << fGlobalScalars->fClk << " (0x"
+ << hex << fGlobalScalars->fClk << dec << ")" << endl;
+ for (int j = 0; j < 4; j++)
+ {
+ cout << "Scaler[" << j << "] : " << fGlobalScalars->fScaler[j] << " (0x"
+ << hex << fGlobalScalars->fScaler[j] << dec << ")" << endl;
+ }
+ cout << "Hold : " << fGlobalScalars->fHold << " (0x"
+ << hex << fGlobalScalars->fHold << dec << ")" << endl;
+ cout << "Spare : " << fGlobalScalars->fSpare << " (0x"
+ << hex << fGlobalScalars->fSpare << dec << ")" << endl;
+ }
+ else
+ {
+ cout << "Scalars == NULL" << endl;
+ }
+}
+
+void AliMUONRawStreamTriggerHP::AliRegionalHeader::Print() const
+{
+ /// Print the regional header and scalars to screen.
+
+ cout << "===== Regional card info =====" << endl;
+ cout << "DarcWord : " << fHeader->fDarcWord << " (0x"
+ << hex << fHeader->fDarcWord << dec << ")" << endl;
+ cout << "Word : " << fHeader->fWord << " (0x"
+ << hex << fHeader->fWord << dec << ")" << endl;
+ cout << "Input[0] : " << fHeader->fInput[0] << " (0x"
+ << hex << fHeader->fInput[0] << dec << ")" << endl;
+ cout << "Input[1] : " << fHeader->fInput[1] << " (0x"
+ << hex << fHeader->fInput[1] << dec << ")" << endl;
+ cout << "L0/Mask : " << fHeader->fL0CountAndMask << " (0x"
+ << hex << fHeader->fL0CountAndMask << dec << ")" << endl;
+ if (fScalars != NULL)
+ {
+ cout << "Clock : " << fScalars->fClk << " (0x"
+ << hex << fScalars->fClk << dec << ")" << endl;
+ for (int i = 0; i < 8; i++)
+ {
+ cout << "Scaler[" << i << "] : " << fScalars->fScaler[i] << " (0x"
+ << hex << fScalars->fScaler[i] << dec << ")" << endl;
+ }
+ cout << "Hold : " << fScalars->fHold << " (0x"
+ << hex << fScalars->fHold << dec << ")" << endl;
+ }
+ else
+ {
+ cout << "Scalars == NULL" << endl;
+ }
+}
+
+void AliMUONRawStreamTriggerHP::AliLocalStruct::Print() const
+{
+ /// Print local trigger structure and scalars to screen.
+
+ cout << "===== Local card info =====" << endl;
+ cout << "X2X1 : " << fLocalStruct->fX2X1 << " (0x"
+ << hex << fLocalStruct->fX2X1 << dec << ")" << endl;
+ cout << "X4X3 : " << fLocalStruct->fX4X3 << " (0x"
+ << hex << fLocalStruct->fX4X3 << dec << ")" << endl;
+ cout << "Y2Y1 : " << fLocalStruct->fY2Y1 << " (0x"
+ << hex << fLocalStruct->fY2Y1 << dec << ")" << endl;
+ cout << "Y4Y3 : " << fLocalStruct->fY4Y3 << " (0x"
+ << hex << fLocalStruct->fY4Y3 << dec << ")" << endl;
+ cout << "Trigger bits : " << fLocalStruct->fTriggerBits << " (0x"
+ << hex << fLocalStruct->fTriggerBits << dec << ")" << endl;
+ if (fScalars != NULL)
+ {
+ cout << "L0 : " << fScalars->fL0 << " (0x"
+ << hex << fScalars->fL0 << dec << ")" << endl;
+ cout << "Hold : " << fScalars->fHold << " (0x"
+ << hex << fScalars->fHold << dec << ")" << endl;
+ cout << "Clock : " << fScalars->fClk << " (0x"
+ << hex << fScalars->fClk << dec << ")" << endl;
+ cout << "LPtNTrig : " << fScalars->fLPtNTrig << " (0x"
+ << hex << fScalars->fLPtNTrig << dec << ")" << endl;
+ cout << "HPtNTrig : " << fScalars->fHPtNTrig << " (0x"
+ << hex << fScalars->fHPtNTrig << dec << ")" << endl;
+ cout << "LPtRTrig : " << fScalars->fLPtRTrig << " (0x"
+ << hex << fScalars->fLPtRTrig << dec << ")" << endl;
+ cout << "HPtRTrig : " << fScalars->fHPtRTrig << " (0x"
+ << hex << fScalars->fHPtRTrig << dec << ")" << endl;
+ cout << "LPtLTrig : " << fScalars->fLPtLTrig << " (0x"
+ << hex << fScalars->fLPtLTrig << dec << ")" << endl;
+ cout << "HPtLTrig : " << fScalars->fHPtLTrig << " (0x"
+ << hex << fScalars->fHPtLTrig << dec << ")" << endl;
+ cout << "LPtSTrig : " << fScalars->fLPtSTrig << " (0x"
+ << hex << fScalars->fLPtSTrig << dec << ")" << endl;
+ cout << "HPtSTrig : " << fScalars->fHPtSTrig << " (0x"
+ << hex << fScalars->fHPtSTrig << dec << ")" << endl;
+ for (int i = 0; i < 8*4; i++)
+ {
+ cout << "Scaler[" << i << "] : " << fScalars->fScaler[i] << " (0x"
+ << hex << fScalars->fScaler[i] << dec << ")" << endl;
+ }
+ cout << "EOS : " << fScalars->fEOS << " (0x"
+ << hex << fScalars->fEOS << dec << ")" << endl;
+ cout << "Reset : " << fScalars->fReset << " (0x"
+ << hex << fScalars->fReset << dec << ")" << endl;
+ }
+ else
+ {
+ cout << "Scalars == NULL" << endl;
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+AliMUONRawStreamTriggerHP::AliDecoderEventHandler::AliDecoderEventHandler() :
+ fRawStream(NULL),
+ fBufferStart(NULL),
+ fDarcHeader(0),
+ fDarcScalars(NULL),
+ fHeaders(),
+ fRegionalsCount(0),
+ fRegionals(NULL),
+ fLocals(NULL),
+ fEndOfLocals(NULL),
+ fCurrentRegional(NULL),
+ fCurrentLocal(NULL),
+ fDarcEoWErrors(0),
+ fGlobalEoWErrors(0),
+ fRegEoWErrors(0),
+ fLocalEoWErrors(0),
+ fWarnings(kTRUE)
+{
+ /// Default constructor
+}
+
+
+AliMUONRawStreamTriggerHP::AliDecoderEventHandler::~AliDecoderEventHandler()
+{
+ /// Default destructor cleans up the allocated memory.
+
+ if (fRegionals != NULL) delete [] fRegionals;
+ if (fLocals != NULL) delete [] fLocals;
+}
+
+
+void AliMUONRawStreamTriggerHP::AliDecoderEventHandler::SetMaxStructs(
+ UInt_t maxRegionals, UInt_t maxLocals
+ )
+{
+ /// Sets the maximum number of structures allowed.
+
+ // Start by clearing the current arrays.
+ if (fRegionals != NULL)
+ {
+ delete [] fRegionals;
+ fRegionals = NULL;
+ }
+ if (fLocals != NULL)
+ {
+ delete [] fLocals;
+ fLocals = NULL;
+ fEndOfLocals = NULL;
+ }
+ fCurrentRegional = NULL;
+ fCurrentLocal = NULL;
+
+ // Allocate new memory.
+ fRegionals = new AliRegionalHeader[maxRegionals];
+ fLocals = new AliLocalStruct[maxRegionals*maxLocals];
+ fEndOfLocals = fLocals;
+}
+
+
+void AliMUONRawStreamTriggerHP::AliDecoderEventHandler::OnNewBuffer(
+ const void* buffer, UInt_t /*bufferSize*/
+ )
+{
+ /// This is called by the high performance decoder when a new DDL payload
+ /// is about to be decoded.
+
+ assert( fRawStream != NULL );
+
+ // remember the start of the buffer to be used in OnError.
+ fBufferStart = buffer;
+
+ // Reset error counters.
+ fDarcEoWErrors = 0;
+ fGlobalEoWErrors = 0;
+ fRegEoWErrors = 0;
+ fLocalEoWErrors = 0;
+
+ // Reset the current pointers which will be used to track where we need to
+ // fill fRegionals and fLocals. We have to subtract one space because we
+ // will increment the pointer the first time in the OnNewRegionalStruct
+ // and OnLocalStruct methods.
+ fCurrentRegional = fRegionals-1;
+ fCurrentLocal = fLocals-1;
+ fRegionalsCount = 0;
+}
+
+
+void AliMUONRawStreamTriggerHP::AliDecoderEventHandler::OnError(
+ ErrorCode error, const void* location
+ )
+{
+ /// 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 logs this with the raw reader.
+ /// \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;
+ //UInt_t word = 0;
+
+ switch (error)
+ {
+ case kWrongEventType:
+ message = Form("Wrong event type obtained from the Darc header, take the one of CDH");
+ break;
+
+ case kBadEndOfDarc:
+ fDarcEoWErrors++;
+ message = Form(
+ "Wrong end of Darc word %x instead of %x\n",
+ *reinterpret_cast<const UInt_t*>(location),
+ AliMUONTriggerDDLDecoder<AliMUONTriggerDDLDecoderEventHandler>::EndOfDarcWord()
+ );
+ fRawStream->GetReader()->AddMajorErrorLog(kDarcEoWErr, message);
+ break;
+
+ case kBadEndOfGlobal:
+ fGlobalEoWErrors++;
+ message = Form(
+ "Wrong end of Global word %x instead of %x\n",
+ *reinterpret_cast<const UInt_t*>(location),
+ AliMUONTriggerDDLDecoder<AliMUONTriggerDDLDecoderEventHandler>::EndOfGlobalWord()
+ );
+ fRawStream->GetReader()->AddMajorErrorLog(kGlobalEoWErr, message);
+ break;
+
+ case kBadEndOfRegional:
+ fRegEoWErrors++;
+ message = Form(
+ "Wrong end of Regional word %x instead of %x\n",
+ *reinterpret_cast<const UInt_t*>(location),
+ AliMUONTriggerDDLDecoder<AliMUONTriggerDDLDecoderEventHandler>::EndOfRegionalWord()
+ );
+ fRawStream->GetReader()->AddMajorErrorLog(kRegEoWErr, message);
+ break;
+
+ case kBadEndOfLocal:
+ fLocalEoWErrors++;
+ message = Form(
+ "Wrong end of Local word %x instead of %x\n",
+ *reinterpret_cast<const UInt_t*>(location),
+ AliMUONTriggerDDLDecoder<AliMUONTriggerDDLDecoderEventHandler>::EndOfLocalWord()
+ );
+ fRawStream->GetReader()->AddMajorErrorLog(kLocalEoWErr, message);
+ break;
+
+ default:
+ message = Form(
+ "%s (At byte %d in DDL.)",
+ ErrorCodeToMessage(error),
+ (unsigned long)location - (unsigned long)fBufferStart + sizeof(AliRawDataHeader)
+ );
+ fRawStream->GetReader()->AddMajorErrorLog(error, message);
+ break;
+ }
+
+ if (fWarnings)
+ {
+ AliWarningGeneral(
+ "AliMUONRawStreamTriggerHP::AliDecoderEventHandler",
+ message
+ );
+ }
+}
+
--- /dev/null
+#ifndef ALIMUONRAWSTREAMTRIGGERHP_H
+#define ALIMUONRAWSTREAMTRIGGERHP_H
+/* This file is property of and copyright by the ALICE HLT Project *
+ * ALICE Experiment at CERN, All rights reserved. *
+ * See cxx source for full Copyright notice */
+
+/* $Id$ */
+
+/// \ingroup raw
+/// \class AliMUONRawStreamTriggerHP
+/// \brief Higher performance decoder stream class for reading MUON raw trigger data.
+///
+// This provides a streamer interface to the high performance decoder which
+// is required for AliRoot.
+//
+// Author Artur Szostak <artursz@iafrica.com>
+
+#include "AliMUONVRawStreamTrigger.h"
+#include "AliMUONTriggerDDLDecoder.h"
+#include "TArrayS.h"
+
+
+class AliMUONRawStreamTriggerHP : public AliMUONVRawStreamTrigger
+{
+public:
+ class AliLocalStruct;
+
+ AliMUONRawStreamTriggerHP();
+ AliMUONRawStreamTriggerHP(AliRawReader* rawReader);
+ virtual ~AliMUONRawStreamTriggerHP();
+
+ /// Initialize iterator
+ virtual void First();
+
+ /// DDL iterator
+ virtual Bool_t NextDDL();
+
+ /// 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(UChar_t& id, UChar_t& dec, Bool_t& trigY,
+ UChar_t& yPos, UChar_t& sXDev, UChar_t& xDev,
+ UChar_t& xPos, Bool_t& triggerY, Bool_t& triggerX,
+ TArrayS& xPattern, TArrayS& yPattern);
+
+ /// Returns the next local trigger structure.
+ const AliLocalStruct* Next();
+
+ /// Return maximum number of DDLs.
+ virtual Int_t GetMaxDDL() const { return fgkMaxDDL; }
+
+ /// Return maximum number of regional cards in the DDL.
+ virtual Int_t GetMaxReg() const { return (Int_t) fDecoder.RegionalsDecoded(); }
+
+ /// Return maximum allowed number of regional cards in the DDL.
+ virtual Int_t GetMaxRegAllowed() const { return (Int_t) fDecoder.MaxRegionals(); }
+
+ /// Set the maximum allowed number of regional cards in the DDL.
+ virtual void SetMaxRegAllowed(Int_t reg);
+
+ /// Return maximum number of local cards in the DDL.
+ virtual Int_t GetMaxLoc() const { return (Int_t) fDecoder.MaxLocals(); }
+
+ /// Sets the maximum number of local cards in the DDL.
+ virtual void SetMaxLoc(Int_t loc);
+
+ /// Return number of the current DDL being handled.
+ virtual Int_t GetDDL() const { return fDDL - 1; }
+
+ /// check error/Warning presence
+ virtual Bool_t IsErrorMessage() const { return fHadError; }
+
+ /// Set warnings flag to disable warnings on data errors.
+ virtual void DisableWarnings() { fDecoder.GetHandler().Warnings(kFALSE); }
+ /// Set warnings flag to enable warnings on data errors.
+ virtual void EnableWarnings() { fDecoder.GetHandler().Warnings(kTRUE); }
+
+ /// Get number of end of DARC word errors.
+ UInt_t GetDarcEoWErrors() const {return fDecoder.GetHandler().GetDarcEoWErrors();}
+
+ /// Get number of end of Global word errors.
+ UInt_t GetGlobalEoWErrors() const {return fDecoder.GetHandler().GetGlobalEoWErrors();}
+
+ /// Get number of end of regional word errors.
+ UInt_t GetRegEoWErrors() const {return fDecoder.GetHandler().GetRegEoWErrors();}
+
+ /// Get number of end of local word errors.
+ UInt_t GetLocalEoWErrors() const {return fDecoder.GetHandler().GetLocalEoWErrors();}
+
+ /// 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)); }
+
+ /// Light weight interface class to the DARC and global header data.
+ class AliHeader
+ {
+ public:
+ /// Default constructor.
+ AliHeader(
+ UInt_t darcHeader = 0,
+ const AliMUONDarcScalarsStruct* darcScalars = NULL,
+ const AliMUONGlobalHeaderStruct* globalHeader = NULL,
+ const AliMUONGlobalScalarsStruct* globalScalars = NULL
+ ) :
+ fDarcHeader(darcHeader), fDarcScalars(darcScalars),
+ fGlobalHeader(globalHeader), fGlobalScalars(globalScalars)
+ {
+ }
+
+ /// Implement shallow copying in the copy constructor.
+ AliHeader(const AliHeader& o) :
+ fDarcHeader(o.fDarcHeader), fDarcScalars(o.fDarcScalars),
+ fGlobalHeader(o.fGlobalHeader), fGlobalScalars(o.fGlobalScalars)
+ {
+ }
+
+ /// Implement shallow copying in the assignment operator.
+ AliHeader& operator = (const AliHeader& object)
+ {
+ memcpy(this, &object, sizeof(AliHeader));
+ return *this;
+ }
+
+ /// Default destructor.
+ ~AliHeader() {};
+
+ /// Return first word
+ UInt_t GetWord() const {return GetDarcHeader();}
+ /// Return global input
+ Int_t GetGlobalInput(Int_t n) const {return fGlobalHeader->fInput[n];}
+ /// Return global output
+ UChar_t GetGlobalOutput() const {return AliMUONTriggerDDLDecoderEventHandler::GetGlobalOutput(fGlobalHeader);}
+ /// Return global config
+ UShort_t GetGlobalConfig() const {return AliMUONTriggerDDLDecoderEventHandler::GetGlobalConfig(fGlobalHeader);}
+
+ /// Return event type
+ UChar_t GetEventType() const {return AliMUONTriggerDDLDecoderEventHandler::GetDarcEventType(GetDarcHeader());}
+ /// Returns true if this was a physics event.
+ Bool_t IsPhysicsEvent() const {return GetEventType() == 0x1;}
+ /// Return Darc type
+ UChar_t GetDarcType() const {return AliMUONTriggerDDLDecoderEventHandler::GetDarcType(GetDarcHeader());}
+ /// Return serial number
+ UChar_t GetSerialNb() const {return AliMUONTriggerDDLDecoderEventHandler::GetDarcSerialNb(GetDarcHeader());}
+ /// Return version
+ UChar_t GetVersion() const {return AliMUONTriggerDDLDecoderEventHandler::GetDarcVersion(GetDarcHeader());}
+ /// Return VME trig
+ Bool_t GetVMETrig() const {return AliMUONTriggerDDLDecoderEventHandler::GetDarcVMETrig(GetDarcHeader());}
+ /// Return global flag
+ Bool_t GetGlobalFlag() const {return AliMUONTriggerDDLDecoderEventHandler::GetDarcGlobalFlag(GetDarcHeader());}
+ /// Return CPT trigger
+ Bool_t GetCTPTrig() const {return AliMUONTriggerDDLDecoderEventHandler::GetDarcCTPTrig(GetDarcHeader());}
+ /// Return DAQ flag
+ Bool_t GetDAQFlag() const {return AliMUONTriggerDDLDecoderEventHandler::GetDarcDAQFlag(GetDarcHeader());}
+ /// Return reg pattern
+ UChar_t GetRegPattern() const {return AliMUONTriggerDDLDecoderEventHandler::GetDarcRegPattern(GetDarcHeader());}
+
+ // DARC get methods
+ /// Return DARC L0 received and used
+ UInt_t GetDarcL0R() const {return (fDarcScalars != NULL) ? fDarcScalars->fL0R : 0;}
+ /// Return DARC L1 physics
+ UInt_t GetDarcL1P() const {return (fDarcScalars != NULL) ? fDarcScalars->fL1P : 0;}
+ /// Return DARC L1 software
+ UInt_t GetDarcL1S() const {return (fDarcScalars != NULL) ? fDarcScalars->fL1S : 0;}
+ /// Return DARC L2 accept
+ UInt_t GetDarcL2A() const {return (fDarcScalars != NULL) ? fDarcScalars->fL2A : 0;}
+ /// Return DARC L2 reject
+ UInt_t GetDarcL2R() const {return (fDarcScalars != NULL) ? fDarcScalars->fL2R : 0;}
+ /// Return DARC clock
+ UInt_t GetDarcClock() const {return (fDarcScalars != NULL) ? fDarcScalars->fClk : 0;}
+ /// Return DARC hold (dead time)
+ UInt_t GetDarcHold() const {return (fDarcScalars != NULL) ? fDarcScalars->fHold : 0;}
+
+ // global get methods
+ /// Return global L0
+ UInt_t GetGlobalL0() const {return (fGlobalScalars != NULL) ? fGlobalScalars->fL0 : 0;}
+ /// Return global clock
+ UInt_t GetGlobalClock() const {return (fGlobalScalars != NULL) ? fGlobalScalars->fClk : 0;}
+ /// Return global scalars or NULL if none exist.
+ const UInt_t* GetGlobalScaler() const {return (fGlobalScalars != NULL) ? &fGlobalScalars->fScaler[0] : NULL;}
+ /// Return global hold (dead time)
+ UInt_t GetGlobalHold() const {return (fGlobalScalars != NULL) ? fGlobalScalars->fHold : 0;}
+ /// Return global spare
+ UInt_t GetGlobalSpare() const {return (fGlobalScalars != NULL) ? fGlobalScalars->fSpare : 0;}
+
+ /// Return true if type for DARC is default.
+ Bool_t DarcIsDefaultType() const {return GetDarcType() == AliMUONTriggerDDLDecoder<AliMUONTriggerDDLDecoderEventHandler>::DarcDefaultType();}
+ /// Return true if type for DARC is Vadorh.
+ Bool_t DarcIsVadohrType() const {return GetDarcType() == AliMUONTriggerDDLDecoder<AliMUONTriggerDDLDecoderEventHandler>::DarcVadorhType();}
+
+ /// Return the DARC header's raw data.
+ UInt_t GetDarcHeader() const {return fDarcHeader;}
+
+ /// Return the DARC scalars raw data or NULL if none exist.
+ const AliMUONDarcScalarsStruct* GetDarcScalars() const {return fDarcScalars;}
+
+ /// Return the global header's raw data.
+ const AliMUONGlobalHeaderStruct* GetGlobalHeader() const {return fGlobalHeader;}
+
+ /// Return the global scalars raw data or NULL if none exist.
+ const AliMUONGlobalScalarsStruct* GetGlobalScalars() const {return fGlobalScalars;}
+
+ /// Print the contents of the headers to screen.
+ void Print() const;
+
+ private:
+
+ UInt_t fDarcHeader; ///< Pointer to DARC header in DDL payload.
+ const AliMUONDarcScalarsStruct* fDarcScalars; ///< Pointer to DARC scalars in DDL payload.
+ const AliMUONGlobalHeaderStruct* fGlobalHeader; ///< Pointer to global header in DDL payload.
+ const AliMUONGlobalScalarsStruct* fGlobalScalars; ///< Pointer to global scalars in DDL payload.
+ };
+
+ /// Light weight interface class to the regional card header data.
+ class AliRegionalHeader
+ {
+ public:
+ /// Default constructor.
+ AliRegionalHeader(
+ const AliLocalStruct* localsArray = NULL,
+ const AliMUONRegionalHeaderStruct* header = NULL,
+ const AliMUONRegionalScalarsStruct* scalars = NULL
+ ) :
+ fNext(NULL), fLocalsCount(0), fFirstLocal(localsArray),
+ fHeader(header), fScalars(scalars)
+ {
+ }
+
+ /// Implement shallow copying in the copy constructor.
+ AliRegionalHeader(const AliRegionalHeader& o) :
+ fNext(o.fNext), fLocalsCount(o.fLocalsCount),
+ fFirstLocal(o.fFirstLocal), fHeader(o.fHeader),
+ fScalars(o.fScalars)
+ {
+ }
+
+ /// Implement shallow copying in the assignment operator.
+ AliRegionalHeader& operator = (const AliRegionalHeader& object)
+ {
+ memcpy(this, &object, sizeof(AliRegionalHeader));
+ return *this;
+ }
+
+ /// Default destructor.
+ ~AliRegionalHeader() {};
+
+ /// Return darc word
+ UInt_t GetDarcWord() const {return fHeader->fDarcWord;}
+ /// Return first reg word
+ UInt_t GetWord() const {return fHeader->fWord;}
+ /// Return regional input
+ UInt_t GetInput(Int_t n) const {assert(n < 2); return fHeader->fInput[n];}
+ /// Return L0
+ UShort_t GetL0() const {return AliMUONTriggerDDLDecoderEventHandler::GetRegionalL0(fHeader);}
+ /// Return mask
+ UShort_t GetMask() const {return AliMUONTriggerDDLDecoderEventHandler::GetRegionalMask(fHeader);}
+
+ //word: phys type:1, reset: 6, serialNb:5, Id:4, version: 8, regional output:8
+ //true for phys, false for soft
+ /// Return RegPhysFlag
+ Bool_t GetRegPhysFlag() const {return AliMUONTriggerDDLDecoderEventHandler::GetRegionalPhysFlag(fHeader);}
+ /// Return ResetNb
+ UChar_t GetResetNb() const {return AliMUONTriggerDDLDecoderEventHandler::GetRegionalResetNb(fHeader);}
+ /// Return SerialNb
+ UChar_t GetSerialNb() const {return AliMUONTriggerDDLDecoderEventHandler::GetRegionalSerialNb(fHeader);}
+ /// Return Id
+ UChar_t GetId() const {return AliMUONTriggerDDLDecoderEventHandler::GetRegionalId(fHeader);}
+ /// Return Version
+ UChar_t GetVersion() const {return AliMUONTriggerDDLDecoderEventHandler::GetRegionalVersion(fHeader);}
+ /// Return Output
+ UChar_t GetOutput() const {return AliMUONTriggerDDLDecoderEventHandler::GetRegionalOutput(fHeader);}
+
+ //Darc Status: error:10, #fpag:3, MBZ:3, phys type:1, present:1, not_full:1
+ // not_empty:1, L2Rej:1, L2Acc:1, L1:1, L0:1, #evt:4, busy:4
+ /// Return ErrorBits
+ UShort_t GetErrorBits() const {return AliMUONTriggerDDLDecoderEventHandler::GetRegionalErrorBits(fHeader);}
+ /// Return FPGANumber
+ UChar_t GetFPGANumber() const {return AliMUONTriggerDDLDecoderEventHandler::GetRegionalFPGANumber(fHeader);}
+ /// Return DarcPhysFlag
+ Bool_t GetDarcPhysFlag() const {return AliMUONTriggerDDLDecoderEventHandler::GetRegionalDarcPhysFlag(fHeader);}
+ /// Return PresentFlag
+ Bool_t GetPresentFlag() const {return AliMUONTriggerDDLDecoderEventHandler::GetRegionalPresentFlag(fHeader);}
+ /// Return RamNotFullFlag
+ Bool_t GetRamNotFullFlag() const {return AliMUONTriggerDDLDecoderEventHandler::GetRegionalRamNotFullFlag(fHeader);}
+ /// Return RamNotEmptyFlag
+ Bool_t GetRamNotEmptyFlag() const {return AliMUONTriggerDDLDecoderEventHandler::GetRegionalRamNotEmptyFlag(fHeader);}
+ /// Return L2RejStatus
+ Bool_t GetL2RejStatus() const {return AliMUONTriggerDDLDecoderEventHandler::GetRegionalL2RejStatus(fHeader);}
+ /// Return L2AccStatus
+ Bool_t GetL2AccStatus() const {return AliMUONTriggerDDLDecoderEventHandler::GetRegionalL2AccStatus(fHeader);}
+ /// Return L1Status
+ Bool_t GetL1Status() const {return AliMUONTriggerDDLDecoderEventHandler::GetRegionalL1Status(fHeader);}
+ /// Return L0Status
+ Bool_t GetL0Status() const {return AliMUONTriggerDDLDecoderEventHandler::GetRegionalL0Status(fHeader);}
+ /// Return EventInRam
+ UChar_t GetEventInRam() const {return AliMUONTriggerDDLDecoderEventHandler::GetRegionalEventInRam(fHeader);}
+ /// Return Busy
+ UChar_t GetBusy() const {return AliMUONTriggerDDLDecoderEventHandler::GetRegionalBusy(fHeader);}
+
+ // scalar methods
+ /// Return regional clock
+ UInt_t GetClock() const {return (fScalars != NULL) ? fScalars->fClk : 0;}
+ /// Return regional ouput
+ const UInt_t* GetScaler() const {return (fScalars != NULL) ? &fScalars->fScaler[0] : NULL;}
+ /// Return regional hold (dead time)
+ UInt_t GetHold() const {return (fScalars != NULL) ? fScalars->fHold : 0;}
+
+ /// Return raw data of regional header.
+ const AliMUONRegionalHeaderStruct* GetHeader() const { return fHeader; }
+
+ /// Return the raw data of the regional scalars or NULL if none exist.
+ const AliMUONRegionalScalarsStruct* GetScalars() const { return fScalars; }
+
+ /// Return the next regional structure header.
+ const AliRegionalHeader* Next() const { return fNext; }
+
+ /// Returns the first AliLocalStruct class in this regional structure.
+ const AliLocalStruct* GetFirstLocalStruct() const { return fFirstLocal; }
+
+ /// Returns the number of local trigger structures within this regional structure.
+ UInt_t GetLocalStructCount() const { return fLocalsCount; }
+
+ /// Return the i'th local trigger structure in this regional structure.
+ const AliLocalStruct* GetLocalStruct(UInt_t i) const
+ {
+ return i < fLocalsCount ? GetFirstLocalStruct() + i : NULL;
+ }
+
+ /// Sets the next regional structure header.
+ void SetNext(const AliRegionalHeader* next) { fNext = next; }
+
+ /// Increments the local trigger structure count.
+ void IncLocalStructCount() { fLocalsCount++; };
+
+ /// Print the contents of the regional header and scalars to screen.
+ void Print() const;
+
+ private:
+
+ const AliRegionalHeader* fNext; ///< Pointer to next regional header.
+ UInt_t fLocalsCount; ///< The number of AliLocalStruct objects found in the array pointed to by fFirstLocal.
+ const AliLocalStruct* fFirstLocal; ///< The first local trigger structure of this regional structure.
+ const AliMUONRegionalHeaderStruct* fHeader; ///< Pointer to the regional header in the DDL payload.
+ const AliMUONRegionalScalarsStruct* fScalars; ///< Pointer to the regional scalars in the DDL payload.
+ };
+
+ /// Light weight interface class to the local trigger card data.
+ class AliLocalStruct
+ {
+ public:
+ /// Default constructor.
+ AliLocalStruct(
+ const AliRegionalHeader* regionalHeader = NULL,
+ const AliMUONLocalInfoStruct* localStruct = NULL,
+ const AliMUONLocalScalarsStruct* scalars = NULL
+ ) :
+ fRegional(regionalHeader), fNext(NULL),
+ fLocalStruct(localStruct), fScalars(scalars)
+ {
+ }
+
+ /// Implement shallow copying in the copy constructor.
+ AliLocalStruct(const AliLocalStruct& o) :
+ fRegional(o.fRegional), fNext(o.fNext),
+ fLocalStruct(o.fLocalStruct), fScalars(o.fScalars)
+ {
+ }
+
+ /// Implement shallow copying in the assignment operator.
+ AliLocalStruct& operator = (const AliLocalStruct& object)
+ {
+ memcpy(this, &object, sizeof(AliLocalStruct));
+ return *this;
+ }
+
+ /// Default destructor.
+ ~AliLocalStruct() {};
+
+ /// Return local data
+ UInt_t GetData(Int_t n) const
+ {
+ assert(n < 5);
+ return (reinterpret_cast<const UInt_t*>(fLocalStruct))[n];
+ }
+
+ /// Return X2
+ UShort_t GetX2() const {return AliMUONTriggerDDLDecoderEventHandler::GetLocalX2(fLocalStruct);}
+ /// Return X1
+ UShort_t GetX1() const {return AliMUONTriggerDDLDecoderEventHandler::GetLocalX1(fLocalStruct);}
+ /// Return X4
+ UShort_t GetX4() const {return AliMUONTriggerDDLDecoderEventHandler::GetLocalX4(fLocalStruct);}
+ /// Return X3
+ UShort_t GetX3() const {return AliMUONTriggerDDLDecoderEventHandler::GetLocalX3(fLocalStruct);}
+
+ /// Return Y2
+ UShort_t GetY2() const {return AliMUONTriggerDDLDecoderEventHandler::GetLocalY2(fLocalStruct);}
+ /// Return Y1
+ UShort_t GetY1() const {return AliMUONTriggerDDLDecoderEventHandler::GetLocalY1(fLocalStruct);}
+ /// Return Y4
+ UShort_t GetY4() const {return AliMUONTriggerDDLDecoderEventHandler::GetLocalY4(fLocalStruct);}
+ /// Return Y3
+ UShort_t GetY3() const {return AliMUONTriggerDDLDecoderEventHandler::GetLocalY3(fLocalStruct);}
+
+ /// return X pattern array
+ void GetXPattern(TArrayS& array) const
+ {
+ Short_t vec[4] = {GetX1(), GetX2(), GetX3(), GetX4()};
+ array.Set(4, vec);
+ }
+
+ /// return Y pattern array
+ void GetYPattern(TArrayS& array) const
+ {
+ Short_t vec[4] = {GetY1(), GetY2(), GetY3(), GetY4()};
+ array.Set(4, vec);
+ }
+
+ /// Return Id
+ UChar_t GetId() const {return AliMUONTriggerDDLDecoderEventHandler::GetLocalId(fLocalStruct);}
+ /// Return Dec
+ UChar_t GetDec() const {return AliMUONTriggerDDLDecoderEventHandler::GetLocalDec(fLocalStruct);}
+ /// Return TrigY
+ Bool_t GetTrigY() const {return AliMUONTriggerDDLDecoderEventHandler::GetLocalTrigY(fLocalStruct);}
+ /// Return TriggerY
+ Bool_t GetTriggerY() const {return AliMUONTriggerDDLDecoderEventHandler::GetLocalTriggerY(fLocalStruct);}
+ /// Return Upos
+ UChar_t GetYPos() const {return AliMUONTriggerDDLDecoderEventHandler::GetLocalYPos(fLocalStruct);}
+ /// Get Sign of X deviation
+ Bool_t GetSXDev() const {return AliMUONTriggerDDLDecoderEventHandler::GetLocalSXDev(fLocalStruct);}
+ /// Get X deviation
+ UChar_t GetXDev() const {return AliMUONTriggerDDLDecoderEventHandler::GetLocalXDev(fLocalStruct);}
+ /// Return TriggerX
+ Bool_t GetTriggerX() const {return AliMUONTriggerDDLDecoderEventHandler::GetLocalTriggerX(fLocalStruct);}
+ /// Return Xpos
+ UChar_t GetXPos() const {return AliMUONTriggerDDLDecoderEventHandler::GetLocalXPos(fLocalStruct);}
+ /// Return LPT
+ UChar_t GetLpt() const {return AliMUONTriggerDDLDecoderEventHandler::GetLocalLpt(fLocalStruct);}
+ /// Return HPT
+ UChar_t GetHpt() const {return AliMUONTriggerDDLDecoderEventHandler::GetLocalHpt(fLocalStruct);}
+
+ // Scaler methods
+ /// Return local L0
+ UInt_t GetL0() const {return (fScalars != NULL) ? fScalars->fL0 : 0;}
+ /// Return local hold (dead time)
+ UInt_t GetHold() const {return (fScalars != NULL) ? fScalars->fHold : 0;}
+ /// Return local clock
+ UInt_t GetClock() const {return (fScalars != NULL) ? fScalars->fClk : 0;}
+
+ /// Return switch
+ UShort_t GetSwitch() const
+ {
+ return (fScalars != NULL) ?
+ AliMUONTriggerDDLDecoderEventHandler::GetLocalSwitch(fScalars) : 0;
+ }
+
+ /// Return ComptXY
+ UChar_t GetComptXY() const
+ {
+ return (fScalars != NULL) ?
+ AliMUONTriggerDDLDecoderEventHandler::GetLocalComptXY(fScalars) : 0;
+ }
+
+ /// Return XY1
+ UShort_t GetXY1(Int_t n) const
+ {
+ return (fScalars != NULL) ?
+ AliMUONTriggerDDLDecoderEventHandler::GetLocalXY1(fScalars, n) : 0;
+ }
+
+ /// Return XY2
+ UShort_t GetXY2(Int_t n) const
+ {
+ return (fScalars != NULL) ?
+ AliMUONTriggerDDLDecoderEventHandler::GetLocalXY2(fScalars, n) : 0;
+ }
+
+ /// Return XY3
+ UShort_t GetXY3(Int_t n) const
+ {
+ return (fScalars != NULL) ?
+ AliMUONTriggerDDLDecoderEventHandler::GetLocalXY3(fScalars, n) : 0;
+ }
+
+ /// Return XY4
+ UShort_t GetXY4(Int_t n) const
+ {
+ return (fScalars != NULL) ?
+ AliMUONTriggerDDLDecoderEventHandler::GetLocalXY4(fScalars, n) : 0;
+ }
+
+ /// Return raw data of the local trigger structure.
+ const AliMUONLocalInfoStruct* GetData() const {return fLocalStruct;}
+
+ /// Return raw data of the local trigger scalars.
+ /// Could be NULL if no scalars present.
+ const AliMUONLocalScalarsStruct* GetScalars() const {return fScalars;}
+
+ /// Return the parent regional header.
+ const AliRegionalHeader* GetRegionalHeader() const { return fRegional; }
+
+ /// Return the next local trigger structure.
+ const AliLocalStruct* Next() const { return fNext; }
+
+ /// Sets the next local trigger structure.
+ void SetNext(const AliLocalStruct* next) { fNext = next; }
+
+ /// Print the contents of the local trigger structure and contents to screen.
+ void Print() const;
+
+ private:
+
+ const AliRegionalHeader* fRegional; ///< The regional structure this local trigger structure belongs to.
+ const AliLocalStruct* fNext; ///< Next local structure object in the regional structure.
+ const AliMUONLocalInfoStruct* fLocalStruct; ///< Pointer to the local trigger structure data in the DDL payload.
+ const AliMUONLocalScalarsStruct* fScalars; ///< Pointer to the local trigger scalars data in the DDL payload.
+ };
+
+ /// Returns the DARC and global headers plus scalars if they exist.
+ const AliHeader* GetHeaders() const { return fDecoder.GetHandler().GetHeaders(); }
+
+ /// Return the number of regional structures in the DDL payload.
+ UInt_t GetRegionalHeaderCount() const
+ {
+ return fDecoder.GetHandler().RegionalHeaderCount();
+ }
+
+ /// Return the first regional structure header.
+ const AliRegionalHeader* GetFirstRegionalHeader() const
+ {
+ return fDecoder.GetHandler().RegionalHeader(0);
+ }
+
+ /// Return the i'th regional header or NULL if not found.
+ const AliRegionalHeader* GetRegionalHeader(UInt_t i) const
+ {
+ return fDecoder.GetHandler().RegionalHeader(i);
+ }
+
+ /// Returns the number of local trigger structures for the given
+ /// regional structure number.
+ UInt_t GetLocalStructCount(UInt_t reg) const
+ {
+ const AliRegionalHeader* r = GetRegionalHeader(reg);
+ return r != NULL ? r->GetLocalStructCount() : 0;
+ }
+
+ /// Returns the i'th local trigger structure for the given regional
+ /// structure number or NULL if not found.
+ const AliLocalStruct* GetLocalStruct(UInt_t reg, UInt_t i) const
+ {
+ const AliRegionalHeader* r = GetRegionalHeader(reg);
+ return r != NULL ? r->GetLocalStruct(i) : NULL;
+ }
+
+ /// Returns the current local struct being decoded or NULL if none found.
+ const AliLocalStruct* CurrentLocalStruct() const
+ {
+ return (fCurrentLocalStruct != fDecoder.GetHandler().EndOfLocalStructs()) ?
+ fCurrentLocalStruct : NULL;
+ }
+
+ /// Returns the current regional structure being decoded
+ /// or NULL if none found.
+ const AliRegionalHeader* CurrentRegionalHeader() const
+ {
+ const AliLocalStruct* local = CurrentLocalStruct();
+ return (local != NULL) ? local->GetRegionalHeader() : NULL;
+ }
+
+private:
+ /// Not implemented
+ AliMUONRawStreamTriggerHP(const AliMUONRawStreamTriggerHP& stream);
+ /// Not implemented
+ AliMUONRawStreamTriggerHP& operator = (const AliMUONRawStreamTriggerHP& stream);
+
+
+ /// 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 AliMUONVRawStreamTrigger, so one
+ /// must set this pointer appropriately before decoding and DDL payload.
+ class AliDecoderEventHandler : public AliMUONTriggerDDLDecoderEventHandler
+ {
+ public:
+
+ /// Default constructor.
+ AliDecoderEventHandler();
+ /// Default destructor.
+ virtual ~AliDecoderEventHandler();
+
+ /// Sets the internal arrays based on the maximum number of structures allowed.
+ void SetMaxStructs(UInt_t maxRegionals, UInt_t maxLocals);
+
+ /// Sets the raw stream object which should be the parent of this class.
+ void SetRawStream(AliMUONVRawStreamTrigger* rawStream) { fRawStream = rawStream; }
+
+ /// Returns the decoded DARC and global headers (and scalars if they exist).
+ const AliHeader* GetHeaders() const { return &fHeaders; }
+
+ /// Returns the number of regional headers.
+ UInt_t RegionalHeaderCount() const { return fRegionalsCount; }
+
+ /// Return the i'th regional structure header.
+ const AliRegionalHeader* RegionalHeader(UInt_t i) const
+ {
+ return i < fRegionalsCount ? &fRegionals[i] : NULL;
+ }
+
+ /// Return the first local structure decoded.
+ const AliLocalStruct* FirstLocalStruct() const { return fLocals; }
+
+ /// Returns the marker to the end of local structures.
+ /// i.e. one position past the last local structure in fLocals.
+ const AliLocalStruct* EndOfLocalStructs() const { return fEndOfLocals; }
+
+ /// Get number of end of DARC word errors.
+ UInt_t GetDarcEoWErrors() const {return fDarcEoWErrors;}
+
+ /// Get number of end of Global word errors.
+ UInt_t GetGlobalEoWErrors() const {return fGlobalEoWErrors;}
+
+ /// Get number of end of regional word errors.
+ UInt_t GetRegEoWErrors() const {return fRegEoWErrors;}
+
+ /// Get number of end of local word errors.
+ UInt_t GetLocalEoWErrors() const {return fLocalEoWErrors;}
+
+ /// Returns the warnings flag.
+ Bool_t Warnings() const { return fWarnings; }
+ /// Sets the warnings flag.
+ void Warnings(Bool_t value) { fWarnings = value; }
+
+ // The following methods are inherited from AliMUONTriggerDDLDecoderEventHandler:
+
+ /// New buffer handler.
+ void OnNewBuffer(const void* buffer, UInt_t bufferSize);
+
+ /// End of buffer handler marks the end of local trigger structures.
+ void OnEndOfBuffer(const void* /*buffer*/, UInt_t /*bufferSize*/)
+ {
+ fEndOfLocals = fCurrentLocal+1;
+ }
+
+ /// Handler for the DARC header which just remembers the pointers for later.
+ void OnDarcHeader(UInt_t header,
+ const AliMUONDarcScalarsStruct* scalars,
+ const void* /*data*/)
+ {
+ fDarcHeader = header;
+ fDarcScalars = scalars;
+ }
+
+ /// Handler for the global header which stores the pointer to the headers.
+ void OnGlobalHeader(const AliMUONGlobalHeaderStruct* header,
+ const AliMUONGlobalScalarsStruct* scalars,
+ const void* /*data*/)
+ {
+ fHeaders = AliHeader(fDarcHeader, fDarcScalars, header, scalars);
+ }
+
+ /// Handler for new regional card structures.
+ void OnNewRegionalStruct(const AliMUONRegionalHeaderStruct* header,
+ const AliMUONRegionalScalarsStruct* scalars,
+ const void* data);
+
+ /// Handler for new local card structures.
+ void OnLocalStruct(const AliMUONLocalInfoStruct* localStruct,
+ const AliMUONLocalScalarsStruct* scalars);
+
+ /// Error handler.
+ void OnError(ErrorCode error, const void* location);
+
+ private:
+
+ // Do not allow copying of this class.
+ /// Not implemented
+ AliDecoderEventHandler(const AliDecoderEventHandler& /*obj*/);
+ /// Not implemented
+ AliDecoderEventHandler& operator = (const AliDecoderEventHandler& /*obj*/);
+
+ AliMUONVRawStreamTrigger* fRawStream; //!< Pointer to the parent raw stream object.
+ const void* fBufferStart; //!< Pointer to the start of the current DDL payload buffer.
+ UInt_t fDarcHeader; //!< Currently decoded DARC header.
+ const AliMUONDarcScalarsStruct* fDarcScalars; //!< Currently decoded DARC scalars.
+ AliHeader fHeaders; //!< Headers of the DDL payload.
+ UInt_t fRegionalsCount; //!< Number of regional headers filled in fRegionals.
+ AliRegionalHeader* fRegionals; //!< Array of regional headers. [0..fMaxRegionals-1]
+ AliLocalStruct* fLocals; //!< Array of decoded local structured. [0..fMaxRegionals*fMaxLocals-1]
+ AliLocalStruct* fEndOfLocals; //!< Marker indicating the position just passed the last filled element in fLocals.
+ AliRegionalHeader* fCurrentRegional; //!< Current regional header position.
+ AliLocalStruct* fCurrentLocal; //!< Current local trigger structure.
+ UInt_t fDarcEoWErrors; //!< Number of end of DARC word errors.
+ UInt_t fGlobalEoWErrors; //!< Number of end of global word errors.
+ UInt_t fRegEoWErrors; //!< Number of end of regional word errors.
+ UInt_t fLocalEoWErrors; //!< Number of end of local word errors.
+ Bool_t fWarnings; //!< Flag indicating if we should generate a warning for errors.
+ };
+
+ AliMUONTriggerDDLDecoder<AliDecoderEventHandler> fDecoder; //!< The decoder for the DDL payload.
+ Int_t fDDL; //!< The current DDL number being handled.
+ 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 AliLocalStruct* fCurrentLocalStruct; //!< The current local trigger structure being handled by Next().
+ 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.
+
+ static const Int_t fgkMaxDDL; //!< Maximum number of DDLs
+
+ ClassDef(AliMUONRawStreamTriggerHP, 0) // Higher performance decoder class for MUON trigger rawdata.
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
+inline const AliMUONRawStreamTriggerHP::AliLocalStruct* AliMUONRawStreamTriggerHP::Next()
+{
+ /// Iterates through all the local trigger structures for the event.
+ /// When no more local triggers are found then NULL is returned.
+
+ do {
+ if (fCurrentLocalStruct != fDecoder.GetHandler().EndOfLocalStructs())
+ return fCurrentLocalStruct++;
+ } while (NextDDL());
+ return NULL;
+}
+
+
+inline void AliMUONRawStreamTriggerHP::AliDecoderEventHandler::OnNewRegionalStruct(
+ const AliMUONRegionalHeaderStruct* header,
+ const AliMUONRegionalScalarsStruct* scalars,
+ const void* /*data*/
+ )
+{
+ /// New regional structure handler is called by the decoder whenever a
+ /// new regional header is found. We just mark the header and increment
+ /// the appropriate counters.
+
+ assert( header != NULL );
+ assert( fCurrentRegional != NULL );
+ assert( fRegionalsCount < (UInt_t)fRawStream->GetMaxReg() );
+
+ // Link the previous regional structure unless it is the first one.
+ if (fRegionalsCount > 0)
+ {
+ fCurrentRegional->SetNext(fCurrentRegional+1);
+ }
+
+ fCurrentRegional++;
+ *fCurrentRegional = AliRegionalHeader(fCurrentLocal+1, header, scalars);
+ fRegionalsCount++;
+}
+
+
+inline void AliMUONRawStreamTriggerHP::AliDecoderEventHandler::OnLocalStruct(
+ const AliMUONLocalInfoStruct* localStruct,
+ const AliMUONLocalScalarsStruct* scalars
+ )
+{
+ /// New local trigger structure handler.
+ /// This is called by the high performance decoder when a new local trigger
+ /// structure is found within the DDL payload.
+ /// We mark the location of the structure in the DDL paytload and increment
+ /// appropriate counters.
+
+ assert( localStruct != NULL );
+ assert( fCurrentLocal != NULL );
+ assert( fCurrentRegional != NULL );
+ assert( fCurrentRegional->GetLocalStructCount() < (UInt_t)fRawStream->GetMaxLoc() );
+
+ // Link the previous local structure unless it is the first one.
+ if (fCurrentRegional->GetLocalStructCount() > 0)
+ {
+ fCurrentLocal->SetNext(fCurrentLocal+1);
+ }
+
+ fCurrentLocal++;
+ *fCurrentLocal = AliLocalStruct(fCurrentRegional, localStruct, scalars);
+ fCurrentRegional->IncLocalStructCount();
+}
+
+#endif // ALIMUONRAWSTREAMTRIGGERHP_H
/// This method decodes the DDL payload contained in the buffer.
bool Decode(const void* buffer, UInt_t bufferSize);
+ /// Returns the block marker key.
+ static UInt_t BlockDataKeyWord() { return fgkBlockDataKey; }
+
+ /// Returns the DSP marker key.
+ static UInt_t DspDataKeyWord() { return fgkDSPDataKey; }
+
+ /// Returns the bus patch marker key.
+ static UInt_t BusPatchDataKeyWord() { return fgkBusPatchDataKey; }
+
+ /// Returns the expected padding word value.
+ static UInt_t PaddingWord() { return fgkPaddingWord; }
+
+ /// Returns the expected end of DDL marker.
+ static UInt_t EndOfDDLWord() { return fgkEndOfDDL; }
+
private:
bool fExitOnError; ///< Indicates if we should exit on the very first error.
--- /dev/null
+#ifndef ALIMUONTRIGGERDDLDECODER_H
+#define ALIMUONTRIGGERDDLDECODER_H
+/**************************************************************************
+ * This file is property of and copyright by the ALICE HLT Project *
+ * All rights reserved. *
+ * *
+ * Primary Authors: *
+ * Artur Szostak <artursz@iafrica.com> *
+ * *
+ * Permission to use, copy, modify and distribute this software and its *
+ * documentation strictly for non-commercial purposes is hereby granted *
+ * without fee, provided that the above copyright notice appears in all *
+ * copies and that both the copyright notice and this permission notice *
+ * appear in the supporting documentation. The authors make no claims *
+ * about the suitability of this software for any purpose. It is *
+ * provided "as is" without express or implied warranty. *
+ **************************************************************************/
+
+/* $Id$ */
+
+///
+/// \file AliMUONTriggerDDLDecoder.h
+/// \author Artur Szostak <artursz@iafrica.com>
+/// \date 28-11-2007
+/// \brief Implementation of a high performance DDL decoder for the muon trigger.
+///
+/// This file implementes the AliMUONTriggerDDLDecoder class, which contains
+/// the core logic for decoding the payload in DDL streams comming from the muon
+/// spectrometer's hardware trigger in a very efficient manner.
+///
+/// This implementation is derived from work done by Christian Finck for the
+/// AliMUONPayloadTrigger class.
+///
+/// Note to maintainers: Please remember that this file is used by the online
+/// dHLT system. As an online system, the dHLT requires the fastest code possible
+/// in the decoders to satisfy its timing constraints. The performance impact
+/// must be checked before any proposed modification is made to this file.
+///
+
+#include "AliMUONTriggerDDLDecoderEventHandler.h"
+
+/// \ingroup raw
+/// \class AliMUONTriggerDDLDecoder
+/// \brief A high performance decoder class for MUON trigger DDL data.
+///
+/// This class implements a high performance decoder for decoding DDL payload
+/// data coming from the muon spectrometers trigger stations.
+/// It has been implemented using the event driven paradigm with templates,
+/// which allows us to minimise the number of method calls made in the inner
+/// loops of the algorithm and minimise the memory footprint.
+/// At least for optimised production compilations.
+/// The decoder class only contains the basic decoding and error checking logic.
+/// It calls methods such as OnNewBuffer, OnDarcHeader, OnNewRegionalStruct,
+/// OnLocalStruct etc in the event handler during the decoding to return the
+/// decoded data and headers.
+/// The event handler class is nothing more than a callback interface to deliver
+/// the next chunks of decoded data.
+/// To actually do something with the data, one needs to implement a custom
+/// event handler (callback) class by inheriting from AliMUONTriggerDDLDecoderEventHandler
+/// and overriding the callback methods like so:
+/// \code
+/// class MyCustomHandler : public AliMUONTriggerDDLDecoderEventHandler
+/// {
+/// public:
+/// void OnLocalStruct(const AliMUONLocalInfoStruct* localStruct,
+/// const AliMUONLocalScalarsStruct* scalars)
+/// {
+/// // I can do something with the data in 'localStruct' here.
+/// // and the 'scalars' if they are not NULL.
+/// }
+/// };
+/// \endcode
+///
+/// Once the custom handler is written then the decoder is instantiated as
+/// shown below, to use your new custom handler. Also to start decoding one needs
+/// to call the Decode() method of the decoder.
+/// \code
+/// AliMUONTriggerDDLDecoder<MyCustomHandler> myDecoder;
+/// muDecoder.Decoder(buffer, bufferSize);
+/// \endcode
+///
+/// Note that this class was written as a template on purpose. To maximise the
+/// compilers chance to make optimisations and inline the code we must use a template.
+/// Depending on exactly what you do inside your handler, the decoder could be
+/// significantly slower if run time polymorphism was used, i.e. making the class
+/// AliMUONTriggerDDLDecoderEventHandler abstract and using virtual methods.
+///
+template <class EventHandler>
+class AliMUONTriggerDDLDecoder
+{
+public:
+
+ /// Default contructor.
+ AliMUONTriggerDDLDecoder() :
+ fExitOnError(true), fTryRecover(false),
+ fAutoDetectScalars(false), fHadError(false),
+ fNoRegionals(0), fMaxRegionals(8), fMaxLocals(16),
+ fHandler()
+ {}
+
+ /// Constant method to return the event handler instance.
+ const EventHandler& GetHandler() const { return fHandler; }
+
+ /// Returns the event handler instance.
+ EventHandler& GetHandler() { return fHandler; }
+
+ /// Returns the "exit on error" flag.
+ /// i.e. should the decoder stop on the very first error found.
+ bool ExitOnError() const { return fExitOnError; }
+
+ /// Sets the "exit on error" flag.
+ /// i.e. should the decoder stop on the very first error found.
+ void ExitOnError(bool value) { fExitOnError = value; }
+
+ /// Returns the "try to recover from errors" flag.
+ /// i.e. should the decoder try to recover from errors found in the
+ /// payload headers.
+ bool TryRecover() const { return fTryRecover; }
+
+ /// 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 value) { fTryRecover = value; }
+
+ /// Returns the flag indicating if we should check for the scalars of
+ /// software triggers automatically or not.
+ bool AutoDetectScalars() const { return fAutoDetectScalars; }
+
+ /// Sets the flag indicating if we should check for the scalars of
+ /// software triggers automatically or not. If set to true then the
+ /// scalarEvent parameter of the Decode method is ignored.
+ void AutoDetectScalars(bool value) { fAutoDetectScalars = value; }
+
+ /// Returns the maximum regional structure count expected in the DDL payload.
+ UInt_t MaxRegionals() const { return fMaxRegionals; }
+
+ /// Sets the maximum regional structure count expected in the DDL payload.
+ void MaxRegionals(UInt_t n) { fMaxRegionals = n; }
+
+ /// Returns the number of regional structures we actually attempted to decode.
+ UInt_t RegionalsDecoded() const { return fNoRegionals; }
+
+ /// Returns the maximum local structure count expected in any given regional
+ /// card structure within the DDL payload.
+ UInt_t MaxLocals() const { return fMaxLocals; }
+
+ /// Sets the maximum local structure count expected in any given regional
+ /// card structure within the DDL payload.
+ void MaxLocals(UInt_t n) { fMaxLocals = n; }
+
+ /// This method decodes the DDL payload contained in the buffer.
+ bool Decode(const void* buffer, UInt_t bufferSize, bool scalarEvent = false);
+
+ /// Returns the end of DARC marker key.
+ static UInt_t EndOfDarcWord() { return fgkEndOfDarc; }
+
+ /// Returns the end of global header marker key.
+ static UInt_t EndOfGlobalWord() { return fgkEndOfGlobal; }
+
+ /// Returns the end of regional structure marker key.
+ static UInt_t EndOfRegionalWord() { return fgkEndOfReg; }
+
+ /// Returns the regional error word.
+ static UInt_t RegionalErrorWord() { return fgkErrorWord; }
+
+ /// Returns the end of local structure marker key.
+ static UInt_t EndOfLocalWord() { return fgkEndOfLocal; }
+
+ /// Returns the local card disable word.
+ static UInt_t LocalDisableWord() { return fgkDisableWord; }
+
+ /// Returns value of default DARC type.
+ static UInt_t DarcDefaultType() { return fgkDarcDefaultType; }
+
+ /// Returns value of Vadorh DARC type.
+ static UInt_t DarcVadorhType() { return fgkDarcVadorhType; }
+
+private:
+
+ bool fExitOnError; ///< Indicates if we should exit on the very first error.
+ bool fTryRecover; ///< Indicates if we should try recover from a corrupt structures.
+ bool fAutoDetectScalars; ///< Flag to indicate if we should auto-detect if there are scalars in the data.
+ bool fHadError; ///< Indicates if we had an error decoding the data.
+ UInt_t fNoRegionals; ///< The number of regional card structures actually decoded.
+ UInt_t fMaxRegionals; ///< Maximum number of regional card structures allowed in a DDL stream.
+ UInt_t fMaxLocals; ///< Maximum number of local card structures per regional structure allowed in a DDL stream.
+ EventHandler fHandler; ///< The event handler which deals with the generated parsing events.
+
+ void DecodeBuffer(const UChar_t* start, const UChar_t* end, bool scalarEvent);
+ void DecodeRegionalStructs(const UChar_t* start, const UChar_t* end, bool scalarEvent);
+ const UChar_t* DecodeLocalStructs(const UChar_t* start, const UChar_t* end, bool scalarEvent);
+
+ const UChar_t* FindKey(
+ UInt_t key, const UChar_t* start, const UChar_t* end
+ );
+
+ static const UInt_t fgkEndOfDarc; ///< Indicates the end of the DARC header.
+ static const UInt_t fgkEndOfGlobal; ///< Indicates the end of the global header just after the DARC header.
+ static const UInt_t fgkEndOfReg; ///< Indicates the end of a regional card structure.
+ static const UInt_t fgkErrorWord; ///< The error word when a regional board is missing.
+ static const UInt_t fgkEndOfLocal; ///< Indicates the end of a local card structure.
+ static const UInt_t fgkDisableWord; ///< Word used to fill "empty" slots.
+ static const UInt_t fgkDarcDefaultType; ///< default type for DARC def.
+ static const UInt_t fgkDarcVadorhType; ///< default type for DARC vadorh
+};
+
+//_____________________________________________________________________________
+
+// The following are the structure key words which are used to demarcate (identify
+// the end) of the structures within the raw trigger data.
+template <class EventHandler>
+const UInt_t AliMUONTriggerDDLDecoder<EventHandler>::fgkEndOfDarc = 0xDEADFACE;
+template <class EventHandler>
+const UInt_t AliMUONTriggerDDLDecoder<EventHandler>::fgkEndOfGlobal = 0xDEADBEEF;
+template <class EventHandler>
+const UInt_t AliMUONTriggerDDLDecoder<EventHandler>::fgkEndOfReg = 0xBEEFFACE;
+template <class EventHandler>
+const UInt_t AliMUONTriggerDDLDecoder<EventHandler>::fgkErrorWord = 0xCAFEDEAD;
+template <class EventHandler>
+const UInt_t AliMUONTriggerDDLDecoder<EventHandler>::fgkEndOfLocal = 0xCAFEFADE;
+template <class EventHandler>
+const UInt_t AliMUONTriggerDDLDecoder<EventHandler>::fgkDisableWord = 0x010CDEAD;
+template <class EventHandler>
+const UInt_t AliMUONTriggerDDLDecoder<EventHandler>::fgkDarcDefaultType = 0x6;
+template <class EventHandler>
+const UInt_t AliMUONTriggerDDLDecoder<EventHandler>::fgkDarcVadorhType = 0x4;
+
+
+template <class EventHandler>
+bool AliMUONTriggerDDLDecoder<EventHandler>::Decode(
+ const void* buffer, UInt_t bufferSize, bool scalarEvent
+ )
+{
+ /// This method should be called to actually decode the DDL payload
+ /// contained in a memory buffer. The payload should be in the muon trigger
+ /// system DDL stream format otherwise it will be recognised as corrupt.
+ /// As the decoder progresses it will make method calls to the event handler
+ /// instance (which can be accessed with the GetHandler() method) to indicate
+ /// the start of the DARC header, global header, new regional structures and
+ /// local card structures.
+ ///
+ /// If an error occurs during the parse, because the data is corrupt, then
+ /// the OnError method is called indicating what the problem was.
+ /// Decoding will stop at this point unless the fExitOnError flag is set
+ /// to false. There is an optional flag fTryRecover which can enable logic
+ /// which will attempt to recover from corruption of the data structures
+ /// in the DDL payload, if they are found to be inconsistent (assumed corrupt).
+ /// The recovery procedure simply involves trying to find in the DDL stream
+ /// the location of the expected end of header/structure marker/key or the
+ /// next expected key, and then continue decoding from there. This kind of
+ /// recovery logic is (and should be) turned off by default and only
+ /// enabled when trying to recover corrupted data.
+ ///
+ /// \param buffer This is the pointer to the start of the memory buffer
+ /// containing the DDL payload. Remember that this must be the start of
+ /// the payload and not the DDL stream. That is, this pointer should be
+ /// equal to: DDL start pointer + 8 * sizeof(UInt_t).
+ /// \param bufferSize This is the pointer to the first byte just past the
+ /// end of the block structure.
+ /// \param scalarEvent Set to true if this DDL contains a scalar event
+ /// and false if it is a normal physics event. If the fAutoDetectScalars
+ /// flag is true then we ignore this parameter.
+ /// \return Returns false if there was any problem with decoding the data,
+ /// and true otherwise. Note: the data may have been partially decoded
+ /// even if false was returned, which would be indicated by at least one
+ /// call to the event handler's OnLocalStruct or OnNewRegionalStruct methods.
+
+ assert( buffer != NULL );
+
+ fHadError = false;
+
+ // We are basically implementing something like a recursive decent parser.
+ // So start by marking the start of buffer position and end of buffer.
+ const UChar_t* start = reinterpret_cast<const UChar_t*>(buffer);
+ const UChar_t* end = start + bufferSize;
+
+ fHandler.OnNewBuffer(buffer, bufferSize);
+ DecodeBuffer(start, end, scalarEvent);
+ fHandler.OnEndOfBuffer(buffer, bufferSize);
+ return not fHadError;
+}
+
+
+template <class EventHandler>
+void AliMUONTriggerDDLDecoder<EventHandler>::DecodeBuffer(
+ const UChar_t* start, const UChar_t* end, bool scalarEvent
+ )
+{
+ /// This method does the work to decode the buffer's payload data. It
+ /// unpacks the DARC header, the global header, then calls the
+ /// DecodeRegionalStructs() method to decode the regional structures.
+ /// For the DARC and global headers the methods OnDarcHeader and
+ /// OnGlobalHeader of the event handler object are called respectively.
+ /// \param start This is the pointer to the start of the buffer to decode.
+ /// \param end This is the pointer to the first byte just past the
+ /// end of the buffer.
+ /// \param scalarEvent Set to true if this DDL contains a scalar event
+ /// and false if it is a normal physics event.
+ ///
+ /// fHadError is set to true if there were any errors decoding the buffer
+ /// and the OnError method of the callback event handler is called for
+ /// each error.
+
+ const UChar_t* current = start;
+
+ // Mark the DARC header, but check that we do not overrun the buffer.
+ const UInt_t* darcHeader = reinterpret_cast<const UInt_t*>(current);
+ current += sizeof(UInt_t);
+ if (current > end)
+ {
+ // Indicate we had an error and stop the decoding because we
+ // hit the end of the buffer already.
+ fHandler.OnError(EventHandler::kNoDarcHeader, darcHeader);
+ fHadError = true;
+ return;
+ }
+
+ // Check if we need to figure out if this is a scalar event.
+ // If we do, then we do this by checking the event type in the DARC header
+ // and double checking this by checking if the fgkEndOfDarc key is in the
+ // expected location for a scalar event DDL payload.
+ if (fAutoDetectScalars)
+ {
+ const UInt_t* expectedEndOfDarc = reinterpret_cast<const UInt_t*>(
+ current + sizeof(AliMUONDarcScalarsStruct)
+ );
+
+ // First make sure not to read past the end of buffer. Then check
+ // the value of the event type in the DARC header.
+ // Physics events are indicated by the two trigger bits of the
+ // DARC header set to 01b. Everything else is a software trigger
+ // of some sort.
+ if (reinterpret_cast<const UChar_t*>(expectedEndOfDarc+1) <= end and
+ EventHandler::GetDarcEventType(*darcHeader) != 0x1
+ and *expectedEndOfDarc == fgkEndOfDarc
+ )
+ {
+ scalarEvent = true;
+ }
+ else
+ {
+ scalarEvent = false;
+ }
+ }
+
+ // Detect how many regional blocks we expect. If we have no idea then
+ // just use what the maximum setting is.
+ switch (EventHandler::GetDarcType(*darcHeader))
+ {
+ case fgkDarcVadorhType: fNoRegionals = 1; break;
+ case fgkDarcDefaultType: fNoRegionals = 8; break;
+ default: fNoRegionals = fMaxRegionals; break;
+ }
+
+ // Check if the DARC header indicates we expect more regionals than we
+ // are allowed to decode according to our max regional structures count.
+ // If we do then this is an error and we should indicate it and exit
+ // if so requested by the user. Also we can fix the number of regionals
+ // to expect if we are trying to recover from errors.
+ if (fNoRegionals > fMaxRegionals)
+ {
+ fHandler.OnError(EventHandler::kTooManyRegionals, darcHeader);
+ fHadError = true;
+ if (fExitOnError) return;
+ if (fTryRecover)
+ {
+ fNoRegionals = fMaxRegionals;
+ }
+ }
+
+ // Check that the DARC header indicates correctly if we are a scalar event or not.
+ bool darcShowsScalar = (EventHandler::GetDarcEventType(*darcHeader) != 0x1);
+ if (darcShowsScalar != scalarEvent)
+ {
+ // Indicate we had an error and stop the decoding if so requested
+ // by the user.
+ fHandler.OnError(EventHandler::kWrongEventType, darcHeader);
+ fHadError = true;
+ if (fExitOnError) return;
+ }
+
+ // Decode the DARC scalars if this is a scalar event.
+ const AliMUONDarcScalarsStruct* darcScalars = NULL;
+ if (scalarEvent)
+ {
+ darcScalars = reinterpret_cast<const AliMUONDarcScalarsStruct*>(current);
+ current += sizeof(AliMUONDarcScalarsStruct);
+ if (current > end)
+ {
+ // Indicate we had an error and stop the decoding because we
+ // hit the end of the buffer already.
+ fHandler.OnError(EventHandler::kNoDarcScalars, darcScalars);
+ fHadError = true;
+ return;
+ }
+ }
+
+ // Now check that the end of DARC header marker is OK.
+ const UInt_t* endOfDarc = reinterpret_cast<const UInt_t*>(current);
+ current += sizeof(UInt_t);
+ if (current > end)
+ {
+ // Indicate we had an error and stop the decoding because we
+ // hit the end of the buffer already.
+ fHandler.OnError(EventHandler::kNoEndOfDarc, endOfDarc);
+ fHadError = true;
+ return;
+ }
+ if (*endOfDarc != fgkEndOfDarc)
+ {
+ // Indicate we had an error and stop the decoding if so requested
+ // by the user.
+ fHandler.OnError(EventHandler::kBadEndOfDarc, endOfDarc);
+ fHadError = true;
+ if (fExitOnError) return;
+
+ // If the user requested for us to try and recover from structure
+ // errors then we need to try locate the key in the data stream
+ // and continue decoding from there.
+ if (fTryRecover)
+ {
+ const UChar_t* keypos = FindKey(fgkEndOfDarc,
+ reinterpret_cast<const UChar_t*>(darcHeader),
+ end
+ );
+ if (keypos != NULL)
+ {
+ // remember to continue decoding just past the key.
+ current = keypos + sizeof(UInt_t);
+ }
+ }
+ }
+
+ fHandler.OnDarcHeader(*darcHeader, darcScalars, current);
+
+ // Next, we mark the Global header and check that we do not overrun the buffer.
+ const AliMUONGlobalHeaderStruct* globalHeader =
+ reinterpret_cast<const AliMUONGlobalHeaderStruct*>(current);
+ current += sizeof(AliMUONGlobalHeaderStruct);
+ if (current > end)
+ {
+ // Indicate we had an error and stop the decoding because we
+ // hit the end of the buffer already.
+ fHandler.OnError(EventHandler::kNoGlobalHeader, globalHeader);
+ fHadError = true;
+ return;
+ }
+
+ // Decode the global scalars if this is a scalar event.
+ const AliMUONGlobalScalarsStruct* globalScalars = NULL;
+ if (scalarEvent)
+ {
+ globalScalars = reinterpret_cast<const AliMUONGlobalScalarsStruct*>(current);
+ current += sizeof(AliMUONGlobalScalarsStruct);
+ if (current > end)
+ {
+ // Indicate we had an error and stop the decoding because we
+ // hit the end of the buffer already.
+ fHandler.OnError(EventHandler::kNoGlobalScalars, globalScalars);
+ fHadError = true;
+ return;
+ }
+ }
+
+ // Now check that the end of global header marker is OK.
+ const UInt_t* endOfGlobal = reinterpret_cast<const UInt_t*>(current);
+ current += sizeof(UInt_t);
+ if (current > end)
+ {
+ // Indicate we had an error and stop the decoding because we
+ // hit the end of the buffer already.
+ fHandler.OnError(EventHandler::kNoEndOfGlobal, endOfGlobal);
+ fHadError = true;
+ return;
+ }
+ if (*endOfGlobal != fgkEndOfGlobal)
+ {
+ // Indicate we had an error and stop the decoding if so requested
+ // by the user.
+ fHandler.OnError(EventHandler::kBadEndOfGlobal, endOfGlobal);
+ fHadError = true;
+ if (fExitOnError) return;
+
+ // If the user requested for us to try and recover from structure
+ // errors then we need to try locate the key in the data stream
+ // and continue decoding from there.
+ if (fTryRecover)
+ {
+ const UChar_t* keypos = FindKey(fgkEndOfGlobal,
+ reinterpret_cast<const UChar_t*>(globalHeader),
+ end
+ );
+ if (keypos != NULL)
+ {
+ // remember to continue decoding just past the key.
+ current = keypos + sizeof(UInt_t);
+ }
+ }
+ }
+
+ fHandler.OnGlobalHeader(globalHeader, globalScalars, current);
+
+ DecodeRegionalStructs(current, end, scalarEvent);
+}
+
+
+template <class EventHandler>
+void AliMUONTriggerDDLDecoder<EventHandler>::DecodeRegionalStructs(
+ const UChar_t* start, const UChar_t* end, bool scalarEvent
+ )
+{
+ /// This method decodes the regional structures in the DDL data.
+ /// For each regional header found, the OnNewRegionalStruct method of
+ /// the event handler is called, to signal the start of each
+ /// new regional structure. The DecodeLocalStructs() method is then
+ /// called to decode the local trigger structures. Finally, a symmetrical
+ /// call to OnEndOfRegionalStruct of the event handler is called to
+ /// signal that the regional structure has been decoded.
+ /// \param start This is the pointer to the start of the buffer.
+ /// \param end This is the pointer to the first byte just past the
+ /// end of the buffer.
+ /// \param scalarEvent Set to true if this DDL contains a scalar event
+ /// and false if it is a normal physics event.
+ ///
+ /// fHadError is set to true if there were any errors decoding the buffer
+ /// and the OnError method of the callback event handler is called for
+ /// each error.
+
+ const UChar_t* current = start;
+
+ for (UInt_t iReg = 0; iReg < fNoRegionals; iReg++)
+ {
+ const AliMUONRegionalHeaderStruct* regionalHeader =
+ reinterpret_cast<const AliMUONRegionalHeaderStruct*>(current);
+ current += sizeof(AliMUONRegionalHeaderStruct);
+
+ if (current > end)
+ {
+ // So we only got part of a regional header, nothing to do but
+ // report the error and exit.
+ fHandler.OnError(EventHandler::kNoRegionalHeader, regionalHeader);
+ fHadError = true;
+ return;
+ }
+
+ // Skip empty regional board (not connected or with error reading).
+ if (regionalHeader->fDarcWord == fgkErrorWord)
+ {
+ //current += sizeof(AliMUONRegionalHeaderStruct); // already done above
+ if (scalarEvent)
+ current += sizeof(AliMUONRegionalScalarsStruct);
+ current += sizeof(UInt_t); // skip the end of regional structure key.
+
+ // now also skip the local structure part:
+ current += fMaxLocals * sizeof(AliMUONLocalInfoStruct);
+ if (scalarEvent)
+ current += fMaxLocals * sizeof(AliMUONLocalScalarsStruct);
+ current += fMaxLocals * sizeof(UInt_t); // skip all the end of local structure keys.
+
+ continue;
+ }
+
+ // Decode the regional scalar words if this is a scalar event.
+ const AliMUONRegionalScalarsStruct* regionalScalars = NULL;
+ if (scalarEvent)
+ {
+ regionalScalars = reinterpret_cast<const AliMUONRegionalScalarsStruct*>(current);
+ current += sizeof(AliMUONRegionalScalarsStruct);
+ if (current > end)
+ {
+ // Indicate we had an error and stop the decoding because we
+ // hit the end of the buffer already.
+ fHandler.OnError(EventHandler::kNoRegionalScalars, regionalScalars);
+ fHadError = true;
+ return;
+ }
+ }
+
+ // Now check that the end of regional header marker is OK.
+ const UInt_t* endOfRegional = reinterpret_cast<const UInt_t*>(current);
+ current += sizeof(UInt_t);
+ if (current > end)
+ {
+ // Indicate we had an error and stop the decoding because we
+ // hit the end of the buffer already.
+ fHandler.OnError(EventHandler::kNoEndOfRegional, endOfRegional);
+ fHadError = true;
+ return;
+ }
+ if (*endOfRegional != fgkEndOfReg)
+ {
+ // Indicate we had an error and stop the decoding if so requested
+ // by the user.
+ fHandler.OnError(EventHandler::kBadEndOfRegional, endOfRegional);
+ fHadError = true;
+ if (fExitOnError) return;
+
+ // If the user requested for us to try and recover from structure
+ // errors then we need to try locate the key in the data stream
+ // and continue decoding from there.
+ if (fTryRecover)
+ {
+ const UChar_t* keypos = FindKey(fgkEndOfReg,
+ reinterpret_cast<const UChar_t*>(regionalHeader),
+ end
+ );
+
+ // If the fgkEndOfReg key was found exactly one regional
+ // structure later then we should not adjust the current
+ // decoding position because it is more likely that the
+ // end of regional structure key was just corrupt rather
+ // than offset.
+ // If we could not find another good key then just continue.
+ size_t sizeOfRegional = sizeof(AliMUONRegionalHeaderStruct) + sizeof(UInt_t)
+ + fMaxLocals * (sizeof(AliMUONLocalInfoStruct) + sizeof(UInt_t));
+ if (scalarEvent)
+ {
+ sizeOfRegional += sizeof(AliMUONRegionalScalarsStruct)
+ + fMaxLocals * sizeof(AliMUONLocalScalarsStruct);
+ }
+
+ if (keypos != NULL and keypos != current + sizeOfRegional)
+ {
+ current = keypos + sizeof(UInt_t);
+ }
+ }
+ }
+
+ // Tell the handler that we have a new regional block and decode it.
+ // When done, tell the handler again.
+ const UChar_t* startOfLocals = current;
+ fHandler.OnNewRegionalStruct(regionalHeader, regionalScalars, startOfLocals);
+ current = DecodeLocalStructs(current, end, scalarEvent);
+ fHandler.OnEndOfRegionalStruct(regionalHeader, regionalScalars, startOfLocals);
+ }
+
+ // Now just check that there is no extra rubbish at the end of the DDL.
+ if (current != end)
+ {
+ fHandler.OnError(EventHandler::kBufferTooBig, current);
+ fHadError = true;
+ }
+}
+
+
+template <class EventHandler>
+const UChar_t* AliMUONTriggerDDLDecoder<EventHandler>::DecodeLocalStructs(
+ const UChar_t* start, const UChar_t* end, bool scalarEvent
+ )
+{
+ /// This method decodes the local structures in the DDL data for a
+ /// single regional structure. For each local trigger structure found,
+ /// the OnLocalStruct method of the event handler is called.
+ /// \param start This is the pointer to the start of the regional structure
+ /// payload (The pointer just past the regional header key).
+ /// \param end This is the pointer to the first byte just past the
+ /// end of the buffer.
+ /// \param scalarEvent Set to true if this DDL contains a scalar event
+ /// and false if it is a normal physics event.
+ /// \returns The position in the buffer where this method stopped decoding.
+ ///
+ /// fHadError is set to true if there were any errors decoding the buffer
+ /// and the OnError method of the callback event handler is called for
+ /// each error.
+
+ const UChar_t* current = start;
+
+ for (UInt_t iLocal = 0; iLocal < fMaxLocals; iLocal++)
+ {
+ const AliMUONLocalInfoStruct* localStruct =
+ reinterpret_cast<const AliMUONLocalInfoStruct*>(current);
+ current += sizeof(AliMUONLocalInfoStruct);
+
+ if (current > end)
+ {
+ // So we only got part of a local structure, nothing to do but
+ // report the error and exit.
+ fHandler.OnError(EventHandler::kNoLocalStruct, localStruct);
+ fHadError = true;
+ return end;
+ }
+
+ // Skip empty local board if card not notified.
+ if (localStruct->fX2X1 == fgkDisableWord and
+ localStruct->fX4X3 == fgkDisableWord and
+ localStruct->fY2Y1 == fgkDisableWord and
+ localStruct->fY4Y3 == fgkDisableWord and
+ localStruct->fTriggerBits == fgkDisableWord
+ )
+ {
+ //current += sizeof(AliMUONLocalInfoStruct); // already done above
+ if (scalarEvent)
+ current += sizeof(AliMUONLocalScalarsStruct);
+ current += sizeof(UInt_t); // skip the end of local structure key.
+ continue;
+ }
+
+ // Decode the regional scalar words if this is a scalar event.
+ const AliMUONLocalScalarsStruct* localScalars = NULL;
+ if (scalarEvent)
+ {
+ localScalars = reinterpret_cast<const AliMUONLocalScalarsStruct*>(current);
+ current += sizeof(AliMUONLocalScalarsStruct);
+ if (current > end)
+ {
+ // Indicate we had an error and stop the decoding because we
+ // hit the end of the buffer already.
+ fHandler.OnError(EventHandler::kNoLocalScalars, localScalars);
+ fHadError = true;
+ return end;
+ }
+ }
+
+ // Now check that the end of regional header marker is OK.
+ const UInt_t* endOfLocal = reinterpret_cast<const UInt_t*>(current);
+ current += sizeof(UInt_t);
+ if (current > end)
+ {
+ // Indicate we had an error and stop the decoding because we
+ // hit the end of the buffer already. We can however signal that
+ // we got a local structure, because the buffer contains enough
+ // data to potencially contain the real data of the structure.
+ fHandler.OnError(EventHandler::kNoEndOfLocal, endOfLocal);
+ if (not fExitOnError)
+ {
+ fHandler.OnLocalStruct(localStruct, localScalars);
+ }
+ fHadError = true;
+ return end;
+ }
+ if (*endOfLocal != fgkEndOfLocal)
+ {
+ // Indicate we had an error and stop the decoding if so requested
+ // by the user.
+ fHandler.OnError(EventHandler::kBadEndOfLocal, endOfLocal);
+ fHadError = true;
+ if (fExitOnError) return current;
+
+ // If the user requested for us to try and recover from structure
+ // errors then we need to try locate the key in the data stream
+ // and continue decoding from there.
+ if (fTryRecover)
+ {
+ const UChar_t* searchPos = reinterpret_cast<const UChar_t*>(localStruct);
+ const UChar_t* firstLocalKey = FindKey(fgkEndOfLocal, searchPos, end);
+ const UChar_t* firstRegionalKey = FindKey(fgkEndOfReg, searchPos, end);
+
+ // If a regional key was found first, then give up on
+ // anymore local structures from this regional block and
+ // continue decoding from the next regional block.
+ // Also if the fgkEndOfLocal key was found exactly one
+ // local structure later then we should not adjust the
+ // current decoding position because it is more likely that
+ // the end of local structure key was just corrupt rather
+ // than offset.
+ if (firstLocalKey != NULL and firstRegionalKey != NULL)
+ {
+ if (firstLocalKey < firstRegionalKey)
+ {
+ size_t sizeOflocalStruct = sizeof(AliMUONLocalInfoStruct) + sizeof(UInt_t);
+ if (scalarEvent)
+ sizeOflocalStruct += sizeof(AliMUONLocalScalarsStruct);
+
+ if (firstLocalKey != current + sizeOflocalStruct)
+ current = firstLocalKey + sizeof(UInt_t);
+ }
+ else
+ {
+ // Adjust back to the start of the regional header.
+ current = firstRegionalKey - sizeof(AliMUONRegionalHeaderStruct);
+ if (scalarEvent)
+ current -= sizeof(AliMUONRegionalScalarsStruct);
+ break;
+ }
+ }
+
+ // If we could not find another good key then just continue.
+ }
+ }
+
+ fHandler.OnLocalStruct(localStruct, localScalars);
+ }
+
+ return current;
+}
+
+
+template <class EventHandler>
+const UChar_t* AliMUONTriggerDDLDecoder<EventHandler>::FindKey(
+ UInt_t key, const UChar_t* start, const UChar_t* end
+ )
+{
+ /// Searches for the first occurrence of the key value in the buffer
+ /// marked by 'start' and 'end'. 'start' should point to the start of
+ /// the buffer and 'end' should point to 'start + bufferSize'.
+ /// \param key The 32 bit word to look for.
+ /// \param start The start location to begin the search at.
+ /// \param end The pointer to the first byte just past end of the
+ /// buffer to check.
+ /// \returns The location of the first occurance of key in the buffer,
+ /// otherwise NULL is returned if nothing was found.
+
+ const UChar_t* current = start;
+ while (current + sizeof(UInt_t) <= end)
+ {
+ UInt_t data = * reinterpret_cast<const UInt_t*>(current);
+ if (data == key) return current;
+ current++;
+ }
+ return NULL;
+}
+
+#endif // ALIMUONTRIGGERDDLDECODER_H
--- /dev/null
+#ifndef ALIMUONTRIGGERDDLDECODEREVENTHANDLER_H
+#define ALIMUONTRIGGERDDLDECODEREVENTHANDLER_H
+/**************************************************************************
+ * This file is property of and copyright by the ALICE HLT Project *
+ * All rights reserved. *
+ * *
+ * Primary Authors: *
+ * Artur Szostak <artursz@iafrica.com> *
+ * *
+ * Permission to use, copy, modify and distribute this software and its *
+ * documentation strictly for non-commercial purposes is hereby granted *
+ * without fee, provided that the above copyright notice appears in all *
+ * copies and that both the copyright notice and this permission notice *
+ * appear in the supporting documentation. The authors make no claims *
+ * about the suitability of this software for any purpose. It is *
+ * provided "as is" without express or implied warranty. *
+ **************************************************************************/
+
+/* $Id$ */
+
+///
+/// \file AliMUONTriggerDDLDecoderEventHandler.h
+/// \author Artur Szostak <artursz@iafrica.com>
+/// \date 28-11-2007
+/// \brief Implementation of the high performance trigger DDL decoder event handler.
+///
+/// This file implementes the AliMUONTriggerDDLDecoderEventHandler class,
+/// which is the callback interface for the AliMUONTriggerDDLDecoder decoder class.
+///
+
+#include <cassert>
+#include <ostream>
+#include <Rtypes.h>
+
+
+// We use C binding for the structures because C is more uniform with its application
+// binary interface (ABI) between compilers.
+extern "C"
+{
+
+// The following structures are the headers found in the DDL payload coming from
+// the muon hardware trigger. The specification is given in ALICE-INT-2005-012
+// (https://edms.cern.ch/file/591904/1/ALICE-INT-2005-012.pdf)
+
+/// The optional DARC board scalars.
+struct AliMUONDarcScalarsStruct
+{
+ UInt_t fL0R; ///< DARC L0 received and used
+ UInt_t fL1P; ///< DARC L1 physics
+ UInt_t fL1S; ///< DARC L1 software
+ UInt_t fL2A; ///< DARC L2 accept
+ UInt_t fL2R; ///< DARC L2 reject
+ UInt_t fClk; ///< DARC clock
+ UInt_t fHold; ///< DARC hold (dead time)
+ UInt_t fSpare; ///< DARC Empty slot (for the moment)
+};
+
+/// The global input and output words just after the DARC header.
+struct AliMUONGlobalHeaderStruct
+{
+ UInt_t fInput[4]; ///< Global input. 8-bit words comming from the each of the 16 regional controlers.
+ UInt_t fOutput; ///< Global ouput
+};
+
+/// The optional global card scalars.
+struct AliMUONGlobalScalarsStruct
+{
+ UInt_t fL0; ///< Global number of L0 triggers
+ UInt_t fClk; ///< Global number of clock cycles
+ UInt_t fScaler[6]; ///< Global card ouput scalars.
+ UInt_t fHold; ///< Global number of hold (dead time)
+ UInt_t fSpare; ///< Global spare word
+};
+
+/// Regional header
+struct AliMUONRegionalHeaderStruct
+{
+ UInt_t fDarcWord; ///< darc word
+ UInt_t fWord; ///< first reg word
+ UInt_t fInput[2]; ///< regional input
+ UInt_t fL0CountAndMask; ///< L0 counter (16 bits) and local mask ("poids faible" 16 bits)
+};
+
+/// Optional regional card scalars.
+struct AliMUONRegionalScalarsStruct
+{
+ UInt_t fClk; ///< Regional number of clock cycles.
+ UInt_t fScaler[8]; ///< Regional ouput scalars.
+ UInt_t fHold; ///< Regional hold (dead time)
+};
+
+
+/// Local card trigger information.
+struct AliMUONLocalInfoStruct
+{
+ UInt_t fX2X1; ///< 16 bits X2 position in 16 most significant bits and 16 bits of X1 in least significant bits.
+ UInt_t fX4X3; ///< 16 bits X4 position in 16 most significant bits and 16 bits of X3 in least significant bits.
+ UInt_t fY2Y1; ///< 16 bits Y2 position in 16 most significant bits and 16 bits of Y1 in least significant bits.
+ UInt_t fY4Y3; ///< 16 bits Y4 position in 16 most significant bits and 16 bits of Y3 in least significant bits.
+ UInt_t fTriggerBits; ///< Trigger bits and deviation.
+};
+
+/// Local card trigger scalars.
+struct AliMUONLocalScalarsStruct
+{
+ UInt_t fL0; ///< local number of L0 triggers.
+ UInt_t fHold; ///< local hold (dead time)
+ UInt_t fClk; ///< local number of clock cycles
+
+ UInt_t fLPtNTrig; ///< local low Pt no trigger
+ UInt_t fHPtNTrig; ///< local high Pt no trigger
+
+ UInt_t fLPtRTrig; ///< local low Pt right trigger
+ UInt_t fHPtRTrig; ///< local high Pt right trigger
+
+ UInt_t fLPtLTrig; ///< local low Pt left trigger
+ UInt_t fHPtLTrig; ///< local high Pt left trigger
+
+ UInt_t fLPtSTrig; ///< local low Pt straight trigger
+ UInt_t fHPtSTrig; ///< local high Pt straight trigger
+
+ UInt_t fScaler[8*4]; ///< local data
+ UInt_t fEOS; ///< contains switches conf. & flag for reading X (0) or Y (1) in fScaler
+ UInt_t fReset; ///< reset signal
+};
+
+} // extern "C"
+
+
+/// \ingroup raw
+/// \class AliMUONTriggerDDLDecoderEventHandler
+/// \brief Callback event handler class for the AliMUONTriggerDDLDecoder.
+/// This class is the base class defining what methods the event handler for the
+/// high performance decoder should have. This handler actually does nothing.
+/// The user of this decoder will have to derive from this class a custom event
+/// handler that actually does something within the callback methods OnNewRegionalHeader,
+/// OnLocalStruct, OnError etc...
+///
+class AliMUONTriggerDDLDecoderEventHandler
+{
+public:
+
+ /// The only reason for a virtual destructor is to make -Weffc++ shutup.
+ /// This should not really be here since we do not actually want or need
+ /// run-time polymorphism.
+ virtual ~AliMUONTriggerDDLDecoderEventHandler() {}
+
+ /// All the possible error codes from the parsing.
+ enum ErrorCode
+ {
+ kNoError = 0, /// Decoding was successful.
+ kTooManyRegionals = 1, /// Too many regional card structures are expected in the DDL payload.
+ kNoDarcHeader = 2, /// The DARC header is missing. The DDL buffer is too short to hold a DARC header.
+ kNoDarcScalars = 3, /// The DARC scalars are missing or corrupt. The DDL buffer is too short to contain them.
+ kWrongEventType = 4, /// Wrong event type obtained from the Darc header.
+ kNoEndOfDarc = 5, /// The DDL buffer is too short to contain an end of DARC header key word.
+ kBadEndOfDarc = 6, /// End of DARC header key word is incorrect or corrupt.
+ kNoGlobalHeader = 7, /// The global header is missing. The DDL buffer is too short to hold a global header.
+ kNoGlobalScalars = 8, /// The global scalars are missing or corrupt. The DDL buffer is too short to contain them.
+ kNoEndOfGlobal = 9, /// The DDL buffer is too short to contain an end of global header key word.
+ kBadEndOfGlobal = 10, /// End of global header key word is incorrect or corrupt.
+ kNoRegionalHeader = 11, /// The regional header is missing. The DDL buffer is too short to hold another regional header.
+ kNoRegionalScalars = 12, /// The regional scalars are missing or corrupt. The DDL buffer is too short to contain them.
+ kNoEndOfRegional = 13, /// The DDL buffer is too short to contain an end of regional header key word.
+ kBadEndOfRegional = 14, /// End of regional header key word is incorrect or corrupt.
+ kNoLocalStruct = 15, /// The local structure is missing. The DDL buffer is too short to hold another local structure.
+ kNoLocalScalars = 16, /// The local scalars are missing or corrupt. The DDL buffer is too short to contain them.
+ kNoEndOfLocal = 17, /// The DDL buffer is too short to contain an end of local structure key word.
+ kBadEndOfLocal = 18, /// End of local structure key word is incorrect or corrupt.
+ kBufferTooBig = 19 /// The DDL raw data is larger than indicated by the headers; extra bytes are probably just garbage.
+ };
+
+ // The following methods should be overridden for specific processing to
+ // take place in your own event handler.
+
+ /// The OnNewBuffer method will be called whenever a new buffer containing
+ /// a DDL payload is about to be processed.
+ /// The default behaviour of this method is to do nothing.
+ /// - param const void* The pointer to the start of the memory buffer storing
+ /// the DDL payload.
+ /// - param UInt_t The size in bytes of the memory buffer.
+ void OnNewBuffer(const void* /*buffer*/, UInt_t /*bufferSize*/) {}
+
+ /// The OnEndOfBuffer method will be called whenever the buffer containing
+ /// a DDL payload has been processed. For each OnNewBuffer method call a
+ /// symmetric call to OnEndOfBuffer is made at the end of processing (after
+ /// the last call to OnLocalStruct)
+ /// The default behaviour of this method is to do nothing.
+ /// - param const void* The pointer to the start of the memory buffer storing
+ /// the DDL payload.
+ /// - param UInt_t The size in bytes of the memory buffer.
+ void OnEndOfBuffer(const void* /*buffer*/, UInt_t /*bufferSize*/) {}
+
+ /// The OnDarcHeader method will be called when the DARC header has been
+ /// found in the DDL payload.
+ /// The default behaviour of this method is to do nothing.
+ /// - param UInt_t The DARC header word as found in the payload.
+ /// - param const AliMUONDarcScalarsStruct* The DARC scalars found in the
+ /// raw data. If there are no scalars in the data then this pointer
+ /// is set to NULL.
+ /// - param const void* A pointer to the remainder of the raw data after
+ /// the DARC header and scalars.
+ void OnDarcHeader(
+ UInt_t /*header*/,
+ const AliMUONDarcScalarsStruct* /*scalars*/,
+ const void* /*data*/
+ )
+ {
+ }
+
+ /// The OnGlobalHeader method will be called when the global header has
+ /// been found in the DDL payload.
+ /// The default behaviour of this method is to do nothing.
+ /// - param const AliMUONGlobalHeaderStruct* A pointer to the global header.
+ /// - param const AliMUONDarcScalarsStruct* The global scalars found in the
+ /// raw data. If there are no scalars in the data then this pointer
+ /// is set to NULL.
+ /// - param const void* A pointer to the start of the regional data blocks.
+ void OnGlobalHeader(
+ const AliMUONGlobalHeaderStruct* /*header*/,
+ const AliMUONGlobalScalarsStruct* /*scalars*/,
+ const void* /*data*/
+ )
+ {
+ }
+
+ /// The OnNewRegionalStruct method will be called for each regional header
+ /// found in the DDL payload.
+ /// The default behaviour of this method is to do nothing.
+ /// - param const AliMUONRegionalHeaderStruct* A pointer to the regional
+ /// structure header.
+ /// - param const AliMUONRegionalScalarsStruct* The regional scalars found
+ /// in the raw data. If there are no scalars in the data then this
+ /// pointer is set to NULL.
+ /// - param const void* A pointer to the start of the local trigger
+ /// structures data for this regional block.
+ void OnNewRegionalStruct(
+ const AliMUONRegionalHeaderStruct* /*regionalStruct*/,
+ const AliMUONRegionalScalarsStruct* /*scalars*/,
+ const void* /*data*/
+ )
+ {
+ }
+
+ /// The OnEndOfRegionalStruct method will be called whenever a regional
+ /// structure has been processed. For each OnNewRegionalStruct method
+ /// call a symmetric call to OnEndOfRegionalStruct is made after processing
+ /// of the regional structure is done (after the last call to OnLocalStruct
+ /// for that regional structure).
+ /// - param const AliMUONRegionalHeaderStruct* A pointer to the regional
+ /// structure header.
+ /// - param const AliMUONRegionalScalarsStruct* The regional scalars found
+ /// in the raw data. If there are no scalars in the data then this
+ /// pointer is set to NULL.
+ /// - param const void* A pointer to the start of the local trigger
+ /// structures data for this regional block.
+ void OnEndOfRegionalStruct(
+ const AliMUONRegionalHeaderStruct* /*regionalStruct*/,
+ const AliMUONRegionalScalarsStruct* /*scalars*/,
+ const void* /*data*/
+ )
+ {
+ }
+
+ /// The OnLocalStruct method will be called for each local trigger
+ /// structure found in the DDL payload. The user must overload this
+ /// method to process the local structures as needed.
+ /// The default behaviour of this method is to do nothing.
+ /// - param const AliMUONRegionalHeaderStruct* A pointer to the local
+ /// trigger structure found.
+ /// - param const AliMUONRegionalScalarsStruct* The local scalars found
+ /// in the raw data. If there are no scalars in the data then this
+ /// pointer is set to NULL.
+ void OnLocalStruct(
+ const AliMUONLocalInfoStruct* /*localStruct*/,
+ const AliMUONLocalScalarsStruct* /*scalars*/
+ )
+ {
+ }
+
+ // The following static methods are helper routines for decoding the
+ // DARC header bits.
+
+ /// Return event type
+ /// \param header Should be the header as given by the OnDarkHeader() method.
+ static UChar_t GetDarcEventType(UInt_t header) { return (UChar_t)(header >> 30) & 0x3; };
+
+ /// Return Darc type
+ /// \param header Should be the header as given by the OnDarkHeader() method.
+ static UChar_t GetDarcType(UInt_t header) { return (UChar_t)(header >> 24) & 0x7; }
+
+ /// Return serial number
+ /// \param header Should be the header as given by the OnDarkHeader() method.
+ static UChar_t GetDarcSerialNb(UInt_t header) { return (UChar_t)(header >> 20) & 0xF; }
+
+ /// Return version
+ /// \param header Should be the header as given by the OnDarkHeader() method.
+ static UChar_t GetDarcVersion(UInt_t header) { return (UChar_t)(header >> 12) & 0xFF; }
+
+ /// Return VME trig
+ /// \param header Should be the header as given by the OnDarkHeader() method.
+ static bool GetDarcVMETrig(UInt_t header) { return (header & 0x800); }
+
+ /// Return global flag
+ /// \param header Should be the header as given by the OnDarkHeader() method.
+ static bool GetDarcGlobalFlag(UInt_t header) { return (header & 0x400); }
+
+ /// Return CPT trigger
+ /// \param header Should be the header as given by the OnDarkHeader() method.
+ static bool GetDarcCTPTrig(UInt_t header) { return (header & 0x200); }
+
+ /// Return DAQ flag
+ /// \param header Should be the header as given by the OnDarkHeader() method.
+ static bool GetDarcDAQFlag(UInt_t header) { return (header & 0x100); }
+
+ /// Return reg pattern
+ /// \param header Should be the header as given by the OnDarkHeader() method.
+ static UChar_t GetDarcRegPattern(UInt_t header) { return (UChar_t)(header & 0xFF); }
+
+ // The following static methods are helper routines for decoding the
+ // regional structure header bits.
+
+ /// Return L0
+ static UShort_t GetRegionalL0(const AliMUONRegionalHeaderStruct* header)
+ {
+ assert( header != NULL );
+ return (header->fL0CountAndMask >> 16) & 0xFFFF;
+ }
+
+ /// Return mask
+ static UShort_t GetRegionalMask(const AliMUONRegionalHeaderStruct* header)
+ {
+ assert( header != NULL );
+ return header->fL0CountAndMask & 0xFFFF;
+ }
+
+ /// Return RegPhysFlag
+ static bool GetRegionalPhysFlag(const AliMUONRegionalHeaderStruct* header)
+ {
+ assert( header != NULL );
+ return (header->fWord & 0x80000000) != 0;
+ }
+
+ /// Return ResetNb
+ static UChar_t GetRegionalResetNb(const AliMUONRegionalHeaderStruct* header)
+ {
+ assert( header != NULL );
+ return (UChar_t)(header->fWord >> 25) & 0x20;
+ }
+
+ /// Return SerialNb
+ static UChar_t GetRegionalSerialNb(const AliMUONRegionalHeaderStruct* header)
+ {
+ assert( header != NULL );
+ return (UChar_t)(header->fWord >> 20) & 0x1F;
+ }
+
+ /// Return Id
+ static UChar_t GetRegionalId(const AliMUONRegionalHeaderStruct* header)
+ {
+ assert( header != NULL );
+ return (UChar_t)(header->fWord >> 16) & 0x0F;
+ }
+
+ /// Return Version
+ static UChar_t GetRegionalVersion(const AliMUONRegionalHeaderStruct* header)
+ {
+ assert( header != NULL );
+ return (UChar_t)(header->fWord >> 8) & 0xFF;
+ }
+
+ /// Return Output
+ static UChar_t GetRegionalOutput(const AliMUONRegionalHeaderStruct* header)
+ {
+ assert( header != NULL );
+ return (UChar_t)(header->fWord & 0xFF);
+ }
+
+ /// Return ErrorBits
+ static UShort_t GetRegionalErrorBits(const AliMUONRegionalHeaderStruct* header)
+ {
+ assert( header != NULL );
+ return (UShort_t)(header->fDarcWord >> 21) & 0x3FF;
+ }
+
+ /// Return FPGANumber
+ static UChar_t GetRegionalFPGANumber(const AliMUONRegionalHeaderStruct* header)
+ {
+ assert( header != NULL );
+ return (UChar_t) (header->fDarcWord >> 18) & 0x7;
+ }
+
+ /// Return DarcPhysFlag
+ static bool GetRegionalDarcPhysFlag(const AliMUONRegionalHeaderStruct* header)
+ {
+ assert( header != NULL );
+ return (header->fDarcWord & 0x1000) != 0;
+ }
+
+ /// Return PresentFlag
+ static bool GetRegionalPresentFlag(const AliMUONRegionalHeaderStruct* header)
+ {
+ assert( header != NULL );
+ return (header->fDarcWord & 0x800) != 0;
+ }
+
+ /// Return RamNotFullFlag
+ static bool GetRegionalRamNotFullFlag(const AliMUONRegionalHeaderStruct* header)
+ {
+ assert( header != NULL );
+ return (header->fDarcWord & 0x400) != 0;
+ }
+
+ /// Return RamNotEmptyFlag
+ static bool GetRegionalRamNotEmptyFlag(const AliMUONRegionalHeaderStruct* header)
+ {
+ assert( header != NULL );
+ return (header->fDarcWord & 0x200) != 0;
+ }
+
+ /// Return L2RejStatus
+ static bool GetRegionalL2RejStatus(const AliMUONRegionalHeaderStruct* header)
+ {
+ assert( header != NULL );
+ return (header->fDarcWord & 0x100) != 0;
+ }
+
+ /// Return L2AccStatus
+ static bool GetRegionalL2AccStatus(const AliMUONRegionalHeaderStruct* header)
+ {
+ assert( header != NULL );
+ return (header->fDarcWord & 0x80) != 0;
+ }
+
+ /// Return L1Status
+ static bool GetRegionalL1Status(const AliMUONRegionalHeaderStruct* header)
+ {
+ assert( header != NULL );
+ return (header->fDarcWord & 0x40) != 0;
+ }
+
+ /// Return L0Status
+ static bool GetRegionalL0Status(const AliMUONRegionalHeaderStruct* header)
+ {
+ assert( header != NULL );
+ return (header->fDarcWord & 0x20) != 0;
+ }
+
+ /// Return EventInRam
+ static UChar_t GetRegionalEventInRam(const AliMUONRegionalHeaderStruct* header)
+ {
+ assert( header != NULL );
+ return (UChar_t) (header->fDarcWord >> 4) & 0x4;
+ }
+
+ /// Return Busy
+ static UChar_t GetRegionalBusy(const AliMUONRegionalHeaderStruct* header)
+ {
+ assert( header != NULL );
+ return (UChar_t) (header->fDarcWord) & 0x4;
+ }
+
+ // The following static methods are helper routines for decoding the
+ // global header bits.
+
+ /// Return global output
+ /// \param header Should be the header as given by the OnGlobalHeader() method.
+ static UChar_t GetGlobalOutput(const AliMUONGlobalHeaderStruct* header)
+ {
+ assert(header != NULL);
+ return header->fOutput & 0xFF;
+ }
+
+ /// Return global config
+ /// \param header Should be the header as given by the OnGlobalHeader() method.
+ static UShort_t GetGlobalConfig(const AliMUONGlobalHeaderStruct* header)
+ {
+ assert(header != NULL);
+ return (header->fOutput >> 16) & 0xFFFF;
+ }
+
+ // The following static methods are helper routines for decoding the
+ // local trigger structure and scalar bits.
+
+ /// Return X2
+ static UShort_t GetLocalX2(const AliMUONLocalInfoStruct* local)
+ {
+ assert(local != NULL);
+ return (local->fX2X1 >> 16) & 0xFFFF;
+ }
+
+ /// Return X1
+ static UShort_t GetLocalX1(const AliMUONLocalInfoStruct* local)
+ {
+ assert(local != NULL);
+ return (local->fX2X1) & 0xFFFF;
+ }
+
+ /// Return X4
+ static UShort_t GetLocalX4(const AliMUONLocalInfoStruct* local)
+ {
+ assert(local != NULL);
+ return (local->fX4X3 >> 16) & 0xFFFF;
+ }
+
+ /// Return X3
+ static UShort_t GetLocalX3(const AliMUONLocalInfoStruct* local)
+ {
+ assert(local != NULL);
+ return (local->fX4X3) & 0xFFFF;
+ }
+
+ /// Return Y2
+ static UShort_t GetLocalY2(const AliMUONLocalInfoStruct* local)
+ {
+ assert(local != NULL);
+ return (local->fY2Y1 >> 16) & 0xFFFF;
+ }
+
+ /// Return Y1
+ static UShort_t GetLocalY1(const AliMUONLocalInfoStruct* local)
+ {
+ assert(local != NULL);
+ return (local->fY2Y1) & 0xFFFF;
+ }
+
+ /// Return Y4
+ static UShort_t GetLocalY4(const AliMUONLocalInfoStruct* local)
+ {
+ assert(local != NULL);
+ return (local->fY4Y3 >> 16) & 0xFFFF;
+ }
+
+ /// Return Y3
+ static UShort_t GetLocalY3(const AliMUONLocalInfoStruct* local)
+ {
+ assert(local != NULL);
+ return (local->fY4Y3) & 0xFFFF;
+ }
+
+ /// Return Id
+ static UChar_t GetLocalId(const AliMUONLocalInfoStruct* local)
+ {
+ assert(local != NULL);
+ return local->fTriggerBits >> 19 & 0xF;
+ }
+
+ /// Return Dec
+ static UChar_t GetLocalDec(const AliMUONLocalInfoStruct* local)
+ {
+ assert(local != NULL);
+ return local->fTriggerBits >> 15 & 0xF;
+ }
+
+ /// Return TrigY
+ static bool GetLocalTrigY(const AliMUONLocalInfoStruct* local)
+ {
+ assert(local != NULL);
+ return (local->fTriggerBits >> 14 & 0x1);
+ }
+
+ /// Return TriggerY
+ static bool GetLocalTriggerY(const AliMUONLocalInfoStruct* local)
+ {
+ return not (GetLocalTrigY(local) and GetLocalYPos(local) == 15);
+ }
+
+ /// Return Upos
+ static UChar_t GetLocalYPos(const AliMUONLocalInfoStruct* local)
+ {
+ assert(local != NULL);
+ return local->fTriggerBits >> 10 & 0xF;
+ }
+
+ /// Get Sign of X deviation
+ static bool GetLocalSXDev(const AliMUONLocalInfoStruct* local)
+ {
+ assert(local != NULL);
+ return (local->fTriggerBits >> 9 & 0x1);
+ }
+
+ /// Get X deviation
+ static UChar_t GetLocalXDev(const AliMUONLocalInfoStruct* local)
+ {
+ assert(local != NULL);
+ return local->fTriggerBits >> 5 & 0xF;
+ }
+
+ /// Return TriggerX
+ static bool GetLocalTriggerX(const AliMUONLocalInfoStruct* local)
+ {
+ return not (GetLocalSXDev(local) and (GetLocalXDev(local) == 0)
+ and GetLocalXPos(local) == 0);
+ }
+
+ /// Return Xpos
+ static UChar_t GetLocalXPos(const AliMUONLocalInfoStruct* local)
+ {
+ assert(local != NULL);
+ return local->fTriggerBits & 0x1F;
+ }
+
+ /// Return LPT
+ static UChar_t GetLocalLpt(const AliMUONLocalInfoStruct* local) {return (GetLocalDec(local) & 0x3);}
+
+ /// Return HPT
+ static UChar_t GetLocalHpt(const AliMUONLocalInfoStruct* local) {return (GetLocalDec(local) >> 2) & 0x3;}
+
+ /// Return switch
+ static UShort_t GetLocalSwitch(const AliMUONLocalScalarsStruct* scalars)
+ {
+ assert(scalars != NULL);
+ return (scalars->fEOS >> 1) & 0x3FF;
+ }
+
+ /// Return ComptXY
+ static UChar_t GetLocalComptXY(const AliMUONLocalScalarsStruct* scalars)
+ {
+ assert(scalars != NULL);
+ return scalars->fEOS & 0x1;
+ }
+
+ /// Return XY1
+ static UShort_t GetLocalXY1(const AliMUONLocalScalarsStruct* scalars, UInt_t n)
+ {
+ assert(scalars != NULL and n < 16);
+ return (n % 2 == 0) ? (scalars->fScaler[(n/2)] & 0xFFFF)
+ : ((scalars->fScaler[(n/2)] >> 16) & 0xFFFF);
+ }
+
+ /// Return XY2
+ static UShort_t GetLocalXY2(const AliMUONLocalScalarsStruct* scalars, UInt_t n)
+ {
+ assert(scalars != NULL and n < 16);
+ return (n % 2 == 0) ? (scalars->fScaler[8 + (n/2)] & 0xFFFF)
+ : ((scalars->fScaler[8 + (n/2)] >> 16) & 0xFFFF);
+ }
+
+ /// Return XY3
+ static UShort_t GetLocalXY3(const AliMUONLocalScalarsStruct* scalars, UInt_t n)
+ {
+ assert(scalars != NULL and n < 16);
+ return (n % 2 == 0) ? (scalars->fScaler[8*2 + (n/2)] & 0xFFFF)
+ : ((scalars->fScaler[8*2 + (n/2)] >> 16) & 0xFFFF);
+ }
+
+ /// Return XY4
+ static UShort_t GetLocalXY4(const AliMUONLocalScalarsStruct* scalars, UInt_t n)
+ {
+ assert(scalars != NULL and n < 16);
+ return (n % 2 == 0) ? (scalars->fScaler[8*3 + (n/2)] & 0xFFFF)
+ : ((scalars->fScaler[8*3 + (n/2)] >> 16) & 0xFFFF);
+ }
+
+ /// Whenever a parsing error of the DDL payload is encountered because of
+ /// corruption of the raw data the OnError method is called immediately at
+ /// the point this error is discovered.
+ /// The default behaviour of this method is to do nothing.
+ /// -param error This is an error code indicating the kind of problem
+ /// encountered with the DDL payload.
+ /// -param location This is a pointer into the DDL payload memory buffer
+ /// indicating the exact location where the parsing error happened
+ /// or i.e. the location of the corruption.
+ /// Note that a relative offset in bytes from the start of the memory buffer
+ /// can be calculated by: storing the buffer pointer recevied in OnNewBuffer
+ /// earlier in fBufferStart for example, and then the offset is given by:
+ /// offset = (unsigned long)location - (unsigned long)fBufferStart;
+ void OnError(ErrorCode /*error*/, const void* /*location*/) {}
+
+ /// This is a utility method which converts an error code to a string
+ /// representation for printing purposes.
+ /// \param code The error code as received in OnError for example.
+ /// \return An ANSI string containing the name of the error code symbol.
+ static const char* ErrorCodeToString(ErrorCode code);
+
+ /// This is a utility method which converts an error code to user friendly
+ /// descriptive message useful for printing to the screen.
+ /// \param code The error code as received in OnError for example.
+ /// \return An ANSI string containing a descriptive message of the error.
+ static const char* ErrorCodeToMessage(ErrorCode code);
+};
+
+//_____________________________________________________________________________
+
+inline const char* AliMUONTriggerDDLDecoderEventHandler::ErrorCodeToString(ErrorCode code)
+{
+ /// This is a utility method which converts an error code to a string
+ /// representation for printing purposes.
+ /// \param code The error code as received in OnError for example.
+ /// \return An ANSI string containing the name of the error code symbol.
+
+ switch (code)
+ {
+ case kNoError: return "kNoError";
+ case kTooManyRegionals: return "kTooManyRegionals";
+ case kNoDarcHeader: return "kNoDarcHeader";
+ case kNoDarcScalars: return "kNoDarcScalars";
+ case kWrongEventType: return "kWrongEventType";
+ case kNoEndOfDarc: return "kNoEndOfDarc";
+ case kBadEndOfDarc: return "kBadEndOfDarc";
+ case kNoGlobalHeader: return "kNoGlobalHeader";
+ case kNoGlobalScalars: return "kNoGlobalScalars";
+ case kNoEndOfGlobal: return "kNoEndOfGlobal";
+ case kBadEndOfGlobal: return "kBadEndOfGlobal";
+ case kNoRegionalHeader: return "kNoRegionalHeader";
+ case kNoRegionalScalars: return "kNoRegionalScalars";
+ case kNoEndOfRegional: return "kNoEndOfRegional";
+ case kBadEndOfRegional: return "kBadEndOfRegional";
+ case kNoLocalStruct: return "kNoLocalStruct";
+ case kNoLocalScalars: return "kNoLocalScalars";
+ case kNoEndOfLocal: return "kNoEndOfLocal";
+ case kBadEndOfLocal: return "kBadEndOfLocal";
+ case kBufferTooBig: return "kBufferTooBig";
+ default: return "INVALID";
+ }
+}
+
+
+inline const char* AliMUONTriggerDDLDecoderEventHandler::ErrorCodeToMessage(ErrorCode code)
+{
+ /// This is a utility method which converts an error code to user friendly
+ /// descriptive message useful for printing to the screen.
+ /// \param code The error code as received in OnError for example.
+ /// \return An ANSI string containing a descriptive message of the error.
+
+ switch (code)
+ {
+ case kNoError:
+ return "Decoding was successful.";
+ case kTooManyRegionals:
+ return "Too many regional card structures are expected in the DDL payload.";
+ case kNoDarcHeader:
+ return "The DARC header is missing. The DDL buffer is too short"
+ " to hold a DARC header.";
+ case kNoDarcScalars:
+ return "The DARC scalars are missing or corrupt."
+ " The DDL buffer is too short to contain them.";
+ case kWrongEventType:
+ return "Wrong event type obtained from the Darc header.";
+ case kNoEndOfDarc:
+ return "The DDL buffer is too short to contain an end of DARC"
+ " header key word.";
+ case kBadEndOfDarc:
+ return "End of DARC header key word is incorrect or corrupt.";
+ case kNoGlobalHeader:
+ return "The global header is missing. The DDL buffer is too"
+ " short to hold a global header.";
+ case kNoGlobalScalars:
+ return "The global scalars are missing or corrupt. The DDL"
+ " buffer is too short to contain them.";
+ case kNoEndOfGlobal:
+ return "The DDL buffer is too short to contain an end of global"
+ " header key word.";
+ case kBadEndOfGlobal:
+ return "End of global header key word is incorrect or corrupt.";
+ case kNoRegionalHeader:
+ return "The regional header is missing. The DDL buffer is too"
+ " short to hold another regional header.";
+ case kNoRegionalScalars:
+ return "The regional scalars are missing or corrupt. The DDL"
+ " buffer is too short to contain them.";
+ case kNoEndOfRegional:
+ return "The DDL buffer is too short to contain an end of regional"
+ " header key word.";
+ case kBadEndOfRegional:
+ return "End of regional header key word is incorrect or corrupt.";
+ case kNoLocalStruct:
+ return "The local structure is missing. The DDL buffer is too"
+ " short to hold another local structure.";
+ case kNoLocalScalars:
+ return "The local scalars are missing or corrupt. The DDL buffer"
+ " is too short to contain them.";
+ case kNoEndOfLocal:
+ return "The DDL buffer is too short to contain an end of local"
+ " structure key word.";
+ case kBadEndOfLocal:
+ return "End of local structure key word is incorrect or corrupt.";
+ case kBufferTooBig:
+ return "The DDL raw data is larger than indicated by the headers;"
+ " extra bytes are probably just garbage.";
+ default:
+ return "Unknown error code!";
+ }
+}
+
+
+inline std::ostream& operator << (std::ostream& os, AliMUONTriggerDDLDecoderEventHandler::ErrorCode code)
+{
+ /// This is the stream operator for std::ostream classes to be able to
+ /// easily write the error messages associated with the error codes generated
+ /// by the decoder to 'cout' or 'cerr' for example.
+
+ os << AliMUONTriggerDDLDecoderEventHandler::ErrorCodeToMessage(code);
+ return os;
+}
+
+#endif // ALIMUONTRIGGERDDLDECODEREVENTHANDLER_H
--- /dev/null
+#ifndef ALIMUONVRAWSTREAMTRIGGER_H
+#define ALIMUONVRAWSTREAMTRIGGER_H
+/* This file is property of and copyright by the ALICE HLT Project *
+ * ALICE Experiment at CERN, All rights reserved. *
+ * See cxx source for full Copyright notice */
+
+/* $Id$ */
+
+/// \ingroup raw
+/// \class AliMUONVRawStreamTrigger
+/// \brief Base class for reading MUON raw trigger data.
+///
+// MUON trigger decoders must derive from this base class.
+//
+// Author Artur Szostak <artursz@iafrica.com>
+
+#include <TObject.h>
+#include "AliMUONRawStream.h"
+
+class TArrayS;
+class AliRawReader;
+
+class AliMUONVRawStreamTrigger : public AliMUONRawStream
+{
+public:
+ AliMUONVRawStreamTrigger();
+ AliMUONVRawStreamTrigger(AliRawReader* rawReader);
+ virtual ~AliMUONVRawStreamTrigger();
+
+ /// Advance one step in the iteration. Returns false if finished.
+ virtual Bool_t Next(UChar_t& id, UChar_t& dec, Bool_t& trigY,
+ UChar_t& yPos, UChar_t& sXDev, UChar_t& xDev,
+ UChar_t& xPos, Bool_t& triggerY, Bool_t& triggerX,
+ TArrayS& xPattern, TArrayS& yPattern) = 0;
+
+ /// Return maximum number of DDLs
+ virtual Int_t GetMaxDDL() const = 0;
+ /// Return maximum number of regional cards in DATE file
+ virtual Int_t GetMaxReg() const = 0;
+ /// Return maximum number of local cards in DATE file
+ virtual Int_t GetMaxLoc() const = 0;
+
+ virtual void SetMaxLoc(Int_t loc) = 0;
+
+ /// Return number of DDL
+ virtual Int_t GetDDL() const = 0;
+
+ /// Disable Warnings
+ virtual void DisableWarnings() = 0;
+
+ /// error numbers
+ enum rawStreamTriggerError
+ {
+ kDarcEoWErr = 6, ///< end of Darc word error
+ kGlobalEoWErr = 7, ///< end of Global word error
+ kRegEoWErr = 8, ///< end of Regional word error
+ kLocalEoWErr = 9 ///< end of local word error
+ };
+
+private:
+ /// Not implemented
+ AliMUONVRawStreamTrigger(const AliMUONVRawStreamTrigger& stream);
+ /// Not implemented
+ AliMUONVRawStreamTrigger& operator = (const AliMUONVRawStreamTrigger& stream);
+
+ ClassDef(AliMUONVRawStreamTrigger, 0) // Base class for MUON trigger rawdata decoders.
+};
+
+#endif // ALIMUONVRAWSTREAMTRIGGER_H
///
/// \author Ch. Finck, Subatech, April 2006
///
+/// Added example routines to show how to use the interface of the high
+/// performance decoder AliMUONRawStreamTriggerrHP.
+/// -- Artur Szostak <artursz@iafrica.com>
+///
/// Implement "digits" iterator.
/// This macro is interface with AliRawReader for RAW.
/// The different stucture of the patload are readout and stored in TClonesArray
// RAW includes
#include "AliRawReader.h"
+#include "AliRawReaderFile.h"
+#include "AliRawReaderRoot.h"
// MUON includes
#include "AliMUONRawStreamTrigger.h"
+#include "AliMUONRawStreamTriggerHP.h"
#include "AliMUONDarcHeader.h"
#include "AliMUONRegHeader.h"
#include "AliMUONLocalStruct.h"
}
+void MUONRawStreamTriggerHPExpert(Int_t maxEvent = 1, Int_t minDDL = 0, Int_t maxDDL = 1, TString fileName = "./")
+{
+ /// Decodes raw MUON trigger data using the fast decoder.
+
+ TStopwatch timer;
+ timer.Start(kTRUE);
+
+ AliRawReader* rawReader = AliRawReader::Create(fileName.Data());
+
+ // Load mapping
+ if ( ! AliMpCDB::LoadDDLStore() ) {
+ printf("Could not access mapping from OCDB !\n");
+ }
+
+ // raw stream
+ AliMUONRawStreamTriggerHP* rawStream = new AliMUONRawStreamTriggerHP(rawReader);
+
+ // Light weight interfaces to the raw data.
+ const AliMUONRawStreamTriggerHP::AliHeader* darcHeader = 0x0;
+ const AliMUONRawStreamTriggerHP::AliRegionalHeader* regHeader = 0x0;
+ const AliMUONRawStreamTriggerHP::AliLocalStruct* localStruct = 0x0;
+
+ // Loop over events.
+ Int_t iEvent = 0;
+
+ while (rawReader->NextEvent()) {
+
+ if (iEvent == maxEvent)
+ break;
+
+ printf("Event %d\n",iEvent++);
+
+ // read DDL while < 2 DDL
+ while(rawStream->NextDDL()) {
+
+ if (rawStream->GetDDL() < minDDL || rawStream->GetDDL() > maxDDL)
+ continue;
+
+ printf("\niDDL %d\n", rawStream->GetDDL());
+
+ darcHeader = rawStream->GetHeaders();
+
+ printf("Global output %x\n", (Int_t)darcHeader->GetGlobalOutput());
+
+ // loop over regional structures
+ Int_t nReg = (Int_t) rawStream->GetRegionalHeaderCount();
+ for(Int_t iReg = 0; iReg < nReg ;iReg++){ //REG loop
+
+// printf("RegionalId %d\n", iReg);
+
+ regHeader = rawStream->GetRegionalHeader(iReg);
+
+ // crate info
+ AliMpTriggerCrate* crate = AliMpDDLStore::Instance()->
+ GetTriggerCrate(rawStream->GetDDL(), iReg);
+
+ // loop over local structures
+ Int_t nLocal = rawStream->GetLocalStructCount(iReg);
+ for(Int_t iLocal = 0; iLocal < nLocal; iLocal++) {
+
+ localStruct = rawStream->GetLocalStruct(iReg, iLocal);
+
+ Int_t iLocCard = crate->GetLocalBoardId(localStruct->GetId());
+
+ if ( !iLocCard ) continue; // empty slot
+
+ // check if trigger
+ if (localStruct->GetTriggerX()
+ || localStruct->GetTriggerY()) { // no empty data
+
+ printf("LocalId %d\n", localStruct->GetId());
+
+ Int_t loStripX = (Int_t)localStruct->GetXPos();
+ Int_t loStripY = (Int_t)localStruct->GetYPos();
+ Int_t loDev = (Int_t)localStruct->GetXDev();
+
+ printf("iLocCard: %d, XPos: %d, YPos: %d Dev: %d\n", iLocCard, loStripX, loStripY, loDev);
+
+ }
+ } // iLocal
+ } // iReg
+ } // NextDDL
+ }// NextEvent
+
+ delete rawReader;
+ delete rawStream;
+
+ timer.Print();
+
+}
+
+
+void MUONRawStreamTriggerHPExpert2(Int_t maxEvent = 1, Int_t minDDL = 0, Int_t maxDDL = 1, TString fileName = "./")
+{
+ /// Decodes raw MUON trigger data using the fast decoder.
+ /// This method shows a slightly different method of iteration over the
+ /// data using the AliMUONRawStreamTriggerHP interface.
+
+ TStopwatch timer;
+ timer.Start(kTRUE);
+
+ AliRawReader* rawReader = AliRawReader::Create(fileName.Data());
+
+ // Load mapping
+ if ( ! AliMpCDB::LoadDDLStore() ) {
+ printf("Could not access mapping from OCDB !\n");
+ }
+
+ // raw stream
+ AliMUONRawStreamTriggerHP* rawStream = new AliMUONRawStreamTriggerHP(rawReader);
+
+ // Light weight interfaces to the raw data.
+ const AliMUONRawStreamTriggerHP::AliHeader* darcHeader = 0x0;
+ const AliMUONRawStreamTriggerHP::AliRegionalHeader* regHeader = 0x0;
+ const AliMUONRawStreamTriggerHP::AliLocalStruct* localStruct = 0x0;
+
+ // Loop over events.
+ Int_t iEvent = 0;
+
+ while (rawReader->NextEvent()) {
+
+ if (iEvent == maxEvent)
+ break;
+
+ printf("Event %d\n",iEvent++);
+
+ // read DDL while < 2 DDL
+ while(rawStream->NextDDL()) {
+
+ if (rawStream->GetDDL() < minDDL || rawStream->GetDDL() > maxDDL)
+ continue;
+
+ printf("\niDDL %d\n", rawStream->GetDDL());
+
+ darcHeader = rawStream->GetHeaders();
+
+ printf("Global output %x\n", (Int_t)darcHeader->GetGlobalOutput());
+
+ // loop over regional structures
+ Int_t nReg = (Int_t) rawStream->GetRegionalHeaderCount();
+ for(Int_t iReg = 0; iReg < nReg ;iReg++){ //REG loop
+
+// printf("RegionalId %d\n", iReg);
+
+ regHeader = rawStream->GetRegionalHeader(iReg);
+
+ // crate info
+ AliMpTriggerCrate* crate = AliMpDDLStore::Instance()->
+ GetTriggerCrate(rawStream->GetDDL(), iReg);
+
+ // loop over local structures
+ Int_t nLocal = regHeader->GetLocalStructCount();
+ for(Int_t iLocal = 0; iLocal < nLocal; iLocal++) {
+
+ localStruct = regHeader->GetLocalStruct(iLocal);
+
+ Int_t iLocCard = crate->GetLocalBoardId(localStruct->GetId());
+
+ if ( !iLocCard ) continue; // empty slot
+
+ // check if trigger
+ if (localStruct->GetTriggerX()
+ || localStruct->GetTriggerY()) { // no empty data
+
+ printf("LocalId %d\n", localStruct->GetId());
+
+ Int_t loStripX = (Int_t)localStruct->GetXPos();
+ Int_t loStripY = (Int_t)localStruct->GetYPos();
+ Int_t loDev = (Int_t)localStruct->GetXDev();
+
+ printf("iLocCard: %d, XPos: %d, YPos: %d Dev: %d\n", iLocCard, loStripX, loStripY, loDev);
+
+ }
+ } // iLocal
+ } // iReg
+ } // NextDDL
+ }// NextEvent
+
+ delete rawReader;
+ delete rawStream;
+
+ timer.Print();
+
+}
+
+
+void MUONRawStreamTriggerHPExpert3(Int_t maxEvent = 1, Int_t minDDL = 0, Int_t maxDDL = 1, TString fileName = "./")
+{
+ /// Decodes raw MUON trigger data using the fast decoder.
+ /// This method shows a jet another method of iteration over the
+ /// data using the AliMUONRawStreamTriggerHP interface.
+
+ TStopwatch timer;
+ timer.Start(kTRUE);
+
+ AliRawReader* rawReader = AliRawReader::Create(fileName.Data());
+
+ // Load mapping
+ if ( ! AliMpCDB::LoadDDLStore() ) {
+ printf("Could not access mapping from OCDB !\n");
+ }
+
+ // raw stream
+ AliMUONRawStreamTriggerHP* rawStream = new AliMUONRawStreamTriggerHP(rawReader);
+
+ // Light weight interfaces to the raw data.
+ const AliMUONRawStreamTriggerHP::AliHeader* darcHeader = 0x0;
+ const AliMUONRawStreamTriggerHP::AliRegionalHeader* regHeader = 0x0;
+ const AliMUONRawStreamTriggerHP::AliLocalStruct* localStruct = 0x0;
+
+ // Loop over events.
+ Int_t iEvent = 0;
+
+ while (rawReader->NextEvent()) {
+
+ if (iEvent == maxEvent)
+ break;
+
+ printf("Event %d\n",iEvent++);
+
+ // read DDL while < 2 DDL
+ while(rawStream->NextDDL()) {
+
+ if (rawStream->GetDDL() < minDDL || rawStream->GetDDL() > maxDDL)
+ continue;
+
+ printf("\niDDL %d\n", rawStream->GetDDL());
+
+ darcHeader = rawStream->GetHeaders();
+
+ printf("Global output %x\n", (Int_t)darcHeader->GetGlobalOutput());
+
+ // loop over regional structures
+ Int_t iReg = 0;
+ regHeader = rawStream->GetFirstRegionalHeader();
+ while (regHeader != NULL)
+ {
+// printf("RegionalId %d\n", iReg);
+
+ regHeader = rawStream->GetRegionalHeader(iReg);
+
+ // crate info
+ AliMpTriggerCrate* crate = AliMpDDLStore::Instance()->
+ GetTriggerCrate(rawStream->GetDDL(), iReg);
+
+ // loop over local structures
+ Int_t iLocal = 0;
+ localStruct = regHeader->GetFirstLocalStruct();
+ while (localStruct != NULL)
+ {
+ Int_t iLocCard = crate->GetLocalBoardId(localStruct->GetId());
+ if ( !iLocCard ) continue; // empty slot
+
+ // check if trigger
+ if (localStruct->GetTriggerX()
+ || localStruct->GetTriggerY()) { // no empty data
+
+ printf("LocalId %d\n", localStruct->GetId());
+
+ Int_t loStripX = (Int_t)localStruct->GetXPos();
+ Int_t loStripY = (Int_t)localStruct->GetYPos();
+ Int_t loDev = (Int_t)localStruct->GetXDev();
+
+ printf("iLocCard: %d, XPos: %d, YPos: %d Dev: %d\n", iLocCard, loStripX, loStripY, loDev);
+
+ }
+ iLocal++;
+ localStruct = localStruct->Next();
+ } // iLocal
+ iReg++;
+ regHeader = regHeader->Next();
+ } // iReg
+ } // NextDDL
+ }// NextEvent
+
+ delete rawReader;
+ delete rawStream;
+
+ timer.Print();
+
+}
+
+
void MUONRawStreamTriggerSimple(Int_t maxEvent = 1, TString fileName = "./")
{
/// Reads the raw data in fileName, using a simplified interface (iterator
timer.Print();
}
+
+
+void MUONRawStreamTriggerHPSimple(Int_t maxEvent = 1, TString fileName = "./")
+{
+ /// Reads the raw data in fileName, using the simplified interface of the
+ /// high performance decoder.
+
+ TStopwatch timer;
+ timer.Start(kTRUE);
+
+ AliRawReader* rawReader = AliRawReader::Create(fileName.Data());
+ AliMUONRawStreamTriggerHP* rawStream = new AliMUONRawStreamTriggerHP(rawReader);
+
+ UChar_t id;
+ UChar_t dec;
+ Bool_t trigY;
+ UChar_t yPos;
+ UChar_t sXDev;
+ UChar_t xDev;
+ UChar_t xPos;
+ Bool_t triggerX;
+ Bool_t triggerY;
+ TArrayS xPattern;
+ TArrayS yPattern;
+
+ // Loop over events
+ Int_t iEvent = 0;
+
+ while (rawReader->NextEvent())
+ {
+
+ if (iEvent == maxEvent)
+ break;
+
+ printf("Event %d\n", iEvent++);
+
+ rawStream->First();
+
+ // read while there are digits
+ while ( rawStream->Next(id, dec, trigY, yPos, sXDev, xDev, xPos,
+ triggerX, triggerY, xPattern, yPattern) )
+ {
+ if ( triggerX || triggerY ) // no empty data
+ printf("iLocCard: %d, XPos: %d, YPos: %d Dev: %d\n", id, xPos, yPos, xDev);
+ }// Next
+ }// NextEvent
+
+ delete rawReader;
+ delete rawStream;
+
+ timer.Print();
+}
+
+
+void MUONRawStreamTriggerHPSimple2(Int_t maxEvent = 1, TString fileName = "./")
+{
+ /// Reads the raw data in fileName, using the simplified interface of the
+ /// high performance decoder.
+
+ TStopwatch timer;
+ timer.Start(kTRUE);
+
+ AliRawReader* rawReader = AliRawReader::Create(fileName.Data());
+ AliMUONRawStreamTriggerHP* rawStream = new AliMUONRawStreamTriggerHP(rawReader);
+
+ const AliMUONRawStreamTriggerHP::AliLocalStruct* localStruct;
+
+ // Loop over events
+ Int_t iEvent = 0;
+
+ while (rawReader->NextEvent())
+ {
+
+ if (iEvent == maxEvent)
+ break;
+
+ printf("Event %d\n", iEvent++);
+
+ rawStream->First();
+
+ // read while there are digits
+ while ( (localStruct = rawStream->Next()) != NULL )
+ {
+ if ( localStruct->GetTriggerX() || localStruct->GetTriggerY() ) // no empty data
+ printf("iLocCard: %d, XPos: %d, YPos: %d Dev: %d\n",
+ localStruct->GetId(),
+ localStruct->GetXPos(),
+ localStruct->GetYPos(),
+ localStruct->GetXDev()
+ );
+ }// Next
+ }// NextEvent
+
+ delete rawReader;
+ delete rawStream;
+
+ timer.Print();
+}
+
UInt_t CountMaxDigits(AliBufferInfo* list)
{
- /// Deletes the memory allocated for the linked list of buffers.
+ /// Counts the maximum number of digits possible in all the buffers.
UInt_t total = 0;
AliBufferInfo* current = list;
{
if (i < maxBufferSize)
{
- buffer->fManuId = manuId;
- buffer->fAdc = adc;
- buffer->fChannelId = manuChannel;
+ buffer[i].fManuId = manuId;
+ buffer[i].fAdc = adc;
+ buffer[i].fChannelId = manuChannel;
i++;
}
}
buspatch->GetData(j, manuId, manuChannel, adc);
if (i < maxBufferSize)
{
- buffer->fManuId = manuId;
- buffer->fAdc = adc;
- buffer->fChannelId = manuChannel;
+ buffer[i].fManuId = manuId;
+ buffer[i].fAdc = adc;
+ buffer[i].fChannelId = manuChannel;
i++;
}
}
{
if (i < maxBufferSize)
{
- buffer->fManuId = manuId;
- buffer->fAdc = adc;
- buffer->fChannelId = manuChannel;
+ buffer[i].fManuId = manuId;
+ buffer[i].fAdc = adc;
+ buffer[i].fChannelId = manuChannel;
i++;
}
}
return timer.RealTime();
}
+
void Loop(const char* filename, Bool_t newDecoder)
{
AliCodeTimerAutoGeneral(Form("Loop %s",(newDecoder ? "NEW":"OLD")));
delete reader;
}
+
void MUONTimeRawStreamTrackerDumb(TString fileName)
{
AliCodeTimer::Instance()->Reset();
AliCodeTimer::Instance()->Print();
}
+
void MUONTimeRawStreamTracker(TString fileName = "./", Int_t maxEvent = 1000)
{
/// Performs a timing of old and new decoders and reports this.
--- /dev/null
+/**************************************************************************
+ * This file is property of and copyright by the ALICE HLT Project *
+ * All rights reserved. *
+ * *
+ * Primary Authors: *
+ * Artur Szostak <artursz@iafrica.com> *
+ * *
+ * Permission to use, copy, modify and distribute this software and its *
+ * documentation strictly for non-commercial purposes is hereby granted *
+ * without fee, provided that the above copyright notice appears in all *
+ * copies and that both the copyright notice and this permission notice *
+ * appear in the supporting documentation. The authors make no claims *
+ * about the suitability of this software for any purpose. It is *
+ * provided "as is" without express or implied warranty. *
+ **************************************************************************/
+
+/// \ingroup macros
+/// \file MUONTimeRawStreamTrigger.C
+/// \brief Macro for checking the timing (speed) performace of the two different trigger decoders.
+///
+/// \author Artur Szostak <artursz@iafrica.com>
+///
+/// This macro is used to check the timing (speed) performance of the existing
+/// offline decoder for the trigger DDLs and also for the new high performance
+/// decoder. It can be invoked as follows:
+///
+/// $ aliroot
+/// .L $ALICE_ROOT/MUON/MUONTimeRawStreamTrigger.C+
+/// MUONTimeRawStreamTrigger(filename, maxEvent);
+///
+/// where \em filename is the name of a file containing the raw data, or alternatively
+/// the directory containing rawX (X being an integer) paths with the raw DDL
+/// data. The \em maxEvent value is the maximum event to process (default set to
+/// 1000). Thus the macro will time the algorithm for all events in the range
+/// [0 .. maxEvent-1].
+///
+
+#if !defined(__CINT__) || defined(__MAKECINT__)
+
+#include "AliCodeTimer.h"
+
+// MUON includes
+#include "AliMUONRawStreamTrigger.h"
+#include "AliMUONRawStreamTriggerHP.h"
+#include "AliMUONDarcHeader.h"
+#include "AliMUONRegHeader.h"
+#include "AliMUONLocalStruct.h"
+#include "AliMUONDDLTrigger.h"
+
+// RAW includes
+#include "AliRawReader.h"
+#include "AliRawReaderMemory.h"
+#include "AliRawDataHeader.h"
+
+#include "TStopwatch.h"
+#include "TMath.h"
+#include "Riostream.h"
+
+#endif
+
+
+// Linked list node for buffer structures.
+struct AliBufferInfo
+{
+ AliBufferInfo* fNext;
+ Int_t fEquipId;
+ UInt_t fBufferSize;
+ UChar_t* fBuffer;
+};
+
+
+// local structure information to store
+struct AliLocalStructInfo
+{
+ UChar_t fId;
+ UChar_t fDec;
+ Bool_t fTrigY;
+ UChar_t fYPos;
+ UChar_t fSXDev;
+ UChar_t fXDev;
+ UChar_t fXPos;
+ Bool_t fTriggerY;
+ Bool_t fTriggerX;
+};
+
+
+UInt_t LoadFiles(AliBufferInfo*& list, TString fileName = "./", Int_t maxEvent = 1000)
+{
+ /// Reads in the DDL files into memory buffers as a linked list.
+
+ AliRawReader* rawReader = AliRawReader::Create(fileName.Data());
+
+ if (rawReader == NULL)
+ {
+ cerr << "ERROR: Could not create AliRawReader." << endl;
+ delete rawReader;
+ return 0;
+ }
+
+ UInt_t count = 0;
+ Int_t iEvent = 0;
+ list = NULL;
+ while (rawReader->NextEvent())
+ {
+ if (iEvent++ >= maxEvent) break;
+
+ rawReader->Select("MUONTRG", 0, 1);
+ while (rawReader->ReadHeader())
+ {
+ AliBufferInfo* info = new AliBufferInfo;
+ if (info == NULL)
+ {
+ cerr << "ERROR: Out of memory, sorry. You should limit the number of events read in." << endl;
+ delete rawReader;
+ return count;
+ }
+ info->fNext = list;
+ info->fEquipId = rawReader->GetEquipmentId();
+ info->fBufferSize = rawReader->GetDataSize() + sizeof(AliRawDataHeader);
+ info->fBuffer = new UChar_t[info->fBufferSize];
+ if (info->fBuffer == NULL)
+ {
+ cerr << "ERROR: Out of memory, sorry. You should limit the number of events read in." << endl;
+ delete rawReader;
+ return count;
+ }
+ list = info;
+
+ // Copy the header.
+ memcpy(info->fBuffer, rawReader->GetDataHeader(), sizeof(AliRawDataHeader));
+
+ // Now copy the payload.
+ if (! rawReader->ReadNext(
+ info->fBuffer + sizeof(AliRawDataHeader),
+ info->fBufferSize - sizeof(AliRawDataHeader)
+ )
+ )
+ {
+ cerr << "ERROR: Failed to read from AliRawReader." << endl;
+ }
+ count++;
+ }
+ }
+
+ delete rawReader;
+ return count;
+}
+
+
+UInt_t CountMaxStructs(AliBufferInfo* list)
+{
+ /// Counts the maximum number of local structures possible
+
+ UInt_t total = 0;
+ AliBufferInfo* current = list;
+ while (current != NULL)
+ {
+ total += current->fBufferSize / 5;
+ current = current->fNext;
+ }
+ return total;
+}
+
+
+void ReleaseBuffers(AliBufferInfo* list)
+{
+ /// Deletes the memory allocated for the linked list of buffers.
+
+ AliBufferInfo* current = list;
+ while (current != NULL)
+ {
+ AliBufferInfo* tmp = current;
+ current = current->fNext;
+ delete [] tmp->fBuffer;
+ delete tmp;
+ }
+}
+
+
+Double_t TimeUsingOldDecoder(AliBufferInfo* list, AliLocalStructInfo* buffer, UInt_t maxBufferSize)
+{
+ /// Perform a timing using the old decoder.
+
+ AliRawReaderMemory rawReader;
+ AliMUONRawStreamTrigger rawStream(&rawReader);
+ rawReader.NextEvent();
+
+ TStopwatch timer;
+ timer.Start(kTRUE);
+
+ UInt_t i = 0;
+ AliBufferInfo* current = list;
+ while (current != NULL)
+ {
+ rawReader.SetMemory(current->fBuffer, current->fBufferSize);
+ rawReader.SetEquipmentID(current->fEquipId);
+ rawReader.Reset();
+
+ rawStream.First();
+
+ TArrayS fXPattern;
+ TArrayS fYPattern;
+
+ while ( rawStream.Next(buffer[i].fId, buffer[i].fDec, buffer[i].fTrigY,
+ buffer[i].fYPos, buffer[i].fSXDev, buffer[i].fXDev,
+ buffer[i].fXPos, buffer[i].fTriggerY, buffer[i].fTriggerX,
+ fXPattern, fYPattern)
+ )
+ {
+ if (i < maxBufferSize-1) i++;
+ }
+
+ current = current->fNext;
+ }
+
+ return timer.RealTime();
+}
+
+
+Double_t TimeUsingNewDecoder(AliBufferInfo* list, AliLocalStructInfo* buffer, UInt_t maxBufferSize)
+{
+ /// Perform a timing using the new decoder.
+
+ AliRawReaderMemory rawReader;
+ AliMUONRawStreamTriggerHP rawStream(&rawReader);
+ rawReader.NextEvent();
+
+ TStopwatch timer;
+ timer.Start(kTRUE);
+
+ UInt_t i = 0;
+ AliBufferInfo* current = list;
+ while (current != NULL)
+ {
+ rawReader.SetMemory(current->fBuffer, current->fBufferSize);
+ rawReader.SetEquipmentID(current->fEquipId);
+ rawReader.Reset();
+
+ rawStream.First();
+
+ const AliMUONRawStreamTriggerHP::AliLocalStruct* local = NULL;
+ while ( (local = rawStream.Next()) != NULL )
+ {
+ if (i < maxBufferSize)
+ {
+ buffer[i].fId = local->GetId();
+ buffer[i].fDec = local->GetDec();
+ buffer[i].fTrigY = local->GetTrigY();
+ buffer[i].fYPos = local->GetYPos();
+ buffer[i].fSXDev = local->GetSXDev();
+ buffer[i].fXDev = local->GetXDev();
+ buffer[i].fXPos = local->GetXPos();
+ buffer[i].fTriggerY = local->GetTriggerY();
+ buffer[i].fTriggerX = local->GetTriggerX();
+ i++;
+ }
+ }
+
+ current = current->fNext;
+ }
+
+ return timer.RealTime();
+}
+
+
+Double_t TimeUsingNewDecoderOldInterface(AliBufferInfo* list, AliLocalStructInfo* buffer, UInt_t maxBufferSize)
+{
+ /// Perform a timing using the new decoder but the old Next() method
+ /// as the interface.
+
+ AliRawReaderMemory rawReader;
+ AliMUONRawStreamTriggerHP rawStream(&rawReader);
+ rawReader.NextEvent();
+
+ TStopwatch timer;
+ timer.Start(kTRUE);
+
+ UInt_t i = 0;
+ AliBufferInfo* current = list;
+ while (current != NULL)
+ {
+ rawReader.SetMemory(current->fBuffer, current->fBufferSize);
+ rawReader.SetEquipmentID(current->fEquipId);
+ rawReader.Reset();
+
+ rawStream.First();
+
+ TArrayS fXPattern;
+ TArrayS fYPattern;
+
+ while ( rawStream.Next(buffer[i].fId, buffer[i].fDec, buffer[i].fTrigY,
+ buffer[i].fYPos, buffer[i].fSXDev, buffer[i].fXDev,
+ buffer[i].fXPos, buffer[i].fTriggerY, buffer[i].fTriggerX,
+ fXPattern, fYPattern)
+ )
+ {
+ if (i < maxBufferSize-1) i++;
+ }
+
+ current = current->fNext;
+ }
+
+ return timer.RealTime();
+}
+
+
+void Loop(const char* filename, Bool_t newDecoder)
+{
+ AliCodeTimerAutoGeneral(Form("Loop %s",(newDecoder ? "NEW":"OLD")));
+
+ AliRawReader* reader = AliRawReader::Create(filename);
+
+ AliMUONVRawStreamTrigger* stream;
+
+ if ( newDecoder )
+ {
+ stream = new AliMUONRawStreamTriggerHP(reader);
+ }
+ else
+ {
+ stream = new AliMUONRawStreamTrigger(reader);
+ }
+
+ UChar_t id;
+ UChar_t dec;
+ Bool_t trigY;
+ UChar_t yPos;
+ UChar_t sXDev;
+ UChar_t xDev;
+ UChar_t xPos;
+ Bool_t triggerY;
+ Bool_t triggerX;
+ TArrayS xPattern;
+ TArrayS yPattern;
+
+ while ( reader->NextEvent() )
+ {
+ stream->First();
+
+ while ( stream->Next(id, dec, trigY, yPos, sXDev, xDev, xPos,
+ triggerY, triggerX, xPattern, yPattern) )
+ {
+ id *= 2;
+ }
+ }
+
+ delete stream;
+ delete reader;
+}
+
+
+void MUONTimeRawStreamTriggerDumb(TString fileName)
+{
+ AliCodeTimer::Instance()->Reset();
+
+ // first check we can open the stream
+ AliRawReader* reader = AliRawReader::Create(fileName.Data());
+ if (!reader)
+ {
+ cerr << "Cannot create reader from " << fileName.Data() << endl;
+ return;
+ }
+ delete reader;
+
+ // now start the timing per se
+
+ Loop(fileName,kFALSE);
+
+ Loop(fileName,kTRUE);
+
+ AliCodeTimer::Instance()->Print();
+}
+
+
+void MUONTimeRawStreamTrigger(TString fileName = "./", Int_t maxEvent = 1000)
+{
+ /// Performs a timing of old and new decoders and reports this.
+
+ AliBufferInfo* list = NULL;
+ UInt_t bufferCount = LoadFiles(list, fileName, maxEvent);
+ if (bufferCount == 0)
+ {
+ cerr << "ERROR: No DDL files found or read in." << endl;
+ return;
+ }
+
+ UInt_t maxBufferSize = CountMaxStructs(list);
+ AliLocalStructInfo* buffer = new AliLocalStructInfo[maxBufferSize];
+ if (buffer == NULL)
+ {
+ ReleaseBuffers(list);
+ cerr << "ERROR: Out of memory, sorry. You should limit the number of events read in." << endl;
+ return;
+ }
+ Double_t oldTimes[100];
+ for (Int_t i = 0; i < 100; i++)
+ {
+ cout << "Timing old decoder: timing iteration " << i+1 << " of 100" << endl;
+ oldTimes[i] = TimeUsingOldDecoder(list, buffer, maxBufferSize);
+ }
+ Double_t newTimes[100];
+ for (Int_t i = 0; i < 100; i++)
+ {
+ cout << "Timing new decoder: timing iteration " << i+1 << " of 100" << endl;
+ newTimes[i] = TimeUsingNewDecoder(list, buffer, maxBufferSize);
+ }
+ Double_t newTimes2[100];
+ for (Int_t i = 0; i < 100; i++)
+ {
+ cout << "Timing new decoder with old interface: timing iteration " << i+1 << " of 100" << endl;
+ newTimes2[i] = TimeUsingNewDecoderOldInterface(list, buffer, maxBufferSize);
+ }
+
+ ReleaseBuffers(list);
+ delete buffer;
+
+ Double_t oldTime = TMath::Mean(100, oldTimes) / Double_t(bufferCount);
+ Double_t oldTimeErr = TMath::RMS(100, oldTimes) / Double_t(bufferCount);
+ Double_t newTime = TMath::Mean(100, newTimes) / Double_t(bufferCount);
+ Double_t newTimeErr = TMath::RMS(100, newTimes) / Double_t(bufferCount);
+ Double_t newTime2 = TMath::Mean(100, newTimes2) / Double_t(bufferCount);
+ Double_t newTime2Err = TMath::RMS(100, newTimes2) / Double_t(bufferCount);
+
+ cout << "Average processing time per DDL for:" << endl;
+ cout << " Old decoder = " << oldTime*1e6 << " +/- " << oldTimeErr*1e6/TMath::Sqrt(100) << " micro seconds" << endl;
+ cout << " New decoder = " << newTime*1e6 << " +/- " << newTimeErr*1e6/TMath::Sqrt(100) << " micro seconds" << endl;
+ cout << "New decoder with old interface = " << newTime2*1e6 << " +/- " << newTime2Err*1e6/TMath::Sqrt(100) << " micro seconds" << endl;
+}
+
#pragma link C++ class AliMUONRawStreamTrackerHP::AliBlockHeader+;
#pragma link C++ class AliMUONRawStreamTrackerHP::AliDspHeader+;
#pragma link C++ class AliMUONRawStreamTrackerHP::AliBusPatch+;
+#pragma link C++ class AliMUONVRawStreamTrigger+;
#pragma link C++ class AliMUONRawStreamTrigger+;
+#pragma link C++ class AliMUONRawStreamTriggerHP+;
+#pragma link C++ class AliMUONRawStreamTriggerHP::AliHeader+;
+#pragma link C++ class AliMUONRawStreamTriggerHP::AliRegionalHeader+;
+#pragma link C++ class AliMUONRawStreamTriggerHP::AliLocalStruct+;
#pragma link C++ class AliMUONRawStream+;
#endif
AliMUONBusStruct.cxx \
AliMUONPayloadTracker.cxx \
AliMUONVRawStreamTracker.cxx \
+ AliMUONVRawStreamTrigger.cxx \
AliMUONRawStreamTracker.cxx \
AliMUONRawStreamTrackerHP.cxx \
AliMUONRawStreamTrigger.cxx \
+ AliMUONRawStreamTriggerHP.cxx \
AliMUONRawStream.cxx
HDRS:= $(SRCS:.cxx=.h)