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
84 if (!fpSimData) fpSimData=new TArrayS;
91 int nofChannels=GetRandom(1, fMaxChannels);
92 if (nofChannels==0) nofChannels=1;
94 HLTDebug("number of channels: %d", nofChannels);
95 int channelAddress=-1;
99 for (int channel=0; channel<nofChannels; channel++) {
100 channelAddress=GetRandom(0, fMaxChannels);
101 //HLTDebug("channel %d: address %d, %d bunch(es)", channel, channelAddress, nofBunches);
102 if (channelAddress==lastChannel) {
104 if (repetitions++>5) break;
107 int nofBunches=GetRandom(1, fMaxBunches);
110 if (repetitions++>5) break;
116 int lastBunchEndTime=0;
118 HLTDebug("simulate channel %d: address %d", channel, channelAddress);
120 // save beginning of this channel for better navigation
121 AliChannelPosition position={channelAddress, dataPos, 0};
123 // add channel address and bunch count at the beginning
124 if (fpSimData->GetSize()<dataPos+2) fpSimData->Set(dataPos+2);
125 (*fpSimData)[dataPos++]=channelAddress;
126 dataPos++; // placeholder for number of bunches
130 // Matthias Oct 2008:
131 // Data was simulated in the wrong order: bunches for the higher timebins
132 // first. But real data is the other way round: bunches are written in the order
133 // of ascending timebins. A new consistency check was added to AliAltroDecoder
134 // (AliAltroBunch) in revision 29090. Now the channels are checked for overlapping
135 // bunches, the time of a bunch must be smaller than time of the previous one
137 // Data is now simulated in the right order in order to fullfil this check.
138 for (bunch=0; bunch<nofBunches && bunchEndTime<fMaxTimebin-3; bunch++) {
139 while ((bunchEndTime+=GetRandom(0, fMaxTimebin-bunchEndTime))-lastBunchEndTime<3) {/*empty body*/};
140 int bunchLength=GetRandom(0, bunchEndTime-lastBunchEndTime<fMaxBunchLength?bunchEndTime-lastBunchEndTime:fMaxBunchLength);
141 if (bunchLength==0) continue;
144 HLTDebug(" bunch %d, length %d, end time %d ", bunch, bunchLength, bunchEndTime);
146 if (fpSimData->GetSize()<dataPos+bunchLength+4) fpSimData->Set(dataPos+bunchLength+4);
147 // write bunch length and time at both ends
148 (*fpSimData)[dataPos++]=bunchLength;
149 int time=bunchEndTime-bunchLength+1;
150 (*fpSimData)[dataPos++]=time;
151 for (; time<=bunchEndTime; time++) {
152 int signal=GetRandom(0, fMaxSignal);
153 (*fpSimData)[dataPos++]=signal;
155 (*fpSimData)[dataPos++]=bunchEndTime;
156 (*fpSimData)[dataPos++]=bunchLength;
157 fNof10BitWords+=bunchLength+2;
158 lastBunchEndTime=bunchEndTime;
159 bunchEndTime+=bunchLength;
161 if (totalBunches>0) {
162 (*fpSimData)[position.fPosition+1]=totalBunches;
163 if (fpSimData->GetSize()<dataPos+2) fpSimData->Set(dataPos+2);
164 (*fpSimData)[dataPos++]=totalBunches;
165 position.fEnd=dataPos;
166 (*fpSimData)[dataPos++]=channelAddress;
167 lastChannel=channelAddress;
168 fNof10BitWords=(fNof10BitWords+7)/4; fNof10BitWords*=4; // align to 4 and add 4
169 fChannelPositions.push_back(position);
170 assert((*fpSimData)[position.fPosition]==(*fpSimData)[position.fEnd]);
171 HLTDebug(" channel %d added: address %d, %d bunch(es)", channel, channelAddress, totalBunches);
174 HLTDebug(" channel %d skipped: address %d, %d bunch(es)", channel, channelAddress, totalBunches);
178 assert(fNof10BitWords%4==0);
183 fpSimData->Set(dataPos);
184 return GetDataSize();
187 int AliHLTAltroGenerator::GetNof40BitAltroWords() const
189 // see header file for class documentation
190 assert(fNof10BitWords%4==0);
191 return fNof10BitWords/4;
194 int AliHLTAltroGenerator::GetDataSize()
196 // see header file for class documentation
198 iResult=(fNof10BitWords*5)/4;
200 *(reinterpret_cast<AliHLTUInt32_t*>(fpTrailer))=GetNof40BitAltroWords();
201 iResult+=fTrailerSize;
203 if (fpCDH) iResult+=fCDHSize;
207 int AliHLTAltroGenerator::GetData(AliHLTUInt8_t* &pBuffer)
209 // see header file for class documentation
210 int iResult=GetDataSize();
212 if (!fpData) fpData=new TArrayC(iResult);
214 if (fpData->GetSize()<iResult) fpData->Set(iResult);
215 if ((iResult=GetData(reinterpret_cast<AliHLTUInt8_t*>(fpData->GetArray()), fpData->GetSize()))>=0) {
216 pBuffer=reinterpret_cast<AliHLTUInt8_t*>(fpData->GetArray());
225 int AliHLTAltroGenerator::GetData(AliHLTUInt8_t* pBuffer, int size)
227 // see header file for class documentation
231 if (size<GetDataSize()) return -ENOSPC;
233 // copy Common Data Header
235 fpCDH->fSize=GetDataSize();
236 memcpy(pBuffer+dataPos, fpCDH, fCDHSize);
240 // encode simulated data
241 if ((iResult=EncodeData(pBuffer+dataPos, size-dataPos))>=0) {
247 memcpy(pBuffer+dataPos, fpTrailer, fTrailerSize);
248 AliHLTUInt32_t* pLast=reinterpret_cast<AliHLTUInt32_t*>(fpTrailer+fTrailerSize-sizeof(AliHLTUInt32_t));
249 *pLast=GetNof40BitAltroWords();
250 dataPos+=fTrailerSize;
253 if (iResult<0) return iResult;
254 assert(fpCDH==NULL || (int)fpCDH->fSize==dataPos);
258 int AliHLTAltroGenerator::SetCDH(AliRawDataHeader* pCDH, int size)
260 // see header file for class documentation
262 if (pCDH && size>0) {
263 if (fpCDH) delete[] fpCDH;
264 fpCDH=new AliRawDataHeader;
266 memcpy(fpCDH, pCDH, size);
277 int AliHLTAltroGenerator::SetRCUTrailer(AliHLTUInt8_t* pTrailer, int size)
279 // see header file for class documentation
281 if (pTrailer && size>=(int)sizeof(AliHLTUInt32_t)) {
282 AliHLTUInt32_t* pLast=reinterpret_cast<AliHLTUInt32_t*>(pTrailer+size-sizeof(AliHLTUInt32_t));
283 if (size!=sizeof(AliHLTUInt32_t)) {
284 // if more than one trailer words, the last one is the trailer length (# 32bit words)
285 if (*pLast!=size/sizeof(AliHLTUInt32_t)) {
286 HLTError("invalid trailer: trailer length (last 32bit word) does not match trailer size (bytes)");
290 if (fpTrailer) delete[] fpTrailer;
291 fpTrailer=new AliHLTUInt8_t[size];
293 memcpy(fpTrailer, pTrailer, size);
304 int AliHLTAltroGenerator::GetChannels(vector<AliHLTUInt16_t> list)
306 // see header file for class documentation
309 for (vector<AliChannelPosition>::iterator element=fChannelPositions.begin();
310 element!=fChannelPositions.end();
312 list.push_back(element->fChannel);
318 int AliHLTAltroGenerator::SetSorting(AliHLTUInt16_t */*array*/, int /*arraySize*/)
320 // see header file for class documentation
322 HLTError("function not yet implemented");
326 int AliHLTAltroGenerator::EncodeData(AliHLTUInt8_t* pBuffer, int size)
328 // see header file for class documentation
330 if (!pBuffer) return -EINVAL;
332 AliHLTAltroEncoder encoder;
333 encoder.SetBuffer(pBuffer, size);
335 Short_t channelAddress=-1;
336 for (vector<AliChannelPosition>::iterator element=fChannelPositions.begin();
337 element!=fChannelPositions.end() && iResult>=0;
340 fpSimData->GetSize()<=element->fPosition ||
345 channelAddress=element->fChannel;
346 assert(fpSimData->At(element->fPosition)==channelAddress);
347 if (fpSimData->At(element->fPosition)!=channelAddress) {
351 int dataPos=element->fPosition+1;
352 int nofBunches=fpSimData->At(dataPos++);
354 for (; bunch<nofBunches; bunch++) {
355 int bunchLength=fpSimData->At(dataPos++);
356 int startTime=fpSimData->At(dataPos++);
358 for (; time<startTime+bunchLength; time++) {
359 iResult=encoder.AddSignal(fpSimData->At(dataPos++), time);
361 assert(time-1==fpSimData->At(dataPos));
362 dataPos++; // DO NOT PUT INTO ASSERT
363 assert(bunchLength==fpSimData->At(dataPos));
364 dataPos++; // DO NOT PUT INTO ASSERT
367 if (iResult>=0 && channelAddress>=0) {
368 assert(nofBunches==fpSimData->At(dataPos));
369 dataPos++; // DO NOT PUT INTO ASSERT
370 assert(channelAddress==fpSimData->At(dataPos));
371 dataPos++; // DO NOT PUT INTO ASSERT
373 encoder.SetChannel(channelAddress);
377 iResult=(encoder.GetTotal40bitWords()*5)/4;
383 int AliHLTAltroGenerator::GetRandom(int min, int max)
385 // see header file for class documentation
386 if (max-min<2) return min;
387 bool setTheSeed=fpRand!=NULL;
391 if (fpRand==NULL) return min;
394 fpRand->SetSeed(dt.Get());
396 return fpRand->Integer(max-min);
399 int AliHLTAltroGenerator::Reset()
401 // see header file for class documentation
402 fChannelPositions.clear();
408 int AliHLTAltroGenerator::Rewind()
410 // see header file for class documentation
413 fCurrentTimeOffset=-1;
417 bool AliHLTAltroGenerator::Next()
419 // see header file for class documentation
421 if (!fpSimData) return false;
423 if ((haveData=(fCurrentTimeOffset>=0 &&
425 ++fCurrentTimeOffset<GetBunchSize()))) {
429 if ((haveData=(NextBunch()) && GetBunchSize()>0)) {
430 fCurrentTimeOffset=0;
433 } while (NextChannel());
437 AliHLTUInt16_t AliHLTAltroGenerator::GetSignal()
439 // see header file for class documentation
440 if (!fpSimData || fCurrentTimeOffset<0) return 0;
441 assert(fCurrentPosition>=0 && fCurrentPosition<(int)fChannelPositions.size());
442 assert(fCurrentBunch>=0);
443 if (fDirection==kForwards) {
444 return fpSimData->At(fCurrentBunch+2+fCurrentTimeOffset);
445 } else if (fDirection==kBackwards){
446 return fpSimData->At(fCurrentBunch-(2+fCurrentTimeOffset));
451 bool AliHLTAltroGenerator::NextChannel()
453 // see header file for class documentation
455 if (fpSimData && fChannelPositions.size()==0) return false;
456 fpSimData->GetArray();
457 if (fCurrentPosition==-1) {
458 if (fDirection==kForwards) fCurrentPosition=0;
459 else fCurrentPosition=fChannelPositions.size()-1;
462 if (fDirection==kForwards && (haveData=(fCurrentPosition+1<(int)fChannelPositions.size()))) {
464 } else if (fDirection==kBackwards && (haveData=(fCurrentPosition>0))) {
470 fCurrentTimeOffset=-1;
474 AliHLTUInt16_t AliHLTAltroGenerator::GetHwAddress()
476 // see header file for class documentation
477 if (fCurrentPosition>=0 && fCurrentPosition<(int)fChannelPositions.size())
478 return fChannelPositions[fCurrentPosition].fChannel;
479 return ~((AliHLTUInt16_t)0);
482 int AliHLTAltroGenerator::GetBunchCount()
484 // see header file for class documentation
485 if (fpSimData && fCurrentPosition>=0 && fCurrentPosition<(int)fChannelPositions.size()) {
486 if (fDirection==kForwards)
487 return fpSimData->At(fChannelPositions[fCurrentPosition].fPosition+1);
488 else if (fDirection==kBackwards)
489 return fpSimData->At(fChannelPositions[fCurrentPosition].fEnd-1);
491 return ~((AliHLTUInt16_t)0);
494 bool AliHLTAltroGenerator::NextBunch()
496 // see header file for class documentation
498 if (fpSimData && fCurrentPosition>=0 && fCurrentPosition<(int)fChannelPositions.size()) {
499 if (fDirection==kBackwards) {
500 if (fCurrentBunch<0) {
501 // bunch count in channel end - 1
502 if ((haveData=(fpSimData->At(fChannelPositions[fCurrentPosition].fEnd-1))>0)) {
503 // first bunch length at channel end - 2
504 fCurrentBunch=fChannelPositions[fCurrentPosition].fEnd-2;
506 } else if (fCurrentBunch>fChannelPositions[fCurrentPosition].fPosition+1) {
507 fCurrentBunch-=fpSimData->At(fCurrentBunch)+4;
508 haveData=fCurrentBunch>fChannelPositions[fCurrentPosition].fPosition+1;
512 assert(fpSimData->At(fCurrentBunch)==fpSimData->At(fCurrentBunch-fpSimData->At(fCurrentBunch)-3));
513 haveData=fpSimData->At(fCurrentBunch)==fpSimData->At(fCurrentBunch-fpSimData->At(fCurrentBunch)-3);
515 } else if (fDirection==kForwards) {
516 if (fCurrentBunch<0) {
517 // bunch count in channel start + 1
518 if ((haveData=(fpSimData->At(fChannelPositions[fCurrentPosition].fPosition+1))>0)) {
519 // first bunch length at channel start + 2
520 fCurrentBunch=fChannelPositions[fCurrentPosition].fPosition+2;
522 } else if (fCurrentBunch<fChannelPositions[fCurrentPosition].fEnd-1) {
523 fCurrentBunch+=fpSimData->At(fCurrentBunch)+4;
524 haveData=fCurrentBunch<fChannelPositions[fCurrentPosition].fEnd-1;
528 assert(fpSimData->At(fCurrentBunch)==fpSimData->At(fCurrentBunch+fpSimData->At(fCurrentBunch)+3));
529 haveData=fpSimData->At(fCurrentBunch)==fpSimData->At(fCurrentBunch+fpSimData->At(fCurrentBunch)+3);
533 fCurrentTimeOffset=-1;
537 AliHLTUInt16_t AliHLTAltroGenerator::GetBunchSize()
539 // see header file for class documentation
540 if (fCurrentBunch<0) return 0;
541 if (fCurrentBunch<fChannelPositions[fCurrentPosition].fPosition+2) return 0;
542 if (fCurrentBunch>fChannelPositions[fCurrentPosition].fEnd-2) return 0;
543 return fpSimData->At(fCurrentBunch);
546 AliHLTUInt16_t AliHLTAltroGenerator::GetStartTime()
548 // see header file for class documentation
549 if (!fpSimData || GetBunchSize()==0) return 0;
550 AliHLTUInt16_t startTime=0;
551 if (fDirection==kForwards) {
552 startTime=fpSimData->At(fCurrentBunch+1);
553 } else if (fDirection==kBackwards) {
554 startTime=fpSimData->At(fCurrentBunch-fpSimData->At(fCurrentBunch)-2);
556 if (fCurrentTimeOffset>=0) {
557 if (fDirection==kForwards) {
558 startTime+=fCurrentTimeOffset;
559 } else if (fDirection==kBackwards) {
560 startTime=GetEndTime();
566 AliHLTUInt16_t AliHLTAltroGenerator::GetEndTime()
568 // see header file for class documentation
569 if (!fpSimData || GetBunchSize()==0) return 0;
570 AliHLTUInt16_t endTime=0;
571 if (fDirection==kForwards) {
572 endTime=fpSimData->At(fCurrentBunch+fpSimData->At(fCurrentBunch)+2);
573 } else if (fDirection==kBackwards) {
574 endTime=fpSimData->At(fCurrentBunch-1);
576 if (fCurrentTimeOffset>=0) {
577 assert(fCurrentTimeOffset<fpSimData->At(fCurrentBunch));
578 if (fDirection==kForwards) {
579 endTime=GetStartTime();
580 } else if (fDirection==kBackwards) {
581 endTime-=fCurrentTimeOffset;
587 const Short_t* AliHLTAltroGenerator::GetSignals()
589 // see header file for class documentation
590 if (!fpSimData || GetBunchSize()==0) return NULL;
591 if (fDirection==kForwards) {
592 return fpSimData->GetArray()+fCurrentBunch+2;
593 } else if (fDirection==kBackwards) {
594 return fpSimData->GetArray()+(fCurrentBunch-fpSimData->At(fCurrentBunch)-1);
599 void AliHLTAltroGenerator::Print()
601 // see header file for class documentation
602 cout << *this << endl;
605 ostream &operator<<(ostream &stream, AliHLTAltroGenerator &generator)
607 // see header file for class documentation
609 Short_t channelAddress=-1;
610 for (vector<AliHLTAltroGenerator::AliChannelPosition>::iterator element=generator.fChannelPositions.begin();
611 element!=generator.fChannelPositions.end() && iResult>=0;
613 if (!generator.fpSimData ||
614 generator.fpSimData->GetSize()<=element->fPosition ||
615 generator.fNof10BitWords==0) {
616 stream << "AliHLTAltroGenerator: no data available" << endl;;
619 channelAddress=element->fChannel;
620 assert(generator.fpSimData->At(element->fPosition)==channelAddress);
621 if (generator.fpSimData->At(element->fPosition)!=channelAddress) {
622 stream << "AliHLTAltroGenerator: internal data mismatch" << endl;;
626 int dataPos=element->fPosition+1;
627 int nofBunches=generator.fpSimData->At(dataPos++);
628 stream << "***************************************************************" << endl;
629 stream << "channel address: " << channelAddress << " " << nofBunches << " bunch(es)" << endl;
631 for (; bunch<nofBunches; bunch++) {
632 int bunchLength=generator.fpSimData->At(dataPos++);
633 int startTime=generator.fpSimData->At(dataPos++);
635 stream << " length " << bunchLength << " start time " << startTime << ": ";
636 for (; time<startTime+bunchLength; time++) {
637 stream << " " << generator.fpSimData->At(dataPos++);
639 assert(time-1==generator.fpSimData->At(dataPos));
640 dataPos++; // DO NOT PUT INTO ASSERT
641 assert(bunchLength==generator.fpSimData->At(dataPos));
642 dataPos++; // DO NOT PUT INTO ASSERT
643 stream << " -> end time " << time-1 << endl;
646 if (iResult>=0 && channelAddress>=0) {
647 assert(nofBunches==generator.fpSimData->At(dataPos));
648 dataPos++; // DO NOT PUT INTO ASSERT
649 assert(channelAddress==generator.fpSimData->At(dataPos));
650 dataPos++; // DO NOT PUT INTO ASSERT