]> git.uio.no Git - u/mrichter/AliRoot.git/blame - MUON/AliMUONRawStreamTrackerHP.cxx
fDebug is in baseclass.
[u/mrichter/AliRoot.git] / MUON / AliMUONRawStreamTrackerHP.cxx
CommitLineData
e3a2b9c9 1/**************************************************************************
2 * This file is property of and copyright by the ALICE HLT Project *
3 * All rights reserved. *
4 * *
5 * Primary Authors: *
6 * Artur Szostak <artursz@iafrica.com> *
7 * *
8 * Permission to use, copy, modify and distribute this software and its *
9 * documentation strictly for non-commercial purposes is hereby granted *
10 * without fee, provided that the above copyright notice appears in all *
11 * copies and that both the copyright notice and this permission notice *
12 * appear in the supporting documentation. The authors make no claims *
13 * about the suitability of this software for any purpose. It is *
14 * provided "as is" without express or implied warranty. *
15 **************************************************************************/
16
17/* $Id$*/
18
19///
20/// \file AliMUONRawStreamTrackerHP.cxx
21/// \author Artur Szostak <artursz@iafrica.com>
22/// \date 29-11-2007
23/// \brief Implementation of the the high performance decoder AliMUONRawStreamTrackerHP.
24///
25
26//-----------------------------------------------------------------------------
27/// \ingroup raw
28/// \class AliMUONRawStreamTrackerHP
29/// \brief A high performance stream decoder for muon tracking DDL streams.
30///
31/// This is the raw stream class which interfaces between the high performance
32/// core decoder and the AliRawReader class.
33/// To gain the most out of the decoder, the Next() method which returns batches
34/// of decoded digit / channel information should be used. That is:
35/// \code
8a0dae7c 36/// const AliBusPatch* Next();
e3a2b9c9 37/// \endcode
38///
8a0dae7c 39/// This decoder tries to implement as similar an interface as possible to
40/// AliMUONRawStreamTracker where possible. However certain constructs which
41/// would slow us down too much are avoided.
42///
e3a2b9c9 43/// \author Artur Szostak <artursz@iafrica.com>
44//-----------------------------------------------------------------------------
45
46#include "AliMUONRawStreamTrackerHP.h"
47#include "AliRawReader.h"
48#include "AliLog.h"
49#include <cassert>
8a0dae7c 50#include <iostream>
51#include <iomanip>
52using std::cout;
53using std::endl;
54using std::hex;
55using std::dec;
e3a2b9c9 56
57/// \cond CLASSIMP
58ClassImp(AliMUONRawStreamTrackerHP)
59/// \endcond
60
61
62AliMUONRawStreamTrackerHP::AliMUONRawStreamTrackerHP() :
63 AliMUONVRawStreamTracker(),
64 fDecoder(),
65 fDDL(0),
e3a2b9c9 66 fBufferSize(8192),
67 fBuffer(new UChar_t[8192]),
8a0dae7c 68 fCurrentBusPatch(NULL),
69 fCurrentData(NULL),
70 fEndOfData(NULL),
71 fHadError(kFALSE),
72 fDone(kFALSE)
e3a2b9c9 73{
74 ///
75 /// Default constructor.
76 ///
8a0dae7c 77
78 // Must set this flag to get all information about parity errors though
79 // the OnData method. OnError gets them either way.
80 fDecoder.ExitOnError(false);
81 fDecoder.SendDataOnParityError(true);
82
83 fDecoder.GetHandler().SetMaxStructs(
84 fDecoder.MaxBlocks(),
85 fDecoder.MaxDSPs(),
86 fDecoder.MaxBusPatches()
87 );
88
89 fDecoder.GetHandler().SetRawStream(this);
e3a2b9c9 90}
91
92
93AliMUONRawStreamTrackerHP::AliMUONRawStreamTrackerHP(AliRawReader* rawReader) :
94 AliMUONVRawStreamTracker(rawReader),
95 fDecoder(),
96 fDDL(0),
e3a2b9c9 97 fBufferSize(8192),
98 fBuffer(new UChar_t[8192]),
8a0dae7c 99 fCurrentBusPatch(NULL),
100 fCurrentData(NULL),
101 fEndOfData(NULL),
102 fHadError(kFALSE),
103 fDone(kFALSE)
e3a2b9c9 104{
105 ///
106 /// Constructor with AliRawReader as argument.
107 ///
108
8a0dae7c 109 // Must set this flag to get all information about parity errors though
110 // the OnData method. OnError gets them either way.
111 fDecoder.ExitOnError(false);
112 fDecoder.SendDataOnParityError(true);
113
114 fDecoder.GetHandler().SetMaxStructs(
115 fDecoder.MaxBlocks(),
116 fDecoder.MaxDSPs(),
117 fDecoder.MaxBusPatches()
118 );
119
e3a2b9c9 120 fDecoder.GetHandler().SetRawStream(this);
121}
122
123
124AliMUONRawStreamTrackerHP::~AliMUONRawStreamTrackerHP()
125{
126 ///
127 /// Default destructor.
128 ///
129
130 if (fBuffer != NULL)
131 {
132 delete [] fBuffer;
133 }
134}
135
136
137void AliMUONRawStreamTrackerHP::First()
138{
139 /// Initialise or reset the iterator.
140 /// The first DDL will be found and decoded.
141
142 assert( GetReader() != NULL );
143
144 fDDL = 0;
8a0dae7c 145 fDone = kFALSE;
e3a2b9c9 146 NextDDL();
147}
148
149
150Bool_t AliMUONRawStreamTrackerHP::NextDDL()
151{
152 /// Reading the next tracker DDL and decode the payload with the
153 /// high performance decoder.
154 /// \return kTRUE if the next DDL was successfully read and kFALSE otherwise.
155
156 assert( GetReader() != NULL );
157
8a0dae7c 158 while (fDDL < GetMaxDDL())
e3a2b9c9 159 {
160 GetReader()->Reset();
161 GetReader()->Select("MUONTRK", fDDL, fDDL); // Select the DDL file to be read.
162 if (GetReader()->ReadHeader()) break;
163 AliDebug(3, Form("Skipping DDL %d which does not seem to be there", fDDL+1));
164 fDDL++;
165 }
8a0dae7c 166
167 // If we reach the end of the DDL list for this event then reset the
168 // DDL counter, mark the iteration as done and
169 if (fDDL >= GetMaxDDL())
170 {
171 fDDL = 0;
172 fDone = kTRUE;
173 return kFALSE;
174 }
175 else
176 {
177 fDone = kFALSE;
178 }
179
e3a2b9c9 180 AliDebug(3, Form("DDL Number %d\n", fDDL));
181
182 Int_t dataSize = GetReader()->GetDataSize(); // in bytes
183 // Check if we have enough buffer space already in fBuffer. If we do then
184 // just continue reading otherwise we need to resize the buffer.
185 if (fBufferSize < dataSize)
186 {
187 if (fBuffer != NULL)
188 {
189 delete [] fBuffer;
190 fBuffer = NULL;
191 fBufferSize = 0;
192 }
193 try
194 {
195 fBuffer = new UChar_t[dataSize];
196 fBufferSize = dataSize;
197 }
198 catch (const std::bad_alloc&)
199 {
200 AliError("Could not allocate more buffer space. Cannot decode DDL.");
201 return kFALSE;
202 }
203 }
204
205 if (not GetReader()->ReadNext(fBuffer, dataSize))
206 {
207 return kFALSE;
208 }
209
210#ifndef R__BYTESWAP
ab0129ae 211 Swap(reinterpret_cast<UInt_t*>(fBuffer), dataSize / sizeof(UInt_t)); // Swap needed for mac power pc.
e3a2b9c9 212#endif
213
214 bool result = false;
215 try
216 {
217 // Since we might allocate memory inside OnNewBuffer in the event
218 // handler we need to trap any memory allocation exception to be robust.
219 result = fDecoder.Decode(fBuffer, dataSize);
8a0dae7c 220 fHadError = (result == true ? kFALSE : kTRUE);
e3a2b9c9 221 }
222 catch (const std::bad_alloc&)
223 {
224 AliError("Could not allocate more buffer space. Cannot decode DDL.");
225 return kFALSE;
226 }
8a0dae7c 227
228 // Update the current bus patch pointers.
229 fCurrentBusPatch = fDecoder.GetHandler().FirstBusPatch();
230 if (fCurrentBusPatch != fDecoder.GetHandler().EndOfBusPatch())
231 {
232 fCurrentData = fCurrentBusPatch->GetData();
233 fEndOfData = fCurrentData + fCurrentBusPatch->GetDataCount();
234 }
235 else
236 {
237 // If the DDL did not have any bus patches then mark both fCurrentData
238 // and fEndOfData as NULL so that in Next() we are forced to find the
239 // first non empty DDL.
240 fCurrentData = fEndOfData = NULL;
241 }
242
e3a2b9c9 243 fDDL++; // Remember to increment index to next DDL.
244 return result;
245}
246
247
248Bool_t AliMUONRawStreamTrackerHP::IsDone() const
249{
250 /// Indicates whether the iteration is finished or not.
251 /// \return kTRUE if we already read all the digits and kFALSE if not.
252
8a0dae7c 253 return fDone;
e3a2b9c9 254}
255
256
257Bool_t AliMUONRawStreamTrackerHP::Next(
258 Int_t& busPatchId, UShort_t& manuId, UChar_t& manuChannel,
259 UShort_t& adc
260 )
261{
262 /// Advance one step in the iteration. Returns false if finished.
263 /// [out] \param busPatchId This is filled with the bus patch ID of the digit.
264 /// [out] \param manuId This is filled with the MANU ID of the digit.
265 /// [out] \param manuChannel This is filled with the MANU channel ID of the digit.
266 /// [out] \param adc This is filled with the ADC signal value of the digit.
267 /// \return kTRUE if we read another digit and kFALSE if we have read all the
268 /// digits already, i.e. at the end of the iteration.
269
8a0dae7c 270retry:
271 // Check if we still have data to be returned for the current bus patch.
272 if (fCurrentData != fEndOfData)
e3a2b9c9 273 {
8a0dae7c 274 busPatchId = fCurrentBusPatch->GetBusPatchId();
275 AliMUONTrackerDDLDecoderEventHandler::UnpackADC(*fCurrentData, manuId, manuChannel, adc);
276 fCurrentData++;
e3a2b9c9 277 return kTRUE;
278 }
279 else
280 {
8a0dae7c 281 // We hit the end of the current bus patch so check if we have any more
282 // bus patches to process for the current DDL. If we do, then increment
283 // the current bus patch, make sure it is not the last one and then try
284 // reading the first element again.
285 if (fCurrentBusPatch != fDecoder.GetHandler().EndOfBusPatch())
e3a2b9c9 286 {
8a0dae7c 287 fCurrentBusPatch++;
288 if (fCurrentBusPatch != fDecoder.GetHandler().EndOfBusPatch())
e3a2b9c9 289 {
8a0dae7c 290 fCurrentData = fCurrentBusPatch->GetData();
291 fEndOfData = fCurrentData + fCurrentBusPatch->GetDataCount();
292 goto retry;
e3a2b9c9 293 }
294 }
8a0dae7c 295
296 // This was the last bus patch in the DDL so read in the next one and
297 // try reading the first data element again.
298 // Note: fCurrentBusPatch is set inside NextDDL().
299 if (NextDDL()) goto retry;
e3a2b9c9 300 }
301 return kFALSE;
302}
303
304
8a0dae7c 305void AliMUONRawStreamTrackerHP::SetMaxBlock(Int_t blk)
e3a2b9c9 306{
8a0dae7c 307 /// Set maximum number of blocks per DDL allowed.
308 fDecoder.MaxBlocks( (UInt_t) blk );
e3a2b9c9 309
8a0dae7c 310 fDecoder.GetHandler().SetMaxStructs(
311 fDecoder.MaxBlocks(),
312 fDecoder.MaxDSPs(),
313 fDecoder.MaxBusPatches()
314 );
315}
316
317
318void AliMUONRawStreamTrackerHP::SetMaxDsp(Int_t dsp)
319{
320 /// Set maximum number of Dsp per block allowed.
321 fDecoder.MaxDSPs( (UInt_t) dsp );
322
323 fDecoder.GetHandler().SetMaxStructs(
324 fDecoder.MaxBlocks(),
325 fDecoder.MaxDSPs(),
326 fDecoder.MaxBusPatches()
327 );
328}
329
330
331void AliMUONRawStreamTrackerHP::SetMaxBus(Int_t bus)
332{
333 /// Set maximum number of Buspatch per Dsp allowed.
334 fDecoder.MaxBusPatches( (UInt_t) bus );
335
336 fDecoder.GetHandler().SetMaxStructs(
337 fDecoder.MaxBlocks(),
338 fDecoder.MaxDSPs(),
339 fDecoder.MaxBusPatches()
340 );
341}
342
343///////////////////////////////////////////////////////////////////////////////
344
345void AliMUONRawStreamTrackerHP::AliBlockHeader::Print() const
346{
347 /// Print header to screen.
348
349 cout << "CRT info" << endl;
350 if (fHeader == NULL)
e3a2b9c9 351 {
8a0dae7c 352 cout << "Header is NULL" << endl;
353 return;
354 }
355 cout << "DataKey: 0x" << hex << fHeader->fDataKey << dec << endl;
356 cout << "TotalLength: " << fHeader->fTotalLength << endl;
357 cout << "Length: " << fHeader->fLength << endl;
358 cout << "DspId: " << fHeader->fDSPId << endl;
359 cout << "L0Trigger: " << fHeader->fL0Trigger << endl;
360 cout << "MiniEventId: " << fHeader->fMiniEventId<< endl;
361 cout << "EventId1: " << fHeader->fEventId1 << endl;
362 cout << "EventId2: " << fHeader->fEventId2 << endl;
363}
364
365
366void AliMUONRawStreamTrackerHP::AliDspHeader::Print() const
367{
368 /// Print header to screen.
369
370 cout << "FRT info" << endl;
371 if (fHeader == NULL)
372 {
373 cout << "Header is NULL" << endl;
374 return;
375 }
376 cout << "DataKey: 0x" << hex << fHeader->fDataKey << dec << endl;
377 cout << "TotalLength: " << fHeader->fTotalLength << endl;
378 cout << "Length : " << fHeader->fLength << endl;
379 cout << "DspId: " << fHeader->fDSPId << endl;
380 cout << "BlkL1ATrigger: " << fHeader->fBlkL1ATrigger << endl;
381 cout << "MiniEventId: " << fHeader->fMiniEventId << endl;
382 cout << "L1ATrigger: " << fHeader->fL1ATrigger << endl;
383 cout << "L1RTrigger: " << fHeader->fL1RTrigger << endl;
384 cout << "PaddingWord: " << fHeader->fPaddingWord << endl;
385 cout << "ErrorWord: " << fHeader->fErrorWord << endl;
386}
387
388
389void AliMUONRawStreamTrackerHP::AliBusPatch::Print(const Option_t* opt) const
390{
391 /// Print header to screen.
392 cout << "Bus patch info" << endl;
393 if (fHeader == NULL)
394 {
395 cout << "Header is NULL" << endl;
396 return;
397 }
398 cout << "DataKey: 0x" << hex << fHeader->fDataKey << dec << endl;
399 cout << "fTotalLength: " << fHeader->fTotalLength << endl;
400 cout << "fLength: " << fHeader->fLength << endl;
401 cout << "fBusPatchId: " << fHeader->fBusPatchId << endl;
402
403 if (TString(opt).Contains("all"))
404 {
405 for (UInt_t i = 0; i < fHeader->fLength; ++i)
406 cout << "Data["<< i << "] = " << fData[i] << endl;
e3a2b9c9 407 }
e3a2b9c9 408}
409
410///////////////////////////////////////////////////////////////////////////////
411
412AliMUONRawStreamTrackerHP::AliDecoderEventHandler::AliDecoderEventHandler() :
e3a2b9c9 413 fRawStream(NULL),
8a0dae7c 414 fBufferStart(NULL),
415 fBlockCount(0),
416 fBlocks(NULL),
417 fDSPs(NULL),
418 fBusPatches(NULL),
419 fEndOfBusPatches(NULL),
420 fMaxChannels(8192),
421 fParityOk(new Bool_t[8192]),
422 fCurrentBlock(NULL),
423 fCurrentDSP(NULL),
424 fCurrentBusPatch(NULL),
425 fCurrentParityOkFlag(NULL),
426 fParityErrors(0),
427 fGlitchErrors(0),
428 fPaddingErrors(0),
429 fWarnings(kTRUE)
e3a2b9c9 430{
8a0dae7c 431 /// Default constructor initialises the internal parity flags buffer to
432 /// store 8192 elements. This array will grow dynamically if needed.
e3a2b9c9 433}
434
435
436AliMUONRawStreamTrackerHP::AliDecoderEventHandler::~AliDecoderEventHandler()
437{
438 /// Default destructor cleans up the allocated memory.
439
8a0dae7c 440 if (fParityOk != NULL) delete [] fParityOk;
441 if (fBlocks != NULL) delete [] fBlocks;
442 if (fDSPs != NULL) delete [] fDSPs;
443 if (fBusPatches != NULL) delete [] fBusPatches;
444}
445
446
447void AliMUONRawStreamTrackerHP::AliDecoderEventHandler::SetMaxStructs(
448 UInt_t maxBlocks, UInt_t maxDsps, UInt_t maxBusPatches
449 )
450{
451 /// Sets the maximum number of structures allowed.
452
453 // Start by clearing the current arrays.
454 if (fBlocks != NULL)
455 {
456 delete [] fBlocks;
457 fBlocks = NULL;
458 }
459 if (fDSPs != NULL)
e3a2b9c9 460 {
8a0dae7c 461 delete [] fDSPs;
462 fDSPs = NULL;
e3a2b9c9 463 }
8a0dae7c 464 if (fBusPatches != NULL)
465 {
466 delete [] fBusPatches;
467 fBusPatches = NULL;
468 }
469 fCurrentBlock = NULL;
470 fCurrentDSP = NULL;
471 fCurrentBusPatch = NULL;
472
473 // Allocate new memory.
474 fBlocks = new AliBlockHeader[maxBlocks];
475 fDSPs = new AliDspHeader[maxBlocks*maxDsps];
476 fBusPatches = new AliBusPatch[maxBlocks*maxDsps*maxBusPatches];
477 fEndOfBusPatches = fEndOfBusPatches;
e3a2b9c9 478}
479
8a0dae7c 480
e3a2b9c9 481void AliMUONRawStreamTrackerHP::AliDecoderEventHandler::OnNewBuffer(
482 const void* buffer, UInt_t bufferSize
483 )
484{
485 /// This is called by the high performance decoder when a new DDL payload
486 /// is about to be decoded.
487 /// \param buffer The pointer to the buffer storing the DDL payload.
488 /// \param bufferSize The size of the buffer in bytes.
489
8a0dae7c 490 assert( fRawStream != NULL );
491
e3a2b9c9 492 // remember the start of the buffer to be used in OnError.
493 fBufferStart = buffer;
8a0dae7c 494
495 // Reset error counters.
496 fParityErrors = 0;
497 fGlitchErrors = 0;
498 fPaddingErrors = 0;
499
500 // Check if we will have enough space in the fParityOk array.
e3a2b9c9 501 // If we do not then we need to resize the array.
502 // bufferSize / sizeof(UInt_t) will be a safe over estimate of the
503 // number of channels that we will find.
8a0dae7c 504 UInt_t maxChannelsPossible = bufferSize / sizeof(UInt_t);
505 if (maxChannelsPossible > fMaxChannels)
e3a2b9c9 506 {
8a0dae7c 507 if (fParityOk != NULL)
e3a2b9c9 508 {
8a0dae7c 509 delete [] fParityOk;
510 fParityOk = NULL;
e3a2b9c9 511 fMaxChannels = 0;
512 }
8a0dae7c 513 fParityOk = new Bool_t[maxChannelsPossible];
514 fMaxChannels = maxChannelsPossible;
e3a2b9c9 515 }
e3a2b9c9 516
8a0dae7c 517 // Reset the current pointers which will be used to track where we need to
518 // fill fBlocks, fDSPs, fBusPatches and the parity flag. We have to subtract
519 // one space because we will increment the pointer the first time in the
520 // OnNewXZY methods.
521 fCurrentBlock = fBlocks-1;
522 fCurrentDSP = fDSPs-1;
523 fCurrentBusPatch = fBusPatches-1;
524 fCurrentParityOkFlag = fParityOk-1;
525 fBlockCount = 0;
e3a2b9c9 526}
527
528
529void AliMUONRawStreamTrackerHP::AliDecoderEventHandler::OnError(
530 ErrorCode error, const void* location
531 )
532{
533 /// This is called by the high performance decoder when a error occurs
534 /// when trying to decode the DDL payload. This indicates corruption in
535 /// the data. This method converts the error code to a descriptive message
536 /// and log this with the raw reader.
537 /// \param error The error code indicating the problem.
538 /// \param location A pointer to the location within the DDL payload buffer
539 /// being decoded where the problem with the data was found.
540
541 assert( fRawStream != NULL );
542 assert( fRawStream->GetReader() != NULL );
543
8a0dae7c 544 Char_t* message = NULL;
545 UInt_t word = 0;
546
e3a2b9c9 547 switch (error)
548 {
8a0dae7c 549 case kGlitchFound:
550 message = Form(
551 "Glitch error detected in DSP %d, skipping event ",
552 fCurrentBlock->GetDspId()
553 );
554 fRawStream->GetReader()->AddMajorErrorLog(error, message);
555 break;
556
e3a2b9c9 557 case kBadPaddingWord:
8a0dae7c 558 // We subtract 1 from the current numbers of blocks, DSPs
559 // and bus patches to get the indices.
560 message = Form(
561 "Padding word error for iBlock %d, iDsp %d, iBus %d\n",
562 fBlockCount-1,
563 fCurrentBlock->GetDspCount()-1,
564 fCurrentDSP->GetBusPatchCount()-1
565 );
566 fRawStream->GetReader()->AddMinorErrorLog(error, message);
567 break;
568
e3a2b9c9 569 case kParityError:
8a0dae7c 570 // location points to the incorrect data word and
571 // fCurrentBusPatch->GetData() returns a pointer to the start of
572 // bus patches data, so the difference divided by 4 gives the 32
573 // bit word number.
574 word = ((unsigned long)location - (unsigned long)fCurrentBusPatch->GetData())
575 / sizeof(UInt_t);
576 message = Form(
577 "Parity error in word %d for manuId %d and channel %d in buspatch %d\n",
578 word,
579 fCurrentBusPatch->GetManuId(word),
580 fCurrentBusPatch->GetChannelId(word),
581 fCurrentBusPatch->GetBusPatchId()
582 );
583 fRawStream->GetReader()->AddMinorErrorLog(error, message);
e3a2b9c9 584 break;
8a0dae7c 585
e3a2b9c9 586 default:
8a0dae7c 587 message = Form(
588 "%s (At byte %d in DDL.)",
589 ErrorCodeToMessage(error),
590 (unsigned long)location - (unsigned long)fBufferStart
591 );
592 fRawStream->GetReader()->AddMajorErrorLog(error, message);
e3a2b9c9 593 break;
594 }
8a0dae7c 595
596 if (fWarnings)
597 {
598 AliWarningGeneral(
599 "AliMUONRawStreamTrackerHP::AliDecoderEventHandler",
600 message
601 );
602 }
e3a2b9c9 603}
604