]>
Commit | Line | Data |
---|---|---|
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" | |
586dda01 | 47 | #include "AliMUONTrackerDDLDecoder.h" |
481d8064 | 48 | #include "AliMUONDspHeader.h" |
49 | #include "AliMUONBlockHeader.h" | |
50 | #include "AliMUONBusStruct.h" | |
51 | #include "AliMUONDDLTracker.h" | |
e3a2b9c9 | 52 | #include "AliRawReader.h" |
53 | #include "AliLog.h" | |
54 | #include <cassert> | |
8a0dae7c | 55 | #include <iostream> |
8a0dae7c | 56 | using std::cout; |
57 | using std::endl; | |
58 | using std::hex; | |
59 | using std::dec; | |
e3a2b9c9 | 60 | |
61 | /// \cond CLASSIMP | |
62 | ClassImp(AliMUONRawStreamTrackerHP) | |
63 | /// \endcond | |
64 | ||
b6f591ae | 65 | const Int_t AliMUONRawStreamTrackerHP::fgkMaxDDL = 20; |
e3a2b9c9 | 66 | |
67 | AliMUONRawStreamTrackerHP::AliMUONRawStreamTrackerHP() : | |
b6f591ae | 68 | TObject(), |
74585128 | 69 | fEnableErrorLogger(kFALSE), |
e3a2b9c9 | 70 | fDecoder(), |
71 | fDDL(0), | |
e3a2b9c9 | 72 | fBufferSize(8192), |
73 | fBuffer(new UChar_t[8192]), | |
586dda01 | 74 | fkCurrentBusPatch(NULL), |
75 | fkCurrentData(NULL), | |
76 | fkEndOfData(NULL), | |
8a0dae7c | 77 | fHadError(kFALSE), |
481d8064 | 78 | fDone(kFALSE), |
b6f591ae | 79 | fDDLObject(NULL), |
74585128 | 80 | fTotalNumberOfGlitchErrors(0), |
81 | fTotalNumberOfParityErrors(0), | |
82 | fTotalNumberOfPaddingErrors(0), | |
83 | fTotalNumberOfTokenLostErrors(0) | |
e3a2b9c9 | 84 | { |
85 | /// | |
86 | /// Default constructor. | |
87 | /// | |
8a0dae7c | 88 | |
89 | // Must set this flag to get all information about parity errors though | |
90 | // the OnData method. OnError gets them either way. | |
91 | fDecoder.ExitOnError(false); | |
92 | fDecoder.SendDataOnParityError(true); | |
93 | ||
94 | fDecoder.GetHandler().SetMaxStructs( | |
95 | fDecoder.MaxBlocks(), | |
96 | fDecoder.MaxDSPs(), | |
97 | fDecoder.MaxBusPatches() | |
98 | ); | |
e3a2b9c9 | 99 | } |
100 | ||
101 | ||
102 | AliMUONRawStreamTrackerHP::AliMUONRawStreamTrackerHP(AliRawReader* rawReader) : | |
74585128 | 103 | TObject(), |
104 | fEnableErrorLogger(kFALSE), | |
e3a2b9c9 | 105 | fDecoder(), |
106 | fDDL(0), | |
e3a2b9c9 | 107 | fBufferSize(8192), |
108 | fBuffer(new UChar_t[8192]), | |
586dda01 | 109 | fkCurrentBusPatch(NULL), |
110 | fkCurrentData(NULL), | |
111 | fkEndOfData(NULL), | |
8a0dae7c | 112 | fHadError(kFALSE), |
481d8064 | 113 | fDone(kFALSE), |
74585128 | 114 | fDDLObject(NULL), |
115 | fTotalNumberOfGlitchErrors(0), | |
116 | fTotalNumberOfParityErrors(0), | |
117 | fTotalNumberOfPaddingErrors(0), | |
118 | fTotalNumberOfTokenLostErrors(0) | |
e3a2b9c9 | 119 | { |
120 | /// | |
121 | /// Constructor with AliRawReader as argument. | |
122 | /// | |
123 | ||
8a0dae7c | 124 | // Must set this flag to get all information about parity errors though |
125 | // the OnData method. OnError gets them either way. | |
126 | fDecoder.ExitOnError(false); | |
127 | fDecoder.SendDataOnParityError(true); | |
128 | ||
129 | fDecoder.GetHandler().SetMaxStructs( | |
130 | fDecoder.MaxBlocks(), | |
131 | fDecoder.MaxDSPs(), | |
132 | fDecoder.MaxBusPatches() | |
133 | ); | |
74585128 | 134 | |
135 | fDecoder.GetHandler().SetReader(rawReader); | |
e3a2b9c9 | 136 | } |
137 | ||
138 | ||
139 | AliMUONRawStreamTrackerHP::~AliMUONRawStreamTrackerHP() | |
140 | { | |
141 | /// | |
142 | /// Default destructor. | |
143 | /// | |
144 | ||
145 | if (fBuffer != NULL) | |
146 | { | |
147 | delete [] fBuffer; | |
148 | } | |
481d8064 | 149 | if (fDDLObject != NULL) |
150 | { | |
151 | delete fDDLObject; | |
152 | } | |
e3a2b9c9 | 153 | } |
154 | ||
155 | ||
156 | void AliMUONRawStreamTrackerHP::First() | |
157 | { | |
158 | /// Initialise or reset the iterator. | |
159 | /// The first DDL will be found and decoded. | |
160 | ||
161 | assert( GetReader() != NULL ); | |
162 | ||
163 | fDDL = 0; | |
8a0dae7c | 164 | fDone = kFALSE; |
e3a2b9c9 | 165 | NextDDL(); |
74585128 | 166 | fTotalNumberOfGlitchErrors = 0; |
167 | fTotalNumberOfPaddingErrors = 0; | |
168 | fTotalNumberOfParityErrors = 0; | |
169 | fTotalNumberOfTokenLostErrors = 0; | |
e3a2b9c9 | 170 | } |
171 | ||
172 | ||
173 | Bool_t AliMUONRawStreamTrackerHP::NextDDL() | |
174 | { | |
175 | /// Reading the next tracker DDL and decode the payload with the | |
176 | /// high performance decoder. | |
177 | /// \return kTRUE if the next DDL was successfully read and kFALSE otherwise. | |
178 | ||
179 | assert( GetReader() != NULL ); | |
180 | ||
481d8064 | 181 | // The temporary object if generated in GetDDLTracker, is now stale, |
182 | // so delete it. | |
183 | if (fDDLObject != NULL) | |
184 | { | |
185 | delete fDDLObject; | |
186 | fDDLObject = NULL; | |
187 | } | |
188 | ||
1788245f | 189 | // Better to reset these pointers. |
586dda01 | 190 | fkCurrentBusPatch = NULL; |
191 | fkCurrentData = NULL; | |
192 | fkEndOfData = NULL; | |
1788245f | 193 | |
8a0dae7c | 194 | while (fDDL < GetMaxDDL()) |
e3a2b9c9 | 195 | { |
196 | GetReader()->Reset(); | |
197 | GetReader()->Select("MUONTRK", fDDL, fDDL); // Select the DDL file to be read. | |
198 | if (GetReader()->ReadHeader()) break; | |
199 | AliDebug(3, Form("Skipping DDL %d which does not seem to be there", fDDL+1)); | |
200 | fDDL++; | |
201 | } | |
8a0dae7c | 202 | |
203 | // If we reach the end of the DDL list for this event then reset the | |
1788245f | 204 | // DDL counter, mark the iteration as done and exit. |
8a0dae7c | 205 | if (fDDL >= GetMaxDDL()) |
206 | { | |
207 | fDDL = 0; | |
208 | fDone = kTRUE; | |
209 | return kFALSE; | |
210 | } | |
211 | else | |
212 | { | |
213 | fDone = kFALSE; | |
214 | } | |
215 | ||
e3a2b9c9 | 216 | AliDebug(3, Form("DDL Number %d\n", fDDL)); |
217 | ||
218 | Int_t dataSize = GetReader()->GetDataSize(); // in bytes | |
219 | // Check if we have enough buffer space already in fBuffer. If we do then | |
220 | // just continue reading otherwise we need to resize the buffer. | |
221 | if (fBufferSize < dataSize) | |
222 | { | |
223 | if (fBuffer != NULL) | |
224 | { | |
225 | delete [] fBuffer; | |
226 | fBuffer = NULL; | |
227 | fBufferSize = 0; | |
228 | } | |
229 | try | |
230 | { | |
231 | fBuffer = new UChar_t[dataSize]; | |
232 | fBufferSize = dataSize; | |
233 | } | |
234 | catch (const std::bad_alloc&) | |
235 | { | |
236 | AliError("Could not allocate more buffer space. Cannot decode DDL."); | |
237 | return kFALSE; | |
238 | } | |
239 | } | |
240 | ||
241 | if (not GetReader()->ReadNext(fBuffer, dataSize)) | |
242 | { | |
243 | return kFALSE; | |
244 | } | |
245 | ||
246 | #ifndef R__BYTESWAP | |
ab0129ae | 247 | Swap(reinterpret_cast<UInt_t*>(fBuffer), dataSize / sizeof(UInt_t)); // Swap needed for mac power pc. |
e3a2b9c9 | 248 | #endif |
249 | ||
250 | bool result = false; | |
251 | try | |
252 | { | |
253 | // Since we might allocate memory inside OnNewBuffer in the event | |
254 | // handler we need to trap any memory allocation exception to be robust. | |
255 | result = fDecoder.Decode(fBuffer, dataSize); | |
8a0dae7c | 256 | fHadError = (result == true ? kFALSE : kTRUE); |
74585128 | 257 | fTotalNumberOfGlitchErrors += fDecoder.GetHandler().GlitchErrorCount(); |
258 | fTotalNumberOfParityErrors += fDecoder.GetHandler().ParityErrorCount(); | |
b6f591ae | 259 | fTotalNumberOfPaddingErrors += fDecoder.GetHandler().PaddingErrorCount(); |
74585128 | 260 | fTotalNumberOfTokenLostErrors += fDecoder.GetHandler().TokenLostCount(); |
e3a2b9c9 | 261 | } |
262 | catch (const std::bad_alloc&) | |
263 | { | |
264 | AliError("Could not allocate more buffer space. Cannot decode DDL."); | |
265 | return kFALSE; | |
266 | } | |
8a0dae7c | 267 | |
268 | // Update the current bus patch pointers. | |
586dda01 | 269 | fkCurrentBusPatch = fDecoder.GetHandler().FirstBusPatch(); |
270 | if (fkCurrentBusPatch != fDecoder.GetHandler().EndOfBusPatch()) | |
8a0dae7c | 271 | { |
586dda01 | 272 | fkCurrentData = fkCurrentBusPatch->GetData(); |
273 | fkEndOfData = fkCurrentData + fkCurrentBusPatch->GetDataCount(); | |
8a0dae7c | 274 | } |
275 | else | |
276 | { | |
277 | // If the DDL did not have any bus patches then mark both fCurrentData | |
278 | // and fEndOfData as NULL so that in Next() we are forced to find the | |
279 | // first non empty DDL. | |
586dda01 | 280 | fkCurrentData = fkEndOfData = NULL; |
8a0dae7c | 281 | } |
282 | ||
e3a2b9c9 | 283 | fDDL++; // Remember to increment index to next DDL. |
29ee96d8 | 284 | return kTRUE; |
e3a2b9c9 | 285 | } |
286 | ||
287 | ||
288 | Bool_t AliMUONRawStreamTrackerHP::IsDone() const | |
289 | { | |
290 | /// Indicates whether the iteration is finished or not. | |
291 | /// \return kTRUE if we already read all the digits and kFALSE if not. | |
292 | ||
8a0dae7c | 293 | return fDone; |
e3a2b9c9 | 294 | } |
295 | ||
296 | ||
b6f591ae | 297 | Bool_t AliMUONRawStreamTrackerHP::Next(Int_t& busPatchId, |
298 | UShort_t& manuId, | |
299 | UChar_t& manuChannel, | |
300 | UShort_t& adc, | |
301 | Bool_t skipParityErrors) | |
e3a2b9c9 | 302 | { |
303 | /// Advance one step in the iteration. Returns false if finished. | |
304 | /// [out] \param busPatchId This is filled with the bus patch ID of the digit. | |
305 | /// [out] \param manuId This is filled with the MANU ID of the digit. | |
306 | /// [out] \param manuChannel This is filled with the MANU channel ID of the digit. | |
307 | /// [out] \param adc This is filled with the ADC signal value of the digit. | |
74585128 | 308 | /// [in] \param skipParityErrors If this is kTRUE, we'll skip the buspatches that |
309 | /// have some parity errors | |
e3a2b9c9 | 310 | /// \return kTRUE if we read another digit and kFALSE if we have read all the |
311 | /// digits already, i.e. at the end of the iteration. | |
312 | ||
586dda01 | 313 | if (fkCurrentData == NULL) return kFALSE; |
1788245f | 314 | |
8a0dae7c | 315 | retry: |
316 | // Check if we still have data to be returned for the current bus patch. | |
586dda01 | 317 | if (fkCurrentData != fkEndOfData) |
e3a2b9c9 | 318 | { |
586dda01 | 319 | busPatchId = fkCurrentBusPatch->GetBusPatchId(); |
320 | AliMUONTrackerDDLDecoderEventHandler::UnpackADC(*fkCurrentData, manuId, manuChannel, adc); | |
321 | fkCurrentData++; | |
e3a2b9c9 | 322 | return kTRUE; |
323 | } | |
324 | else | |
325 | { | |
8a0dae7c | 326 | // We hit the end of the current bus patch so check if we have any more |
327 | // bus patches to process for the current DDL. If we do, then increment | |
328 | // the current bus patch, make sure it is not the last one and then try | |
329 | // reading the first element again. | |
586dda01 | 330 | if (fkCurrentBusPatch != fDecoder.GetHandler().EndOfBusPatch()) |
e3a2b9c9 | 331 | { |
586dda01 | 332 | fkCurrentBusPatch++; |
333 | if (fkCurrentBusPatch != fDecoder.GetHandler().EndOfBusPatch()) | |
e3a2b9c9 | 334 | { |
586dda01 | 335 | fkCurrentData = fkCurrentBusPatch->GetData(); |
336 | fkEndOfData = fkCurrentData + fkCurrentBusPatch->GetDataCount(); | |
74585128 | 337 | if ( skipParityErrors ) |
338 | { | |
339 | Bool_t ok(kTRUE); | |
340 | for ( Int_t i = 0; i < fkCurrentBusPatch->GetLength() && ok; ++ i ) | |
341 | { | |
342 | ok = fkCurrentBusPatch->IsParityOk(i); | |
343 | } | |
344 | if (!ok) fkCurrentData = fkEndOfData; | |
345 | } | |
8a0dae7c | 346 | goto retry; |
e3a2b9c9 | 347 | } |
348 | } | |
8a0dae7c | 349 | |
350 | // This was the last bus patch in the DDL so read in the next one and | |
351 | // try reading the first data element again. | |
352 | // Note: fCurrentBusPatch is set inside NextDDL(). | |
353 | if (NextDDL()) goto retry; | |
e3a2b9c9 | 354 | } |
355 | return kFALSE; | |
356 | } | |
357 | ||
358 | ||
481d8064 | 359 | AliMUONDDLTracker* AliMUONRawStreamTrackerHP::GetDDLTracker() const |
360 | { | |
361 | /// Construct and return a pointer to the DDL payload object. | |
362 | /// \return Pointer to internally constructed AliMUONDDLTracker object. | |
363 | /// The object is owned by this class and should not be deleted | |
364 | /// by the caller. | |
365 | /// | |
366 | /// \note This method should not be used just to gain access to the DDL | |
367 | /// payload, unless there is a good reason to have the AliMUONDDLTracker | |
368 | /// object. For example, if you want to modify the data and then save it | |
369 | /// to another DDL stream. Otherwise it can be an order of magnitude | |
370 | /// faster to access the DDL headers and data with the GetBlockHeader, | |
371 | /// GetDspHeader and GetBusPatch methods for example. | |
372 | /// Refer to the MUONRawStreamTracker.C macro to see how to use the fast | |
373 | /// decoder interface optimally. | |
374 | ||
375 | if (fDDLObject != NULL) return fDDLObject; | |
376 | ||
377 | fDDLObject = new AliMUONDDLTracker; | |
378 | for (Int_t iBlock = 0; iBlock < (Int_t)GetBlockCount(); iBlock++) | |
379 | { | |
380 | AliMUONBlockHeader blockHeader; | |
381 | AliMUONDspHeader dspHeader; | |
382 | AliMUONBusStruct busPatch; | |
383 | ||
384 | const AliBlockHeader* bh = GetBlockHeader(iBlock); | |
385 | // Copy block header and add it to the DDL object. | |
386 | memcpy(blockHeader.GetHeader(), bh->GetHeader(), sizeof(AliMUONBlockHeaderStruct)); | |
387 | fDDLObject->AddBlkHeader(blockHeader); | |
388 | ||
389 | for (Int_t iDsp = 0; iDsp < (Int_t)bh->GetDspCount(); iDsp++) | |
390 | { | |
391 | const AliDspHeader* dh = bh->GetDspHeader(iDsp); | |
392 | // Copy DSP header and add it to the DDL object. | |
393 | memcpy(dspHeader.GetHeader(), dh->GetHeader(), sizeof(AliMUONDSPHeaderStruct)); | |
394 | fDDLObject->AddDspHeader(dspHeader, iBlock); | |
395 | ||
396 | const AliBusPatch* bp = dh->GetFirstBusPatch(); | |
397 | while (bp != NULL) | |
398 | { | |
399 | // Copy bus patch header, data and add everything into DDL object. | |
400 | memcpy(busPatch.GetHeader(), bp->GetHeader(), sizeof(AliMUONBusPatchHeaderStruct)); | |
401 | busPatch.SetAlloc(bp->GetLength()); | |
402 | memcpy(busPatch.GetData(), bp->GetData(), bp->GetDataCount()*sizeof(UInt_t)); | |
403 | busPatch.SetBlockId(iBlock); | |
404 | busPatch.SetDspId(iDsp); | |
405 | fDDLObject->AddBusPatch(busPatch, iBlock, iDsp); | |
406 | bp = bp->Next(); | |
407 | } | |
408 | } | |
409 | } | |
410 | ||
411 | return fDDLObject; | |
412 | } | |
413 | ||
414 | ||
8a0dae7c | 415 | void AliMUONRawStreamTrackerHP::SetMaxBlock(Int_t blk) |
e3a2b9c9 | 416 | { |
8a0dae7c | 417 | /// Set maximum number of blocks per DDL allowed. |
418 | fDecoder.MaxBlocks( (UInt_t) blk ); | |
e3a2b9c9 | 419 | |
8a0dae7c | 420 | fDecoder.GetHandler().SetMaxStructs( |
421 | fDecoder.MaxBlocks(), | |
422 | fDecoder.MaxDSPs(), | |
423 | fDecoder.MaxBusPatches() | |
424 | ); | |
425 | } | |
426 | ||
427 | ||
428 | void AliMUONRawStreamTrackerHP::SetMaxDsp(Int_t dsp) | |
429 | { | |
430 | /// Set maximum number of Dsp per block allowed. | |
431 | fDecoder.MaxDSPs( (UInt_t) dsp ); | |
432 | ||
433 | fDecoder.GetHandler().SetMaxStructs( | |
434 | fDecoder.MaxBlocks(), | |
435 | fDecoder.MaxDSPs(), | |
436 | fDecoder.MaxBusPatches() | |
437 | ); | |
438 | } | |
439 | ||
440 | ||
441 | void AliMUONRawStreamTrackerHP::SetMaxBus(Int_t bus) | |
442 | { | |
443 | /// Set maximum number of Buspatch per Dsp allowed. | |
444 | fDecoder.MaxBusPatches( (UInt_t) bus ); | |
445 | ||
446 | fDecoder.GetHandler().SetMaxStructs( | |
447 | fDecoder.MaxBlocks(), | |
448 | fDecoder.MaxDSPs(), | |
449 | fDecoder.MaxBusPatches() | |
450 | ); | |
451 | } | |
452 | ||
b6f591ae | 453 | AliRawReader* AliMUONRawStreamTrackerHP::GetReader() |
454 | { | |
455 | return fDecoder.GetHandler().GetReader(); | |
456 | } | |
457 | ||
458 | void AliMUONRawStreamTrackerHP::SetReader(AliRawReader* reader) | |
459 | { | |
460 | fDecoder.GetHandler().SetReader(reader); | |
461 | } | |
462 | ||
8a0dae7c | 463 | /////////////////////////////////////////////////////////////////////////////// |
464 | ||
465 | void AliMUONRawStreamTrackerHP::AliBlockHeader::Print() const | |
466 | { | |
467 | /// Print header to screen. | |
468 | ||
469 | cout << "CRT info" << endl; | |
470 | if (fHeader == NULL) | |
e3a2b9c9 | 471 | { |
8a0dae7c | 472 | cout << "Header is NULL" << endl; |
473 | return; | |
474 | } | |
475 | cout << "DataKey: 0x" << hex << fHeader->fDataKey << dec << endl; | |
476 | cout << "TotalLength: " << fHeader->fTotalLength << endl; | |
477 | cout << "Length: " << fHeader->fLength << endl; | |
478 | cout << "DspId: " << fHeader->fDSPId << endl; | |
479 | cout << "L0Trigger: " << fHeader->fL0Trigger << endl; | |
480 | cout << "MiniEventId: " << fHeader->fMiniEventId<< endl; | |
481 | cout << "EventId1: " << fHeader->fEventId1 << endl; | |
482 | cout << "EventId2: " << fHeader->fEventId2 << endl; | |
483 | } | |
484 | ||
485 | ||
486 | void AliMUONRawStreamTrackerHP::AliDspHeader::Print() const | |
487 | { | |
488 | /// Print header to screen. | |
489 | ||
490 | cout << "FRT info" << endl; | |
491 | if (fHeader == NULL) | |
492 | { | |
493 | cout << "Header is NULL" << endl; | |
494 | return; | |
495 | } | |
496 | cout << "DataKey: 0x" << hex << fHeader->fDataKey << dec << endl; | |
497 | cout << "TotalLength: " << fHeader->fTotalLength << endl; | |
498 | cout << "Length : " << fHeader->fLength << endl; | |
499 | cout << "DspId: " << fHeader->fDSPId << endl; | |
500 | cout << "BlkL1ATrigger: " << fHeader->fBlkL1ATrigger << endl; | |
501 | cout << "MiniEventId: " << fHeader->fMiniEventId << endl; | |
502 | cout << "L1ATrigger: " << fHeader->fL1ATrigger << endl; | |
503 | cout << "L1RTrigger: " << fHeader->fL1RTrigger << endl; | |
504 | cout << "PaddingWord: " << fHeader->fPaddingWord << endl; | |
505 | cout << "ErrorWord: " << fHeader->fErrorWord << endl; | |
506 | } | |
507 | ||
508 | ||
509 | void AliMUONRawStreamTrackerHP::AliBusPatch::Print(const Option_t* opt) const | |
510 | { | |
511 | /// Print header to screen. | |
512 | cout << "Bus patch info" << endl; | |
513 | if (fHeader == NULL) | |
514 | { | |
515 | cout << "Header is NULL" << endl; | |
516 | return; | |
517 | } | |
518 | cout << "DataKey: 0x" << hex << fHeader->fDataKey << dec << endl; | |
519 | cout << "fTotalLength: " << fHeader->fTotalLength << endl; | |
520 | cout << "fLength: " << fHeader->fLength << endl; | |
521 | cout << "fBusPatchId: " << fHeader->fBusPatchId << endl; | |
522 | ||
523 | if (TString(opt).Contains("all")) | |
524 | { | |
525 | for (UInt_t i = 0; i < fHeader->fLength; ++i) | |
526 | cout << "Data["<< i << "] = " << fData[i] << endl; | |
e3a2b9c9 | 527 | } |
e3a2b9c9 | 528 | } |
529 | ||
530 | /////////////////////////////////////////////////////////////////////////////// | |
531 | ||
532 | AliMUONRawStreamTrackerHP::AliDecoderEventHandler::AliDecoderEventHandler() : | |
74585128 | 533 | fRawReader(0x0), |
8a0dae7c | 534 | fBufferStart(NULL), |
535 | fBlockCount(0), | |
536 | fBlocks(NULL), | |
537 | fDSPs(NULL), | |
538 | fBusPatches(NULL), | |
539 | fEndOfBusPatches(NULL), | |
540 | fMaxChannels(8192), | |
541 | fParityOk(new Bool_t[8192]), | |
542 | fCurrentBlock(NULL), | |
543 | fCurrentDSP(NULL), | |
544 | fCurrentBusPatch(NULL), | |
545 | fCurrentParityOkFlag(NULL), | |
546 | fParityErrors(0), | |
547 | fGlitchErrors(0), | |
548 | fPaddingErrors(0), | |
74585128 | 549 | fTokenLostErrors(0), |
b6f591ae | 550 | fWarnings(kTRUE), |
74585128 | 551 | fMaxBlocks(), |
552 | fMaxDsps(), | |
553 | fMaxBusPatches() | |
e3a2b9c9 | 554 | { |
8a0dae7c | 555 | /// Default constructor initialises the internal parity flags buffer to |
556 | /// store 8192 elements. This array will grow dynamically if needed. | |
e3a2b9c9 | 557 | } |
558 | ||
559 | ||
560 | AliMUONRawStreamTrackerHP::AliDecoderEventHandler::~AliDecoderEventHandler() | |
561 | { | |
562 | /// Default destructor cleans up the allocated memory. | |
563 | ||
8a0dae7c | 564 | if (fParityOk != NULL) delete [] fParityOk; |
565 | if (fBlocks != NULL) delete [] fBlocks; | |
566 | if (fDSPs != NULL) delete [] fDSPs; | |
567 | if (fBusPatches != NULL) delete [] fBusPatches; | |
568 | } | |
569 | ||
570 | ||
571 | void AliMUONRawStreamTrackerHP::AliDecoderEventHandler::SetMaxStructs( | |
572 | UInt_t maxBlocks, UInt_t maxDsps, UInt_t maxBusPatches | |
573 | ) | |
574 | { | |
575 | /// Sets the maximum number of structures allowed. | |
576 | ||
577 | // Start by clearing the current arrays. | |
578 | if (fBlocks != NULL) | |
579 | { | |
580 | delete [] fBlocks; | |
581 | fBlocks = NULL; | |
582 | } | |
583 | if (fDSPs != NULL) | |
e3a2b9c9 | 584 | { |
8a0dae7c | 585 | delete [] fDSPs; |
586 | fDSPs = NULL; | |
e3a2b9c9 | 587 | } |
8a0dae7c | 588 | if (fBusPatches != NULL) |
589 | { | |
590 | delete [] fBusPatches; | |
591 | fBusPatches = NULL; | |
592 | } | |
593 | fCurrentBlock = NULL; | |
594 | fCurrentDSP = NULL; | |
595 | fCurrentBusPatch = NULL; | |
596 | ||
597 | // Allocate new memory. | |
598 | fBlocks = new AliBlockHeader[maxBlocks]; | |
599 | fDSPs = new AliDspHeader[maxBlocks*maxDsps]; | |
600 | fBusPatches = new AliBusPatch[maxBlocks*maxDsps*maxBusPatches]; | |
1788245f | 601 | fEndOfBusPatches = fBusPatches; |
b6f591ae | 602 | |
74585128 | 603 | fMaxBlocks = maxBlocks; |
604 | fMaxDsps = maxDsps; | |
605 | fMaxBusPatches = maxBusPatches; | |
e3a2b9c9 | 606 | } |
607 | ||
8a0dae7c | 608 | |
e3a2b9c9 | 609 | void AliMUONRawStreamTrackerHP::AliDecoderEventHandler::OnNewBuffer( |
610 | const void* buffer, UInt_t bufferSize | |
611 | ) | |
612 | { | |
613 | /// This is called by the high performance decoder when a new DDL payload | |
614 | /// is about to be decoded. | |
615 | /// \param buffer The pointer to the buffer storing the DDL payload. | |
616 | /// \param bufferSize The size of the buffer in bytes. | |
617 | ||
618 | // remember the start of the buffer to be used in OnError. | |
619 | fBufferStart = buffer; | |
8a0dae7c | 620 | |
621 | // Reset error counters. | |
622 | fParityErrors = 0; | |
623 | fGlitchErrors = 0; | |
624 | fPaddingErrors = 0; | |
74585128 | 625 | fTokenLostErrors = 0; |
8a0dae7c | 626 | |
627 | // Check if we will have enough space in the fParityOk array. | |
e3a2b9c9 | 628 | // If we do not then we need to resize the array. |
629 | // bufferSize / sizeof(UInt_t) will be a safe over estimate of the | |
630 | // number of channels that we will find. | |
8a0dae7c | 631 | UInt_t maxChannelsPossible = bufferSize / sizeof(UInt_t); |
632 | if (maxChannelsPossible > fMaxChannels) | |
e3a2b9c9 | 633 | { |
8a0dae7c | 634 | if (fParityOk != NULL) |
e3a2b9c9 | 635 | { |
8a0dae7c | 636 | delete [] fParityOk; |
637 | fParityOk = NULL; | |
e3a2b9c9 | 638 | fMaxChannels = 0; |
639 | } | |
8a0dae7c | 640 | fParityOk = new Bool_t[maxChannelsPossible]; |
641 | fMaxChannels = maxChannelsPossible; | |
e3a2b9c9 | 642 | } |
e3a2b9c9 | 643 | |
8a0dae7c | 644 | // Reset the current pointers which will be used to track where we need to |
645 | // fill fBlocks, fDSPs, fBusPatches and the parity flag. We have to subtract | |
646 | // one space because we will increment the pointer the first time in the | |
647 | // OnNewXZY methods. | |
648 | fCurrentBlock = fBlocks-1; | |
649 | fCurrentDSP = fDSPs-1; | |
650 | fCurrentBusPatch = fBusPatches-1; | |
651 | fCurrentParityOkFlag = fParityOk-1; | |
652 | fBlockCount = 0; | |
e3a2b9c9 | 653 | } |
654 | ||
655 | ||
656 | void AliMUONRawStreamTrackerHP::AliDecoderEventHandler::OnError( | |
657 | ErrorCode error, const void* location | |
658 | ) | |
659 | { | |
660 | /// This is called by the high performance decoder when a error occurs | |
661 | /// when trying to decode the DDL payload. This indicates corruption in | |
662 | /// the data. This method converts the error code to a descriptive message | |
1788245f | 663 | /// and logs this with the raw reader. |
e3a2b9c9 | 664 | /// \param error The error code indicating the problem. |
665 | /// \param location A pointer to the location within the DDL payload buffer | |
666 | /// being decoded where the problem with the data was found. | |
667 | ||
b6f591ae | 668 | assert( fRawReader != NULL ); |
e3a2b9c9 | 669 | |
8a0dae7c | 670 | Char_t* message = NULL; |
671 | UInt_t word = 0; | |
672 | ||
e3a2b9c9 | 673 | switch (error) |
674 | { | |
8a0dae7c | 675 | case kGlitchFound: |
1788245f | 676 | fGlitchErrors++; |
8a0dae7c | 677 | message = Form( |
74585128 | 678 | "Glitch error detected in DSP %d (0x%X), skipping event ", |
679 | fCurrentBlock->GetDspId(), fCurrentBlock->GetDspId() | |
8a0dae7c | 680 | ); |
b6f591ae | 681 | fRawReader->AddMajorErrorLog(error, message); |
8a0dae7c | 682 | break; |
683 | ||
e3a2b9c9 | 684 | case kBadPaddingWord: |
1788245f | 685 | fPaddingErrors++; |
8a0dae7c | 686 | // We subtract 1 from the current numbers of blocks, DSPs |
687 | // and bus patches to get the indices. | |
688 | message = Form( | |
689 | "Padding word error for iBlock %d, iDsp %d, iBus %d\n", | |
690 | fBlockCount-1, | |
691 | fCurrentBlock->GetDspCount()-1, | |
692 | fCurrentDSP->GetBusPatchCount()-1 | |
693 | ); | |
b6f591ae | 694 | fRawReader->AddMinorErrorLog(error, message); |
8a0dae7c | 695 | break; |
696 | ||
e3a2b9c9 | 697 | case kParityError: |
1788245f | 698 | fParityErrors++; |
8a0dae7c | 699 | // location points to the incorrect data word and |
700 | // fCurrentBusPatch->GetData() returns a pointer to the start of | |
701 | // bus patches data, so the difference divided by 4 gives the 32 | |
702 | // bit word number. | |
703 | word = ((unsigned long)location - (unsigned long)fCurrentBusPatch->GetData()) | |
704 | / sizeof(UInt_t); | |
705 | message = Form( | |
706 | "Parity error in word %d for manuId %d and channel %d in buspatch %d\n", | |
707 | word, | |
708 | fCurrentBusPatch->GetManuId(word), | |
709 | fCurrentBusPatch->GetChannelId(word), | |
710 | fCurrentBusPatch->GetBusPatchId() | |
711 | ); | |
b6f591ae | 712 | fRawReader->AddMinorErrorLog(error, message); |
e3a2b9c9 | 713 | break; |
74585128 | 714 | |
715 | case kTokenLost: | |
716 | fTokenLostErrors++; | |
717 | word = *reinterpret_cast<const UInt_t*>(location); | |
718 | message = Form( | |
719 | "Lost token error detected in DSP %d (0x%X) with address 0x%X and code %d.", | |
720 | fCurrentBlock->GetDspId(), fCurrentBlock->GetDspId(), | |
721 | ((word & 0xFFFF0000) >> 16), | |
722 | (word & 0xF) | |
723 | ); | |
724 | fRawReader->AddMinorErrorLog(error, message); | |
725 | break; | |
8a0dae7c | 726 | |
e3a2b9c9 | 727 | default: |
8a0dae7c | 728 | message = Form( |
729 | "%s (At byte %d in DDL.)", | |
730 | ErrorCodeToMessage(error), | |
29ee96d8 | 731 | (unsigned long)location - (unsigned long)fBufferStart + sizeof(AliRawDataHeader) |
8a0dae7c | 732 | ); |
b6f591ae | 733 | fRawReader->AddMajorErrorLog(error, message); |
e3a2b9c9 | 734 | break; |
735 | } | |
8a0dae7c | 736 | |
737 | if (fWarnings) | |
738 | { | |
739 | AliWarningGeneral( | |
740 | "AliMUONRawStreamTrackerHP::AliDecoderEventHandler", | |
741 | message | |
742 | ); | |
743 | } | |
e3a2b9c9 | 744 | } |
745 |