3 /**************************************************************************
4 * This file is property of and copyright by the ALICE HLT Project *
5 * ALICE Experiment at CERN, All rights reserved. *
7 * Primary Authors: Matthias Richter <Matthias.Richter@ift.uib.no> *
8 * for The ALICE HLT Project. *
10 * Permission to use, copy, modify and distribute this software and its *
11 * documentation strictly for non-commercial purposes is hereby granted *
12 * without fee, provided that the above copyright notice appears in all *
13 * copies and that both the copyright notice and this permission notice *
14 * appear in the supporting documentation. The authors make no claims *
15 * about the suitability of this software for any purpose. It is *
16 * provided "as is" without express or implied warranty. *
17 **************************************************************************/
19 /** @file testAliHLTAltroEncoder.C
20 @author Matthias Richter
22 @brief Test macro/program for the AliHLTAltroEncoder
32 #include "AliRawDataHeader.h"
33 #include "AliAltroDecoder.h"
34 #include "AliAltroData.h"
35 #include "AliAltroBunch.h"
36 #include "AliHLTAltroEncoder.h"
37 #include "AliHLTSystem.h"
42 const int sizeofAliRawDataHeader=sizeof(AliRawDataHeader);
44 // cint does not handle sizeof correctly
45 const int sizeofAliRawDataHeader=32;
48 /////////////////////////////////////////////////////////////////
49 /////////////////////////////////////////////////////////////////
50 /////////////////////////////////////////////////////////////////
52 // configuration of the test program
56 const bool bVerbose=false;
58 // the encoder can be used in two different modes: using
59 // AddSignal and terminating each channel by explicitely calling
60 // SetChannel, or the combined version AddChannelSignal
61 const bool bUseAddChannelSignal=true;
64 const int maxChannels=100;
65 const int maxBunches=50;
66 const int maxTimebin=1024;
67 const int maxSignal=1024;
68 const int maxEncodedDataSize=40000+sizeofAliRawDataHeader;
71 const char* encDataDumpFile=NULL;//"/tmp/altro-enc.dat";
72 const char* encodedDataFile="/tmp/altro-encoded.dat";
73 const char* simulatedDataFile="/tmp/altro-simulated.dat";
75 /////////////////////////////////////////////////////////////////
76 /////////////////////////////////////////////////////////////////
77 /////////////////////////////////////////////////////////////////
79 Bool_t seedSet=kFALSE;
82 * Get a random number in the given range.
84 int GetRandom(int min, int max)
86 if (max-min<2) return min;
90 rand.SetSeed(dt.Get());
93 return rand.Integer(max-min);
97 * Print the bunch information of a channel.
98 * The function goes recursively to the first bunch of the
99 * channel and prints this one first.
100 * @return number of 10bit words
102 int DumpBunchRecursive(int nofBunches, int* pData, int size)
104 if (!pData || size<2) return -1;
106 int bunchLength=pData[--pos];
107 int bunchEndTime=pData[--pos];
109 if (bunchLength<pos && nofBunches>1) {
110 read=DumpBunchRecursive(nofBunches-1, pData, pos-bunchLength);
112 cout << " bunch length " << bunchLength << ", end time " << bunchEndTime << ":";
114 for (int time=bunchEndTime; time>bunchEndTime-bunchLength; time--) {
117 cerr << "no data for bunch " << endl;
120 //cout << " " << pData[--pos];
123 if (read<0) return read;
124 return read+2+bunchLength;
128 * Write the encoded data to a file.
131 void DumpDataArray(T *array, const char* filename, int memberSize)
133 if (array->GetSize()==0) return;
135 ios::openmode filemode=(ios::openmode)0;
136 ofstream rawfile(filename, filemode);
137 if (rawfile.good()) {
138 rawfile.write(reinterpret_cast<const char*>(array->GetArray()), array->GetSize()*memberSize);
144 * Print the simulated data.
146 void PrintSimulatedData(TArrayI& data)
148 cout << endl << "****** readback *******" << endl << endl;
149 int dataPos=data.GetSize();
151 int channelAddress=data[--dataPos];
152 int nofBunches=data[--dataPos];
153 cout << " ------------------ new channel -------------------------" << endl;
155 int read=DumpBunchRecursive(nofBunches, data.GetArray(), dataPos);
159 cout << " channel " << channelAddress << ": number of bunches " << nofBunches << endl;
163 int Compare(TArrayI& simData, TArrayC& encData)
165 if (bVerbose) cout << endl << "****** compare *******" << endl << endl;
167 // can not have a static AltroDecoder, crash when function
168 // is called. I had a similar problem in the AliHLTAltroChannelSelectorComponent
171 AliAltroDecoder* decoder=new AliAltroDecoder;
172 if (iResult>=0 && decoder->SetMemory((UChar_t*)encData.GetArray(), (UInt_t)encData.GetSize())<0) {
173 cout << "error setting up decoder " << endl;
177 if (iResult>=0 && !decoder->Decode()) {
178 cout << "error decoding data" << endl;
182 AliAltroData altrochannel;
183 int dataPos=simData.GetSize();
184 while (iResult>=0 && decoder->NextChannel(&altrochannel)) {
185 int hwadd=altrochannel.GetHadd();
187 cout << "missmatch in simulated data" << endl;
191 int channelAddress=simData[--dataPos];
192 int nofBunches=simData[--dataPos];
193 if (channelAddress!=hwadd) {
194 cout << "channel address missmatch: simulated " << channelAddress << " encoded " << hwadd << endl;
199 if (bVerbose) cout << "comparing channel " << channelAddress << ", " << nofBunches << " bunche(s)" << endl;
201 AliAltroBunch altrobunch;
202 while (iResult>=0 && altrochannel.NextBunch(&altrobunch) && nofBunches-->0) {
204 cout << "error reading bunch size and time bin from simulated data" << endl;
208 int bunchLength=simData[--dataPos];
209 int bunchEndTime=simData[--dataPos];
210 if (bunchLength!=(int)altrobunch.GetBunchSize()) {
211 cout << "bunch length missmatch: simulated " << bunchLength << " encoded " << altrobunch.GetBunchSize() << hex << " (" << altrobunch.GetBunchSize() << ")" << dec << endl;
215 if (bunchEndTime!=(int)altrobunch.GetEndTimeBin()) {
216 cout << "bunch end time missmatch: simulated " << bunchEndTime << " encoded " << altrobunch.GetEndTimeBin() << endl;
220 if (bVerbose) cout << " bunch length " << bunchLength << ", end time " << bunchEndTime << endl;
221 const UInt_t* bunchData=altrobunch.GetData();
222 if (bunchLength>dataPos) {
223 cout << "error reading simulated bunch data, required "<< bunchLength << " available " << dataPos << endl;
227 Int_t* pSim=simData.GetArray();
228 for (int bin=0; bin<bunchLength; bin++) {
229 if ((int)bunchData[bin]!=pSim[dataPos-bunchLength+bin]) {
230 cout << "data missmatch at bunch position " << bin << " : simulated " << simData[dataPos] << " encoded " << bunchData[bin] << endl;
235 dataPos-=bunchLength;
244 void CompareDumpFiles()
246 TString param=encodedDataFile;
247 param+="?filetype=raw";
248 TFile encFile(param);
249 if (encFile.IsZombie()) {
250 cout << "can not open file " << encodedDataFile << endl;
254 TArrayC encData(encFile.GetSize());
255 if (encFile.ReadBuffer(encData.GetArray(), encData.GetSize())) {
256 cout << "error reading file " << encodedDataFile << endl;
260 param=simulatedDataFile;
261 param+="?filetype=raw";
262 TFile simFile(param);
263 if (simFile.IsZombie()) {
264 cout << "can not open file " << simulatedDataFile << endl;
268 TArrayI simData(simFile.GetSize()/4);
269 if (simFile.ReadBuffer((char*)simData.GetArray(), simData.GetSize()*4)) {
270 cout << "error reading file " << simulatedDataFile << endl;
274 Compare(simData, encData);
277 int testAliHLTAltroEncoder()
280 string ld_library_path="../.libs:";
281 ld_library_path+=gSystem->GetDynamicPath();
282 gSystem->SetDynamicPath(ld_library_path.c_str());
283 gSystem->Load("libAliHLTRCU.so");
287 int nofChannels=GetRandom(1, maxChannels);
288 if (nofChannels==0) nofChannels=1;
290 TArrayC encData(maxEncodedDataSize);
291 const int maxAltroDataSize=encData.GetSize()-sizeofAliRawDataHeader;
294 AliHLTAltroEncoder encoder;
295 encoder.SetBuffer((AliHLTUInt8_t*)encData.GetArray(), encData.GetSize());
297 // set the common data header
298 TArrayC dummyCdh(sizeofAliRawDataHeader);
299 encoder.SetCDH((AliHLTUInt8_t*)dummyCdh.GetArray(), dummyCdh.GetSize());
301 // set a trailer like in the real data format of the v1 RCU format (1 trailer word)
303 encoder.SetRCUTrailer((AliHLTUInt8_t*)&trailer, 4);
305 if (bVerbose) cout << "number of channels: " << nofChannels << endl;
306 int channelAddress=-1;
309 // The nof10BitWords value is aligned to 4. In addition, one
310 // 40bit word is needed for the channel trailer
311 for (int channel=0; channel<nofChannels && (((nof10BitWords/4)+2)*5)<maxAltroDataSize; channel++) {
312 channelAddress=GetRandom(0, 0xfff);
313 if (channelAddress==lastChannel) continue;
314 int nofBunches=GetRandom(1, maxBunches);
315 if (nofBunches==0) continue;
317 int bunchEndTime=maxTimebin;
319 if (bVerbose) cout << " ------------------ new channel -------------------------" << endl;
321 for (bunch=0; bunch<nofBunches && bunchEndTime>0; bunch++) {
322 bunchEndTime=GetRandom(0, bunchEndTime-1);
323 int bunchLength=GetRandom(0, bunchEndTime<10?bunchEndTime:10);
324 if (bunchLength==0) continue;
325 // check if there is enough space for all the signals, end time
326 // and bunch length. The value is aligned to 4. In addition, one
327 // 40bit word is needed for the channel trailer
328 if (((((nof10BitWords+bunchLength+2)/4)+2)*5)>=maxAltroDataSize) break;
331 if (bVerbose) cout << " bunch " << bunch << ", length " << bunchLength << ", end time " << bunchEndTime << ":";
333 if (simData.GetSize()<dataPos+bunchLength+2) simData.Set(dataPos+bunchLength+2);
334 for (int time=bunchEndTime-bunchLength+1; time<=bunchEndTime; time++) {
335 int signal=GetRandom(0, maxSignal);
336 simData[dataPos++]=signal;
337 if (bVerbose) cout << " " << signal;
339 if (bUseAddChannelSignal) {
340 added=encoder.AddChannelSignal(signal, time, channelAddress);
342 if (encoder.AddSignal(signal, time)<0) {
343 cout << "AddSignal failed" << endl;
346 lastChannel=channelAddress;
347 if (added>0) nof10BitWords+=added;
349 if (bVerbose) cout << endl;
350 simData[dataPos++]=bunchEndTime;
351 simData[dataPos++]=bunchLength;
353 if (simData.GetSize()<dataPos+2) simData.Set(dataPos+2);
354 if (totalBunches>0) {
355 simData[dataPos++]=totalBunches;
356 simData[dataPos++]=channelAddress;
359 if (!bUseAddChannelSignal && lastChannel>=0) {
360 encoder.SetChannel(lastChannel);
363 if (bVerbose) cout << " channel " << channelAddress << ": number of bunches " << totalBunches << endl;
367 int dataSize=encoder.SetLength();
369 cerr << "error finalizing encoded buffer" << endl;
372 int nof40bitWords=encoder.GetTotal40bitWords();
373 encData.Set(dataSize);
375 if (bVerbose) cout << "simulated data array:" << simData.GetSize() << " , ALTRO block length: " << nof40bitWords << " ALTRO words -> encoded data: " << encData.GetSize() << endl;
377 /////////////////////////////////////////////////////////
378 // some debugging options
380 if (encDataDumpFile) DumpDataArray(&encData, encDataDumpFile, 1);
382 simData.Set(dataPos);
383 if (bVerbose) PrintSimulatedData(simData);
385 /////////////////////////////////////////////////////////
386 // read back end compare the encoded data
388 if (simData.GetSize()>0 && Compare(simData, encData)<0) {
389 // dump files for further debugging
390 DumpDataArray(&encData, encodedDataFile, 1);
391 DumpDataArray(&simData, simulatedDataFile, 4);
394 if (bVerbose) cout << "check successfully completed: " << nof40bitWords << " ALTRO words" << endl;
400 int main(int /*argc*/, const char** /*argv*/)
402 // CompareDumpFiles();
407 for (int i=0; i<iCount; i++) {
408 if ((iResult=testAliHLTAltroEncoder())<0) {
409 cout << "missmatch in block no " << i << endl;
413 cout << "checking: " << iCount << " encoding cycle(s) successfully tested" << endl;