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