ALIROOT-5433 Transition to CDHv3 in HLT
[u/mrichter/AliRoot.git] / HLT / RCU / AliHLTAltroGenerator.cxx
CommitLineData
c3800c65 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 AliHLTAltroGenerator.cxx
20 @author Matthias Richter
21 @date
22 @brief Simulation class of 10/40bit Altro Data.
23*/
24
25#include <cassert>
26#include <cerrno>
27#include "AliHLTAltroGenerator.h"
28#include "TArrayS.h"
29#include "TArrayC.h"
30#include "TRandom.h"
31#include "TDatime.h"
16e6f752 32#include "AliRawDataHeaderV3.h"
c3800c65 33#include "AliHLTAltroEncoder.h"
34
35/** ROOT macro for the implementation of ROOT specific class methods */
36ClassImp(AliHLTAltroGenerator)
37
38AliHLTAltroGenerator::AliHLTAltroGenerator(int maxChannels,
39 int maxBunches,
40 int maxBunchLength,
41 int maxTimebin,
42 int maxSignal)
43 :
44 fpData(NULL),
45 fpSimData(NULL),
46 fChannelPositions(),
47 fNof10BitWords(0),
48 fpCDH(NULL),
49 fCDHSize(0),
50 fpTrailer(NULL),
51 fTrailerSize(0),
52 fMaxChannels(maxChannels),
53 fMaxBunches(maxBunches),
54 fMaxBunchLength(maxBunchLength),
55 fMaxTimebin(maxTimebin),
56 fMaxSignal(maxSignal),
57 fpRand(NULL),
58 fDirection(kBackwards),
59 fCurrentPosition(-1),
60 fCurrentBunch(-1),
61 fCurrentTimeOffset(-1)
62{
63 // see header file for class documentation
64 // or
65 // refer to README to build package
66 // or
67 // visit http://web.ift.uib.no/~kjeks/doc/alice-hlt
68}
69
70AliHLTAltroGenerator::~AliHLTAltroGenerator()
71{
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;
77}
78
79int AliHLTAltroGenerator::Generate()
80{
81 // see header file for class documentation
c3800c65 82 if (!fpSimData) fpSimData=new TArrayS;
83 if (!fpSimData) {
84 return -ENOMEM;
85 }
86
87 Reset();
88
89 int nofChannels=GetRandom(1, fMaxChannels);
90 if (nofChannels==0) nofChannels=1;
91
92 HLTDebug("number of channels: %d", nofChannels);
93 int channelAddress=-1;
94 int lastChannel=-1;
95 int dataPos=0;
96 int repetitions=0;
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) {
101 channel--;
102 if (repetitions++>5) break;
103 continue;
104 }
105 int nofBunches=GetRandom(1, fMaxBunches);
106 if (nofBunches==0) {
107 channel--;
108 if (repetitions++>5) break;
109 continue;
110 }
111 repetitions=0;
112 int totalBunches=0;
b0714bad 113 int bunchEndTime=0;
114 int lastBunchEndTime=0;
c3800c65 115
116 HLTDebug("simulate channel %d: address %d", channel, channelAddress);
117
118 // save beginning of this channel for better navigation
2cb809a5 119 AliChannelPosition position={static_cast<AliHLTUInt16_t>(channelAddress), dataPos, 0};
c3800c65 120
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
125
126 int bunch=0;
b0714bad 127
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
134 // minus its length.
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++) {
95e36f3d 137 while ((bunchEndTime+=GetRandom(0, fMaxTimebin-bunchEndTime))-lastBunchEndTime<3) {/*empty body*/};
b0714bad 138 int bunchLength=GetRandom(0, bunchEndTime-lastBunchEndTime<fMaxBunchLength?bunchEndTime-lastBunchEndTime:fMaxBunchLength);
c3800c65 139 if (bunchLength==0) continue;
140 totalBunches++;
141
142 HLTDebug(" bunch %d, length %d, end time %d ", bunch, bunchLength, bunchEndTime);
143
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;
152 }
153 (*fpSimData)[dataPos++]=bunchEndTime;
154 (*fpSimData)[dataPos++]=bunchLength;
155 fNof10BitWords+=bunchLength+2;
b0714bad 156 lastBunchEndTime=bunchEndTime;
157 bunchEndTime+=bunchLength;
c3800c65 158 }
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);
170 } else {
171 dataPos-=2;
172 HLTDebug(" channel %d skipped: address %d, %d bunch(es)", channel, channelAddress, totalBunches);
173 }
174 }
175
176 assert(fNof10BitWords%4==0);
c3800c65 177 fpSimData->Set(dataPos);
178 return GetDataSize();
179}
180
181int AliHLTAltroGenerator::GetNof40BitAltroWords() const
182{
183 // see header file for class documentation
184 assert(fNof10BitWords%4==0);
185 return fNof10BitWords/4;
186}
187
188int AliHLTAltroGenerator::GetDataSize()
189{
190 // see header file for class documentation
191 int iResult=0;
192 iResult=(fNof10BitWords*5)/4;
193 if (fpTrailer) {
194 *(reinterpret_cast<AliHLTUInt32_t*>(fpTrailer))=GetNof40BitAltroWords();
195 iResult+=fTrailerSize;
196 }
197 if (fpCDH) iResult+=fCDHSize;
198 return iResult;
199}
200
201int AliHLTAltroGenerator::GetData(AliHLTUInt8_t* &pBuffer)
202{
203 // see header file for class documentation
204 int iResult=GetDataSize();
205 if (iResult>0) {
206 if (!fpData) fpData=new TArrayC(iResult);
207 if (fpData) {
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());
211 }
212 } else {
213 iResult=-ENOMEM;
214 }
215 }
216 return iResult;
217}
218
219int AliHLTAltroGenerator::GetData(AliHLTUInt8_t* pBuffer, int size)
220{
221 // see header file for class documentation
222 int iResult=0;
223 int dataPos=0;
224
225 if (size<GetDataSize()) return -ENOSPC;
226
227 // copy Common Data Header
228 if (fpCDH) {
229 fpCDH->fSize=GetDataSize();
230 memcpy(pBuffer+dataPos, fpCDH, fCDHSize);
231 dataPos+=fCDHSize;
232 }
233
234 // encode simulated data
235 if ((iResult=EncodeData(pBuffer+dataPos, size-dataPos))>=0) {
236 dataPos+=iResult;
237 }
238
239 // copy trailer
240 if (fpTrailer) {
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;
245 }
246
247 if (iResult<0) return iResult;
248 assert(fpCDH==NULL || (int)fpCDH->fSize==dataPos);
249 return dataPos;
250}
251
16e6f752 252int AliHLTAltroGenerator::SetCDH(AliRawDataHeaderV3* pCDH, int size)
c3800c65 253{
254 // see header file for class documentation
255 int iResult=0;
256 if (pCDH && size>0) {
257 if (fpCDH) delete[] fpCDH;
16e6f752 258 fpCDH=new AliRawDataHeaderV3;
c3800c65 259 if (fpCDH) {
260 memcpy(fpCDH, pCDH, size);
261 fCDHSize=size;
262 } else {
263 iResult=-ENOMEM;
264 }
265 } else {
266 iResult=-EINVAL;
267 }
268 return iResult;
269}
270
271int AliHLTAltroGenerator::SetRCUTrailer(AliHLTUInt8_t* pTrailer, int size)
272{
273 // see header file for class documentation
274 int iResult=0;
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)");
281 return -EBADF;
282 }
283 }
284 if (fpTrailer) delete[] fpTrailer;
285 fpTrailer=new AliHLTUInt8_t[size];
286 if (fpTrailer) {
287 memcpy(fpTrailer, pTrailer, size);
288 fTrailerSize=size;
289 } else {
290 iResult=-ENOMEM;
291 }
292 } else {
293 iResult=-EINVAL;
294 }
295 return iResult;
296}
297
298int AliHLTAltroGenerator::GetChannels(vector<AliHLTUInt16_t> list)
299{
300 // see header file for class documentation
301 int iResult=0;
302 list.clear();
303 for (vector<AliChannelPosition>::iterator element=fChannelPositions.begin();
304 element!=fChannelPositions.end();
305 element++) {
306 list.push_back(element->fChannel);
307 }
308 iResult=list.size();
309 return iResult;
310}
311
312int AliHLTAltroGenerator::SetSorting(AliHLTUInt16_t */*array*/, int /*arraySize*/)
313{
314 // see header file for class documentation
315 int iResult=0;
316 HLTError("function not yet implemented");
317 return iResult;
318}
319
320int AliHLTAltroGenerator::EncodeData(AliHLTUInt8_t* pBuffer, int size)
321{
322 // see header file for class documentation
323 int iResult=0;
324 if (!pBuffer) return -EINVAL;
325
326 AliHLTAltroEncoder encoder;
327 encoder.SetBuffer(pBuffer, size);
328
329 Short_t channelAddress=-1;
330 for (vector<AliChannelPosition>::iterator element=fChannelPositions.begin();
331 element!=fChannelPositions.end() && iResult>=0;
332 element++) {
333 if (!fpSimData ||
334 fpSimData->GetSize()<=element->fPosition ||
335 fNof10BitWords==0) {
336 iResult=-ENODATA;
337 break;
338 }
339 channelAddress=element->fChannel;
340 assert(fpSimData->At(element->fPosition)==channelAddress);
341 if (fpSimData->At(element->fPosition)!=channelAddress) {
342 iResult=-ENODATA;
343 break;
344 }
345 int dataPos=element->fPosition+1;
346 int nofBunches=fpSimData->At(dataPos++);
347 int bunch=0;
348 for (; bunch<nofBunches; bunch++) {
349 int bunchLength=fpSimData->At(dataPos++);
350 int startTime=fpSimData->At(dataPos++);
351 int time=startTime;
352 for (; time<startTime+bunchLength; time++) {
c5123824 353 iResult=encoder.AddSignal(fpSimData->At(dataPos++), time);
c3800c65 354 }
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
359 }
360
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
366 }
c5123824 367 encoder.SetChannel(channelAddress);
c3800c65 368 }
c3800c65 369
370 if (iResult>=0) {
371 iResult=(encoder.GetTotal40bitWords()*5)/4;
372 }
373
374 return iResult;
375}
376
377int AliHLTAltroGenerator::GetRandom(int min, int max)
378{
379 // see header file for class documentation
380 if (max-min<2) return min;
381 bool setTheSeed=fpRand!=NULL;
382 if (fpRand==NULL) {
383 fpRand=new TRandom;
384 }
385 if (fpRand==NULL) return min;
386 if (!setTheSeed) {
387 TDatime dt;
388 fpRand->SetSeed(dt.Get());
389 }
390 return fpRand->Integer(max-min);
391}
392
393int AliHLTAltroGenerator::Reset()
394{
395 // see header file for class documentation
396 fChannelPositions.clear();
397 fNof10BitWords=0;
398 Rewind();
399 return 0;
400}
401
402int AliHLTAltroGenerator::Rewind()
403{
404 // see header file for class documentation
405 fCurrentPosition=-1;
406 fCurrentBunch=-1;
407 fCurrentTimeOffset=-1;
408 return 0;
409}
410
411bool AliHLTAltroGenerator::Next()
412{
413 // see header file for class documentation
414 bool haveData=false;
415 if (!fpSimData) return false;
416 do {
32f88fc5 417 if ((haveData=(fCurrentTimeOffset>=0 &&
418 fCurrentBunch>0 &&
419 ++fCurrentTimeOffset<GetBunchSize()))) {
c3800c65 420 break;
421 }
422
32f88fc5 423 if ((haveData=(NextBunch()) && GetBunchSize()>0)) {
c3800c65 424 fCurrentTimeOffset=0;
425 break;
426 }
427 } while (NextChannel());
428 return haveData;
429}
430
431AliHLTUInt16_t AliHLTAltroGenerator::GetSignal()
432{
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));
441 }
442 return 0;
443}
444
445bool AliHLTAltroGenerator::NextChannel()
446{
447 // see header file for class documentation
448 bool haveData=false;
59c0011e 449 if (!fpSimData || fChannelPositions.size()==0) return false;
c3800c65 450 fpSimData->GetArray();
451 if (fCurrentPosition==-1) {
452 if (fDirection==kForwards) fCurrentPosition=0;
453 else fCurrentPosition=fChannelPositions.size()-1;
454 haveData=true;
455 } else {
456 if (fDirection==kForwards && (haveData=(fCurrentPosition+1<(int)fChannelPositions.size()))) {
457 fCurrentPosition++;
458 } else if (fDirection==kBackwards && (haveData=(fCurrentPosition>0))) {
459 fCurrentPosition--;
460 }
461 }
462
463 fCurrentBunch=-1;
464 fCurrentTimeOffset=-1;
465 return haveData;
466}
467
468AliHLTUInt16_t AliHLTAltroGenerator::GetHwAddress()
469{
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);
474}
475
476int AliHLTAltroGenerator::GetBunchCount()
477{
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);
484 }
485 return ~((AliHLTUInt16_t)0);
486}
487
488bool AliHLTAltroGenerator::NextBunch()
489{
490 // see header file for class documentation
491 bool haveData=false;
492 if (fpSimData && fCurrentPosition>=0 && fCurrentPosition<(int)fChannelPositions.size()) {
493 if (fDirection==kBackwards) {
494 if (fCurrentBunch<0) {
495 // bunch count in channel end - 1
32f88fc5 496 if ((haveData=(fpSimData->At(fChannelPositions[fCurrentPosition].fEnd-1))>0)) {
c3800c65 497 // first bunch length at channel end - 2
498 fCurrentBunch=fChannelPositions[fCurrentPosition].fEnd-2;
499 }
500 } else if (fCurrentBunch>fChannelPositions[fCurrentPosition].fPosition+1) {
501 fCurrentBunch-=fpSimData->At(fCurrentBunch)+4;
502 haveData=fCurrentBunch>fChannelPositions[fCurrentPosition].fPosition+1;
503 }
504 // cross check
505 if (haveData) {
506 assert(fpSimData->At(fCurrentBunch)==fpSimData->At(fCurrentBunch-fpSimData->At(fCurrentBunch)-3));
507 haveData=fpSimData->At(fCurrentBunch)==fpSimData->At(fCurrentBunch-fpSimData->At(fCurrentBunch)-3);
508 }
509 } else if (fDirection==kForwards) {
510 if (fCurrentBunch<0) {
511 // bunch count in channel start + 1
32f88fc5 512 if ((haveData=(fpSimData->At(fChannelPositions[fCurrentPosition].fPosition+1))>0)) {
c3800c65 513 // first bunch length at channel start + 2
514 fCurrentBunch=fChannelPositions[fCurrentPosition].fPosition+2;
515 }
516 } else if (fCurrentBunch<fChannelPositions[fCurrentPosition].fEnd-1) {
517 fCurrentBunch+=fpSimData->At(fCurrentBunch)+4;
518 haveData=fCurrentBunch<fChannelPositions[fCurrentPosition].fEnd-1;
519 }
520 // cross check
521 if (haveData) {
522 assert(fpSimData->At(fCurrentBunch)==fpSimData->At(fCurrentBunch+fpSimData->At(fCurrentBunch)+3));
523 haveData=fpSimData->At(fCurrentBunch)==fpSimData->At(fCurrentBunch+fpSimData->At(fCurrentBunch)+3);
524 }
525 }
526 }
527 fCurrentTimeOffset=-1;
528 return haveData;
529}
530
531AliHLTUInt16_t AliHLTAltroGenerator::GetBunchSize()
532{
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);
538}
539
540AliHLTUInt16_t AliHLTAltroGenerator::GetStartTime()
541{
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);
549 }
550 if (fCurrentTimeOffset>=0) {
551 if (fDirection==kForwards) {
552 startTime+=fCurrentTimeOffset;
553 } else if (fDirection==kBackwards) {
554 startTime=GetEndTime();
555 }
556 }
557 return startTime;
558}
559
560AliHLTUInt16_t AliHLTAltroGenerator::GetEndTime()
561{
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);
569 }
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;
576 }
577 }
578 return endTime;
579}
580
581const Short_t* AliHLTAltroGenerator::GetSignals()
582{
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);
589 }
590 return NULL;
591}
592
593void AliHLTAltroGenerator::Print()
594{
595 // see header file for class documentation
596 cout << *this << endl;
597}
598
599ostream &operator<<(ostream &stream, AliHLTAltroGenerator &generator)
600{
601 // see header file for class documentation
602 int iResult=0;
603 Short_t channelAddress=-1;
604 for (vector<AliHLTAltroGenerator::AliChannelPosition>::iterator element=generator.fChannelPositions.begin();
605 element!=generator.fChannelPositions.end() && iResult>=0;
606 element++) {
607 if (!generator.fpSimData ||
608 generator.fpSimData->GetSize()<=element->fPosition ||
609 generator.fNof10BitWords==0) {
610 stream << "AliHLTAltroGenerator: no data available" << endl;;
611 break;
612 }
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;;
617 iResult=-ENODATA;
618 break;
619 }
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;
624 int bunch=0;
625 for (; bunch<nofBunches; bunch++) {
626 int bunchLength=generator.fpSimData->At(dataPos++);
627 int startTime=generator.fpSimData->At(dataPos++);
628 int time=startTime;
629 stream << " length " << bunchLength << " start time " << startTime << ": ";
630 for (; time<startTime+bunchLength; time++) {
631 stream << " " << generator.fpSimData->At(dataPos++);
632 }
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;
638 }
639
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
645 }
646 }
647
648 return stream;
649}