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);
349 assert(time-1==fpSimData->At(dataPos));
350 dataPos++; // DO NOT PUT INTO ASSERT
351 assert(bunchLength==fpSimData->At(dataPos));
352 dataPos++; // DO NOT PUT INTO ASSERT
355 if (iResult>=0 && channelAddress>=0) {
356 assert(nofBunches==fpSimData->At(dataPos));
357 dataPos++; // DO NOT PUT INTO ASSERT
358 assert(channelAddress==fpSimData->At(dataPos));
359 dataPos++; // DO NOT PUT INTO ASSERT
361 encoder.SetChannel(channelAddress);
365 iResult=(encoder.GetTotal40bitWords()*5)/4;
371 int AliHLTAltroGenerator::GetRandom(int min, int max)
373 // see header file for class documentation
374 if (max-min<2) return min;
375 bool setTheSeed=fpRand!=NULL;
379 if (fpRand==NULL) return min;
382 fpRand->SetSeed(dt.Get());
384 return fpRand->Integer(max-min);
387 int AliHLTAltroGenerator::Reset()
389 // see header file for class documentation
390 fChannelPositions.clear();
396 int AliHLTAltroGenerator::Rewind()
398 // see header file for class documentation
401 fCurrentTimeOffset=-1;
405 bool AliHLTAltroGenerator::Next()
407 // see header file for class documentation
409 if (!fpSimData) return false;
411 if (haveData=(fCurrentTimeOffset>=0 &&
413 ++fCurrentTimeOffset<GetBunchSize())) {
417 if (haveData=(NextBunch() && GetBunchSize()>0)) {
418 fCurrentTimeOffset=0;
421 } while (NextChannel());
425 AliHLTUInt16_t AliHLTAltroGenerator::GetSignal()
427 // see header file for class documentation
428 if (!fpSimData || fCurrentTimeOffset<0) return 0;
429 assert(fCurrentPosition>=0 && fCurrentPosition<(int)fChannelPositions.size());
430 assert(fCurrentBunch>=0);
431 if (fDirection==kForwards) {
432 return fpSimData->At(fCurrentBunch+2+fCurrentTimeOffset);
433 } else if (fDirection==kBackwards){
434 return fpSimData->At(fCurrentBunch-(2+fCurrentTimeOffset));
439 bool AliHLTAltroGenerator::NextChannel()
441 // see header file for class documentation
443 if (fpSimData && fChannelPositions.size()==0) return false;
444 fpSimData->GetArray();
445 if (fCurrentPosition==-1) {
446 if (fDirection==kForwards) fCurrentPosition=0;
447 else fCurrentPosition=fChannelPositions.size()-1;
450 if (fDirection==kForwards && (haveData=(fCurrentPosition+1<(int)fChannelPositions.size()))) {
452 } else if (fDirection==kBackwards && (haveData=(fCurrentPosition>0))) {
458 fCurrentTimeOffset=-1;
462 AliHLTUInt16_t AliHLTAltroGenerator::GetHwAddress()
464 // see header file for class documentation
465 if (fCurrentPosition>=0 && fCurrentPosition<(int)fChannelPositions.size())
466 return fChannelPositions[fCurrentPosition].fChannel;
467 return ~((AliHLTUInt16_t)0);
470 int AliHLTAltroGenerator::GetBunchCount()
472 // see header file for class documentation
473 if (fpSimData && fCurrentPosition>=0 && fCurrentPosition<(int)fChannelPositions.size()) {
474 if (fDirection==kForwards)
475 return fpSimData->At(fChannelPositions[fCurrentPosition].fPosition+1);
476 else if (fDirection==kBackwards)
477 return fpSimData->At(fChannelPositions[fCurrentPosition].fEnd-1);
479 return ~((AliHLTUInt16_t)0);
482 bool AliHLTAltroGenerator::NextBunch()
484 // see header file for class documentation
486 if (fpSimData && fCurrentPosition>=0 && fCurrentPosition<(int)fChannelPositions.size()) {
487 if (fDirection==kBackwards) {
488 if (fCurrentBunch<0) {
489 // bunch count in channel end - 1
490 if (haveData=(fpSimData->At(fChannelPositions[fCurrentPosition].fEnd-1))>0) {
491 // first bunch length at channel end - 2
492 fCurrentBunch=fChannelPositions[fCurrentPosition].fEnd-2;
494 } else if (fCurrentBunch>fChannelPositions[fCurrentPosition].fPosition+1) {
495 fCurrentBunch-=fpSimData->At(fCurrentBunch)+4;
496 haveData=fCurrentBunch>fChannelPositions[fCurrentPosition].fPosition+1;
500 assert(fpSimData->At(fCurrentBunch)==fpSimData->At(fCurrentBunch-fpSimData->At(fCurrentBunch)-3));
501 haveData=fpSimData->At(fCurrentBunch)==fpSimData->At(fCurrentBunch-fpSimData->At(fCurrentBunch)-3);
503 } else if (fDirection==kForwards) {
504 if (fCurrentBunch<0) {
505 // bunch count in channel start + 1
506 if (haveData=(fpSimData->At(fChannelPositions[fCurrentPosition].fPosition+1))>0) {
507 // first bunch length at channel start + 2
508 fCurrentBunch=fChannelPositions[fCurrentPosition].fPosition+2;
510 } else if (fCurrentBunch<fChannelPositions[fCurrentPosition].fEnd-1) {
511 fCurrentBunch+=fpSimData->At(fCurrentBunch)+4;
512 haveData=fCurrentBunch<fChannelPositions[fCurrentPosition].fEnd-1;
516 assert(fpSimData->At(fCurrentBunch)==fpSimData->At(fCurrentBunch+fpSimData->At(fCurrentBunch)+3));
517 haveData=fpSimData->At(fCurrentBunch)==fpSimData->At(fCurrentBunch+fpSimData->At(fCurrentBunch)+3);
521 fCurrentTimeOffset=-1;
525 AliHLTUInt16_t AliHLTAltroGenerator::GetBunchSize()
527 // see header file for class documentation
528 if (fCurrentBunch<0) return 0;
529 if (fCurrentBunch<fChannelPositions[fCurrentPosition].fPosition+2) return 0;
530 if (fCurrentBunch>fChannelPositions[fCurrentPosition].fEnd-2) return 0;
531 return fpSimData->At(fCurrentBunch);
534 AliHLTUInt16_t AliHLTAltroGenerator::GetStartTime()
536 // see header file for class documentation
537 if (!fpSimData || GetBunchSize()==0) return 0;
538 AliHLTUInt16_t startTime=0;
539 if (fDirection==kForwards) {
540 startTime=fpSimData->At(fCurrentBunch+1);
541 } else if (fDirection==kBackwards) {
542 startTime=fpSimData->At(fCurrentBunch-fpSimData->At(fCurrentBunch)-2);
544 if (fCurrentTimeOffset>=0) {
545 if (fDirection==kForwards) {
546 startTime+=fCurrentTimeOffset;
547 } else if (fDirection==kBackwards) {
548 startTime=GetEndTime();
554 AliHLTUInt16_t AliHLTAltroGenerator::GetEndTime()
556 // see header file for class documentation
557 if (!fpSimData || GetBunchSize()==0) return 0;
558 AliHLTUInt16_t endTime=0;
559 if (fDirection==kForwards) {
560 endTime=fpSimData->At(fCurrentBunch+fpSimData->At(fCurrentBunch)+2);
561 } else if (fDirection==kBackwards) {
562 endTime=fpSimData->At(fCurrentBunch-1);
564 if (fCurrentTimeOffset>=0) {
565 assert(fCurrentTimeOffset<fpSimData->At(fCurrentBunch));
566 if (fDirection==kForwards) {
567 endTime=GetStartTime();
568 } else if (fDirection==kBackwards) {
569 endTime-=fCurrentTimeOffset;
575 const Short_t* AliHLTAltroGenerator::GetSignals()
577 // see header file for class documentation
578 if (!fpSimData || GetBunchSize()==0) return NULL;
579 if (fDirection==kForwards) {
580 return fpSimData->GetArray()+fCurrentBunch+2;
581 } else if (fDirection==kBackwards) {
582 return fpSimData->GetArray()+(fCurrentBunch-fpSimData->At(fCurrentBunch)-1);
587 void AliHLTAltroGenerator::Print()
589 // see header file for class documentation
590 cout << *this << endl;
593 ostream &operator<<(ostream &stream, AliHLTAltroGenerator &generator)
595 // see header file for class documentation
597 Short_t channelAddress=-1;
598 for (vector<AliHLTAltroGenerator::AliChannelPosition>::iterator element=generator.fChannelPositions.begin();
599 element!=generator.fChannelPositions.end() && iResult>=0;
601 if (!generator.fpSimData ||
602 generator.fpSimData->GetSize()<=element->fPosition ||
603 generator.fNof10BitWords==0) {
604 stream << "AliHLTAltroGenerator: no data available" << endl;;
607 channelAddress=element->fChannel;
608 assert(generator.fpSimData->At(element->fPosition)==channelAddress);
609 if (generator.fpSimData->At(element->fPosition)!=channelAddress) {
610 stream << "AliHLTAltroGenerator: internal data mismatch" << endl;;
614 int dataPos=element->fPosition+1;
615 int nofBunches=generator.fpSimData->At(dataPos++);
616 stream << "***************************************************************" << endl;
617 stream << "channel address: " << channelAddress << " " << nofBunches << " bunch(es)" << endl;
619 for (; bunch<nofBunches; bunch++) {
620 int bunchLength=generator.fpSimData->At(dataPos++);
621 int startTime=generator.fpSimData->At(dataPos++);
623 stream << " length " << bunchLength << " start time " << startTime << ": ";
624 for (; time<startTime+bunchLength; time++) {
625 stream << " " << generator.fpSimData->At(dataPos++);
627 assert(time-1==generator.fpSimData->At(dataPos));
628 dataPos++; // DO NOT PUT INTO ASSERT
629 assert(bunchLength==generator.fpSimData->At(dataPos));
630 dataPos++; // DO NOT PUT INTO ASSERT
631 stream << " -> end time " << time-1 << endl;
634 if (iResult>=0 && channelAddress>=0) {
635 assert(nofBunches==generator.fpSimData->At(dataPos));
636 dataPos++; // DO NOT PUT INTO ASSERT
637 assert(channelAddress==generator.fpSimData->At(dataPos));
638 dataPos++; // DO NOT PUT INTO ASSERT