]> git.uio.no Git - u/mrichter/AliRoot.git/blob - HLT/RCU/test/testAliHLTAltroEncoder.C
bugfixes in HLT build system: /prog/versions_AliRoot/AliRoot_HEAD_2008-07-17/PHOS...
[u/mrichter/AliRoot.git] / HLT / RCU / test / testAliHLTAltroEncoder.C
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
19 /** @file   testAliHLTAltroEncoder.C
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"
37 #include "AliHLTSystem.h"
38 #include <ostream>
39 #endif //__CINT__
40
41 #ifndef __CINT__
42 const int sizeofAliRawDataHeader=sizeof(AliRawDataHeader);
43 #else
44 // cint does not handle sizeof correctly
45 const int sizeofAliRawDataHeader=32;
46 #endif
47
48 /////////////////////////////////////////////////////////////////
49 /////////////////////////////////////////////////////////////////
50 /////////////////////////////////////////////////////////////////
51 //
52 // configuration of the test program
53 //
54
55 // printouts or not
56 const 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
61 const bool bUseAddChannelSignal=true;
62
63 // some defaults
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;
69
70 // file dumps
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";
74
75 /////////////////////////////////////////////////////////////////
76 /////////////////////////////////////////////////////////////////
77 /////////////////////////////////////////////////////////////////
78
79 Bool_t seedSet=kFALSE;
80
81 /**
82  * Get a random number in the given range.
83  */
84 int 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  */
102 int 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  */
130 template<typename T> 
131 void 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  */
146 void 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
163 int 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];
193     if (channelAddress!=hwadd) {
194       cout << "channel address missmatch: simulated " << channelAddress << " encoded " << hwadd << endl;
195       iResult=-1;
196       break;
197     }
198
199     if (bVerbose) cout << "comparing channel " << channelAddress << ", " << nofBunches << " bunche(s)" << endl;
200
201     AliAltroBunch altrobunch;
202     while (iResult>=0 && altrochannel.NextBunch(&altrobunch) && nofBunches-->0) {
203       if (dataPos<2) {
204         cout << "error reading bunch size and time bin from simulated data" << endl;
205         iResult=-1;
206         break;
207       }
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;
212         iResult=-1;
213         break;
214       }
215       if (bunchEndTime!=(int)altrobunch.GetEndTimeBin()) {
216         cout << "bunch end time missmatch: simulated " << bunchEndTime << " encoded " << altrobunch.GetEndTimeBin() << endl;
217         iResult=-1;
218         break;
219       }
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;
224         iResult=-1;
225         break;
226       }
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;
231           iResult=-1;
232           break;
233         }
234       }
235       dataPos-=bunchLength;
236     }
237
238   }
239
240   delete decoder;
241   return iResult;
242 }
243
244 void CompareDumpFiles()
245 {
246   TString param=encodedDataFile;
247   param+="?filetype=raw";
248   TFile encFile(param);
249   if (encFile.IsZombie()) {
250     cout << "can not open file " << encodedDataFile << endl;
251     return;
252   }
253
254   TArrayC encData(encFile.GetSize());
255   if (encFile.ReadBuffer(encData.GetArray(), encData.GetSize())) {
256     cout << "error reading file " << encodedDataFile << endl;
257     return;
258   }  
259
260   param=simulatedDataFile;
261   param+="?filetype=raw";
262   TFile simFile(param);
263   if (simFile.IsZombie()) {
264     cout << "can not open file " << simulatedDataFile << endl;
265     return;
266   }
267
268   TArrayI simData(simFile.GetSize()/4);
269   if (simFile.ReadBuffer((char*)simData.GetArray(), simData.GetSize()*4)) {
270     cout << "error reading file " << simulatedDataFile << endl;
271     return;
272   }
273
274   Compare(simData, encData);
275 }
276
277 int testAliHLTAltroEncoder()
278 {
279 #ifdef __CINT__
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");
284 #endif
285   AliHLTSystem gHLT;
286
287   int nofChannels=GetRandom(1, maxChannels);
288   if (nofChannels==0) nofChannels=1;
289   TArrayI simData;
290   TArrayC encData(maxEncodedDataSize);
291   const int maxAltroDataSize=encData.GetSize()-sizeofAliRawDataHeader;
292   int dataPos=0;
293
294   AliHLTAltroEncoder encoder;
295   encoder.SetBuffer((AliHLTUInt8_t*)encData.GetArray(), encData.GetSize());
296
297   // set the common data header
298   TArrayC dummyCdh(sizeofAliRawDataHeader);
299   encoder.SetCDH((AliHLTUInt8_t*)dummyCdh.GetArray(), dummyCdh.GetSize());
300
301   // set a trailer like in the real data format of the v1 RCU format (1 trailer word)
302   Int_t trailer=0;
303   encoder.SetRCUTrailer((AliHLTUInt8_t*)&trailer, 4);
304
305   if (bVerbose) cout << "number of channels: " << nofChannels << endl;
306   int channelAddress=-1;
307   int lastChannel=-1;
308   int nof10BitWords=0;
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;
316     int totalBunches=0;
317     int bunchEndTime=maxTimebin;
318     
319     if (bVerbose) cout << " ------------------ new channel -------------------------" << endl;
320     int bunch=0;
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;
329       totalBunches++;
330
331       if (bVerbose) cout << "       bunch " << bunch << ", length " << bunchLength << ", end time " << bunchEndTime << ":";
332
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;
338         int added=1;
339         if (bUseAddChannelSignal) {
340           added=encoder.AddChannelSignal(signal, time, channelAddress);
341         } else {
342           if (encoder.AddSignal(signal, time)<0) {
343             cout << "AddSignal failed" << endl;
344           }
345         }
346         lastChannel=channelAddress;
347         if (added>0) nof10BitWords+=added;
348       }
349       if (bVerbose) cout << endl;
350       simData[dataPos++]=bunchEndTime;
351       simData[dataPos++]=bunchLength;
352     }
353     if (simData.GetSize()<dataPos+2) simData.Set(dataPos+2);
354     if (totalBunches>0) {
355       simData[dataPos++]=totalBunches;
356       simData[dataPos++]=channelAddress;
357     }
358
359     if (!bUseAddChannelSignal && lastChannel>=0) {
360       encoder.SetChannel(lastChannel);
361     }
362
363     if (bVerbose) cout << " channel " << channelAddress << ":  number of bunches " << totalBunches << endl;
364
365   }
366
367   int dataSize=encoder.SetLength();
368   if (dataSize<0) {
369     cerr << "error finalizing encoded buffer" << endl;
370     return -1;
371   }
372   int nof40bitWords=encoder.GetTotal40bitWords();
373   encData.Set(dataSize);
374
375   if (bVerbose) cout << "simulated data array:" << simData.GetSize() << " , ALTRO block length: " << nof40bitWords << " ALTRO words -> encoded data: " << encData.GetSize() << endl;
376
377   /////////////////////////////////////////////////////////
378   // some debugging options
379
380   if (encDataDumpFile) DumpDataArray(&encData, encDataDumpFile, 1);
381
382   simData.Set(dataPos);
383   if (bVerbose) PrintSimulatedData(simData);
384
385   /////////////////////////////////////////////////////////
386   // read back end compare the encoded data
387
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);
392     return -1;
393   } else {
394     if (bVerbose) cout << "check successfully completed: " << nof40bitWords << " ALTRO words" << endl;
395   }
396
397   return 0;
398 }
399
400 int main(int /*argc*/, const char** /*argv*/)
401 {
402 //   CompareDumpFiles();
403 //   return 0;
404
405   int iResult=0;
406   int iCount=10000;
407   for (int i=0; i<iCount; i++) {
408     if ((iResult=testAliHLTAltroEncoder())<0) {
409       cout << "missmatch in block no " << i << endl;
410       return iResult;
411     }
412   }
413   cout << "checking: " << iCount << " encoding cycle(s) successfully tested" << endl;
414   return 0;
415 }