Line data Source code
1 : // $Id$
2 : //****************************************************************************
3 : //* This file is property of and copyright by the ALICE HLT Project *
4 : //* ALICE Experiment at CERN, All rights reserved. *
5 : //* *
6 : //* Primary Authors: Sergey Gorbunov, Torsten Alt *
7 : //* Developers: Sergey Gorbunov <sergey.gorbunov@fias.uni-frankfurt.de> *
8 : //* Torsten Alt <talt@cern.ch> *
9 : //* for The ALICE HLT Project. *
10 : //* *
11 : //* Permission to use, copy, modify and distribute this software and its *
12 : //* documentation strictly for non-commercial purposes is hereby granted *
13 : //* without fee, provided that the above copyright notice appears in all *
14 : //* copies and that both the copyright notice and this permission notice *
15 : //* appear in the supporting documentation. The authors make no claims *
16 : //* about the suitability of this software for any purpose. It is *
17 : //* provided "as is" without express or implied warranty. *
18 : //****************************************************************************
19 :
20 : // @file AliHLTTPCHWCFSupport.cxx
21 : // @author Sergey Gorbunov <sergey.gorbunov@fias.uni-frankfurt.de>
22 : // @author Torsten Alt <talt@cern.ch>
23 : // @brief Input interfaces for FPGA ClusterFinder Emulator for TPC
24 : // @brief ( see AliHLTTPCHWCFEmulator class )
25 : // @note
26 :
27 :
28 : #include "AliHLTTPCHWCFSupport.h"
29 : #include "AliHLTDataTypes.h"
30 : #include "AliHLTTPCMapping.h"
31 : #include "AliHLTTPCDigitReaderUnpacked.h"
32 : #include "AliHLTTPCGeometry.h"
33 : #include "AliHLTTPCDefinitions.h"
34 : #include "AliHLTCDHWrapper.h"
35 : #include "AliHLTTPCHWCFEmulator.h"
36 : #include "AliTPCcalibDB.h"
37 : #include "AliTPCCalPad.h"
38 : #include "AliTPCCalROC.h"
39 : #include "TMath.h"
40 :
41 : #include <cstdlib>
42 : #include <algorithm>
43 : #include <cerrno>
44 : #include <sys/time.h>
45 :
46 : using namespace std;
47 :
48 : AliHLTTPCHWCFSupport::AliHLTTPCHWCFSupport()
49 : :
50 3 : AliHLTLogging(),
51 3 : fProcessingRCU2Data(0),
52 3 : fEventMemory(0),
53 3 : fEventMCMemory(0)
54 15 : {
55 : // see header file for class documentation
56 222 : for( int i=0; i<fgkNSlices; i++ )
57 1512 : for( int j=0; j<fgkNPatches; j++ ) fMapping[i][j] = 0;
58 6 : }
59 :
60 :
61 : AliHLTTPCHWCFSupport::~AliHLTTPCHWCFSupport()
62 12 : {
63 : // see header file for class documentation
64 222 : for( int i=0; i<fgkNSlices; i++ )
65 2160 : for( int j=0; j<fgkNPatches; j++ ) delete[] fMapping[i][j];
66 3 : ReleaseEventMemory();
67 6 : }
68 :
69 : AliHLTTPCHWCFSupport::AliHLTTPCHWCFSupport(const AliHLTTPCHWCFSupport&)
70 : :
71 0 : AliHLTLogging(),
72 0 : fProcessingRCU2Data(0),
73 0 : fEventMemory(0),
74 0 : fEventMCMemory(0)
75 0 : {
76 : // dummy
77 0 : }
78 :
79 : AliHLTTPCHWCFSupport& AliHLTTPCHWCFSupport::operator=(const AliHLTTPCHWCFSupport&){
80 : // dummy
81 0 : return *this;
82 : }
83 :
84 :
85 : void AliHLTTPCHWCFSupport::ReleaseEventMemory()
86 : {
87 : // clean up
88 6 : if( fEventMemory ) delete[] fEventMemory;
89 3 : if( fEventMCMemory )delete[] fEventMCMemory;
90 3 : fEventMemory = 0;
91 3 : fEventMCMemory = 0;
92 3 : }
93 :
94 : void AliHLTTPCHWCFSupport::UnloadMapping()
95 : {
96 : // unload mapping
97 0 : for( int i=0; i<fgkNSlices; i++ ){
98 0 : for( int j=0; j<fgkNPatches; j++ ){
99 0 : delete[] fMapping[i][j];
100 0 : fMapping[i][j] = NULL;
101 : }
102 : }
103 0 : }
104 :
105 : const AliHLTUInt32_t *AliHLTTPCHWCFSupport::GetMapping( int slice, int patch )
106 : {
107 : // see header file for class documentation
108 0 : if( slice<0 || slice>=fgkNSlices ){
109 0 : HLTFatal("Wrong slice number %d, no mapping is provided.", slice);
110 0 : return 0;
111 : }
112 0 : if( patch<0 || patch>= fgkNPatches ){
113 0 : HLTFatal("Wrong patch number %d, no mapping is provided.", patch);
114 0 : return 0;
115 : }
116 0 : if( !fMapping[slice][patch] ) fMapping[slice][patch] = ReadMapping(slice,patch);
117 0 : return fMapping[slice][patch];
118 0 : }
119 :
120 :
121 : AliHLTUInt32_t *AliHLTTPCHWCFSupport::ReadMapping( int slice, int patch, const char *mappingFileName ) const
122 : {
123 : // Create mapping array for one patch
124 : // If no mapping file provided, reads from default file
125 : // Output: mapping [] array of type AliHLTUInt32_t, where :
126 : //
127 : // mapping[0] == N hardware adresses in the array (mapping size is maping[0] + 1 )
128 : // mapping[hwAddress] == configWord
129 : //
130 : // configWord consist of:
131 : //
132 : // bits 0-7: pad number
133 : // bits 8-13: row number
134 : // bit 14 : flag for border pad
135 : // bit 15 : is the pad active
136 : // bits 16->28 : gain calibration as 13 bit fixed point,
137 : // with 1 bit position before decimal point
138 :
139 : const AliHLTUInt32_t kBorderFlag = (1 << 14);
140 : const AliHLTUInt32_t kActiveFlag = (1 << 15);
141 :
142 0 : if( slice<0 || slice>=fgkNSlices ){
143 0 : HLTFatal("Wrong slice number %d, no mapping is provided.", slice);
144 0 : return 0;
145 : }
146 :
147 0 : if( patch<0 || patch>5 ){
148 0 : HLTFatal("Wrong patch number %d, no mapping is provided.", patch);
149 0 : return 0;
150 : }
151 :
152 : // AliHLTTPCGeometry::GetFirstRow returns first row in scheme A.
153 : // We have to transform to scheme B by AliHLTTPCGeometry::Slice2Sector.
154 :
155 : UInt_t offsetSchemeB=0;
156 0 : Int_t sector = 0;
157 : {
158 0 : Int_t tmp=0;
159 0 : AliHLTTPCGeometry::Slice2Sector(slice, AliHLTTPCGeometry::GetFirstRow(patch),
160 : sector, tmp);
161 0 : offsetSchemeB = (UInt_t) tmp;
162 0 : }
163 :
164 :
165 0 : AliTPCcalibDB *calib = AliTPCcalibDB::Instance();
166 : AliTPCCalPad * gainTPC = 0;
167 : AliTPCCalROC * gainROC = 0;
168 0 : if( calib ) gainTPC = calib->GetPadGainFactor();
169 0 : if( gainTPC ) gainROC = gainTPC->GetCalROC(sector); // pad gains per given sector
170 : else{
171 0 : HLTWarning("No TPC gain calibration found");
172 : }
173 :
174 0 : TString filename;
175 :
176 0 : if( mappingFileName ){
177 0 : filename = mappingFileName;
178 : } else {
179 0 : const char* basePath=getenv("ALICE_ROOT");
180 0 : if (basePath) filename.Form("%s/TPC/mapping/Patch%d.data", basePath,patch);
181 : }
182 :
183 0 : ifstream inFile;
184 0 : inFile.open(filename.Data());
185 0 : if (!inFile) {
186 0 : HLTFatal("Unable to open mapping file: %s This means no mapping is provided.", filename.Data());
187 0 : return 0;
188 : }
189 :
190 :
191 : AliHLTUInt32_t *mapping = 0;
192 : AliHLTUInt32_t *rowBranchPadHw = 0;
193 : bool err = 1;
194 : do{
195 :
196 0 : UInt_t nHWAdd=0;
197 0 : UInt_t maxHWAdd=0;
198 :
199 0 : if( !(inFile >> nHWAdd ) || !(inFile >> maxHWAdd) ){
200 0 : HLTError("Mapping file for patch %d corrupted &s", patch,filename.Data());
201 0 : break;
202 : }
203 :
204 0 : if( maxHWAdd > 0xFFF ){
205 0 : HLTError("Max hardware address exceeded for patch %d, max number is %d, number from mapping file is %d.",patch, 0xFFF, maxHWAdd+1);
206 0 : break;
207 : }
208 :
209 0 : if(nHWAdd > maxHWAdd ){
210 0 : HLTError("Too large number of hardware addresses for patch %d: max number is %d, number from mapping file is %d.",patch, maxHWAdd, nHWAdd );
211 0 : break;
212 : }
213 :
214 0 : mapping = new AliHLTUInt32_t[maxHWAdd+2];
215 0 : rowBranchPadHw = new AliHLTUInt32_t[nHWAdd];
216 0 : if( !mapping || !rowBranchPadHw ){
217 0 : HLTError("Can not allocate &d bytes of memory", (maxHWAdd+1+nHWAdd)*sizeof(AliHLTUInt32_t));
218 0 : break;
219 : }
220 :
221 0 : for( unsigned int i=0; i<maxHWAdd+2; i++ ) mapping[i] = 0;
222 0 : for( unsigned int i=0; i<nHWAdd; i++ ) rowBranchPadHw[i] = 0;
223 0 : mapping[0] = maxHWAdd+1;
224 : UInt_t nRead = 0;
225 : err = 0;
226 0 : while(!err ){
227 0 : UInt_t hwAdd=0;
228 0 : UInt_t row=0;
229 0 : UInt_t pad=0;
230 0 : if( !(inFile>>hwAdd) || !(inFile>>row) || !(inFile>>pad) ) break;
231 :
232 : err = 1;
233 :
234 0 : if ( nRead >= nHWAdd ){
235 0 : HLTError("Too many hardware addresses: %d, expected %d, mapping file %s corrupted?", nRead+1, nHWAdd, filename.Data());
236 0 : break;
237 : }
238 0 : if (hwAdd>maxHWAdd) {
239 0 : HLTError("hardware address exceeds max hwAddress %d, mapping file %s corrupted?", maxHWAdd, filename.Data());
240 0 : break;
241 : }
242 :
243 0 : if( row < offsetSchemeB ){
244 0 : HLTError("row number %d below minimum %d for patch %d, mapping file %s corrupted?", row, offsetSchemeB, patch, filename.Data());
245 0 : break;
246 : }
247 :
248 0 : row -= offsetSchemeB;
249 :
250 0 : if( row > 0x3F ){
251 0 : HLTError("row number %d withing patch exceed the maximum %d for patch %d, mapping file %s corrupted?", row, 0x3F, patch, filename.Data());
252 0 : break;
253 : }
254 :
255 0 : if( pad > 0xFF ){
256 0 : HLTError("pad number %d exceed the maximum %d for patch %d, mapping file %s corrupted?", pad, 0xFF, patch, filename.Data());
257 0 : break;
258 : }
259 :
260 : bool active = true; // Currently all channels are always active
261 : //
262 :
263 : AliHLTFloat64_t gain = 1.;
264 0 : if( gainROC ){
265 0 : gain = gainROC->GetValue(offsetSchemeB+row,pad);
266 0 : if( gain>1.e-4 ) gain = 1./gain;
267 : else gain = 0;
268 : }
269 0 : gain*= (1<<12);
270 0 : AliHLTUInt32_t gainCalib = TMath::Nint(gain);
271 0 : if( gainCalib > 0x1FFF ) gainCalib = 0x1FFF;
272 :
273 0 : AliHLTUInt32_t configWord = ( (row & 0x3F) << 8 ) | (pad & 0xFF);
274 0 : if ( active ) configWord |= kActiveFlag;
275 0 : configWord |= (gainCalib & 0x1FFF) << 16;
276 :
277 0 : mapping[1+hwAdd] = configWord;
278 :
279 0 : AliHLTUInt32_t branch = (hwAdd >> 11) & 0x1;
280 0 : if( fProcessingRCU2Data ) branch = 0;
281 0 : rowBranchPadHw[nRead] = (row<<25) | (branch<<24) | (pad<<16) | hwAdd;
282 :
283 0 : nRead++;
284 : err = 0;
285 0 : }
286 :
287 0 : if( err ) break;
288 :
289 0 : if ( nRead!= nHWAdd ){
290 0 : HLTError("Too less hardware addresses: %d, expected %d, mapping file %s corrupted?", nRead, nHWAdd, filename.Data());
291 : err = 1;
292 0 : break;
293 : }
294 :
295 : // mark pads at borders of A/B branches
296 :
297 0 : std::sort(rowBranchPadHw, rowBranchPadHw + nHWAdd);
298 : int rowBranchPadLast = -10;
299 0 : for( unsigned int i=0; i<nHWAdd; i++ ){
300 0 : int rowBranchPad = rowBranchPadHw[i]>>16;
301 0 : if( rowBranchPad != rowBranchPadLast+1 ){
302 0 : mapping[1+(rowBranchPadHw[i] & 0xFFF)] |= kBorderFlag;
303 0 : if( i>0 ) mapping[1+(rowBranchPadHw[i-1] & 0xFFF)] |= kBorderFlag;
304 : }
305 : rowBranchPadLast = rowBranchPad;
306 : }
307 0 : mapping[1+(rowBranchPadHw[nRead-1] & 0xFFF)] |= kBorderFlag;
308 :
309 0 : } while(0);
310 :
311 0 : inFile.close();
312 :
313 0 : delete[] rowBranchPadHw;
314 :
315 0 : if( err ){
316 0 : delete[] mapping;
317 0 : return 0;
318 : }
319 0 : return mapping;
320 0 : }
321 :
322 :
323 : int AliHLTTPCHWCFSupport::CreateRawEvent
324 : ( const AliHLTComponentBlockData* block,
325 : const AliHLTUInt32_t *&rawEvent, AliHLTUInt32_t &rawEventSize32,
326 : const AliHLTTPCClusterMCLabel *&mcLabels, AliHLTUInt32_t &nMCLabels
327 : )
328 : {
329 : // the method creates TPC raw data out of the input block
330 : // MC labels are provided if possible
331 : //
332 :
333 0 : ReleaseEventMemory();
334 :
335 0 : rawEvent = 0;
336 0 : rawEventSize32 = 0;
337 0 : mcLabels = 0;
338 0 : nMCLabels = 0;
339 :
340 0 : if( block->fPtr==NULL ){
341 0 : HLTWarning("NULL pointer to the data block");
342 0 : return 0;
343 : }
344 :
345 0 : Int_t slice = AliHLTTPCDefinitions::GetMinSliceNr( *block );
346 0 : Int_t patch = AliHLTTPCDefinitions::GetMinPatchNr( *block );
347 0 : AliHLTTPCMapping mapping(patch);
348 :
349 0 : const char *str=Form("slice %d patch %d:", slice, patch);
350 :
351 0 : if ( block->fDataType == (kAliHLTDataTypeDDLRaw | kAliHLTDataOriginTPC) )
352 : {
353 : // already raw format -> only set the pointers and estimate the size
354 :
355 : // read CDH header, estimate size of the data
356 0 : AliHLTCDHWrapper cdhHeader(block->fPtr);
357 :
358 0 : AliHLTUInt64_t headerSize = cdhHeader.GetHeaderSize();
359 :
360 0 : AliHLTUInt64_t blockSize = block->fSize; // size of the raw data in bytes
361 :
362 0 : if( cdhHeader.GetDataSize()!=0xFFFFFFFF ){ // use size information from the header
363 0 : blockSize = cdhHeader.GetDataSize();
364 0 : if( blockSize > block->fSize ){
365 0 : HLTWarning("%s Could not find a valid DDL header!",str);
366 0 : return 0;
367 : }
368 : }
369 :
370 0 : if( blockSize < headerSize ){
371 0 : HLTWarning("%s Buffer size is smaller than CDH header size", str);
372 0 : return 0;
373 : }
374 :
375 0 : rawEvent = reinterpret_cast<AliHLTUInt32_t*> (reinterpret_cast<UChar_t*>(block->fPtr)+headerSize);
376 0 : rawEventSize32 = ( blockSize - headerSize )/sizeof(AliHLTUInt32_t);
377 :
378 0 : }
379 0 : else if ( block->fDataType == AliHLTTPCDefinitions::fgkUnpackedRawDataType )
380 : {
381 :
382 0 : AliHLTTPCDigitReaderUnpacked digitReader;
383 0 : digitReader.SetUnsorted(kTRUE);
384 :
385 0 : if( digitReader.InitBlock(block->fPtr,block->fSize,patch,slice)<0 ) {
386 0 : HLTWarning("failed setting up digit reader (InitBlock)");
387 0 : return 0;
388 : }
389 :
390 : int nDigitsTotal = 0;
391 : int nBunchesTotal = 0;
392 :
393 0 : while( digitReader.NextChannel() ){
394 0 : while(digitReader.NextBunch()){
395 0 : nBunchesTotal++;
396 0 : nDigitsTotal+=digitReader.GetBunchSize();
397 : }
398 : }
399 :
400 0 : digitReader.Reset();
401 :
402 0 : if( digitReader.InitBlock(block->fPtr,block->fSize,patch,slice)<0) {
403 0 : HLTWarning("failed setting up digit reader (InitBlock)");
404 0 : return 0;
405 : }
406 :
407 : Int_t nPadsTotal = 0;
408 0 : Int_t firstRow = AliHLTTPCGeometry::GetFirstRow(patch);
409 0 : Int_t nRows = AliHLTTPCGeometry::GetNRows(patch);
410 :
411 0 : for( int i=0; i<nRows; i++ ){
412 0 : nPadsTotal += AliHLTTPCGeometry::GetNPads(firstRow+i);
413 : }
414 :
415 0 : AliHLTUInt32_t totalSize32 = (nDigitsTotal + nBunchesTotal*2)/3+2*nPadsTotal + 10;
416 0 : AliHLTUInt32_t totalNMC = nDigitsTotal + 10;
417 :
418 0 : fEventMemory = new AliHLTUInt32_t[totalSize32];
419 0 : if( !fEventMemory ){
420 0 : HLTWarning("Not enougth memory: can not allocate %d bytes",totalSize32*8);
421 0 : return 0;
422 : }
423 :
424 0 : fEventMCMemory = new AliHLTTPCClusterMCLabel[totalNMC];
425 0 : if( !fEventMCMemory ){
426 0 : HLTWarning("Not enougth memory: can not allocate %d bytes",totalNMC*sizeof(AliHLTTPCClusterMCLabel));
427 0 : delete[] fEventMemory;
428 0 : fEventMemory = 0;
429 0 : return 0;
430 : }
431 :
432 0 : AliHLTUInt32_t nWords32 = 0;
433 : AliHLTUInt32_t mcIndex = 0;
434 : int err=0;
435 :
436 0 : AliHLTTPCDigitData tmpDigit;
437 0 : tmpDigit.fTrackID[0] = -1;
438 0 : tmpDigit.fTrackID[1] = -1;
439 0 : tmpDigit.fTrackID[2] = -1;
440 :
441 0 : while( !err && digitReader.NextChannel() ){
442 :
443 0 : Int_t row=digitReader.GetRow();
444 0 : Int_t pad=digitReader.GetPad();
445 :
446 0 : AliHLTUInt32_t hwAddr = mapping.GetHwAddress(row, pad);
447 :
448 : // create header
449 :
450 0 : if( nWords32 >= totalSize32){ err = 1; break; }
451 :
452 0 : AliHLTUInt32_t *header = fEventMemory + nWords32;
453 0 : nWords32++;
454 :
455 0 : int seek10 = 2;
456 : int prevTime = 10000000;
457 : int nWords10 = 0;
458 0 : while(digitReader.NextBunch()){
459 :
460 0 : if( hwAddr > 0xFFF ) continue;
461 :
462 0 : Int_t nSignals = digitReader.GetBunchSize();
463 0 : if( nSignals <=0 ){
464 0 : HLTWarning("Empty bunch received");
465 0 : continue;
466 : }
467 :
468 0 : Int_t time = digitReader.GetTime() + nSignals-1;
469 :
470 0 : if( time-nSignals+1<0 || time>=AliHLTTPCGeometry::GetNTimeBins() ){
471 0 : HLTWarning("Wrong time bins received: %d-%d for row %d pad %d", time-nSignals+1, time, row, pad);
472 0 : break;
473 : }
474 :
475 0 : if( time >= prevTime ){
476 0 : HLTWarning("Unexpected order of TPC bunches in row %d, pad %d", row, pad);
477 0 : break;
478 : }
479 :
480 : prevTime = time-nSignals+1;
481 :
482 0 : if( nWords32+( 2+nSignals)/3+1 >= totalSize32 ){ err = 1; break; }
483 0 : if( mcIndex + nSignals >= totalNMC ){ err = 1; break; }
484 :
485 0 : if( nWords10 + 2 + nSignals > 0x3FF ){
486 0 : HLTWarning("Too much data in row %d, pad %d", row, pad);
487 0 : break;
488 : }
489 :
490 0 : nWords10 += 2 + nSignals;
491 :
492 0 : Add10Word( nWords32, seek10, nSignals + 2 );
493 0 : Add10Word( nWords32, seek10, time );
494 :
495 0 : const UInt_t *bunchData = digitReader.GetSignals();
496 0 : const AliHLTTPCDigitData *mcDigits = digitReader.GetBunchDigits();
497 0 : if( !mcDigits ){
498 0 : HLTWarning("No MC labels found for a bunch of digits");
499 : }
500 :
501 0 : for(Int_t is=nSignals-1; is>=0; is--){
502 0 : Add10Word( nWords32, seek10, bunchData[is] );
503 0 : const AliHLTTPCDigitData &digit = mcDigits ?mcDigits[is] :tmpDigit;
504 : int nmc = 0;
505 0 : for( int i=0; i<3; i++ ) if( digit.fTrackID[i] >=0 ) nmc++;
506 0 : for( int i=0; i<3; i++ ){
507 0 : fEventMCMemory[mcIndex].fClusterID[i].fMCID = digit.fTrackID[i];
508 0 : fEventMCMemory[mcIndex].fClusterID[i].fWeight = 0;
509 0 : if( digit.fTrackID[i] >=0 ){
510 0 : fEventMCMemory[mcIndex].fClusterID[i].fWeight = ((float)bunchData[is])/nmc;
511 0 : }
512 : }
513 0 : mcIndex++;
514 : }
515 :
516 0 : } // bunches
517 :
518 0 : *header = (1<<30) | ((nWords10&0x3FF)<<16) | (hwAddr & 0xFFF);
519 :
520 0 : }// channels (pads)
521 :
522 0 : if( err ){
523 0 : HLTError("Internal error: too less memory allocated");
524 : } else {
525 0 : for( AliHLTUInt32_t i=0; i<nWords32; i++ ) fEventMemory[i] = AliHLTTPCHWCFEmulator::WriteBigEndian(fEventMemory[i]);
526 0 : rawEvent = fEventMemory;
527 0 : rawEventSize32 = nWords32;
528 0 : mcLabels = fEventMCMemory;
529 0 : nMCLabels = mcIndex;
530 : }
531 :
532 0 : } // unpacked data type
533 :
534 0 : return 0;
535 0 : }
536 :
537 :
538 : void AliHLTTPCHWCFSupport::Add10Word( AliHLTUInt32_t &nWords32, int &seek10, UInt_t data )
539 : {
540 : // add 10-bit data to the 32-bit word
541 : // fEventMemory [nWords32] --- current 32-bit word
542 : // *seek10 --- 10-bit position withing the word
543 : // pointers are increased, a new word is first initialised to 0
544 :
545 0 : data = data & 0x3FF; // truncate to 10 bits
546 :
547 0 : if( seek10 == 2 ){
548 0 : nWords32++;
549 0 : fEventMemory[nWords32-1] = data<<20;
550 0 : seek10 = 1;
551 0 : } else if( seek10 == 1 ){
552 0 : fEventMemory[nWords32-1] &= 0xFFF003FF;
553 0 : fEventMemory[nWords32-1] |= (data<<10);
554 0 : seek10 = 0;
555 0 : } else if( seek10 == 0 ){
556 0 : fEventMemory[nWords32-1] &= 0xFFFFFC00;
557 0 : fEventMemory[nWords32-1] |= data;
558 0 : seek10 = 2;
559 0 : }
560 0 : }
561 :
562 :
563 :
564 : int AliHLTTPCHWCFSupport::CheckRawData( const AliHLTUInt32_t *buffer,
565 : unsigned long bufferSize32, int patch, int slice )
566 : {
567 : //
568 : // The procedure checks consistency of the data
569 : //
570 :
571 :
572 0 : if (!buffer) return 0;
573 :
574 0 : AliHLTCDHWrapper cdh((void*)buffer);
575 0 : const unsigned int headerSize32 = cdh.GetHeaderSize()/4;
576 :
577 0 : const char *str=Form("slice %d patch %d:", slice, patch);
578 :
579 0 : if( bufferSize32 < headerSize32 ){
580 0 : HLTWarning("%s Buffer size is smaller than CDH header size", str);
581 0 : return kFALSE;
582 : }
583 :
584 : // read data header
585 :
586 0 : AliHLTUInt32_t blockSize32 = bufferSize32; // size of the raw data in words
587 :
588 0 : if( buffer[0]!=0xFFFFFFFF ) blockSize32 = buffer[0]/4; // use size information from the header
589 0 : if( blockSize32 > bufferSize32 ){
590 0 : HLTWarning(Form("%s Could not find a valid DDL header!",str));
591 0 : return 0;
592 : }
593 :
594 0 : UChar_t rcuVer = (UChar_t)( (buffer[1] >> 24) & 0xFF );
595 :
596 0 : if (rcuVer < 2) {
597 0 : HLTWarning("%s Old data format, RCU version %d", str,rcuVer);
598 0 : return 0;
599 : }
600 :
601 : // is the block valid
602 : //AliHLTUInt32_t blockAttributes = buffer[3]; // block attributes (bits 24-31) and participating sub detectors
603 : //cout<<blockAttributes<<" "<<(blockAttributes >> 24)<<endl;
604 : //if ( !( (blockAttributes >> 24) & 1) ) return 0;
605 :
606 :
607 0 : const AliHLTUInt32_t* fData = buffer + headerSize32;
608 0 : unsigned long dataSize32 = blockSize32 - headerSize32;
609 :
610 : // Read the RCU trailer according to the RCU formware version specified in CDH
611 : // Cross-check with version found in the trailer
612 : // The two major bit should be 11 (identifies the end of the trailer)
613 :
614 0 : AliHLTUInt32_t word = fData[dataSize32 - 1];
615 :
616 0 : if ((word >> 30) != 3) {
617 0 : HLTWarning("%s Last RCU trailer word not found!", str);
618 0 : return 0;
619 : }
620 :
621 0 : UChar_t ver = (word >> 16) & 0xFF;
622 : //AliHLTUInt32_t rcuId = (Int_t)((word >> 7) & 0x1FF);
623 0 : AliHLTUInt32_t rcuTrailerSize32 = (word & 0x7F); // size of RCU trailer data in words
624 :
625 0 : if (ver != rcuVer) {
626 0 : HLTWarning("%s Wrong RCU firmware version detected: %d != %d",
627 : str,ver,rcuVer);
628 0 : return 0;
629 : }
630 :
631 0 : if (rcuTrailerSize32 < 2) {
632 0 : HLTWarning(Form("Invalid trailer size found (%d bytes) !",
633 : rcuTrailerSize32*4));
634 0 : return 0;
635 : }
636 :
637 0 : if( rcuTrailerSize32 > dataSize32 ){
638 0 : HLTWarning(Form("%s Invalid trailer size found (%d bytes) ! The size is bigger than the raw data size (%ld bytes)!",
639 : str, rcuTrailerSize32*4,dataSize32*4));
640 0 : return 0;
641 : }
642 :
643 : // check the trailer
644 :
645 0 : Int_t trailerIndex = dataSize32 - rcuTrailerSize32;
646 :
647 0 : for( unsigned int i=trailerIndex; i<dataSize32-1; i++){
648 0 : if ((fData[i] >> 30) != 2) {
649 0 : HLTWarning("%s Missing RCU trailer identifier pattern!",str);
650 : continue;
651 : }
652 : }
653 :
654 : // Read the payload size
655 :
656 0 : Int_t rcuPayloadSize32 = fData[trailerIndex] & 0x3FFFFFF;
657 :
658 0 : if ( rcuPayloadSize32 + rcuTrailerSize32 != dataSize32) {
659 0 : HLTWarning(Form("%s Inconsistent raw data size ! Raw data size - %ld bytes (from CDH), RCU trailer - %d bytes, raw data size (from RCU trailer) - %d bytes !",
660 : str, dataSize32*4,
661 : (rcuTrailerSize32)*4,
662 : rcuPayloadSize32*4));
663 0 : return 0;
664 : }
665 :
666 :
667 : //AliHLTTPCMapping *mapping = new AliHLTTPCMapping(patch);
668 : const int kMaxNTimeBins = 2000;
669 :
670 0 : UShort_t *channelData10 = new UShort_t[kMaxNTimeBins]; // cache for the decoded altro payload
671 :
672 : Int_t position = 0; // current position (32-bit words) in fData
673 :
674 0 : while(1){
675 :
676 : // Search for the next Altro channel
677 :
678 : word = 0;
679 0 : while( position < rcuPayloadSize32 ){
680 0 : word = fData[position++];
681 0 : if( (word >> 30) == 1) break;
682 : }
683 0 : if (position >= rcuPayloadSize32 ) break; // no next channel found
684 :
685 : // extract channel payload and hw address
686 :
687 0 : Int_t channelPayloadSize10 = (word >> 16) & 0x3FF; // payload size in 10-bit words
688 0 : Int_t channelPayloadSize32 = (channelPayloadSize10+2)/3;
689 0 : Bool_t channelIOErrors = (word >> 29) & 0x1; // check for readout errors
690 0 : Short_t channelHWAddress = word & 0xFFF;
691 :
692 0 : if( position + channelPayloadSize32-1> rcuPayloadSize32 ){
693 0 : HLTWarning(Form("%s Inconsistent channel payload data size: expected <= %d bytes from RCU trailer, found %d bytes in the channel header!",
694 : str,(rcuPayloadSize32 - position)*4, channelPayloadSize32*4 ));
695 0 : continue;
696 : }
697 :
698 : //bool channelBranchAB = ((channelHWAddress >> 11) & 0x1);
699 : // int channelFEC = ((channelHWAddress >> 7) & 0xF); // front-end card index
700 : //int channelAltro = ((channelHWAddress >> 4) & 0x7); // altro chip index
701 : //int channelIndex = (channelHWAddress & 0xF); // channel index
702 : //int channelRow = mapping->GetRow(channelHWAddress);
703 : //int channelPad = mapping->GetPad(channelHWAddress);
704 :
705 : // Now unpack the Altro data: 10-bit words to 16 bit-words
706 :
707 : Int_t channelData10Index = 0;// current position in the payload
708 :
709 0 : for (Int_t iword = 0; iword < channelPayloadSize32; iword++) {
710 0 : word = fData[position++];
711 0 : if ((word >> 30) != 0) {
712 0 : HLTWarning(Form("%s Unexpected end of payload in altro channel payload! Address=0x%x, word=0x%x",
713 : str, channelHWAddress,word));
714 : channelIOErrors = 1;
715 : position--;
716 0 : break;
717 : }
718 0 : channelData10[channelData10Index++] = (word >> 20) & 0x3FF;
719 0 : channelData10[channelData10Index++] = (word >> 10) & 0x3FF;
720 0 : channelData10[channelData10Index++] = word & 0x3FF;
721 : }
722 :
723 0 : if ( channelIOErrors ) continue;
724 :
725 : // read bunches
726 :
727 : Int_t prevTimeBin = 1024;
728 : channelData10Index = 0;
729 :
730 0 : while(1){
731 :
732 : // Read next Altro bunch
733 :
734 0 : if ((channelData10Index+1 >= channelPayloadSize10) ) break;
735 :
736 0 : Int_t bunchLength = channelData10[channelData10Index++];
737 0 : Int_t bunchStartTimeBin = channelData10[channelData10Index++];
738 :
739 0 : if (bunchLength <= 2) {
740 : // Invalid bunch size
741 0 : HLTWarning(Form("%s Too short bunch length (%d) in Address=0x%x!",
742 : str, bunchLength,channelHWAddress));
743 0 : break;
744 : }
745 0 : if( channelData10Index + bunchLength - 2 > channelPayloadSize10 ){
746 : // Too long bunch detected
747 0 : HLTWarning(Form("%s Too long bunch detected in Address=0x%x! Expected <= %d 10-bit words, found %d !",
748 : str,channelHWAddress,channelPayloadSize10-channelData10Index,bunchLength));
749 0 : break;
750 : }
751 :
752 0 : if( bunchStartTimeBin-bunchLength+1 < 0) {
753 0 : HLTWarning(Form("%s Invalid start time-bin in Address=0x%x ! (%d-%d+1) < 0",
754 : str,channelHWAddress,bunchStartTimeBin,bunchLength));
755 0 : break;
756 : }
757 0 : if (bunchStartTimeBin >= prevTimeBin) {
758 0 : HLTWarning(Form("%s Invalid start time-bin in Address=0x%x! (%d>=%d)",
759 : str,channelHWAddress,bunchStartTimeBin,prevTimeBin));
760 0 : break;
761 : }
762 :
763 : prevTimeBin = bunchStartTimeBin-bunchLength+1;
764 :
765 0 : bunchLength -= 2;
766 :
767 : //UShort_t* bunchData = &channelData10[channelData10Index]; // pointer to the current bunch samples
768 0 : channelData10Index += bunchLength;
769 0 : }
770 0 : }
771 :
772 0 : delete[] channelData10;
773 : //delete mapping;
774 :
775 : return 1;
776 0 : }
777 :
|