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 AliHLTAltroGenerator.cxx
20 @author Matthias Richter
22 @brief Simulation class of 10/40bit Altro Data.
27 #include "AliHLTAltroGenerator.h"
32 #include "AliRawDataHeader.h"
33 #include "AliHLTAltroEncoder.h"
35 /** ROOT macro for the implementation of ROOT specific class methods */
36 ClassImp(AliHLTAltroGenerator)
38 AliHLTAltroGenerator::AliHLTAltroGenerator(int maxChannels,
52 fMaxChannels(maxChannels),
53 fMaxBunches(maxBunches),
54 fMaxBunchLength(maxBunchLength),
55 fMaxTimebin(maxTimebin),
56 fMaxSignal(maxSignal),
58 fDirection(kBackwards),
61 fCurrentTimeOffset(-1)
63 // see header file for class documentation
65 // refer to README to build package
67 // visit http://web.ift.uib.no/~kjeks/doc/alice-hlt
70 AliHLTAltroGenerator::~AliHLTAltroGenerator()
72 // see header file for class documentation
73 if (fpTrailer) delete[] fpTrailer;
74 if (fpCDH) delete[] fpCDH;
75 if (fpSimData) delete fpSimData;
76 if (fpData) delete fpData;
79 int AliHLTAltroGenerator::Generate()
81 // see header file for class documentation
82 if (!fpSimData) fpSimData=new TArrayS;
89 int nofChannels=GetRandom(1, fMaxChannels);
90 if (nofChannels==0) nofChannels=1;
92 HLTDebug("number of channels: %d", nofChannels);
93 int channelAddress=-1;
97 for (int channel=0; channel<nofChannels; channel++) {
98 channelAddress=GetRandom(0, fMaxChannels);
99 //HLTDebug("channel %d: address %d, %d bunch(es)", channel, channelAddress, nofBunches);
100 if (channelAddress==lastChannel) {
102 if (repetitions++>5) break;
105 int nofBunches=GetRandom(1, fMaxBunches);
108 if (repetitions++>5) break;
114 int lastBunchEndTime=0;
116 HLTDebug("simulate channel %d: address %d", channel, channelAddress);
118 // save beginning of this channel for better navigation
119 AliChannelPosition position={channelAddress, dataPos, 0};
121 // add channel address and bunch count at the beginning
122 if (fpSimData->GetSize()<dataPos+2) fpSimData->Set(dataPos+2);
123 (*fpSimData)[dataPos++]=channelAddress;
124 dataPos++; // placeholder for number of bunches
128 // Matthias Oct 2008:
129 // Data was simulated in the wrong order: bunches for the higher timebins
130 // first. But real data is the other way round: bunches are written in the order
131 // of ascending timebins. A new consistency check was added to AliAltroDecoder
132 // (AliAltroBunch) in revision 29090. Now the channels are checked for overlapping
133 // bunches, the time of a bunch must be smaller than time of the previous one
135 // Data is now simulated in the right order in order to fullfil this check.
136 for (bunch=0; bunch<nofBunches && bunchEndTime<fMaxTimebin-3; bunch++) {
137 while ((bunchEndTime+=GetRandom(0, fMaxTimebin-bunchEndTime))-lastBunchEndTime<3) {/*empty body*/};
138 int bunchLength=GetRandom(0, bunchEndTime-lastBunchEndTime<fMaxBunchLength?bunchEndTime-lastBunchEndTime:fMaxBunchLength);
139 if (bunchLength==0) continue;
142 HLTDebug(" bunch %d, length %d, end time %d ", bunch, bunchLength, bunchEndTime);
144 if (fpSimData->GetSize()<dataPos+bunchLength+4) fpSimData->Set(dataPos+bunchLength+4);
145 // write bunch length and time at both ends
146 (*fpSimData)[dataPos++]=bunchLength;
147 int time=bunchEndTime-bunchLength+1;
148 (*fpSimData)[dataPos++]=time;
149 for (; time<=bunchEndTime; time++) {
150 int signal=GetRandom(0, fMaxSignal);
151 (*fpSimData)[dataPos++]=signal;
153 (*fpSimData)[dataPos++]=bunchEndTime;
154 (*fpSimData)[dataPos++]=bunchLength;
155 fNof10BitWords+=bunchLength+2;
156 lastBunchEndTime=bunchEndTime;
157 bunchEndTime+=bunchLength;
159 if (totalBunches>0) {
160 (*fpSimData)[position.fPosition+1]=totalBunches;
161 if (fpSimData->GetSize()<dataPos+2) fpSimData->Set(dataPos+2);
162 (*fpSimData)[dataPos++]=totalBunches;
163 position.fEnd=dataPos;
164 (*fpSimData)[dataPos++]=channelAddress;
165 lastChannel=channelAddress;
166 fNof10BitWords=(fNof10BitWords+7)/4; fNof10BitWords*=4; // align to 4 and add 4
167 fChannelPositions.push_back(position);
168 assert((*fpSimData)[position.fPosition]==(*fpSimData)[position.fEnd]);
169 HLTDebug(" channel %d added: address %d, %d bunch(es)", channel, channelAddress, totalBunches);
172 HLTDebug(" channel %d skipped: address %d, %d bunch(es)", channel, channelAddress, totalBunches);
176 assert(fNof10BitWords%4==0);
177 fpSimData->Set(dataPos);
178 return GetDataSize();
181 int AliHLTAltroGenerator::GetNof40BitAltroWords() const
183 // see header file for class documentation
184 assert(fNof10BitWords%4==0);
185 return fNof10BitWords/4;
188 int AliHLTAltroGenerator::GetDataSize()
190 // see header file for class documentation
192 iResult=(fNof10BitWords*5)/4;
194 *(reinterpret_cast<AliHLTUInt32_t*>(fpTrailer))=GetNof40BitAltroWords();
195 iResult+=fTrailerSize;
197 if (fpCDH) iResult+=fCDHSize;
201 int AliHLTAltroGenerator::GetData(AliHLTUInt8_t* &pBuffer)
203 // see header file for class documentation
204 int iResult=GetDataSize();
206 if (!fpData) fpData=new TArrayC(iResult);
208 if (fpData->GetSize()<iResult) fpData->Set(iResult);
209 if ((iResult=GetData(reinterpret_cast<AliHLTUInt8_t*>(fpData->GetArray()), fpData->GetSize()))>=0) {
210 pBuffer=reinterpret_cast<AliHLTUInt8_t*>(fpData->GetArray());
219 int AliHLTAltroGenerator::GetData(AliHLTUInt8_t* pBuffer, int size)
221 // see header file for class documentation
225 if (size<GetDataSize()) return -ENOSPC;
227 // copy Common Data Header
229 fpCDH->fSize=GetDataSize();
230 memcpy(pBuffer+dataPos, fpCDH, fCDHSize);
234 // encode simulated data
235 if ((iResult=EncodeData(pBuffer+dataPos, size-dataPos))>=0) {
241 memcpy(pBuffer+dataPos, fpTrailer, fTrailerSize);
242 AliHLTUInt32_t* pLast=reinterpret_cast<AliHLTUInt32_t*>(fpTrailer+fTrailerSize-sizeof(AliHLTUInt32_t));
243 *pLast=GetNof40BitAltroWords();
244 dataPos+=fTrailerSize;
247 if (iResult<0) return iResult;
248 assert(fpCDH==NULL || (int)fpCDH->fSize==dataPos);
252 int AliHLTAltroGenerator::SetCDH(AliRawDataHeader* pCDH, int size)
254 // see header file for class documentation
256 if (pCDH && size>0) {
257 if (fpCDH) delete[] fpCDH;
258 fpCDH=new AliRawDataHeader;
260 memcpy(fpCDH, pCDH, size);
271 int AliHLTAltroGenerator::SetRCUTrailer(AliHLTUInt8_t* pTrailer, int size)
273 // see header file for class documentation
275 if (pTrailer && size>=(int)sizeof(AliHLTUInt32_t)) {
276 AliHLTUInt32_t* pLast=reinterpret_cast<AliHLTUInt32_t*>(pTrailer+size-sizeof(AliHLTUInt32_t));
277 if (size!=sizeof(AliHLTUInt32_t)) {
278 // if more than one trailer words, the last one is the trailer length (# 32bit words)
279 if (*pLast!=size/sizeof(AliHLTUInt32_t)) {
280 HLTError("invalid trailer: trailer length (last 32bit word) does not match trailer size (bytes)");
284 if (fpTrailer) delete[] fpTrailer;
285 fpTrailer=new AliHLTUInt8_t[size];
287 memcpy(fpTrailer, pTrailer, size);
298 int AliHLTAltroGenerator::GetChannels(vector<AliHLTUInt16_t> list)
300 // see header file for class documentation
303 for (vector<AliChannelPosition>::iterator element=fChannelPositions.begin();
304 element!=fChannelPositions.end();
306 list.push_back(element->fChannel);
312 int AliHLTAltroGenerator::SetSorting(AliHLTUInt16_t */*array*/, int /*arraySize*/)
314 // see header file for class documentation
316 HLTError("function not yet implemented");
320 int AliHLTAltroGenerator::EncodeData(AliHLTUInt8_t* pBuffer, int size)
322 // see header file for class documentation
324 if (!pBuffer) return -EINVAL;
326 AliHLTAltroEncoder encoder;
327 encoder.SetBuffer(pBuffer, size);
329 Short_t channelAddress=-1;
330 for (vector<AliChannelPosition>::iterator element=fChannelPositions.begin();
331 element!=fChannelPositions.end() && iResult>=0;
334 fpSimData->GetSize()<=element->fPosition ||
339 channelAddress=element->fChannel;
340 assert(fpSimData->At(element->fPosition)==channelAddress);
341 if (fpSimData->At(element->fPosition)!=channelAddress) {
345 int dataPos=element->fPosition+1;
346 int nofBunches=fpSimData->At(dataPos++);
348 for (; bunch<nofBunches; bunch++) {
349 int bunchLength=fpSimData->At(dataPos++);
350 int startTime=fpSimData->At(dataPos++);
352 for (; time<startTime+bunchLength; time++) {
353 iResult=encoder.AddSignal(fpSimData->At(dataPos++), time);
355 assert(time-1==fpSimData->At(dataPos));
356 dataPos++; // DO NOT PUT INTO ASSERT
357 assert(bunchLength==fpSimData->At(dataPos));
358 dataPos++; // DO NOT PUT INTO ASSERT
361 if (iResult>=0 && channelAddress>=0) {
362 assert(nofBunches==fpSimData->At(dataPos));
363 dataPos++; // DO NOT PUT INTO ASSERT
364 assert(channelAddress==fpSimData->At(dataPos));
365 dataPos++; // DO NOT PUT INTO ASSERT
367 encoder.SetChannel(channelAddress);
371 iResult=(encoder.GetTotal40bitWords()*5)/4;
377 int AliHLTAltroGenerator::GetRandom(int min, int max)
379 // see header file for class documentation
380 if (max-min<2) return min;
381 bool setTheSeed=fpRand!=NULL;
385 if (fpRand==NULL) return min;
388 fpRand->SetSeed(dt.Get());
390 return fpRand->Integer(max-min);
393 int AliHLTAltroGenerator::Reset()
395 // see header file for class documentation
396 fChannelPositions.clear();
402 int AliHLTAltroGenerator::Rewind()
404 // see header file for class documentation
407 fCurrentTimeOffset=-1;
411 bool AliHLTAltroGenerator::Next()
413 // see header file for class documentation
415 if (!fpSimData) return false;
417 if ((haveData=(fCurrentTimeOffset>=0 &&
419 ++fCurrentTimeOffset<GetBunchSize()))) {
423 if ((haveData=(NextBunch()) && GetBunchSize()>0)) {
424 fCurrentTimeOffset=0;
427 } while (NextChannel());
431 AliHLTUInt16_t AliHLTAltroGenerator::GetSignal()
433 // see header file for class documentation
434 if (!fpSimData || fCurrentTimeOffset<0) return 0;
435 assert(fCurrentPosition>=0 && fCurrentPosition<(int)fChannelPositions.size());
436 assert(fCurrentBunch>=0);
437 if (fDirection==kForwards) {
438 return fpSimData->At(fCurrentBunch+2+fCurrentTimeOffset);
439 } else if (fDirection==kBackwards){
440 return fpSimData->At(fCurrentBunch-(2+fCurrentTimeOffset));
445 bool AliHLTAltroGenerator::NextChannel()
447 // see header file for class documentation
449 if (!fpSimData || fChannelPositions.size()==0) return false;
450 fpSimData->GetArray();
451 if (fCurrentPosition==-1) {
452 if (fDirection==kForwards) fCurrentPosition=0;
453 else fCurrentPosition=fChannelPositions.size()-1;
456 if (fDirection==kForwards && (haveData=(fCurrentPosition+1<(int)fChannelPositions.size()))) {
458 } else if (fDirection==kBackwards && (haveData=(fCurrentPosition>0))) {
464 fCurrentTimeOffset=-1;
468 AliHLTUInt16_t AliHLTAltroGenerator::GetHwAddress()
470 // see header file for class documentation
471 if (fCurrentPosition>=0 && fCurrentPosition<(int)fChannelPositions.size())
472 return fChannelPositions[fCurrentPosition].fChannel;
473 return ~((AliHLTUInt16_t)0);
476 int AliHLTAltroGenerator::GetBunchCount()
478 // see header file for class documentation
479 if (fpSimData && fCurrentPosition>=0 && fCurrentPosition<(int)fChannelPositions.size()) {
480 if (fDirection==kForwards)
481 return fpSimData->At(fChannelPositions[fCurrentPosition].fPosition+1);
482 else if (fDirection==kBackwards)
483 return fpSimData->At(fChannelPositions[fCurrentPosition].fEnd-1);
485 return ~((AliHLTUInt16_t)0);
488 bool AliHLTAltroGenerator::NextBunch()
490 // see header file for class documentation
492 if (fpSimData && fCurrentPosition>=0 && fCurrentPosition<(int)fChannelPositions.size()) {
493 if (fDirection==kBackwards) {
494 if (fCurrentBunch<0) {
495 // bunch count in channel end - 1
496 if ((haveData=(fpSimData->At(fChannelPositions[fCurrentPosition].fEnd-1))>0)) {
497 // first bunch length at channel end - 2
498 fCurrentBunch=fChannelPositions[fCurrentPosition].fEnd-2;
500 } else if (fCurrentBunch>fChannelPositions[fCurrentPosition].fPosition+1) {
501 fCurrentBunch-=fpSimData->At(fCurrentBunch)+4;
502 haveData=fCurrentBunch>fChannelPositions[fCurrentPosition].fPosition+1;
506 assert(fpSimData->At(fCurrentBunch)==fpSimData->At(fCurrentBunch-fpSimData->At(fCurrentBunch)-3));
507 haveData=fpSimData->At(fCurrentBunch)==fpSimData->At(fCurrentBunch-fpSimData->At(fCurrentBunch)-3);
509 } else if (fDirection==kForwards) {
510 if (fCurrentBunch<0) {
511 // bunch count in channel start + 1
512 if ((haveData=(fpSimData->At(fChannelPositions[fCurrentPosition].fPosition+1))>0)) {
513 // first bunch length at channel start + 2
514 fCurrentBunch=fChannelPositions[fCurrentPosition].fPosition+2;
516 } else if (fCurrentBunch<fChannelPositions[fCurrentPosition].fEnd-1) {
517 fCurrentBunch+=fpSimData->At(fCurrentBunch)+4;
518 haveData=fCurrentBunch<fChannelPositions[fCurrentPosition].fEnd-1;
522 assert(fpSimData->At(fCurrentBunch)==fpSimData->At(fCurrentBunch+fpSimData->At(fCurrentBunch)+3));
523 haveData=fpSimData->At(fCurrentBunch)==fpSimData->At(fCurrentBunch+fpSimData->At(fCurrentBunch)+3);
527 fCurrentTimeOffset=-1;
531 AliHLTUInt16_t AliHLTAltroGenerator::GetBunchSize()
533 // see header file for class documentation
534 if (fCurrentBunch<0) return 0;
535 if (fCurrentBunch<fChannelPositions[fCurrentPosition].fPosition+2) return 0;
536 if (fCurrentBunch>fChannelPositions[fCurrentPosition].fEnd-2) return 0;
537 return fpSimData->At(fCurrentBunch);
540 AliHLTUInt16_t AliHLTAltroGenerator::GetStartTime()
542 // see header file for class documentation
543 if (!fpSimData || GetBunchSize()==0) return 0;
544 AliHLTUInt16_t startTime=0;
545 if (fDirection==kForwards) {
546 startTime=fpSimData->At(fCurrentBunch+1);
547 } else if (fDirection==kBackwards) {
548 startTime=fpSimData->At(fCurrentBunch-fpSimData->At(fCurrentBunch)-2);
550 if (fCurrentTimeOffset>=0) {
551 if (fDirection==kForwards) {
552 startTime+=fCurrentTimeOffset;
553 } else if (fDirection==kBackwards) {
554 startTime=GetEndTime();
560 AliHLTUInt16_t AliHLTAltroGenerator::GetEndTime()
562 // see header file for class documentation
563 if (!fpSimData || GetBunchSize()==0) return 0;
564 AliHLTUInt16_t endTime=0;
565 if (fDirection==kForwards) {
566 endTime=fpSimData->At(fCurrentBunch+fpSimData->At(fCurrentBunch)+2);
567 } else if (fDirection==kBackwards) {
568 endTime=fpSimData->At(fCurrentBunch-1);
570 if (fCurrentTimeOffset>=0) {
571 assert(fCurrentTimeOffset<fpSimData->At(fCurrentBunch));
572 if (fDirection==kForwards) {
573 endTime=GetStartTime();
574 } else if (fDirection==kBackwards) {
575 endTime-=fCurrentTimeOffset;
581 const Short_t* AliHLTAltroGenerator::GetSignals()
583 // see header file for class documentation
584 if (!fpSimData || GetBunchSize()==0) return NULL;
585 if (fDirection==kForwards) {
586 return fpSimData->GetArray()+fCurrentBunch+2;
587 } else if (fDirection==kBackwards) {
588 return fpSimData->GetArray()+(fCurrentBunch-fpSimData->At(fCurrentBunch)-1);
593 void AliHLTAltroGenerator::Print()
595 // see header file for class documentation
596 cout << *this << endl;
599 ostream &operator<<(ostream &stream, AliHLTAltroGenerator &generator)
601 // see header file for class documentation
603 Short_t channelAddress=-1;
604 for (vector<AliHLTAltroGenerator::AliChannelPosition>::iterator element=generator.fChannelPositions.begin();
605 element!=generator.fChannelPositions.end() && iResult>=0;
607 if (!generator.fpSimData ||
608 generator.fpSimData->GetSize()<=element->fPosition ||
609 generator.fNof10BitWords==0) {
610 stream << "AliHLTAltroGenerator: no data available" << endl;;
613 channelAddress=element->fChannel;
614 assert(generator.fpSimData->At(element->fPosition)==channelAddress);
615 if (generator.fpSimData->At(element->fPosition)!=channelAddress) {
616 stream << "AliHLTAltroGenerator: internal data mismatch" << endl;;
620 int dataPos=element->fPosition+1;
621 int nofBunches=generator.fpSimData->At(dataPos++);
622 stream << "***************************************************************" << endl;
623 stream << "channel address: " << channelAddress << " " << nofBunches << " bunch(es)" << endl;
625 for (; bunch<nofBunches; bunch++) {
626 int bunchLength=generator.fpSimData->At(dataPos++);
627 int startTime=generator.fpSimData->At(dataPos++);
629 stream << " length " << bunchLength << " start time " << startTime << ": ";
630 for (; time<startTime+bunchLength; time++) {
631 stream << " " << generator.fpSimData->At(dataPos++);
633 assert(time-1==generator.fpSimData->At(dataPos));
634 dataPos++; // DO NOT PUT INTO ASSERT
635 assert(bunchLength==generator.fpSimData->At(dataPos));
636 dataPos++; // DO NOT PUT INTO ASSERT
637 stream << " -> end time " << time-1 << endl;
640 if (iResult>=0 && channelAddress>=0) {
641 assert(nofBunches==generator.fpSimData->At(dataPos));
642 dataPos++; // DO NOT PUT INTO ASSERT
643 assert(channelAddress==generator.fpSimData->At(dataPos));
644 dataPos++; // DO NOT PUT INTO ASSERT