]> git.uio.no Git - u/mrichter/AliRoot.git/blame - HLT/RCU/test/testAliHLTAltroEncoder.C
minor update of documentation
[u/mrichter/AliRoot.git] / HLT / RCU / test / testAliHLTAltroEncoder.C
CommitLineData
768be5c3 1// $Id$
2
3/**************************************************************************
4 * This file is property of and copyright by the ALICE HLT Project *
5 * ALICE Experiment at CERN, All rights reserved. *
6 * *
7 * Primary Authors: Matthias Richter <Matthias.Richter@ift.uib.no> *
8 * for The ALICE HLT Project. *
9 * *
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 **************************************************************************/
18
c3800c65 19/** @file testAliHLTAltroEncoder.C
768be5c3 20 @author Matthias Richter
21 @date
22 @brief Test macro/program for the AliHLTAltroEncoder
23 */
24
25#ifndef __CINT__
26#include "TFile.h"
27#include "TDatime.h"
28#include "TRandom.h"
29#include "TArrayI.h"
30#include "TArrayC.h"
31#include "TSystem.h"
32#include "AliRawDataHeader.h"
33#include "AliAltroDecoder.h"
34#include "AliAltroData.h"
35#include "AliAltroBunch.h"
36#include "AliHLTAltroEncoder.h"
521766bd 37#include "AliHLTSystem.h"
768be5c3 38#include <ostream>
39#endif //__CINT__
40
41#ifndef __CINT__
42const int sizeofAliRawDataHeader=sizeof(AliRawDataHeader);
43#else
44// cint does not handle sizeof correctly
45const int sizeofAliRawDataHeader=32;
46#endif
47
48/////////////////////////////////////////////////////////////////
49/////////////////////////////////////////////////////////////////
50/////////////////////////////////////////////////////////////////
51//
52// configuration of the test program
53//
54
55// printouts or not
56const bool bVerbose=false;
57
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
61const bool bUseAddChannelSignal=true;
62
63// some defaults
64const int maxChannels=100;
65const int maxBunches=50;
66const int maxTimebin=1024;
67const int maxSignal=1024;
b0714bad 68const int maxEncodedDataSize=4000000+sizeofAliRawDataHeader;
768be5c3 69
70// file dumps
71const char* encDataDumpFile=NULL;//"/tmp/altro-enc.dat";
72const char* encodedDataFile="/tmp/altro-encoded.dat";
73const char* simulatedDataFile="/tmp/altro-simulated.dat";
74
75/////////////////////////////////////////////////////////////////
76/////////////////////////////////////////////////////////////////
77/////////////////////////////////////////////////////////////////
78
79Bool_t seedSet=kFALSE;
80
81/**
82 * Get a random number in the given range.
83 */
84int GetRandom(int min, int max)
85{
86 if (max-min<2) return min;
87 static TRandom rand;
88 if (!seedSet) {
89 TDatime dt;
90 rand.SetSeed(dt.Get());
91 seedSet=kTRUE;
92 }
93 return rand.Integer(max-min);
94}
95
96/**
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
101 */
102int DumpBunchRecursive(int nofBunches, int* pData, int size)
103{
104 if (!pData || size<2) return -1;
105 int pos=size;
106 int bunchLength=pData[--pos];
107 int bunchEndTime=pData[--pos];
108 int read=0;
109 if (bunchLength<pos && nofBunches>1) {
110 read=DumpBunchRecursive(nofBunches-1, pData, pos-bunchLength);
111 }
112 cout << " bunch length " << bunchLength << ", end time " << bunchEndTime << ":";
113
114 for (int time=bunchEndTime; time>bunchEndTime-bunchLength; time--) {
115 if (pos<1) {
116 pos=0;
117 cerr << "no data for bunch " << endl;
118 return -1;
119 }
120 //cout << " " << pData[--pos];
121 }
122 cout << endl;
123 if (read<0) return read;
124 return read+2+bunchLength;
125}
126
127/**
128 * Write the encoded data to a file.
129 */
130template<typename T>
131void DumpDataArray(T *array, const char* filename, int memberSize)
132{
133 if (array->GetSize()==0) return;
134
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);
139 }
140 rawfile.close();
141}
142
143/**
144 * Print the simulated data.
145 */
146void PrintSimulatedData(TArrayI& data)
147{
148 cout << endl << "****** readback *******" << endl << endl;
149 int dataPos=data.GetSize();
150 while (dataPos>0) {
151 int channelAddress=data[--dataPos];
152 int nofBunches=data[--dataPos];
153 cout << " ------------------ new channel -------------------------" << endl;
154 if (nofBunches>0) {
155 int read=DumpBunchRecursive(nofBunches, data.GetArray(), dataPos);
156 if (read<0) return;
157 dataPos-=read;
158 }
159 cout << " channel " << channelAddress << ": number of bunches " << nofBunches << endl;
160 }
161}
162
163int Compare(TArrayI& simData, TArrayC& encData)
164{
165 if (bVerbose) cout << endl << "****** compare *******" << endl << endl;
166
167 // can not have a static AltroDecoder, crash when function
168 // is called. I had a similar problem in the AliHLTAltroChannelSelectorComponent
169
170 int iResult=0;
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;
174 iResult=-1;
175 }
176
177 if (iResult>=0 && !decoder->Decode()) {
178 cout << "error decoding data" << endl;
179 iResult=-1;
180 }
181
182 AliAltroData altrochannel;
183 int dataPos=simData.GetSize();
184 while (iResult>=0 && decoder->NextChannel(&altrochannel)) {
185 int hwadd=altrochannel.GetHadd();
186 if (dataPos<2) {
187 cout << "missmatch in simulated data" << endl;
188 iResult=-1;
189 break;
190 }
191 int channelAddress=simData[--dataPos];
192 int nofBunches=simData[--dataPos];
b0714bad 193 int nofBunchesBackup=nofBunches;
768be5c3 194 if (channelAddress!=hwadd) {
195 cout << "channel address missmatch: simulated " << channelAddress << " encoded " << hwadd << endl;
196 iResult=-1;
197 break;
198 }
199
200 if (bVerbose) cout << "comparing channel " << channelAddress << ", " << nofBunches << " bunche(s)" << endl;
201
202 AliAltroBunch altrobunch;
203 while (iResult>=0 && altrochannel.NextBunch(&altrobunch) && nofBunches-->0) {
204 if (dataPos<2) {
205 cout << "error reading bunch size and time bin from simulated data" << endl;
206 iResult=-1;
207 break;
208 }
209 int bunchLength=simData[--dataPos];
210 int bunchEndTime=simData[--dataPos];
211 if (bunchLength!=(int)altrobunch.GetBunchSize()) {
212 cout << "bunch length missmatch: simulated " << bunchLength << " encoded " << altrobunch.GetBunchSize() << hex << " (" << altrobunch.GetBunchSize() << ")" << dec << endl;
213 iResult=-1;
214 break;
215 }
216 if (bunchEndTime!=(int)altrobunch.GetEndTimeBin()) {
217 cout << "bunch end time missmatch: simulated " << bunchEndTime << " encoded " << altrobunch.GetEndTimeBin() << endl;
218 iResult=-1;
219 break;
220 }
221 if (bVerbose) cout << " bunch length " << bunchLength << ", end time " << bunchEndTime << endl;
222 const UInt_t* bunchData=altrobunch.GetData();
223 if (bunchLength>dataPos) {
224 cout << "error reading simulated bunch data, required "<< bunchLength << " available " << dataPos << endl;
225 iResult=-1;
226 break;
227 }
228 Int_t* pSim=simData.GetArray();
229 for (int bin=0; bin<bunchLength; bin++) {
230 if ((int)bunchData[bin]!=pSim[dataPos-bunchLength+bin]) {
231 cout << "data missmatch at bunch position " << bin << " : simulated " << simData[dataPos] << " encoded " << bunchData[bin] << endl;
232 iResult=-1;
233 break;
234 }
235 }
236 dataPos-=bunchLength;
237 }
b0714bad 238 if (nofBunches>0 && iResult==0) {
239 cout << "error getting " << nofBunches << " of " << nofBunchesBackup << " bunches from channel " << channelAddress << endl;
240 iResult=-1;
241 }
768be5c3 242
243 }
244
245 delete decoder;
246 return iResult;
247}
248
249void CompareDumpFiles()
250{
251 TString param=encodedDataFile;
252 param+="?filetype=raw";
253 TFile encFile(param);
254 if (encFile.IsZombie()) {
255 cout << "can not open file " << encodedDataFile << endl;
256 return;
257 }
258
259 TArrayC encData(encFile.GetSize());
260 if (encFile.ReadBuffer(encData.GetArray(), encData.GetSize())) {
261 cout << "error reading file " << encodedDataFile << endl;
262 return;
263 }
264
265 param=simulatedDataFile;
266 param+="?filetype=raw";
267 TFile simFile(param);
268 if (simFile.IsZombie()) {
269 cout << "can not open file " << simulatedDataFile << endl;
270 return;
271 }
272
273 TArrayI simData(simFile.GetSize()/4);
274 if (simFile.ReadBuffer((char*)simData.GetArray(), simData.GetSize()*4)) {
275 cout << "error reading file " << simulatedDataFile << endl;
276 return;
277 }
278
279 Compare(simData, encData);
280}
281
c3800c65 282int testAliHLTAltroEncoder()
768be5c3 283{
521766bd 284#ifdef __CINT__
8bc1d5fb 285 string ld_library_path="../.libs:";
286 ld_library_path+=gSystem->GetDynamicPath();
287 gSystem->SetDynamicPath(ld_library_path.c_str());
521766bd 288 gSystem->Load("libAliHLTRCU.so");
289#endif
290 AliHLTSystem gHLT;
291
768be5c3 292 int nofChannels=GetRandom(1, maxChannels);
293 if (nofChannels==0) nofChannels=1;
294 TArrayI simData;
295 TArrayC encData(maxEncodedDataSize);
296 const int maxAltroDataSize=encData.GetSize()-sizeofAliRawDataHeader;
297 int dataPos=0;
298
768be5c3 299 AliHLTAltroEncoder encoder;
4a7578f5 300 encoder.SetBuffer((AliHLTUInt8_t*)encData.GetArray(), encData.GetSize());
301
302 // set the common data header
303 TArrayC dummyCdh(sizeofAliRawDataHeader);
304 encoder.SetCDH((AliHLTUInt8_t*)dummyCdh.GetArray(), dummyCdh.GetSize());
305
306 // set a trailer like in the real data format of the v1 RCU format (1 trailer word)
307 Int_t trailer=0;
308 encoder.SetRCUTrailer((AliHLTUInt8_t*)&trailer, 4);
768be5c3 309
310 if (bVerbose) cout << "number of channels: " << nofChannels << endl;
311 int channelAddress=-1;
312 int lastChannel=-1;
313 int nof10BitWords=0;
314 // The nof10BitWords value is aligned to 4. In addition, one
315 // 40bit word is needed for the channel trailer
316 for (int channel=0; channel<nofChannels && (((nof10BitWords/4)+2)*5)<maxAltroDataSize; channel++) {
317 channelAddress=GetRandom(0, 0xfff);
318 if (channelAddress==lastChannel) continue;
319 int nofBunches=GetRandom(1, maxBunches);
320 if (nofBunches==0) continue;
321 int totalBunches=0;
b0714bad 322 int bunchEndTime=0;
323 int lastBunchEndTime=0;
768be5c3 324
325 if (bVerbose) cout << " ------------------ new channel -------------------------" << endl;
326 int bunch=0;
b0714bad 327
328 // Matthias Oct 2008:
329 // Data was simulated in the wrong order: bunches for the higher timebins
330 // first. But real data is the other way round: bunches are written in the order
331 // of ascending timebins. A new consistency check was added to AliAltroDecoder
332 // (AliAltroBunch) in revision 29090. Now the channels are checked for overlapping
333 // bunches, the time of a bunch must be smaller than time of the previous one
334 // minus its length.
335 // Data is now simulated in the right order in order to fullfil this check.
336 for (bunch=0; bunch<nofBunches && bunchEndTime<maxTimebin-3; bunch++) {
337 while ((bunchEndTime+=GetRandom(0, maxTimebin-bunchEndTime))-lastBunchEndTime<3);
338 int bunchLength=GetRandom(0, bunchEndTime-lastBunchEndTime);
768be5c3 339 if (bunchLength==0) continue;
340 // check if there is enough space for all the signals, end time
341 // and bunch length. The value is aligned to 4. In addition, one
342 // 40bit word is needed for the channel trailer
343 if (((((nof10BitWords+bunchLength+2)/4)+2)*5)>=maxAltroDataSize) break;
344 totalBunches++;
345
346 if (bVerbose) cout << " bunch " << bunch << ", length " << bunchLength << ", end time " << bunchEndTime << ":";
347
348 if (simData.GetSize()<dataPos+bunchLength+2) simData.Set(dataPos+bunchLength+2);
349 for (int time=bunchEndTime-bunchLength+1; time<=bunchEndTime; time++) {
350 int signal=GetRandom(0, maxSignal);
351 simData[dataPos++]=signal;
352 if (bVerbose) cout << " " << signal;
353 int added=1;
354 if (bUseAddChannelSignal) {
355 added=encoder.AddChannelSignal(signal, time, channelAddress);
356 } else {
357 if (encoder.AddSignal(signal, time)<0) {
358 cout << "AddSignal failed" << endl;
359 }
360 }
361 lastChannel=channelAddress;
362 if (added>0) nof10BitWords+=added;
363 }
364 if (bVerbose) cout << endl;
365 simData[dataPos++]=bunchEndTime;
366 simData[dataPos++]=bunchLength;
b0714bad 367 lastBunchEndTime=bunchEndTime;
368 bunchEndTime+=bunchLength;
768be5c3 369 }
370 if (simData.GetSize()<dataPos+2) simData.Set(dataPos+2);
371 if (totalBunches>0) {
372 simData[dataPos++]=totalBunches;
373 simData[dataPos++]=channelAddress;
374 }
375
376 if (!bUseAddChannelSignal && lastChannel>=0) {
377 encoder.SetChannel(lastChannel);
378 }
379
380 if (bVerbose) cout << " channel " << channelAddress << ": number of bunches " << totalBunches << endl;
381
382 }
768be5c3 383
4a7578f5 384 int dataSize=encoder.SetLength();
385 if (dataSize<0) {
386 cerr << "error finalizing encoded buffer" << endl;
387 return -1;
388 }
768be5c3 389 int nof40bitWords=encoder.GetTotal40bitWords();
4a7578f5 390 encData.Set(dataSize);
768be5c3 391
392 if (bVerbose) cout << "simulated data array:" << simData.GetSize() << " , ALTRO block length: " << nof40bitWords << " ALTRO words -> encoded data: " << encData.GetSize() << endl;
393
394 /////////////////////////////////////////////////////////
395 // some debugging options
396
397 if (encDataDumpFile) DumpDataArray(&encData, encDataDumpFile, 1);
398
399 simData.Set(dataPos);
400 if (bVerbose) PrintSimulatedData(simData);
401
402 /////////////////////////////////////////////////////////
403 // read back end compare the encoded data
404
405 if (simData.GetSize()>0 && Compare(simData, encData)<0) {
406 // dump files for further debugging
407 DumpDataArray(&encData, encodedDataFile, 1);
408 DumpDataArray(&simData, simulatedDataFile, 4);
409 return -1;
410 } else {
411 if (bVerbose) cout << "check successfully completed: " << nof40bitWords << " ALTRO words" << endl;
412 }
413
414 return 0;
415}
416
4a7578f5 417int main(int /*argc*/, const char** /*argv*/)
768be5c3 418{
419// CompareDumpFiles();
420// return 0;
421
422 int iResult=0;
b0714bad 423 int iCount=1000;
768be5c3 424 for (int i=0; i<iCount; i++) {
c3800c65 425 if ((iResult=testAliHLTAltroEncoder())<0) {
768be5c3 426 cout << "missmatch in block no " << i << endl;
427 return iResult;
428 }
429 }
c3800c65 430 cout << "checking: " << iCount << " encoding cycle(s) successfully tested" << endl;
768be5c3 431 return 0;
432}