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;
115 int bunchEndTime=fMaxTimebin;
117 HLTDebug("simulate channel %d: address %d", channel, channelAddress);
119 // save beginning of this channel for better navigation
120 AliChannelPosition position={channelAddress, dataPos, 0};
122 // add channel address and bunch count at the beginning
123 if (fpSimData->GetSize()<dataPos+2) fpSimData->Set(dataPos+2);
124 (*fpSimData)[dataPos++]=channelAddress;
125 dataPos++; // placeholder for number of bunches
128 for (bunch=0; bunch<nofBunches && bunchEndTime>0; bunch++) {
129 bunchEndTime=GetRandom(0, bunchEndTime-1);
130 int bunchLength=GetRandom(0, bunchEndTime<fMaxBunchLength?bunchEndTime:fMaxBunchLength);
131 if (bunchLength==0) continue;
134 HLTDebug(" bunch %d, length %d, end time %d ", bunch, bunchLength, bunchEndTime);
136 if (fpSimData->GetSize()<dataPos+bunchLength+4) fpSimData->Set(dataPos+bunchLength+4);
137 // write bunch length and time at both ends
138 (*fpSimData)[dataPos++]=bunchLength;
139 int time=bunchEndTime-bunchLength+1;
140 (*fpSimData)[dataPos++]=time;
141 for (; time<=bunchEndTime; time++) {
142 int signal=GetRandom(0, fMaxSignal);
143 (*fpSimData)[dataPos++]=signal;
145 (*fpSimData)[dataPos++]=bunchEndTime;
146 (*fpSimData)[dataPos++]=bunchLength;
147 fNof10BitWords+=bunchLength+2;
149 if (totalBunches>0) {
150 (*fpSimData)[position.fPosition+1]=totalBunches;
151 if (fpSimData->GetSize()<dataPos+2) fpSimData->Set(dataPos+2);
152 (*fpSimData)[dataPos++]=totalBunches;
153 position.fEnd=dataPos;
154 (*fpSimData)[dataPos++]=channelAddress;
155 lastChannel=channelAddress;
156 fNof10BitWords=(fNof10BitWords+7)/4; fNof10BitWords*=4; // align to 4 and add 4
157 fChannelPositions.push_back(position);
158 assert((*fpSimData)[position.fPosition]==(*fpSimData)[position.fEnd]);
159 HLTDebug(" channel %d added: address %d, %d bunch(es)", channel, channelAddress, totalBunches);
162 HLTDebug(" channel %d skipped: address %d, %d bunch(es)", channel, channelAddress, totalBunches);
166 assert(fNof10BitWords%4==0);
171 fpSimData->Set(dataPos);
172 return GetDataSize();
175 int AliHLTAltroGenerator::GetNof40BitAltroWords() const
177 // see header file for class documentation
178 assert(fNof10BitWords%4==0);
179 return fNof10BitWords/4;
182 int AliHLTAltroGenerator::GetDataSize()
184 // see header file for class documentation
186 iResult=(fNof10BitWords*5)/4;
188 *(reinterpret_cast<AliHLTUInt32_t*>(fpTrailer))=GetNof40BitAltroWords();
189 iResult+=fTrailerSize;
191 if (fpCDH) iResult+=fCDHSize;
195 int AliHLTAltroGenerator::GetData(AliHLTUInt8_t* &pBuffer)
197 // see header file for class documentation
198 int iResult=GetDataSize();
200 if (!fpData) fpData=new TArrayC(iResult);
202 if (fpData->GetSize()<iResult) fpData->Set(iResult);
203 if ((iResult=GetData(reinterpret_cast<AliHLTUInt8_t*>(fpData->GetArray()), fpData->GetSize()))>=0) {
204 pBuffer=reinterpret_cast<AliHLTUInt8_t*>(fpData->GetArray());
213 int AliHLTAltroGenerator::GetData(AliHLTUInt8_t* pBuffer, int size)
215 // see header file for class documentation
219 if (size<GetDataSize()) return -ENOSPC;
221 // copy Common Data Header
223 fpCDH->fSize=GetDataSize();
224 memcpy(pBuffer+dataPos, fpCDH, fCDHSize);
228 // encode simulated data
229 if ((iResult=EncodeData(pBuffer+dataPos, size-dataPos))>=0) {
235 memcpy(pBuffer+dataPos, fpTrailer, fTrailerSize);
236 AliHLTUInt32_t* pLast=reinterpret_cast<AliHLTUInt32_t*>(fpTrailer+fTrailerSize-sizeof(AliHLTUInt32_t));
237 *pLast=GetNof40BitAltroWords();
238 dataPos+=fTrailerSize;
241 if (iResult<0) return iResult;
242 assert(fpCDH==NULL || (int)fpCDH->fSize==dataPos);
246 int AliHLTAltroGenerator::SetCDH(AliRawDataHeader* pCDH, int size)
248 // see header file for class documentation
250 if (pCDH && size>0) {
251 if (fpCDH) delete[] fpCDH;
252 fpCDH=new AliRawDataHeader;
254 memcpy(fpCDH, pCDH, size);
265 int AliHLTAltroGenerator::SetRCUTrailer(AliHLTUInt8_t* pTrailer, int size)
267 // see header file for class documentation
269 if (pTrailer && size>=(int)sizeof(AliHLTUInt32_t)) {
270 AliHLTUInt32_t* pLast=reinterpret_cast<AliHLTUInt32_t*>(pTrailer+size-sizeof(AliHLTUInt32_t));
271 if (size!=sizeof(AliHLTUInt32_t)) {
272 // if more than one trailer words, the last one is the trailer length (# 32bit words)
273 if (*pLast!=size/sizeof(AliHLTUInt32_t)) {
274 HLTError("invalid trailer: trailer length (last 32bit word) does not match trailer size (bytes)");
278 if (fpTrailer) delete[] fpTrailer;
279 fpTrailer=new AliHLTUInt8_t[size];
281 memcpy(fpTrailer, pTrailer, size);
292 int AliHLTAltroGenerator::GetChannels(vector<AliHLTUInt16_t> list)
294 // see header file for class documentation
297 for (vector<AliChannelPosition>::iterator element=fChannelPositions.begin();
298 element!=fChannelPositions.end();
300 list.push_back(element->fChannel);
306 int AliHLTAltroGenerator::SetSorting(AliHLTUInt16_t */*array*/, int /*arraySize*/)
308 // see header file for class documentation
310 HLTError("function not yet implemented");
314 int AliHLTAltroGenerator::EncodeData(AliHLTUInt8_t* pBuffer, int size)
316 // see header file for class documentation
318 if (!pBuffer) return -EINVAL;
320 AliHLTAltroEncoder encoder;
321 encoder.SetBuffer(pBuffer, size);
323 Short_t channelAddress=-1;
324 for (vector<AliChannelPosition>::iterator element=fChannelPositions.begin();
325 element!=fChannelPositions.end() && iResult>=0;
328 fpSimData->GetSize()<=element->fPosition ||
333 channelAddress=element->fChannel;
334 assert(fpSimData->At(element->fPosition)==channelAddress);
335 if (fpSimData->At(element->fPosition)!=channelAddress) {
339 int dataPos=element->fPosition+1;
340 int nofBunches=fpSimData->At(dataPos++);
342 for (; bunch<nofBunches; bunch++) {
343 int bunchLength=fpSimData->At(dataPos++);
344 int startTime=fpSimData->At(dataPos++);
346 for (; time<startTime+bunchLength; time++) {
347 //iResult=encoder.AddSignal(fpSimData->At(dataPos++), time);
348 iResult=encoder.AddChannelSignal(fpSimData->At(dataPos++), time, channelAddress);
350 assert(time-1==fpSimData->At(dataPos));
351 dataPos++; // DO NOT PUT INTO ASSERT
352 assert(bunchLength==fpSimData->At(dataPos));
353 dataPos++; // DO NOT PUT INTO ASSERT
356 if (iResult>=0 && channelAddress>=0) {
357 assert(nofBunches==fpSimData->At(dataPos));
358 dataPos++; // DO NOT PUT INTO ASSERT
359 assert(channelAddress==fpSimData->At(dataPos));
360 dataPos++; // DO NOT PUT INTO ASSERT
362 //encoder.SetChannel(channelAddress);
364 if (iResult>=0 && channelAddress>=0) {
365 encoder.SetChannel(channelAddress);
369 iResult=(encoder.GetTotal40bitWords()*5)/4;
375 int AliHLTAltroGenerator::GetRandom(int min, int max)
377 // see header file for class documentation
378 if (max-min<2) return min;
379 bool setTheSeed=fpRand!=NULL;
383 if (fpRand==NULL) return min;
386 fpRand->SetSeed(dt.Get());
388 return fpRand->Integer(max-min);
391 int AliHLTAltroGenerator::Reset()
393 // see header file for class documentation
394 fChannelPositions.clear();
400 int AliHLTAltroGenerator::Rewind()
402 // see header file for class documentation
405 fCurrentTimeOffset=-1;
409 bool AliHLTAltroGenerator::Next()
411 // see header file for class documentation
413 if (!fpSimData) return false;
415 if (haveData=(fCurrentTimeOffset>=0 &&
417 ++fCurrentTimeOffset<GetBunchSize())) {
421 if (haveData=(NextBunch() && GetBunchSize()>0)) {
422 fCurrentTimeOffset=0;
425 } while (NextChannel());
429 AliHLTUInt16_t AliHLTAltroGenerator::GetSignal()
431 // see header file for class documentation
432 if (!fpSimData || fCurrentTimeOffset<0) return 0;
433 assert(fCurrentPosition>=0 && fCurrentPosition<(int)fChannelPositions.size());
434 assert(fCurrentBunch>=0);
435 if (fDirection==kForwards) {
436 return fpSimData->At(fCurrentBunch+2+fCurrentTimeOffset);
437 } else if (fDirection==kBackwards){
438 return fpSimData->At(fCurrentBunch-(2+fCurrentTimeOffset));
443 bool AliHLTAltroGenerator::NextChannel()
445 // see header file for class documentation
447 if (fpSimData && fChannelPositions.size()==0) return false;
448 fpSimData->GetArray();
449 if (fCurrentPosition==-1) {
450 if (fDirection==kForwards) fCurrentPosition=0;
451 else fCurrentPosition=fChannelPositions.size()-1;
454 if (fDirection==kForwards && (haveData=(fCurrentPosition+1<(int)fChannelPositions.size()))) {
456 } else if (fDirection==kBackwards && (haveData=(fCurrentPosition>0))) {
462 fCurrentTimeOffset=-1;
466 AliHLTUInt16_t AliHLTAltroGenerator::GetHwAddress()
468 // see header file for class documentation
469 if (fCurrentPosition>=0 && fCurrentPosition<(int)fChannelPositions.size())
470 return fChannelPositions[fCurrentPosition].fChannel;
471 return ~((AliHLTUInt16_t)0);
474 int AliHLTAltroGenerator::GetBunchCount()
476 // see header file for class documentation
477 if (fpSimData && fCurrentPosition>=0 && fCurrentPosition<(int)fChannelPositions.size()) {
478 if (fDirection==kForwards)
479 return fpSimData->At(fChannelPositions[fCurrentPosition].fPosition+1);
480 else if (fDirection==kBackwards)
481 return fpSimData->At(fChannelPositions[fCurrentPosition].fEnd-1);
483 return ~((AliHLTUInt16_t)0);
486 bool AliHLTAltroGenerator::NextBunch()
488 // see header file for class documentation
490 if (fpSimData && fCurrentPosition>=0 && fCurrentPosition<(int)fChannelPositions.size()) {
491 if (fDirection==kBackwards) {
492 if (fCurrentBunch<0) {
493 // bunch count in channel end - 1
494 if (haveData=(fpSimData->At(fChannelPositions[fCurrentPosition].fEnd-1))>0) {
495 // first bunch length at channel end - 2
496 fCurrentBunch=fChannelPositions[fCurrentPosition].fEnd-2;
498 } else if (fCurrentBunch>fChannelPositions[fCurrentPosition].fPosition+1) {
499 fCurrentBunch-=fpSimData->At(fCurrentBunch)+4;
500 haveData=fCurrentBunch>fChannelPositions[fCurrentPosition].fPosition+1;
504 assert(fpSimData->At(fCurrentBunch)==fpSimData->At(fCurrentBunch-fpSimData->At(fCurrentBunch)-3));
505 haveData=fpSimData->At(fCurrentBunch)==fpSimData->At(fCurrentBunch-fpSimData->At(fCurrentBunch)-3);
507 } else if (fDirection==kForwards) {
508 if (fCurrentBunch<0) {
509 // bunch count in channel start + 1
510 if (haveData=(fpSimData->At(fChannelPositions[fCurrentPosition].fPosition+1))>0) {
511 // first bunch length at channel start + 2
512 fCurrentBunch=fChannelPositions[fCurrentPosition].fPosition+2;
514 } else if (fCurrentBunch<fChannelPositions[fCurrentPosition].fEnd-1) {
515 fCurrentBunch+=fpSimData->At(fCurrentBunch)+4;
516 haveData=fCurrentBunch<fChannelPositions[fCurrentPosition].fEnd-1;
520 assert(fpSimData->At(fCurrentBunch)==fpSimData->At(fCurrentBunch+fpSimData->At(fCurrentBunch)+3));
521 haveData=fpSimData->At(fCurrentBunch)==fpSimData->At(fCurrentBunch+fpSimData->At(fCurrentBunch)+3);
525 fCurrentTimeOffset=-1;
529 AliHLTUInt16_t AliHLTAltroGenerator::GetBunchSize()
531 // see header file for class documentation
532 if (fCurrentBunch<0) return 0;
533 if (fCurrentBunch<fChannelPositions[fCurrentPosition].fPosition+2) return 0;
534 if (fCurrentBunch>fChannelPositions[fCurrentPosition].fEnd-2) return 0;
535 return fpSimData->At(fCurrentBunch);
538 AliHLTUInt16_t AliHLTAltroGenerator::GetStartTime()
540 // see header file for class documentation
541 if (!fpSimData || GetBunchSize()==0) return 0;
542 AliHLTUInt16_t startTime=0;
543 if (fDirection==kForwards) {
544 startTime=fpSimData->At(fCurrentBunch+1);
545 } else if (fDirection==kBackwards) {
546 startTime=fpSimData->At(fCurrentBunch-fpSimData->At(fCurrentBunch)-2);
548 if (fCurrentTimeOffset>=0) {
549 if (fDirection==kForwards) {
550 startTime+=fCurrentTimeOffset;
551 } else if (fDirection==kBackwards) {
552 startTime=GetEndTime();
558 AliHLTUInt16_t AliHLTAltroGenerator::GetEndTime()
560 // see header file for class documentation
561 if (!fpSimData || GetBunchSize()==0) return 0;
562 AliHLTUInt16_t endTime=0;
563 if (fDirection==kForwards) {
564 endTime=fpSimData->At(fCurrentBunch+fpSimData->At(fCurrentBunch)+2);
565 } else if (fDirection==kBackwards) {
566 endTime=fpSimData->At(fCurrentBunch-1);
568 if (fCurrentTimeOffset>=0) {
569 assert(fCurrentTimeOffset<fpSimData->At(fCurrentBunch));
570 if (fDirection==kForwards) {
571 endTime=GetStartTime();
572 } else if (fDirection==kBackwards) {
573 endTime-=fCurrentTimeOffset;
579 const Short_t* AliHLTAltroGenerator::GetSignals()
581 // see header file for class documentation
582 if (!fpSimData || GetBunchSize()==0) return NULL;
583 if (fDirection==kForwards) {
584 return fpSimData->GetArray()+fCurrentBunch+2;
585 } else if (fDirection==kBackwards) {
586 return fpSimData->GetArray()+(fCurrentBunch-fpSimData->At(fCurrentBunch)-1);
591 void AliHLTAltroGenerator::Print()
593 // see header file for class documentation
594 cout << *this << endl;
597 ostream &operator<<(ostream &stream, AliHLTAltroGenerator &generator)
599 // see header file for class documentation
601 Short_t channelAddress=-1;
602 for (vector<AliHLTAltroGenerator::AliChannelPosition>::iterator element=generator.fChannelPositions.begin();
603 element!=generator.fChannelPositions.end() && iResult>=0;
605 if (!generator.fpSimData ||
606 generator.fpSimData->GetSize()<=element->fPosition ||
607 generator.fNof10BitWords==0) {
608 stream << "AliHLTAltroGenerator: no data available" << endl;;
611 channelAddress=element->fChannel;
612 assert(generator.fpSimData->At(element->fPosition)==channelAddress);
613 if (generator.fpSimData->At(element->fPosition)!=channelAddress) {
614 stream << "AliHLTAltroGenerator: internal data mismatch" << endl;;
618 int dataPos=element->fPosition+1;
619 int nofBunches=generator.fpSimData->At(dataPos++);
620 stream << "***************************************************************" << endl;
621 stream << "channel address: " << channelAddress << " " << nofBunches << " bunch(es)" << endl;
623 for (; bunch<nofBunches; bunch++) {
624 int bunchLength=generator.fpSimData->At(dataPos++);
625 int startTime=generator.fpSimData->At(dataPos++);
627 stream << " length " << bunchLength << " start time " << startTime << ": ";
628 for (; time<startTime+bunchLength; time++) {
629 stream << " " << generator.fpSimData->At(dataPos++);
631 assert(time-1==generator.fpSimData->At(dataPos));
632 dataPos++; // DO NOT PUT INTO ASSERT
633 assert(bunchLength==generator.fpSimData->At(dataPos));
634 dataPos++; // DO NOT PUT INTO ASSERT
635 stream << " -> end time " << time-1 << endl;
638 if (iResult>=0 && channelAddress>=0) {
639 assert(nofBunches==generator.fpSimData->At(dataPos));
640 dataPos++; // DO NOT PUT INTO ASSERT
641 assert(channelAddress==generator.fpSimData->At(dataPos));
642 dataPos++; // DO NOT PUT INTO ASSERT