X-Git-Url: http://git.uio.no/git/?a=blobdiff_plain;f=RAW%2FAliAltroDecoder.cxx;h=f6c9e65832ac7b2fd8a17cdeb3885895aa610b66;hb=56918e2f25bc0d2137afd6f4487c43f20c3adf04;hp=8ddf26406169604a74523440f77071b22d6136b9;hpb=ac672c4c0df3eac8fe55eeb69327c647b2709097;p=u%2Fmrichter%2FAliRoot.git diff --git a/RAW/AliAltroDecoder.cxx b/RAW/AliAltroDecoder.cxx index 8ddf2640616..f6c9e65832a 100644 --- a/RAW/AliAltroDecoder.cxx +++ b/RAW/AliAltroDecoder.cxx @@ -1,9 +1,11 @@ +// $Id$ + /************************************************************************** * This file is property of and copyright by the ALICE HLT Project * * All rights reserved. * * * * Primary Authors: Per Thomas Hille * - * Øystein Djuvsland * + * Oystein Djuvsland * * * * Permission to use, copy, modify and distribute this software and its * * documentation strictly for non-commercial purposes is hereby granted * @@ -14,20 +16,29 @@ * provided "as is" without express or implied warranty. * **************************************************************************/ +/** + @file AliAltroDocoder.cxx + @author Per Thomas Hille, Oystein Djuvsland + @date + @brief High performance decoder class for the RCU/Altro data format +*/ + +#include #include #include "AliAltroDecoder.h" #include "AliAltroData.h" +#include "AliLog.h" // Class for fast decoding of RCU/Altro raw data format (DDL format) // to PC readable form. The decoding is done in 3 steps. -// 1) The RCU payload consistist of a variable number of 160 bit words -// denoted a DDL block. All the DDL blocks of an RCU payload is transformed -// to 16 integers wich is then put into a buffer of integers big enought to contain the +// 1) The RCU payload consist of a variable number of 160 bit words +// denoted a DDL block. All the DDL blocks of an RCU payload are transformed +// into 16 bit integers and stored into a buffer of integers big enought to contain the // biggest number of samples possible // 2) The decoded buffer is then accesible for the NextChannel functions wich reads // the altro channel data (samples) contained in the payload. The first call to NextChannel gives the -// last altro channel of the back linked list, the next call the second last channel ..etc untill -// all channles are read. +// last altro channel of the back linked list, the next call the second last channel ..etc until +// all channels are read. // 3) (optional) For each Altro channel one chan invoke the member function NextBunch which gives on first call // The last bunch (the bunch with the highest timestamp), on next call the second last bunch..etc // untill all bunches are read @@ -42,7 +53,7 @@ AliAltroDecoder::AliAltroDecoder() : f32DtaPtr(0), fN40RcuAltroWords(0), fNDDLBlocks(0), f32LastDDLBlockSize(5), - f32PayloadSize(0), + f8PayloadSize(0), fOutBufferIndex(0), fSize(0), fNAltro10bitWords(0), @@ -50,7 +61,8 @@ AliAltroDecoder::AliAltroDecoder() : f32DtaPtr(0), fInComplete(0), fDecodeIfCorruptedTrailer(kTRUE), fIsDecoded(kFALSE), - fIsFatalCorruptedTrailer(kTRUE) + fIsFatalCorruptedTrailer(kTRUE) + // fIsFirstChannelOfPayload(kTRUE) { // Default constructor } @@ -64,7 +76,7 @@ AliAltroDecoder::~AliAltroDecoder() Bool_t AliAltroDecoder::CheckPayloadTrailer() const { - //Check wether or not there is consistency between the number of 40 bit altro words given by + //Check consistency between the number of 40 bit altro words given by //the RCU payload and the number of 40 bit words calculated from the size of the RCU payload. if(fN40AltroWords != fN40RcuAltroWords) @@ -80,16 +92,23 @@ Bool_t AliAltroDecoder::CheckPayloadTrailer() const Bool_t AliAltroDecoder::Decode() { - // Decodes the RCU payload (all altro channels in one go) from the DDL format to - // PC readable form + // Decodes the RCU payload (all altro channels in one go) from the DDL/Altro + // format to PC readable format. + // The 10 bit words of the 40/10 bit Altro format are transformed to separated + // integers. if( fIsFatalCorruptedTrailer == kTRUE) { - printf("\n AliAltroDecoder::Decode(), WARNING, attempt to decode badly corrupted data\n"); - printf("\n AliAltroDecoder::Decode(). Please check on the return value (-1 if fataly corrupted) of the SetMemory() function\n"); + // printf("\n AliAltroDecoder::Decode(), WARNING, attempt to decode badly corrupted data\n"); + // printf("\n AliAltroDecoder::Decode(). Please check on the return value (-1 if fataly corrupted) of the SetMemory() function\n"); + return kFALSE; + } + else if (!f8DtaPtr || !f32DtaPtr || + (UChar_t*)f32DtaPtr < f8DtaPtr-fSize || + (UChar_t*)f32DtaPtr > f8DtaPtr) + { return kFALSE; } - else { // see header file for class documentation @@ -113,7 +132,6 @@ Bool_t AliAltroDecoder::Decode() if( ((CheckPayloadTrailer() == kTRUE) || fDecodeIfCorruptedTrailer == kTRUE ) && (fSize > 32) ) { - // fDDLBlockCnt = 0; fOutBufferIndex = 0; for(Int_t i = 0; i < fNDDLBlocks; i++) @@ -123,19 +141,16 @@ Bool_t AliAltroDecoder::Decode() DecodeLastDDLBlock(); fOutBufferIndex = fN40AltroWords*4 - 1; - - // DumpData(fOutBuffer, 400,4); - fIsDecoded = kTRUE; return kTRUE; } else { - cout <<" ERROR: data integrity check failed, discarding data" << endl; - cout << "Size of datablock is " << fSize << endl; - cout << "fN40AltroWords = " << fN40AltroWords << endl; - cout << "fN40RcuAltroWords = " << fN40RcuAltroWords << endl; +// cout <<" ERROR: data integrity check failed, discarding data" << endl; +// cout << "Size of datablock is " << fSize << endl; +// cout << "fN40AltroWords = " << fN40AltroWords << endl; +// cout << "fN40RcuAltroWords = " << fN40RcuAltroWords << endl; return kFALSE; } @@ -143,17 +158,17 @@ Bool_t AliAltroDecoder::Decode() } + + Bool_t AliAltroDecoder::NextChannel(AliAltroData *altroDataPtr) { // Reads the next altro channel in the RCU payload after the RCU payload - // has been decoded. The channles are read strarting from the end (backlinked list) - // Returns kTRUE as long as ther are unread channles in the payload - // Returns kFALSE when all the channels has been read. + // has been decoded. The channels are read starting from the end (backlinked list) + // Returns kTRUE as long as ther are unread channels in the payload + // Returns kFALSE when all the channels have been read. if(fIsFatalCorruptedTrailer == kTRUE) { - printf("\n AliAltroDecoder::NextChannel(), WARNING, attempt to decode badly corrupted data\n"); - printf("\n AliAltroDecoder::NextChannel(), Please check on the return value (-1 if fataly corrupted) of the SetMemory() function\n"); return kFALSE; } @@ -162,13 +177,16 @@ Bool_t AliAltroDecoder::NextChannel(AliAltroData *altroDataPtr) if(fIsDecoded != kTRUE) { - cout <<"AliAltroDecoder::NextChanne, WARNING, buffer was not decoded, decoding now.. "<< endl; Decode(); } - if(fOutBufferIndex > fkN32HeaderWords) + // an altro block must constist of at least 2 40bit words: + // - 40bit Altro trailer + // - at least 3 10bit words (bunch length, time bin, signal) padded to 40 bit + // we are reading backwards, so the index is already 1 inside the block + if(fOutBufferIndex >= 7) { - if((fOutBuffer[fOutBufferIndex] << 4 ) | ((fOutBuffer[fOutBufferIndex-1] & 0x3c0) >> 6) == 0x2aaa) + if(((fOutBuffer[fOutBufferIndex] << 4 ) | ((fOutBuffer[fOutBufferIndex-1] & 0x3c0) >> 6)) == 0x2aaa) { altroDataPtr->SetIsComplete(kTRUE); fComplete ++; @@ -182,7 +200,7 @@ Bool_t AliAltroDecoder::NextChannel(AliAltroData *altroDataPtr) fOutBufferIndex --; fNAltro10bitWords = ( (fOutBuffer[fOutBufferIndex] & 0x3f) << 4 ) | ((fOutBuffer[fOutBufferIndex -1] & (0xF << 6)) >> 6) ; fOutBufferIndex --; - altroDataPtr->SetHadd( ((fOutBuffer[fOutBufferIndex] & 0x3)) << 10 | ( fOutBuffer[fOutBufferIndex-1] ) ); + altroDataPtr->SetHadd( ((fOutBuffer[fOutBufferIndex] & 0x3)) << 10 | ( fOutBuffer[fOutBufferIndex-1] ), fOutBufferIndex); fOutBufferIndex --; @@ -194,12 +212,19 @@ Bool_t AliAltroDecoder::NextChannel(AliAltroData *altroDataPtr) { fOutBufferIndex = fOutBufferIndex - fNAltro10bitWords -(4 - fNAltro10bitWords%4); } - - - altroDataPtr->SetData( &fOutBuffer[fOutBufferIndex] ); - fOutBufferIndex --; - altroDataPtr->SetDataSize( fNAltro10bitWords ); - return kTRUE; + + if(fOutBufferIndex >= 0) + { + altroDataPtr->SetData( &fOutBuffer[fOutBufferIndex] ); + fOutBufferIndex --; + altroDataPtr->SetDataSize( fNAltro10bitWords ); + return kTRUE; + } + else + { + //TODO write a fatal log message when this happends + return kFALSE; + } } else @@ -217,8 +242,13 @@ Int_t AliAltroDecoder::CountAAApaddings() const // Patch for incorrectly simulated data. Counts the number of // 2aaa word in the trailer of the payload and tries to figure out // the correct number of 40 bit altro words in the RCU pauload + // + // The simulated raw data differs from the real data by a number + // of additional 0x2aa words between the Altro payload and the + // RCU trailer. This is most likely to bring the total number of + // bytes to a common multiple of 4 and 5. - UShort_t *tailPtr= (UShort_t *)(f32DtaPtr +f32PayloadSize); + UShort_t *tailPtr= (UShort_t *)((UChar_t*)f32DtaPtr + f8PayloadSize); Int_t cnt = 0; tailPtr --; @@ -241,21 +271,22 @@ Float_t AliAltroDecoder::GetFailureRate() // is missing the 2aaa trailer. Float_t tmp = 0; - cout << "Number of Complete channles = " << fComplete <>16)==0xaaaa) { + haveFw2=true; + tmpTrailerSize = tmpTrailerSize&0x7f; // 7 LSBs of the last word + } else if(tmpTrailerSize <= MAX_TRAILER_WORDS) { tmpTrailerSize = tmpTrailerSize; //assume that the last word of the buffer gives the number of trailer words } - else + // nof 10bit AltroWords * 5/4 + bytes in the CDH + 4 bytes RCU trailer + else if (((*(f32DtaPtr-1)*5)/4 + fkN32HeaderWords*4 + 4)<=fSize) { tmpTrailerSize = 1; //assume that last word is ONE, and that the this word gives the number of 40 bit altro words } + else + { + tmpTrailerSize=0; + fIsFatalCorruptedTrailer = kTRUE; + iRet = -1; + } - f32PayloadSize = fSize/4 - (fkN32HeaderWords + tmpTrailerSize); - fN40AltroWords = (32*f32PayloadSize)/40; - fNDDLBlocks = f32PayloadSize/5; - f32LastDDLBlockSize = f32PayloadSize%DDL_32BLOCK_SIZE; - - if(tmpTrailerSize > 0 && tmpTrailerSize < 5) + if(tmpTrailerSize > 0 && (fkN32HeaderWords + tmpTrailerSize)*4<=fSize) { + f8PayloadSize = fSize - (fkN32HeaderWords + tmpTrailerSize)*4; + fN40AltroWords = f8PayloadSize/5; + fNDDLBlocks = fN40AltroWords/4; + f32LastDDLBlockSize = ((f8PayloadSize%(4*DDL_32BLOCK_SIZE))+3)/4; + f32DtaPtr = f32DtaPtr - tmpTrailerSize; fN40RcuAltroWords = *f32DtaPtr; f32DtaPtr = (UInt_t *)dtaPtr + fkN32HeaderWords; fIsFatalCorruptedTrailer = kFALSE; } - else - { - printf("\n AliAltroDecoder::SetMemory, ERROR\n, trailer is corrupted"); - fIsFatalCorruptedTrailer = kTRUE; - iRet = -1; - } - + + // all subsequent consistency checks depend on the correct initialization + // of the pointer and size variables + assert(f8DtaPtr == dtaPtr + fSize); return iRet; } @@ -364,12 +430,18 @@ void AliAltroDecoder::DecodeDDLBlock() } + + + + + + void AliAltroDecoder::DecodeLastDDLBlock() { // Decode one 160 bit DDL block into 16 integers. // In order to use the same decoding function (DecodeDDLBlock()) // a copy of the the last DDL block is made and - // if the las block does not align with 160 bits then it is padded with zeroes + // if the last block does not align with 160 bits then it is padded with zeroes for(Int_t i=0; i < f32LastDDLBlockSize; i++) { @@ -378,6 +450,133 @@ void AliAltroDecoder::DecodeLastDDLBlock() } f32DtaPtr = fDDLBlockDummy; - f32DtaPtr ++; DecodeDDLBlock(); + f32DtaPtr=(UInt_t*)(f8DtaPtr-fSize+f8PayloadSize+fkN32HeaderWords*4); +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Int_t AliAltroDecoder::CopyBackward(Byte_t* pBuffer, Int_t bufferSize) +{ + // Copy the original 10/40 bit encecoded data of the current channel. + // The funtions copies the data to the end of the provided buffer. + // @param pBuffer target buffer + // @param bufferSize size of target buffer + // @return number of copied bytes, neg. error code if failed + Int_t iCopy=0; + + if(fIsDecoded != kTRUE) { + AliWarning("buffer has not been decoded, no channel data available"); + return 0; + } + + // This method does not need to be the fastest possible implementation + // For the sake of stability, there are a lot of consistency checks. + + // the fOutBufferIndex always points to the next channel, since we are + // reading backwards, this is one byte before the start of the current + // channel. + Int_t currentIndex=fOutBufferIndex+1; + if (fNAltro10bitWords>0 && currentIndex < fN40AltroWords*4 ) { + + // calculate the position in the encoded data, beginning right + // after the CDH. 10 -> 8 bit: needs 5/4 times the index + Int_t position=(currentIndex*5)/4; + if (position*4==currentIndex*5) { + // no of 10 bit words is without the fill words to fill complete 40 bit words + // in addition, align to complete 40 bit words (the '+3') + iCopy=((fNAltro10bitWords+3)/4)*5; + + // calculate the source pointer in the encoded data + // f8DtaPtr was set to the end of the whole data buffer + // f32DtaPtr is behind the payload after decoding + Byte_t* pSrc=f8DtaPtr-fSize+(fkN32HeaderWords*4)+position; + if (pSrc+5<(Byte_t*)f32DtaPtr) { + + // check the first byte of the source buffer, has to be consistent + // with the 8 LSBs of the decoded 10 bit word at the beginning of + // the current channel + //assert(*pSrc==fOutBuffer[currentIndex]&0xff); + if (*pSrc==(fOutBuffer[currentIndex]&0xff)) { + + // try to verfify the length of the channel + UInt_t lenCheck=*(pSrc+iCopy+2)|(*(pSrc+iCopy+3)&0x3)<<8; + if (lenCheck==fNAltro10bitWords) { + + // copy including the 40 bit altro trailer + iCopy+=5; + if (iCopy<=bufferSize) { + + // copy to the end of the buffer + Byte_t* pTgt=pBuffer+bufferSize-iCopy; + memcpy(pTgt, pSrc, iCopy); + } else { + AliError(Form("target buffer too small: available %d, required %d", bufferSize, iCopy)); + iCopy=-1; + } + } else { + AliWarning(Form("format error: can not reproduce channel length: expected %d, read %d", fNAltro10bitWords, lenCheck)); + iCopy=-1; + } + } else { + AliError(Form("first byte of encoded data (%#x at %d) does not match decoded word (%#x at %d)", *pSrc, position, fOutBuffer[currentIndex]&0xff, currentIndex)); + iCopy=-1; + } + } else { + AliError(Form("buffer size missmatch: payload ends at %p, but current channel pretends to end at %p", f32DtaPtr, pSrc+5)); + iCopy=-1; + } + } else { + AliError(Form("current position does not match a byte: currentIndex=%d", currentIndex)); + iCopy=-1; + } + } + return iCopy; +} + +Bool_t AliAltroDecoder::GetRCUTrailerData(UChar_t*& data) const +{ + // Provide a pointer to RCU trailer. + // The type of the parameter might not be optimal, but the function has + // been chosen that way to be similar to the counterpart in + // AliAltroRawStream. + // @return kTRUE if trailer available; + if (!f8DtaPtr) return kFALSE; + data=f8DtaPtr-(fSize-(f8PayloadSize+fkN32HeaderWords*sizeof(UInt_t))); + assert((UChar_t*)f32DtaPtr == data); + return kTRUE; +} + +Int_t AliAltroDecoder::GetRCUTrailerSize() const +{ + // Provide size of RCU trailer. + if (!f8DtaPtr || !fIsDecoded || fSize==0) return 0; + assert(fSize>(f8PayloadSize+fkN32HeaderWords*sizeof(UInt_t))); + return fSize-(f8PayloadSize+fkN32HeaderWords*sizeof(UInt_t)); }