fd6df3dd2440b6f73c9e6d6c05a77b101c66ec25
[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   altro-encoder.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 <ostream>
38 #endif //__CINT__
39
40 #ifndef __CINT__
41 const int sizeofAliRawDataHeader=sizeof(AliRawDataHeader);
42 #else
43 // cint does not handle sizeof correctly
44 const int sizeofAliRawDataHeader=32;
45 #endif
46
47 /////////////////////////////////////////////////////////////////
48 /////////////////////////////////////////////////////////////////
49 /////////////////////////////////////////////////////////////////
50 //
51 // configuration of the test program
52 //
53
54 // printouts or not
55 const bool bVerbose=false;
56
57 // the encoder can be used in two different modes: using
58 // AddSignal and terminating each channel by explicitely calling
59 // SetChannel, or the combined version AddChannelSignal
60 const bool bUseAddChannelSignal=true;
61
62 // some defaults
63 const int maxChannels=100;
64 const int maxBunches=50;
65 const int maxTimebin=1024;
66 const int maxSignal=1024;
67 const int maxEncodedDataSize=40000+sizeofAliRawDataHeader;
68
69 // file dumps
70 const char* encDataDumpFile=NULL;//"/tmp/altro-enc.dat";
71 const char* encodedDataFile="/tmp/altro-encoded.dat";
72 const char* simulatedDataFile="/tmp/altro-simulated.dat";
73
74 /////////////////////////////////////////////////////////////////
75 /////////////////////////////////////////////////////////////////
76 /////////////////////////////////////////////////////////////////
77
78 Bool_t seedSet=kFALSE;
79
80 /**
81  * Get a random number in the given range.
82  */
83 int GetRandom(int min, int max)
84 {
85   if (max-min<2) return min;
86   static TRandom rand;
87   if (!seedSet) {
88     TDatime dt;
89     rand.SetSeed(dt.Get());
90     seedSet=kTRUE;
91   }
92   return rand.Integer(max-min);
93 }
94
95 /**
96  * Print the bunch information of a channel.
97  * The function goes recursively to the first bunch of the
98  * channel and prints this one first.
99  * @return number of 10bit words
100  */
101 int DumpBunchRecursive(int nofBunches, int* pData, int size)
102 {
103   if (!pData || size<2) return -1;
104   int pos=size;
105   int bunchLength=pData[--pos];
106   int bunchEndTime=pData[--pos];
107   int read=0;
108   if (bunchLength<pos && nofBunches>1) {
109     read=DumpBunchRecursive(nofBunches-1, pData, pos-bunchLength);
110   }
111   cout << "       bunch length " << bunchLength << ", end time " << bunchEndTime << ":";
112
113   for (int time=bunchEndTime; time>bunchEndTime-bunchLength; time--) {  
114     if (pos<1) {
115       pos=0;
116       cerr << "no data for bunch " << endl;
117       return -1;
118     }
119     //cout << " " << pData[--pos];
120   }
121   cout << endl;
122   if (read<0) return read;
123   return read+2+bunchLength;
124 }
125
126 /**
127  * Write the encoded data to a file.
128  */
129 template<typename T> 
130 void DumpDataArray(T *array, const char* filename, int memberSize)
131 {
132   if (array->GetSize()==0) return;
133
134   ios::openmode filemode=(ios::openmode)0;
135   ofstream rawfile(filename, filemode);
136   if (rawfile.good()) {
137     rawfile.write(reinterpret_cast<const char*>(array->GetArray()), array->GetSize()*memberSize);
138   }
139   rawfile.close();
140 }
141
142 /**
143  * Print the simulated data.
144  */
145 void PrintSimulatedData(TArrayI& data)
146 {
147   cout << endl << "******  readback *******" << endl << endl;
148   int dataPos=data.GetSize();
149   while (dataPos>0) {
150     int channelAddress=data[--dataPos];
151     int nofBunches=data[--dataPos];
152     cout << " ------------------ new channel -------------------------" << endl;
153     if (nofBunches>0) {
154       int read=DumpBunchRecursive(nofBunches, data.GetArray(), dataPos);
155       if (read<0) return;
156       dataPos-=read;
157     }
158     cout << " channel " << channelAddress << ":  number of bunches " << nofBunches << endl;
159   }
160 }
161
162 int Compare(TArrayI& simData, TArrayC& encData)
163 {
164   if (bVerbose) cout << endl << "******  compare *******" << endl << endl;
165
166   // can not have a static AltroDecoder, crash when function
167   // is called. I had a similar problem in the AliHLTAltroChannelSelectorComponent
168
169   int iResult=0;
170   AliAltroDecoder* decoder=new AliAltroDecoder;
171   if (iResult>=0 && decoder->SetMemory((UChar_t*)encData.GetArray(), (UInt_t)encData.GetSize())<0) {
172     cout << "error setting up decoder " << endl;
173     iResult=-1;
174   }
175
176   if (iResult>=0 && !decoder->Decode()) {
177     cout << "error decoding data" << endl;
178     iResult=-1;    
179   }
180
181   AliAltroData altrochannel;
182   int dataPos=simData.GetSize();
183   while (iResult>=0 && decoder->NextChannel(&altrochannel)) {
184     int hwadd=altrochannel.GetHadd();
185     if (dataPos<2) {
186       cout << "missmatch in simulated data" << endl;
187       iResult=-1;
188       break;
189     }
190     int channelAddress=simData[--dataPos];
191     int nofBunches=simData[--dataPos];
192     if (channelAddress!=hwadd) {
193       cout << "channel address missmatch: simulated " << channelAddress << " encoded " << hwadd << endl;
194       iResult=-1;
195       break;
196     }
197
198     if (bVerbose) cout << "comparing channel " << channelAddress << ", " << nofBunches << " bunche(s)" << endl;
199
200     AliAltroBunch altrobunch;
201     while (iResult>=0 && altrochannel.NextBunch(&altrobunch) && nofBunches-->0) {
202       if (dataPos<2) {
203         cout << "error reading bunch size and time bin from simulated data" << endl;
204         iResult=-1;
205         break;
206       }
207       int bunchLength=simData[--dataPos];
208       int bunchEndTime=simData[--dataPos];
209       if (bunchLength!=(int)altrobunch.GetBunchSize()) {
210         cout << "bunch length missmatch: simulated " << bunchLength << " encoded " << altrobunch.GetBunchSize() << hex << " (" << altrobunch.GetBunchSize() << ")" << dec << endl;
211         iResult=-1;
212         break;
213       }
214       if (bunchEndTime!=(int)altrobunch.GetEndTimeBin()) {
215         cout << "bunch end time missmatch: simulated " << bunchEndTime << " encoded " << altrobunch.GetEndTimeBin() << endl;
216         iResult=-1;
217         break;
218       }
219       if (bVerbose) cout << " bunch length " << bunchLength << ", end time " << bunchEndTime << endl;
220       const  UInt_t* bunchData=altrobunch.GetData();
221       if (bunchLength>dataPos) {
222         cout << "error reading simulated bunch data, required "<< bunchLength << "  available " << dataPos << endl;
223         iResult=-1;
224         break;
225       }
226       Int_t* pSim=simData.GetArray();
227       for (int bin=0; bin<bunchLength; bin++) {
228         if ((int)bunchData[bin]!=pSim[dataPos-bunchLength+bin]) {
229           cout << "data missmatch at bunch position " << bin << " : simulated " << simData[dataPos] << " encoded " << bunchData[bin] << endl;
230           iResult=-1;
231           break;
232         }
233       }
234       dataPos-=bunchLength;
235     }
236
237   }
238
239   delete decoder;
240   return iResult;
241 }
242
243 void CompareDumpFiles()
244 {
245   TString param=encodedDataFile;
246   param+="?filetype=raw";
247   TFile encFile(param);
248   if (encFile.IsZombie()) {
249     cout << "can not open file " << encodedDataFile << endl;
250     return;
251   }
252
253   TArrayC encData(encFile.GetSize());
254   if (encFile.ReadBuffer(encData.GetArray(), encData.GetSize())) {
255     cout << "error reading file " << encodedDataFile << endl;
256     return;
257   }  
258
259   param=simulatedDataFile;
260   param+="?filetype=raw";
261   TFile simFile(param);
262   if (simFile.IsZombie()) {
263     cout << "can not open file " << simulatedDataFile << endl;
264     return;
265   }
266
267   TArrayI simData(simFile.GetSize()/4);
268   if (simFile.ReadBuffer((char*)simData.GetArray(), simData.GetSize()*4)) {
269     cout << "error reading file " << simulatedDataFile << endl;
270     return;
271   }
272
273   Compare(simData, encData);
274 }
275
276 int altro_encoder()
277 {
278   int nofChannels=GetRandom(1, maxChannels);
279   if (nofChannels==0) nofChannels=1;
280   TArrayI simData;
281   TArrayC encData(maxEncodedDataSize);
282   const int maxAltroDataSize=encData.GetSize()-sizeofAliRawDataHeader;
283   int dataPos=0;
284
285 #ifdef __CINT__
286   gSystem->Load("libAliHLTRCU.so");
287 #endif
288
289   AliHLTAltroEncoder encoder;
290   Char_t* pTgt=encData.GetArray();
291   pTgt+=sizeofAliRawDataHeader;
292   encoder.SetBuffer((AliHLTUInt8_t*)pTgt, maxAltroDataSize);
293
294   if (bVerbose) cout << "number of channels: " << nofChannels << endl;
295   int channelAddress=-1;
296   int lastChannel=-1;
297   int nof10BitWords=0;
298   // The nof10BitWords value is aligned to 4. In addition, one
299   // 40bit word is needed for the channel trailer
300   for (int channel=0; channel<nofChannels && (((nof10BitWords/4)+2)*5)<maxAltroDataSize; channel++) {
301     channelAddress=GetRandom(0, 0xfff);
302     if (channelAddress==lastChannel) continue;
303     int nofBunches=GetRandom(1, maxBunches);
304     if (nofBunches==0) continue;
305     int totalBunches=0;
306     int bunchEndTime=maxTimebin;
307     
308     if (bVerbose) cout << " ------------------ new channel -------------------------" << endl;
309     int bunch=0;
310     for (bunch=0; bunch<nofBunches && bunchEndTime>0; bunch++) {
311       bunchEndTime=GetRandom(0, bunchEndTime-1);
312       int bunchLength=GetRandom(0, bunchEndTime<10?bunchEndTime:10);
313       if (bunchLength==0) continue;
314       // check if there is enough space for all the signals, end time
315       // and bunch length. The value is aligned to 4. In addition, one
316       // 40bit word is needed for the channel trailer
317       if (((((nof10BitWords+bunchLength+2)/4)+2)*5)>=maxAltroDataSize) break;
318       totalBunches++;
319
320       if (bVerbose) cout << "       bunch " << bunch << ", length " << bunchLength << ", end time " << bunchEndTime << ":";
321
322       if (simData.GetSize()<dataPos+bunchLength+2) simData.Set(dataPos+bunchLength+2);
323       for (int time=bunchEndTime-bunchLength+1; time<=bunchEndTime; time++) {   
324         int signal=GetRandom(0, maxSignal);
325         simData[dataPos++]=signal;
326         if (bVerbose) cout << " " << signal;
327         int added=1;
328         if (bUseAddChannelSignal) {
329           added=encoder.AddChannelSignal(signal, time, channelAddress);
330         } else {
331           if (encoder.AddSignal(signal, time)<0) {
332             cout << "AddSignal failed" << endl;
333           }
334         }
335         lastChannel=channelAddress;
336         if (added>0) nof10BitWords+=added;
337       }
338       if (bVerbose) cout << endl;
339       simData[dataPos++]=bunchEndTime;
340       simData[dataPos++]=bunchLength;
341     }
342     if (simData.GetSize()<dataPos+2) simData.Set(dataPos+2);
343     if (totalBunches>0) {
344       simData[dataPos++]=totalBunches;
345       simData[dataPos++]=channelAddress;
346     }
347
348     if (!bUseAddChannelSignal && lastChannel>=0) {
349       encoder.SetChannel(lastChannel);
350     }
351
352     if (bVerbose) cout << " channel " << channelAddress << ":  number of bunches " << totalBunches << endl;
353
354   }
355   if (bUseAddChannelSignal && lastChannel>=0) encoder.SetChannel(lastChannel);
356
357   int nof40bitWords=encoder.GetTotal40bitWords();
358   pTgt+=nof40bitWords*5/4;
359   *((Int_t*)pTgt)=nof40bitWords;
360   int encDataSize=sizeofAliRawDataHeader+nof40bitWords*5/4+sizeof(Int_t);
361   encData.Set(encDataSize);
362
363   if (bVerbose) cout << "simulated data array:" << simData.GetSize() << " , ALTRO block length: " << nof40bitWords << " ALTRO words -> encoded data: " << encData.GetSize() << endl;
364
365   /////////////////////////////////////////////////////////
366   // some debugging options
367
368   if (encDataDumpFile) DumpDataArray(&encData, encDataDumpFile, 1);
369
370   simData.Set(dataPos);
371   if (bVerbose) PrintSimulatedData(simData);
372
373   /////////////////////////////////////////////////////////
374   // read back end compare the encoded data
375
376   if (simData.GetSize()>0 && Compare(simData, encData)<0) {
377     // dump files for further debugging
378     DumpDataArray(&encData, encodedDataFile, 1);
379     DumpDataArray(&simData, simulatedDataFile, 4);
380     return -1;
381   } else {
382     if (bVerbose) cout << "check successfully completed: " << nof40bitWords << " ALTRO words" << endl;
383   }
384
385   return 0;
386 }
387
388 int main(int argc, const char** argv)
389 {
390 //   CompareDumpFiles();
391 //   return 0;
392
393   int iResult=0;
394   int iCount=10000;
395   for (int i=0; i<iCount; i++) {
396     if ((iResult=altro_encoder())<0) {
397       cout << "missmatch in block no " << i << endl;
398       return iResult;
399     }
400   }
401   cout << iCount << " encoding cycle(s) successfully tested" << endl;
402   return 0;
403 }