ATLAS Offline Software
Classes | Public Member Functions | Private Member Functions | Private Attributes | List of all members
L1CaloBsDecoderRun3 Class Reference

#include <L1CaloBsDecoderRun3.h>

Collaboration diagram for L1CaloBsDecoderRun3:

Classes

class  Logging
 Interface class for logging, can be overriden to e.g. More...
 

Public Member Functions

 L1CaloBsDecoderRun3 ()
 
void setVerbosity (bool verbosity)
 
void setLogger (std::unique_ptr< Logging > &&logger)
 
void decodeEfexData (const uint32_t *beg, const uint32_t *end, std::list< L1CaloRdoEfexTower > &dat, std::list< L1CaloRdoRodInfo >::const_iterator rodInfo) const
 Decode eFEX input fibre data. More...
 
void decodeEfexTobs (const uint32_t *beg, const uint32_t *end, std::list< L1CaloRdoEfexTob > &tob, std::list< L1CaloRdoRodInfo >::const_iterator rodInfo) const
 Decode eFEX TOBs and XTOBs. More...
 
void decodeJfexData (const uint32_t *beg, const uint32_t *end, std::list< L1CaloRdoJfexTower > &dat, std::list< L1CaloRdoRodInfo >::const_iterator rodInfo)
 Decode jFEX input fibre data. More...
 
void decodeJfexTobs (const uint32_t *beg, const uint32_t *end, std::list< L1CaloRdoJfexTob > &tob, std::list< L1CaloRdoRodInfo >::const_iterator rodInfo)
 Decode jFEX TOBs and XTOBs. More...
 
void decodeGfexData (const uint32_t *beg, const uint32_t *end, std::list< L1CaloRdoGfexTower > &dat, std::list< L1CaloRdoRodInfo >::const_iterator rodInfo)
 Decode gFEX input fibre data. More...
 
void decodeGfexTobs (const uint32_t *beg, const uint32_t *end, std::list< L1CaloRdoGfexTob > &dat, std::list< L1CaloRdoRodInfo >::const_iterator rodInfo)
 Decode gFEX TOBs. More...
 
void decodePh1TopoData (const uint32_t *beg, const uint32_t *end, std::list< L1CaloRdoEfexTob > &etob, std::list< L1CaloRdoJfexTob > &jtob, std::list< L1CaloRdoGfexTob > &gtob, std::list< L1CaloRdoMuonTob > &mtob, std::list< L1CaloRdoRodInfo >::const_iterator rodInfo)
 Decode Ph1Topo input data: these are TOBs from FEXes and MuCTPI. More...
 
void decodePh1TopoHits (const uint32_t *beg, const uint32_t *end, std::list< L1CaloRdoPh1TopoHit > &hit, std::list< L1CaloRdoRodInfo >::const_iterator rodInfo)
 Decode Ph1Topo hit results. More...
 

Private Member Functions

void decodeOneEfexTob (const uint32_t word[], const uint32_t shelfNumber, const uint32_t efexNumber, const uint32_t fpgaNumber, const uint32_t errorMask, const uint32_t numSlices, const uint32_t sliceNum, L1CaloRdoFexTob::TobType tobType, L1CaloRdoFexTob::TobSource tobSource, std::list< L1CaloRdoEfexTob > &tob, std::list< L1CaloRdoRodInfo >::const_iterator rodInfo) const
 Decode word(s) for one eFEX TOB (or xTOB) and create one RDO. More...
 
uint32_t decodeEfexDataChan (const uint32_t payload[], const uint32_t efexNumber, const uint32_t shelfNumber, const uint32_t errorMask, std::list< L1CaloRdoEfexTower > &dat, std::list< L1CaloRdoRodInfo >::const_iterator rodInfo) const
 Decode the data from one eFEX input fibre (only ever one slice). More...
 
bool decodeEfexTobSlice (const uint32_t payload[], size_t &index, const uint32_t efexNumber, const uint32_t shelfNumber, const uint32_t numSlices, const uint32_t errorMask, std::list< L1CaloRdoEfexTob > &tob, std::list< L1CaloRdoRodInfo >::const_iterator rodInfo) const
 Decode one eFEX FPGA block of TOBs and XTOBs for one slice. More...
 
uint32_t decodeJfexDataChan (const uint32_t payload[], const uint32_t jfexNumber, const uint32_t fpgaNumber, const uint32_t errorMask, std::list< L1CaloRdoJfexTower > &dat, std::list< L1CaloRdoRodInfo >::const_iterator rodInfo)
 Decode the data from one jFEX input fibre (only ever one slice). More...
 
bool decodeJfexTobSlice (const uint32_t payload[], size_t blockSize, size_t &index, const uint32_t jfexNumber, const uint32_t fpgaNumber, const uint32_t sliceNumber, const uint32_t numSlices, const uint32_t errorMask, std::list< L1CaloRdoJfexTob > &tob, std::list< L1CaloRdoRodInfo >::const_iterator rodInfo)
 Decode one jFEX FPGA block of TOBs and XTOBs for one slice. More...
 
uint32_t decodeGfexDataChan (const uint32_t payload[], const uint32_t fpgaNumber, const uint32_t chanNumber, const uint32_t errorMask, std::list< L1CaloRdoGfexTower > &dat, std::list< L1CaloRdoRodInfo >::const_iterator rodInfo)
 Decode the data from one gFEX input fibre (only ever one slice). More...
 
bool decodeGfexTobSlice (const uint32_t payload[], const uint32_t blockType, const uint32_t sliceNumber, const uint32_t numSlices, const uint32_t errorMask, std::list< L1CaloRdoGfexTob > &tob, std::list< L1CaloRdoRodInfo >::const_iterator rodInfo)
 Decode one gFEX FPGA block of TOBs for one slice. More...
 
bool checkFibreCRC (std::vector< uint32_t > &data) const
 Check the CRC in an input fibre block of words. More...
 

Private Attributes

int m_verbosity
 
std::unique_ptr< Loggingm_logger
 

Detailed Description

Decoder for Run 3 data formats: eFEX, jFEX, gFEX and phase 1 Topo. Utility methods shared with Runs 1 & 2 are now in L1CaloBsDecoderUtil.

Definition at line 22 of file L1CaloBsDecoderRun3.h.

Constructor & Destructor Documentation

◆ L1CaloBsDecoderRun3()

L1CaloBsDecoderRun3::L1CaloBsDecoderRun3 ( )

Definition at line 48 of file L1CaloBsDecoderRun3.cxx.

49 : m_verbosity(0), m_logger(std::make_unique<Logging>())
50 {
51 
52  // Force initialisation of mapping tables.
53  EfexCellMapping dummyEfexMapping(0,0,0,0,0,0);
54  if (!dummyEfexMapping.getDetectorRegion().getValidity()) {
55  LOG_ERROR("ctor", "unexpected invalid eFEX mapping!?","");
56  }
57 #ifndef OFFLINE_DECODER
58  JfexCellMapping dummyJfexMapping(0,1,0,0); // Processor number 1-4
59  if (!dummyJfexMapping.getDetectorRegion().getValidity()) {
60  LOG_ERROR("ctor", "unexpected invalid jFEX mapping!?","");
61  }
62  GfexCellMapping dummyGfexMapping(0,0,0,0); // Processor number 0-2?
63  if (!dummyGfexMapping.getDetectorRegion().getValidity()) {
64  LOG_ERROR("ctor","unexpected invalid gFEX mapping!?","");
65  }
66 #endif
67 }

Member Function Documentation

◆ checkFibreCRC()

bool L1CaloBsDecoderRun3::checkFibreCRC ( std::vector< uint32_t > &  data) const
private

Check the CRC in an input fibre block of words.

The CRC field should be the top 9 bits in the 7 word block. This means we calculate the CRC over the remaining 215 bits.

Parameters
datavector of 7 input fibre words
Returns
true if the CRC is valid

Definition at line 669 of file L1CaloBsDecoderRun3.cxx.

670 {
671  const size_t numWords = FexDefs::num32BitWordsPerFibre();
672  if ( data.size() != numWords ) {
673  return false;
674  }
675  GenericCrc crc;
676  const size_t numPayloadBits = ( 32 * numWords ) - 9;
677  unsigned int actualCRC = ( data[numWords-1] >> 23 ) & 0x1ff;
678  data[0] &= 0xffffff00; // Zero the K character
679  unsigned int expectCRC = crc.crc9fibre( data, numPayloadBits );
680 
681  return (actualCRC == expectCRC);
682 }

◆ decodeEfexData()

void L1CaloBsDecoderRun3::decodeEfexData ( const uint32_t *  beg,
const uint32_t *  end,
std::list< L1CaloRdoEfexTower > &  tower,
std::list< L1CaloRdoRodInfo >::const_iterator  rodInfo 
) const

Decode eFEX input fibre data.

For the EM layer we have up to 10 supercell values per tower though there is still just a single hadronic value. It seemed overkill to have an RDO per supercell, so instead the main RDO "Value" is set to the sum of 10 EM supercells with the individual supercell Ets saved in a separate vector. These are always stored in 1441 order (PS, F0-F3, M0-M3, BK) even in regions where some supercells are missing. The flag field is used for status/error bits.

Parameters
begpointer to start of rod data payload
endpointer to end of rod data payload
towerlist of RDO to be filled
rodInfoiterator to ROD information for this block

Definition at line 85 of file L1CaloBsDecoderRun3.cxx.

88 {
89  const uint32_t* payload( beg );
90  const size_t fragmentSize = end - beg;
91 
92  // The data block is optimised for production by firmware with the length
93  // in a trailer at the end. The SWROD concatenates a number of such blocks
94  // (removing the 2 word header used to fill the ROD fragment header).
95  // So we need to find the end and work backwards.
96 
97  size_t numTowers = tower.size();
98  size_t index = fragmentSize;
99 
100  // Loop looking backwards for eFEX processor input data blocks.
101  while ( index > 0 ) {
102  if ( index < 4 ) {
103  LOG_ERROR("decodeEfexData", "block size error",
104  "remaining block size " << index
105  << " is too small for the eFEX FPGA trailer");
106  return;
107  }
108  const uint32_t ctrlTrailer2 = payload[--index];
109  const uint32_t ctrlTrailer1 = payload[--index];
110  const uint32_t fpgaTrailer2 = payload[--index];
111  const uint32_t fpgaTrailer1 = payload[--index];
112 
113  const uint32_t ctrlErrors = ctrlTrailer2 & 0x3f;
114  const uint32_t efexNumber = (ctrlTrailer1 >> 12) & 0xf;
115  const uint32_t shelfNumber = (ctrlTrailer1 >> 16) & 0x1; // Just use 1 bit from 4 bit field
116  const size_t payloadSize = (ctrlTrailer1 & 0xfff) - 2;
117 
118  if ( payloadSize > index ) {
119  LOG_ERROR("decodeEfexData", "block size error","remaining eFEX block size "
120  << index << " is too small for the claimed payload size "
121  << payloadSize);
122  return;
123  }
124 
125  if (efexNumber >= CrateDefs::numAtcaFexSlots() ) {
126  LOG_ERROR("decodeEfexData","invalid eFEX number " << efexNumber,
127  " (out of range 0-" << CrateDefs::numAtcaFexSlots()-1 << ")");
128  return;
129  }
130 
131  // We can now work forwards from the start of this block
132  // decoding each set of 8 words per input fibre channel.
133  // The payloadSize has had two trailer words subtracted.
134  index -= payloadSize;
135  size_t chanIndex = 0;
136  uint32_t chanErrorOR = 0;
137  std::bitset<49> chansWithError;
138  bool anyErrorBit = false;
139  while ( chanIndex < payloadSize ) {
140  if ( (payloadSize - chanIndex) < 8 ) {
141  LOG_ERROR("decodeEfexData s" << shelfNumber << " e" << efexNumber,"block size error",
142  (payloadSize - chanIndex)<< " is too small for one eFEX input fibre block (8)");
143  return;
144  }
145  const uint32_t chanNumber = payload[index+chanIndex+7] & 0xff;
146  const uint32_t chanErrors = this->decodeEfexDataChan ( &payload[index+chanIndex], efexNumber, shelfNumber,
147  ctrlErrors, tower, rodInfo );
148  if ( chanErrors ) {
149  chanErrorOR |= ( chanErrors & 0x7 ); // Only three lowest bits get ORed
150  chansWithError[chanNumber] = 1;
151  anyErrorBit = true;
152  }
153  chanIndex += 8;
154  }
155  if ( anyErrorBit ) {
156  chanErrorOR |= 0x8; // Extra bit set if any of the three lower bits are set
157  }
158  const uint64_t fpgaErrorBits = ( (uint64_t)(fpgaTrailer2 & 0x1ffff) << 32 ) | fpgaTrailer1;
159  const uint64_t chanErrorBits = chansWithError.to_ullong();
160  const uint32_t fpgaErrorOR = ( fpgaTrailer2 >> 28 ) & 0xf;
161  if ( fpgaErrorBits != chanErrorBits || fpgaErrorOR != chanErrorOR ) {
162  LOG_ERROR("decodeEfexData: s" << shelfNumber << " e" << efexNumber,"errorbit mismatch",
163  "mismatch between errors in FPGA trailer: "
164  << std::hex << fpgaErrorBits << " " << fpgaErrorOR
165  << " and those derived from channels: " << chanErrorBits << " " << chanErrorOR
166  << std::dec);
167  }
168  }
169  if ( m_verbosity > 0 )
170  {
171  std::cout << "L1CaloBsDecoderRun3::decodeEfexData: n.towers added="
172  << tower.size() - numTowers << std::endl;
173  }
174 }

◆ decodeEfexDataChan()

uint32_t L1CaloBsDecoderRun3::decodeEfexDataChan ( const uint32_t  payload[],
const uint32_t  efexNumber,
const uint32_t  shelfNumber,
const uint32_t  errorMask,
std::list< L1CaloRdoEfexTower > &  tower,
std::list< L1CaloRdoRodInfo >::const_iterator  rodInfo 
) const
private

Decode the data from one eFEX input fibre (only ever one slice).

Parameters
payloadpayload vector starting at this 8 word block
efexNumbernumber of this eFEX in its shelf
shelfNumbershelf number (here 0 or 1)
errorMaskglobal error bits set for this ROD fragment
towerlist of RDO to be filled
rodInfoiterator to ROD information for this block
Returns
whether decoding succeeded (false to abort decoding)

Definition at line 187 of file L1CaloBsDecoderRun3.cxx.

192 {
193  // The EM and hadronic fibres have different encoding and cover
194  // different numbers of towers with more or less granularity.
195  // Channel numbers 0-39 are EM, 40-48 are hadronic.
196  const uint32_t chanNumber = ( payload[7] ) & 0xff;
197  const uint32_t fpgaNumber = ( payload[7] >> 8 ) & 0x3;
198  const uint32_t errorBits = ( payload[7] >> 28 ) & 0x7;
199  const uint32_t disabled = ( payload[7] >> 31 ) & 0x1;
200  if ((int)chanNumber >= EfexDefs::numInputFibresPerFpga()) {
201  LOG_ERROR("decodeEfexDataChan s" << shelfNumber << "e" << efexNumber << "f" << fpgaNumber, "invalid channel",
202  chanNumber << " (out of range 0-" << EfexDefs::numInputFibresPerFpga()-1 << ")");
203  return 0xffffffff;
204  }
205 
206  // Some endcap channels are inactive and have the disabled bit set
207  // if the full data is being read out. Just skip these.
208  if (disabled) {
209  return 0;
210  }
211 
212  // The EfexCellMapping returns global coordinates but the RDO objects
213  // expect local eta,phi within the module. So prepare these here.
214  // Find local eta,phi from global EfexCellMapping and module offset.
215  // There is no good way of handling the localEta. Below we add one
216  // so the barrel eta has core towers in localEta 1-16 with 0 and 17
217  // being core towers on C and A sides. Overlap towers extend further
218  // and both localEta and localPhi may be negative.
219  int moduleEta = -24 + (efexNumber % 3) * 16;
220  int modulePhi = 2 + (shelfNumber * 32) + (efexNumber / 3) * 8;
221 
222  // The fibre packer decoder methods expect a vector of seven words.
223  std::vector<FibrePackerBase::myDataWord> encodedData;
224  for ( size_t i = 0; i < 7; i++ ) {
225  encodedData.push_back( payload[i] );
226  }
228 
229  // Build up error flag for towers on this fibre.
230  // Bits 0-5 from ROD block trailer
231  // Bit 7 fibre CRC error flag
232  // Bits 8-10 from fibre trailer
233  bool rightCRC = this->checkFibreCRC( encodedData );
234  const uint32_t errorField = ( errorMask & 0x3f )
235  | ( rightCRC ? 0 : 0x80 )
236  | ( errorBits << 8 );
237 
238  if (chanNumber < 40) {
239  // Each EM fibre has 10 supercells for each of two 0.1*0.1 trigger towers.
240  // The EfexLatomeFibrePacker returns the complete set of 20 supercells.
241  EfexLatomeFibrePacker packer;
242  std::vector<FibrePackerBase::myDataWord> cells = packer.getUnpackedData( encodedData, frameType );
243 
244  // Create two tower RDOs, each containing half the supercells.
245  // NB all the middle layer supercells come first, then the rest
246  // for each tower: 4xM0, 4xM1, P0,4xF0,B0, P1,4xF1,B1.
247  // Hard code this to avoid too many calls to EfexCellMapping.
248  // We just call it with the first supercell word for each tower.
249  const std::vector<uint32_t> cellIndex = { 0, 1, 2, 3, 8, 9,10,11,12,13, // Tower0: MMMMPFFFFB
250  4, 5, 6, 7,14,15,16,17,18,19 }; // Tower1: MMMMPFFFFB
251  for ( size_t k = 0; k < 2; k++ ) {
252  std::vector<uint32_t> towerCells( 10, 0 );
253  uint32_t towerSumEt( 0 );
254  uint32_t wordNumber = 0;
255  for (size_t i = 0; i < 10; i++) {
256  uint32_t iCell = cellIndex[i+k*10];
257  if (i == 0) {
258  wordNumber = iCell;
259  }
260  towerCells[i] = cells[iCell];
261  towerSumEt += towerCells[i];
262  }
263 
264  // **FIXME** Fibre packer does not yet return quality bits!
265  // There should be one per middle layer supercell.
266  // We can OR those with error bits for this fibre.
267  uint32_t towerFlag = errorField;
268 
269  if ( towerSumEt || towerFlag ) {
270  EfexCellMapping mapping( shelfNumber, efexNumber, fpgaNumber, chanNumber, wordNumber );
271  L1CaloDetectorRegion region = mapping.getDetectorRegion();
272  EfexHardwareInfo hwInfo( mapping.getHardwareInfo() );
273  if ( region.getValidity() && hwInfo.getValidity() ) {
274  int localEta = region.getEtaIndex() - moduleEta + 1;
275  int localPhi = region.getPhiIndex() - modulePhi;
276 
277  const uint32_t layer = 0; // EM
278  L1CaloRdoEfexTower newOne( shelfNumber, efexNumber, localEta, localPhi, layer, region );
279  newOne.setRodInfo( rodInfo );
280  L1CaloRdoEfexTower& rdo = L1CaloBsDecoderUtil::findRdo( newOne, tower );
281 
282  rdo.setHardwareInfo( fpgaNumber, chanNumber, wordNumber,
283  hwInfo.getMpodNumber(), hwInfo.getFibreNumber(),
284  hwInfo.getOverlap() );
285  rdo.setValue( towerSumEt );
286  rdo.setFlag( towerFlag );
287  rdo.setSupercells( towerCells );
288  if ( m_verbosity > 0 )
289  {
290  std::cout << "L1CaloBsDecoderRun3::decodeEfexDataChan: EM"
291  << ", shelf=" << shelfNumber << ", module=" << efexNumber
292  << std::hex << ", Et=0x" << towerSumEt << ", flag=0x" << towerFlag
293  << std::dec << std::endl;
294  }
295  }
296  }
297  }
298  }
299 
300  else {
301  // Each hadronic fibre has a 4*4 array of 16 towers.
302  EfexTrexFibrePacker packer;
303  std::vector<FibrePackerBase::myDataWord> towerVals = packer.getUnpackedData( encodedData, frameType );
304  size_t numHadTowers = std::min(towerVals.size(),(size_t)16);
305 
306  // Create an RDO for each tower.
307  for ( size_t wordNumber = 0; wordNumber < numHadTowers; wordNumber++ ) {
308  const uint32_t towerEt = ( towerVals[wordNumber] == 0x3fe ) ? 0 : towerVals[wordNumber];
309  const uint32_t invalid = ( towerVals[wordNumber] == 0x3fe ) ? 1 : 0;
310  const uint32_t towerFlag = errorMask | ( invalid << 31 );
311 
312  if ( towerEt || towerFlag ) {
313  EfexCellMapping mapping( shelfNumber, efexNumber, fpgaNumber, chanNumber, wordNumber );
314  L1CaloDetectorRegion region = mapping.getDetectorRegion();
315  EfexHardwareInfo hwInfo( mapping.getHardwareInfo() );
316  if ( region.getValidity() && hwInfo.getValidity() ) {
317  // Need to decide if data is Tile/TREX or HEC/LATOME as TREX tower Et is still
318  // limited to 8 bits, at least for the start of Run 3, as in Runs 1 & 2.
319  // After the legacy CP/JEP system is decommissioned this may change to enable
320  // use of the full 10 bit field.
321  if ( (region.getEtaIndex() >= -15) && (region.getEtaIndex() < 15) ) { // Tile/TREX
322  towerVals[wordNumber] &= 0xff;
323  }
324 
325  int localEta = region.getEtaIndex() - moduleEta + 1;
326  int localPhi = region.getPhiIndex() - modulePhi;
327 
328  const uint32_t layer = 1; // Hadronic
329  L1CaloRdoEfexTower newOne( shelfNumber, efexNumber, localEta, localPhi, layer, region );
330  newOne.setRodInfo( rodInfo );
331  L1CaloRdoEfexTower& rdo = L1CaloBsDecoderUtil::findRdo( newOne, tower );
332 
333  rdo.setHardwareInfo( fpgaNumber, chanNumber, wordNumber,
334  hwInfo.getMpodNumber(), hwInfo.getFibreNumber(),
335  hwInfo.getOverlap() );
336  rdo.setValue( towerEt );
337  rdo.setFlag( towerFlag );
338  if ( m_verbosity > 0 )
339  {
340  std::cout << "L1CaloBsDecoderRun3::decodeEfexDataChan: Had"
341  << ", shelf=" << shelfNumber << ", module=" << efexNumber
342  << std::hex << ", Et=0x" << towerEt << ", flag=0x" << towerFlag
343  << std::dec << std::endl;
344  }
345  }
346  }
347  }
348  }
349 
350  return errorBits;
351 }

◆ decodeEfexTobs()

void L1CaloBsDecoderRun3::decodeEfexTobs ( const uint32_t *  beg,
const uint32_t *  end,
std::list< L1CaloRdoEfexTob > &  tob,
std::list< L1CaloRdoRodInfo >::const_iterator  rodInfo 
) const

Decode eFEX TOBs and XTOBs.

The RDO value encodes the cluster Et in the value field and the isolation bits and other information in the flag.

Parameters
begpointer to start of rod data payload
endpointer to end of rod data payload
toblist of RDO to be filled
rodInfoiterator to ROD information for this block

Definition at line 363 of file L1CaloBsDecoderRun3.cxx.

366 {
367  const uint32_t* payload( beg );
368  const size_t fragmentSize = end - beg;
369 
370  // The data block is optimised for production by firmware as a set
371  // of nested blocks with the lengths at the end. So we need to find
372  // the end and work backwards.
373 
374  if ( fragmentSize < 2 ) {
375  LOG_ERROR("decodeEfexTobs", "ROD trailer fragment size", fragmentSize
376  << " is too small for the ROD trailer");
377  return;
378  }
379 
380  size_t index = fragmentSize;
381  const uint32_t rodTrailer2 = payload[--index];
382  const uint32_t rodTrailer1 = payload[--index];
383 
384  const uint32_t rodErrors = rodTrailer2 & 0x7f;
385  const size_t payloadSize = rodTrailer1 & 0xffff;
386  if ( (rodErrors >> 6) & 0x1 ) {
387  LOG_ERROR("decodeEfexTobs","Unknown corrective trailer " << std::hex << rodErrors << std::dec,"");
388  return;
389  }
390  if ( (payloadSize + 2) != fragmentSize ) {
391  // Actual ROD fragment payload size does not match that claimed in the trailer.
392  LOG_ERROR("decodeEfexTobs","inconsistent ROD fragment size","payload size " << payloadSize
393  << " vs ROD fragment size " << fragmentSize);
394  return;
395  }
396 
397  // Loop looking backwards for eFEX module blocks.
398  while ( index > 0 ) {
399  if ( index < 2 ) {
400  LOG_ERROR("decodeEfexTobs","block size error", index
401  << " is too small for the eFEX trailer");
402  return;
403  }
404  size_t efexIndex = index;
405  const uint32_t efexTrailer2 = payload[--efexIndex];
406  const uint32_t efexTrailer1 = payload[--efexIndex];
407 
408  // check if this is actually a ROD corrective trailer instead of
409  // a control trailer
410  const uint32_t corrective = (efexTrailer2 >> 5) & 0x1;
411  if ( corrective ) {
412  // Corrective ROD trailer
413  size_t corrBlockSize = (efexTrailer1) & 0xffff;
414  const uint32_t efexNumber = (efexTrailer1 >> 16) & 0xf;
415  const uint32_t shelfNumber = (efexTrailer1 >> 20) & 0x1;
416  const uint32_t ctrlErr = efexTrailer2 & 0x3f;
417 
418  LOG_ERROR("decodeEfexTobs s" << shelfNumber << "e" << efexNumber,
419  "rod corrective trailer " << std::hex << ctrlErr << std::dec,"");
420 
421  if (corrBlockSize > index) {
422  LOG_ERROR("decodeEfexTobs s" << shelfNumber << "e" << efexNumber, "excessive rod corrective blocksize",
423  "rod corrective blocksize " << corrBlockSize <<
424  " > remaining blocksize ");
425  return;
426  }
427 
428  index -= corrBlockSize; // Ought to be 2
429  continue;
430  }
431 
432 
433  const size_t efexBlockSize = efexTrailer1 & 0xfff;
434  const uint32_t efexNumber = (efexTrailer1 >> 12) & 0xf;
435  const uint32_t shelfNumber = (efexTrailer1 >> 16) & 0x1; // 4 bit field, but only 1 but used
436  //??const uint32_t procErrMap = (efexTrailer1 >> 20) & 0xf; // Currently unused
437  const uint32_t numSlices = (efexTrailer1 >> 24) & 0xf;
438  //??const uint32_t l1aSlice = (efexTrailer1 >> 28) & 0xf; // Currently unused
439  const uint32_t efexErrors = efexTrailer2 & 0x3f;
440  if ( efexBlockSize > index ) {
441  LOG_ERROR("decodeEfexTobs s" << shelfNumber << "e" << efexNumber,"excessive block size", efexBlockSize
442  << " exceeds remaining data size " << index);
443  return;
444  }
445  // Update index to previous eFEX block (if any).
446  index = efexIndex - efexBlockSize;
447 
448  // Combine rod and efex error fields.
449  const uint32_t errorMask = efexErrors | (rodErrors << 6);
450 
451  // Loop looking backwards for eFEX processor blocks.
452  // There should be one block per slice per FPGA
453  // (except for errors giving corrective trailers).
454  while ( efexIndex > index ) {
455  if ( (efexIndex - index) < 2 ) {
456  LOG_ERROR("decodeEfexTobs s"<< shelfNumber << "e" << efexNumber,
457  "blocksize deficit",
458  (efexIndex - index) << " is too small for the eFEX slice trailer");
459  return;
460  }
461  size_t procIndex = efexIndex;
462  bool ret = this->decodeEfexTobSlice ( payload, procIndex, efexNumber, shelfNumber,
463  numSlices, errorMask, tob, rodInfo );
464  if ( ! ret ) {
465  return;
466  }
467  efexIndex = procIndex;
468  }
469  }
470 }

◆ decodeEfexTobSlice()

bool L1CaloBsDecoderRun3::decodeEfexTobSlice ( const uint32_t  payload[],
size_t &  index,
const uint32_t  efexNumber,
const uint32_t  shelfNumber,
const uint32_t  numSlices,
const uint32_t  errorMask,
std::list< L1CaloRdoEfexTob > &  tob,
std::list< L1CaloRdoRodInfo >::const_iterator  rodInfo 
) const
private

Decode one eFEX FPGA block of TOBs and XTOBs for one slice.

Parameters
payloadentire ROD fragment payload vector
indexjust past end of block for this slice (this method updates it to the start of the block)
efexNumbernumber of this eFEX in its shelf
shelfNumbershelf number
numSlicesnumber of TOB slices read out in this event
errorMaskglobal error bits set for this ROD fragment
toblist of RDO to be filled
rodInfoiterator to ROD information for this block
Returns
whether decoding succeeded (false to abort decoding in which case the returned index is not valid)

Definition at line 487 of file L1CaloBsDecoderRun3.cxx.

492 {
493  if ( index < 1 ) {
494  return false;
495  }
496 
497  const uint32_t sliceTrailer = payload[index-1];
498  const uint32_t corrective = (sliceTrailer >> 31) & 0x01;
499 
500 
501  if ( corrective ) {
502  // Corrective trailer: no data from this processor FPGA.
503  // Not much we can do so just report it and carry on.
504  size_t corrBlockSize = sliceTrailer & 0xfff;
505  //const uint32_t failingBCN = (sliceTrailer >> 12) & 0xfff; - don't print this to avoid too many different error messages
506  const uint32_t fpgaNumber = (sliceTrailer >> 24) & 0x3;
507  const uint32_t plErr = (sliceTrailer >> 30) & 0x01;
508  const uint32_t bcnErr = (sliceTrailer >> 29) & 0x01;
509  LOG_ERROR("decodeEfexTobSlice s" << shelfNumber << "e" << efexNumber << "f" << fpgaNumber,
510  "ctrl corrective trailer " << std::hex << (plErr*2+bcnErr) << std::dec,"error bits: PacketLength=" << plErr << ", BCNMismatch=" << bcnErr);
511  // corrective trailer blockSize doesn't include the trailer itself (length of one)
512  // and also doesn't include padding word (which occurs if the blockSize is even
513  // because the corrective trailer adds one more word and then a padding word is needed
514  corrBlockSize += ((corrBlockSize % 2) == 1) ? 1 : 2;
515 
516  if (corrBlockSize > index) {
517  LOG_ERROR("decodeEfexTobSlice s" << shelfNumber << "e" << efexNumber << "f" << fpgaNumber, "excessive ctrl corrective blocksize",
518  "corrective blocksize " << corrBlockSize <<
519  " > remaining blocksize ");
520  return false;
521  }
522 
523  index -= corrBlockSize; // Ought to be 2
524  }
525  else {
526  // October 2021: New format implemented! K.Char in lowest 8 bits.
527  const uint32_t tobType = (sliceTrailer >> 8) & 0x1;
528  const uint32_t numTobs = (sliceTrailer >> 9) & 0x7;
529  const uint32_t numEmXtobs = (sliceTrailer >> 12) & 0x3f;
530  const uint32_t numTauXtobs = (sliceTrailer >> 18) & 0x3f;
531  const uint32_t sliceNumber = (sliceTrailer >> 24) & 0x7;
532  const uint32_t safeMode = (sliceTrailer >> 27) & 0x1;
533  const uint32_t fpgaNumber = (sliceTrailer >> 28) & 0x3;
534 
535  // Work out how long this block should be. Each TOB is one word,
536  // each XTOB is two words. If the total is odd (including one word
537  // for the trailer) there should be an extra zero padding word.
538  // However in safe mode all the TOBs and XTOBs are suppressed
539  // and we only have the trailer and padding word.
540  size_t tobSize = (safeMode == 0)
541  ? (1 + numTobs + 2 * (numEmXtobs + numTauXtobs))
542  : 2;
543  tobSize += (tobSize % 2);
544 
545  // Move index to start of this block.
546  if (tobSize > index) {
547  LOG_ERROR( "decodeEfexTobSlice s" << shelfNumber << "e" << efexNumber << "f" << fpgaNumber,
548  "excessive blocksize",
549  "TOB blocksize " << tobSize << " > remaining blocksize " << index);
550  return false;
551  }
552  index -= tobSize;
553 
554  if ( safeMode ) {
555  LOG_ERROR( "decodeEfexTobSlice s" << shelfNumber << "e" << efexNumber << "f" << fpgaNumber,
556  "safe mode",
557  "missed " << numTobs << " TOBs, " << numEmXtobs << " EM XTOBs, "
558  << numTauXtobs << " Tau XTOBs" );
559  }
560  else {
561  // Luxury, we can now work forwards inside the slice block!
562  // We expect first TOBs (if any) then EM xTOBs, then Tau xTOBs.
563  const size_t totalTobs = numTobs + numEmXtobs + numTauXtobs;
564  L1CaloRdoFexTob::TobType fexTobType = (tobType == 0)
567  L1CaloRdoFexTob::TobSource fexTobSource = L1CaloRdoFexTob::TobSource::EfexTob;
568  size_t sliceIndex = index;
569  for (size_t iTOB = 0; iTOB < totalTobs; iTOB++) {
570  if (iTOB >= numTobs) {
571  fexTobSource = L1CaloRdoFexTob::TobSource::EfexXtob;
572  fexTobType = (iTOB < (numTobs + numEmXtobs))
575  }
576  this->decodeOneEfexTob ( &payload[sliceIndex], shelfNumber, efexNumber, fpgaNumber,
577  errorMask, numSlices, sliceNumber, fexTobType, fexTobSource,
578  tob, rodInfo );
579  // One or two words per TOB or xTOB.
580  sliceIndex += (fexTobSource == L1CaloRdoFexTob::TobSource::EfexTob) ? 1 : 2;
581  }
582  }
583  }
584  return true;
585 }

◆ decodeGfexData()

void L1CaloBsDecoderRun3::decodeGfexData ( const uint32_t *  beg,
const uint32_t *  end,
std::list< L1CaloRdoGfexTower > &  tower,
std::list< L1CaloRdoRodInfo >::const_iterator  rodInfo 
)

Decode gFEX input fibre data.

We create one RDO per tower using the value field for its Et. The flag field is used for status/error bits.

Parameters
begpointer to start of rod data payload
endpointer to end of rod data payload
towerlist of RDO to be filled
rodInfoiterator to ROD information for this block

Definition at line 1184 of file L1CaloBsDecoderRun3.cxx.

1187 {
1188  const uint32_t* payload( beg );
1189 
1190  // The data block consists of up to three sections, one per processor FPGA.
1191  // Each block starts with a one word header that identifies the FPGA and has
1192  // the block length and a few other fields.
1193 
1194  size_t numTowers = tower.size();
1195 
1196  // Loop looking backwards for jFEX processor input data blocks.
1197  while ( payload < end ) {
1198  const uint32_t word = *payload++;
1199 
1200  // The first word must be the header.
1201 
1202  const uint32_t fpgaCode = ( word >> 28 ) & 0xf;
1203  if ( fpgaCode < 0xa || fpgaCode > 0xc ) {
1204  LOG_ERROR("decodeGfexData","","invalid FPGA code 0x"
1205  << std::hex << fpgaCode << std::dec);
1206  return;
1207  }
1208  const uint32_t fpgaNumber = fpgaCode - 0xa; // A=0, B=1, C=2
1209  const uint32_t headerVer = ( word >> 24 ) & 0xf;
1210  const uint32_t headerLen = ( word >> 22 ) & 0x3;
1211  if ( headerVer > 1 || headerLen > 1 ) {
1212  LOG_ERROR("decodeGfexData","",": header version " << headerVer
1213  << " or length " << headerLen << " is not yet supported");
1214  return;
1215  }
1216  const uint32_t truncatedFlag = (word >> 12) & 0x1;
1217  if ( truncatedFlag ) {
1218  LOG_ERROR("decodeGfexData","","WARNING data truncated");
1219  }
1220  const uint32_t numFpgaWords = word & 0xfff;
1221  if ( ( numFpgaWords % 7 ) != 0 ) {
1222  LOG_ERROR("decodeGfexData","","input data size " << numFpgaWords
1223  << " is not a multiple of 7");
1224  return;
1225  }
1226  const uint32_t numInputFibres = numFpgaWords / 7;
1227 
1228  // Loop over the input fibres and decode each block of 7 words.
1229  // **FIXME** Not sure if gFEX data will have error flags?
1230  // **FIXME** For the moment hard code to zero.
1231 
1232  const uint32_t fpgaErrors = 0;
1233 
1234  for ( size_t chanNumber = 0; chanNumber < numInputFibres; chanNumber++ ) {
1235  // Ignore the spare fibres for the moment.
1236  if ( chanNumber < 48 || chanNumber >= 52 ) {
1237  this->decodeGfexDataChan ( payload, fpgaNumber, chanNumber,
1238  fpgaErrors, tower, rodInfo );
1239  }
1240  payload += 7;
1241  }
1242  }
1243  if ( m_verbosity > 0 )
1244  {
1245  std::cout << "L1CaloBsDecoderRun3::decodeGfexData: n.towers added="
1246  << tower.size() - numTowers << std::endl;
1247  }
1248 }

◆ decodeGfexDataChan()

uint32_t L1CaloBsDecoderRun3::decodeGfexDataChan ( const uint32_t  payload[],
const uint32_t  fpgaNumber,
const uint32_t  chanNumber,
const uint32_t  errorMask,
std::list< L1CaloRdoGfexTower > &  tower,
std::list< L1CaloRdoRodInfo >::const_iterator  rodInfo 
)
private

Decode the data from one gFEX input fibre (only ever one slice).

Parameters
payloadpayload vector starting at this 7 word block
fpgaNumberFPGA number (0-2 for A-C)
errorMaskglobal error bits set for this ROD fragment
towerlist of RDO to be filled
rodInfoiterator to ROD information for this block
Returns
whether decoding succeeded (false to abort decoding)

Definition at line 1260 of file L1CaloBsDecoderRun3.cxx.

1266 {
1267  const uint32_t shelfNumber = 0x23; // Hard code to P1 value (35)
1268  const uint32_t gfexNumber = 0; // **CHECK** What is used in COOL/OKS?
1269 
1270  // Ignore the spare fibres for the moment.
1271  if ( chanNumber >= 48 && chanNumber < 52 ) {
1272  return 0;
1273  }
1274 
1275  // Ignore FPGA C for the moment (different format).
1276  if ( fpgaNumber >= 2 ) {
1277  return 0;
1278  }
1279 
1280  // The fibre packer decoder methods expect a vector of seven words.
1281  std::vector<FibrePackerBase::myDataWord> encodedData;
1282  for ( size_t i = 0; i < 7; i++ ) {
1283  encodedData.push_back( payload[i] );
1284  }
1286 
1287  // Unpack up to sixteen gCaloTowers. NB central FPGAs only have eight
1288  // Et values per EM fibre but additionally have eight fine positions.
1289  // For the moment we ignore the latter.
1290  // We need the central Latome decoder for FPGAs A&B for both EM layer
1291  // and hadronic layer outside the central eight 0.2 eta bins (to 1.6).
1292  // The hadronic fibres within |eta|<1.6 are TREX.
1293  // However due to overlaps and potentially unused words on fibres
1294  // its safer to decode in all possible ways and work out which one
1295  // to use afterwards.
1296  GfexTrexFibrePacker trexPacker;
1297  GfexLatomeCentralFibrePacker clarPacker;
1298  GfexLatomeForwardFibrePacker flarPacker;
1299  std::vector<FibrePackerBase::myDataWord> trexTowers = trexPacker.getUnpackedData( encodedData, frameType );
1300  std::vector<FibrePackerBase::myDataWord> clarTowers = clarPacker.getUnpackedData( encodedData, frameType );
1301  std::vector<FibrePackerBase::myDataWord> flarTowers = flarPacker.getUnpackedData( encodedData, frameType );
1302  size_t numTowers = GfexDefs::maxGTowersPerFibre();
1303  size_t numCentral = numTowers / 2; // 8
1304 
1305  // Create RDO per tower.
1306  for ( size_t iTower = 0; iTower < numTowers; iTower++ ) {
1307  GfexCellMapping mapping( 0, fpgaNumber, chanNumber, iTower );
1308  L1CaloDetectorRegion region = mapping.getDetectorRegion();
1309  GfexHardwareInfo hwInfo( mapping.getHardwareInfo() );
1310  if ( !region.getValidity() || !hwInfo.getValidity() ) {
1311  continue;
1312  }
1313  // Currently GfexCellMapping sets local eta,phi within each FPGA.
1314  // We want to convert to global values (whole module or system).
1315  int globalPhi = region.getPhiIndex() * 2;
1316  int globalEta = GfexDefs::localToGlobalEta(fpgaNumber,region.getEtaIndex());
1317  if (globalEta < -49 || globalEta >= 49) {
1318  continue; // Invalid or not yet implemented
1319  }
1320  int layer = (region.getLayer() == L1CaloDetectorRegion::Electromagnetic) ? 0 : 1;
1321 
1322  // Work out which decoding we ought to use.
1323  // For the moment avoid regions of potential confusion, eg Tile/HEC
1324  // overlap, anything outside |eta|>2.4, etc.
1325  // **FIXME** Ideally this should definitively come from the mapping.
1326  int towerEt = 0;
1327  if ( layer == 1 && std::abs(globalEta) < 14 ) {
1328  // TREX within Tile/HEC overlap.
1329  towerEt = trexTowers[iTower];
1330  }
1331  else if ( layer == 1 && std::abs(globalEta) >= 16 && std::abs(globalEta) < 24 ) {
1332  // HEC outside Tile/HEC overlap.
1333  towerEt = flarTowers[iTower];
1334  }
1335  else if ( layer == 0 && std::abs(globalEta) < 14 && iTower < numCentral ) {
1336  // EM layer within barrel/endcap overlap.
1337  towerEt = clarTowers[iTower];
1338  }
1339  else if ( layer == 0 && std::abs(globalEta) >= 16 && std::abs(globalEta) < 24 && iTower < numCentral ) {
1340  // EM layer outside barrel/endcap overlap.
1341  towerEt = clarTowers[iTower];
1342  }
1343  else {
1344  continue;
1345  }
1346 
1347  if ( towerEt || errorMask ) {
1348 
1349  L1CaloRdoGfexTower newOne( shelfNumber, gfexNumber, globalEta, globalPhi, layer, region );
1350  newOne.setRodInfo( rodInfo );
1351  L1CaloRdoGfexTower& rdo = L1CaloBsDecoderUtil::findRdo( newOne, tower );
1352 
1353  rdo.setHardwareInfo( hwInfo.getFpgaNumber(), chanNumber, iTower,
1354  GfexDefs::minipodNumFromName(hwInfo.getMpodName()),
1355  hwInfo.getMpodChannel() );
1356  rdo.setValue( towerEt );
1357  rdo.setFlag( errorMask );
1358 
1359  if ( m_verbosity > 0 )
1360  {
1361  std::cout << "L1CaloBsDecoderRun3::decodeGfexDataChan: "
1362  << "FPGA=" << fpgaNumber
1363  << std::hex << ", Et=0x" << towerEt << ", flag=0x" << errorMask
1364  << std::dec << std::endl;
1365  }
1366  //std::cout << "L1CaloBsDecoderRun3::decodeGfexDataChan: fpga=" << fpgaNumber
1367  // << ", chan=" << chanNumber << ", word=" << iTower
1368  // << ", mpod=" << GfexDefs::minipodNumFromName(hwInfo.getMpodName())
1369  // << ", mpodFibre=" << hwInfo.getMpodChannel()
1370  // << ", globalEta=" << globalEta
1371  // << ", globalPhi=" << globalPhi
1372  // << ", layer=" << layer
1373  // << ", Et=" << towerEt
1374  // << ", errors=0x" << std::hex << errorMask << std::dec
1375  // << std::endl;
1376  }
1377  }
1378 
1379  return 0; // No error bits yet
1380 }

◆ decodeGfexTobs()

void L1CaloBsDecoderRun3::decodeGfexTobs ( const uint32_t *  beg,
const uint32_t *  end,
std::list< L1CaloRdoGfexTob > &  tob,
std::list< L1CaloRdoRodInfo >::const_iterator  rodInfo 
)

Decode gFEX TOBs.

We create one RDO per TOB using the value field for its Et. The flag field is used for status/error bits. FIXME We also create one RDO for the energy TOBs.

Parameters
begpointer to start of rod data payload
endpointer to end of rod data payload
toblist of RDO to be filled
rodInfoiterator to ROD information for this block

Definition at line 1393 of file L1CaloBsDecoderRun3.cxx.

1396 {
1397  // **FIXME** To be implemented!
1398  const uint32_t* payload( beg );
1399  const size_t fragmentSize = end - beg;
1400 
1401  // The data block is constructed by the SWROD. It consists of up to six
1402  // subblocks for Jets and MET TOBs from each of the three FPGAs.
1403  // Each subblock starts with a 1 word header which identifies the block
1404  // type and gives its length.
1405  // Each subblock contains two sets of seven data words that are (or for
1406  // MET could be) transmitted to Ph1Topo on the fibres. If multiple slices
1407  // are read out, each subblock should have multiples of 14 words.
1408 
1409  size_t index = 0;
1410  while ( index < fragmentSize ) {
1411  const uint32_t headerWord = payload[index];
1412  const uint32_t blockType = (headerWord >> 28) & 0xf;
1413  //const uint32_t version = (headerWord >> 24) & 0xf; // Currently unused (1)
1414  const uint32_t headerSize = (headerWord >> 22) & 0x3;
1415  const uint32_t errorFlags = (headerWord >> 12) & 0x1;
1416  const uint32_t dataSize = headerWord & 0xfff;
1417 
1418  const uint32_t blockSize = headerSize + dataSize;
1419  if ( (index + blockSize) > fragmentSize ) {
1420  LOG_ERROR("decodeGfexTobs","","remaining block size "
1421  << (fragmentSize - index)
1422  << " is too small for subblock of type " << blockType
1423  << " with headerSize " << headerSize
1424  << " and dataSize " << dataSize);
1425  return;
1426  }
1427  index += headerSize;
1428 
1429  const uint32_t wordsPerSlice = 2 * FexDefs::num32BitWordsPerFibre();
1430  const uint32_t numSlices = dataSize / wordsPerSlice;
1431  if ( numSlices * wordsPerSlice != dataSize ) {
1432  LOG_ERROR("decodeGfexTobs","","subblock type " << blockType
1433  << " with dataSize " << dataSize
1434  << " is not a multiple of " << wordsPerSlice << " words");
1435  return;
1436  }
1437 
1438  // Create TOB RDOs for each slice.
1439  for (size_t sliceNumber = 0; sliceNumber < numSlices; sliceNumber++) {
1440  bool ret = this->decodeGfexTobSlice( &payload[index], blockType, sliceNumber, numSlices,
1441  errorFlags, tob, rodInfo );
1442  if ( ! ret ) {
1443  return;
1444  }
1445  index += wordsPerSlice;
1446  }
1447  }
1448 }

◆ decodeGfexTobSlice()

bool L1CaloBsDecoderRun3::decodeGfexTobSlice ( const uint32_t  payload[],
const uint32_t  blockType,
const uint32_t  sliceNumber,
const uint32_t  numSlices,
const uint32_t  errorMask,
std::list< L1CaloRdoGfexTob > &  tob,
std::list< L1CaloRdoRodInfo >::const_iterator  rodInfo 
)
private

Decode one gFEX FPGA block of TOBs for one slice.

See https://edms.cern.ch/ui/file/1492098/1/L1CaloTOBFormats_v010.pdf

Parameters
payloadpointer to this slice in ROD fragment payload
blockTypecode for Jet or MET TOB
sliceNumbernumber of this readout slice
numSlicestotal number of TOB slices read out in this event
errorFlagsglobal error bits set for this subblock (or ROD fragment?)
toblist of RDO to be filled
rodInfoiterator to ROD information for this block
Returns
whether decoding succeeded (false to abort decoding)

Definition at line 1463 of file L1CaloBsDecoderRun3.cxx.

1468 {
1469  // The subblock type is 0xA,B,C for jet TOBs from FPGA A,B,C
1470  // and 0x1,2,3 for global (MET) TOBs.
1471  bool isMet = (blockType >= 0x1 && blockType <= 0x3);
1472  bool isJet = (blockType >= 0xA && blockType <= 0xC);
1473  if ( !isJet && !isMet ) {
1474  LOG_ERROR("decodeGfexTobSlice","",": invalid block type "
1475  << blockType);
1476  return false;
1477  }
1478  const uint32_t fpgaNumber = (isJet) ? (blockType - 0x1) : (blockType - 0xA);
1479 
1480  // We expect two fibres each of 7 words.
1481  size_t index = 0;
1482  for ( size_t iFibre = 0; iFibre < 2; iFibre++ ) {
1483  for ( size_t iWord = 0; iWord < (size_t)FexDefs::num32BitWordsPerFibre(); iWord++, index++ ) {
1484  // Jet TOBs.
1485  if (isJet) {
1486  const uint32_t tobID = payload[index] & 0x1f;
1487  const uint32_t status = (payload[index] >> 7) & 0x1;
1488  const uint32_t etValue = (payload[index] >> 8) & 0xfff;
1489  const uint32_t tobEta = (payload[index] >> 20) & 0x3f;
1490  const uint32_t tobPhi = (payload[index] >> 26) & 0x1f;
1491  const uint32_t saturated = (payload[index] >> 31) & 0x1;
1492 
1493  L1CaloRdoFexTob::TobType fexTobType( L1CaloRdoFexTob::TobType::Invalid );
1494  L1CaloRdoFexTob::TobSource fexTobSource( L1CaloRdoFexTob::TobSource::GfexTob );
1495  if ( tobID >= 1 && tobID <= 4 ) {
1496  fexTobType = L1CaloRdoFexTob::TobType::SmallJet;
1497  }
1498  else if ( tobID >= 5 && tobID <= 6 ) {
1499  fexTobType = L1CaloRdoFexTob::TobType::LargeJet;
1500  }
1501 
1502  if ( ( etValue || saturated || errorMask ) && tobID ) {
1503  // Zero suppress (as gFEX always sends something).
1504  // **FIXME** Not sure what to do with status or satured bits.
1505  // **FIXME** For the moment set them in the error flags
1506  // **FIXME** Check use of tobEta and tobPhi (is it per FPGA?).
1507  const uint32_t flagMask = errorMask | (saturated << 31) | (status << 30);
1508  const uint32_t shelfNumber = 0x23; // Hard code to P1 value (35)
1509  const uint32_t moduleNumber = 0; // Hard code to P1 value (0) **FIXME** CHECK!
1510  L1CaloRdoGfexTob newOne( shelfNumber, moduleNumber, tobEta, tobPhi,
1511  numSlices, fexTobType, fexTobSource );
1512  newOne.setRodInfo( rodInfo );
1513  L1CaloRdoGfexTob& rdo = L1CaloBsDecoderUtil::findRdo( newOne, tob );
1514  rdo.setValue( etValue, sliceNumber );
1515  rdo.setFlag( flagMask, sliceNumber );
1516  if ( m_verbosity > 0 )
1517  {
1518  std::cout << "L1CaloBsDecoderRun3::decodeGfexTobSlice: tobType=" << fexTobType
1519  << ", tobSource=" << fexTobSource << ", slice=" << sliceNumber
1520  << ", fpga=" << fpgaNumber << ", eta=" << tobEta << ", phi=" << tobPhi
1521  << std::hex << ", Et=0x" << etValue << ", flag=0x" << flagMask
1522  << std::dec << ", numSlices=" << numSlices << std::endl;
1523  }
1524  }
1525  }
1526 
1527  // MET TOBs. **FIXME** To be implemented!
1528  else if (isMet) {
1529  }
1530  }
1531  }
1532 
1533  return true;
1534 }

◆ decodeJfexData()

void L1CaloBsDecoderRun3::decodeJfexData ( const uint32_t *  beg,
const uint32_t *  end,
std::list< L1CaloRdoJfexTower > &  tower,
std::list< L1CaloRdoRodInfo >::const_iterator  rodInfo 
)

Decode jFEX input fibre data.

We create one RDO per tower using the value field for its Et. The flag field is used for status/error bits.

Parameters
begpointer to start of rod data payload
endpointer to end of rod data payload
towerlist of RDO to be filled
rodInfoiterator to ROD information for this block

Definition at line 695 of file L1CaloBsDecoderRun3.cxx.

698 {
699  const uint32_t* payload( beg );
700  const size_t fragmentSize = end - beg;
701 
702  // The data block is optimised for production by firmware with the length
703  // in a trailer at the end. The SWROD concatenates a number of such blocks
704  // (removing the 2 word header used to fill the ROD fragment header).
705  // So we need to find the end and work backwards.
706 
707  size_t numTowers = tower.size();
708  size_t index = fragmentSize;
709 
710  // Loop looking backwards for jFEX processor input data blocks.
711  while ( index > 0 ) {
712  if ( index < 2 ) {
713  LOG_ERROR("decodeJfexData","","remaining block size " << index
714  << " is too small for the jFEX FPGA trailer");
715  return;
716  }
717  const uint32_t fpgaTrailer2 = payload[--index];
718  const uint32_t fpgaTrailer1 = payload[--index];
719 
720  const uint32_t fpgaErrors = fpgaTrailer2 & 0x3f;
721  const uint32_t jfexNumber = (fpgaTrailer1 >> 20) & 0x7;
722  const uint32_t fpgaNumber = (fpgaTrailer1 >> 18) & 0x3;
723  const size_t payloadSize = (fpgaTrailer1 & 0xffff);
724 
725  if ( payloadSize > index ) {
726  LOG_ERROR("decodeJfexData","","remaining jFEX block size "
727  << index << " is too small for the claimed payload size "
728  << payloadSize);
729  return;
730  }
731 
732  // We can now work forwards from the start of this block
733  // decoding each set of 8 words per input fibre channel.
734  index -= payloadSize;
735  size_t chanIndex = 0;
736  while ( chanIndex < payloadSize ) {
737  if ( (payloadSize - chanIndex) < 8 ) {
738  LOG_ERROR("decodeJfexData","","decodeJfexData: remaining jFEX block size "
739  << (payloadSize - chanIndex)
740  << " is too small for one jFEX input fibre block (8)");
741  return;
742  }
743  this->decodeJfexDataChan ( &payload[index+chanIndex], jfexNumber, fpgaNumber,
744  fpgaErrors, tower, rodInfo );
745  chanIndex += 8;
746  }
747  }
748  if ( m_verbosity > 0 )
749  {
750  std::cout << "L1CaloBsDecoderRun3::decodeJfexData: n.towers added="
751  << tower.size() - numTowers << std::endl;
752  }
753 }

◆ decodeJfexDataChan()

uint32_t L1CaloBsDecoderRun3::decodeJfexDataChan ( const uint32_t  payload[],
const uint32_t  jfexNumber,
const uint32_t  fpgaNumber,
const uint32_t  errorMask,
std::list< L1CaloRdoJfexTower > &  tower,
std::list< L1CaloRdoRodInfo >::const_iterator  rodInfo 
)
private

Decode the data from one jFEX input fibre (only ever one slice).

Parameters
payloadpayload vector starting at this 8 word block
jfexNumbernumber of this jFEX in its shelf
fpgaNumberFPGA number
errorMaskglobal error bits set for this ROD fragment
towerlist of RDO to be filled
rodInfoiterator to ROD information for this block
Returns
whether decoding succeeded (false to abort decoding)

Definition at line 766 of file L1CaloBsDecoderRun3.cxx.

771 {
772  const uint32_t shelfNumber = 0x22; // Hard code to P1 value (34)
773 
774  // The LATOME and TREX fibres have slightly different encoding.
775  // Towards the forward regions and especially FCAL they cover
776  // different numbers of towers with more or less granularity.
777  // Channels 0-23 & 36-59 are standard inputs, 24-35 are overlap.
778  // The HEC overlap minipod (AVR) is #3 of 1-5 in each FPGA.
779  const uint32_t chanNumber = ( payload[7] ) & 0xff;
780  const uint32_t errorBits = ( payload[7] >> 28 ) & 0xf;
781 
782  // **FIXME** Ignore overlap for the moment.
783  if (chanNumber >= 24 && // **FIXME** Remove this!
784  chanNumber < 36) { // **FIXME** Remove this!
785  return 0; // **FIXME** Remove this!
786  } // **FIXME** Remove this!
787  // **FIXME** Ignore end jFEX modules for now.
788  if (jfexNumber == 0 || // **FIXME** Remove this!
789  jfexNumber == 5) { // **FIXME** Remove this!
790  return 0; // **FIXME** Remove this!
791  } // **FIXME** Remove this!
792 
793  // The JfexCellMapping returns global coordinates but the RDO objects
794  // expect local eta within the module. So prepare this here.
795  // **FIXME** Not sure how to handle internal eta for FCAL (esp C side).
796  int moduleEta = -24 + (jfexNumber % 6) * 8;
797 
798  // The fibre packer decoder methods expect a vector of seven words.
799  std::vector<FibrePackerBase::myDataWord> encodedData;
800  for ( size_t i = 0; i < 7; i++ ) {
801  encodedData.push_back( payload[i] );
802  }
804 
805  // **FIXME** Need mapping to decide when to use Latome vs TREX decoders.
806  // **FIXME** But they are identical apart from handling of saturation
807  // **FIXME** so for the moment always use Latome.
808 
809  bool trex = false; // **FIXME**
810 
811  // Unpack sixteen 0.1*0.1 trigger towers.
812  std::vector<FibrePackerBase::myDataWord> towers;
813  if (trex) {
814  JfexTrexFibrePacker packer;
815  towers = packer.getUnpackedData( encodedData, frameType );
816  }
817  else {
818  // Unpack sixteen 0.1*0.1 trigger towers.
819  JfexLatomeFibrePacker packer;
820  towers = packer.getUnpackedData( encodedData, frameType );
821  }
822 
823  // Create RDO per tower.
824  for ( size_t iTower = 0; iTower < towers.size(); iTower++ ) {
825  const uint32_t towerEt = towers[iTower];
826 
827  if ( towerEt || errorMask ) {
828  // The JfexCellMapping needs the "unit number", ie U1-U4 which
829  // is the FPGA "processor" number in the readout+1. Additionally
830  // the readout uses 0-3 whereas JfexCellMapping expects 1-4.
831  // We also want the fibre number. The (FPGA,chan) JfexCellMapping
832  // constructor returns that (numbered with the whole module).
833  // NB per FPGA minipod (AVR) 1, 2, 4 & 5 are full input data.
834  // Minipod 3 is the overlap one, also used for TTC, IPbus, etc.
835  // The channel (MGT) numbering in the readout is 0-59 which are
836  // the direct fibres. But in firmware and mappings 0-59 are PMA
837  // loopback channels. The direct fibres are actually 60-119.
838  // But for the moment the PMA loopback inputs are not read out
839  // so, except for the mapping lookup, we use 0-59.
840  // The mapping tool prefers zero based FPGA numbers which increment
841  // with increasing phi, so convert back to that style in procNumber.
842  int unitNumber = fpgaNumber + 1;
843  int procNumber = JfexDefs::processorNumberToUnitNumber(unitNumber) - 1;
844  JfexHardwareInfo hwInfoFpga( JfexCellMapping( unitNumber, chanNumber+60 ).getHardwareInfo() );
845  int mgtFibreNumber = hwInfoFpga.getFibreNumber();
846  JfexCellMapping mapping( jfexNumber, unitNumber, mgtFibreNumber, iTower );
847  L1CaloDetectorRegion region = mapping.getDetectorRegion();
848  JfexHardwareInfo hwInfo( mapping.getHardwareInfo() );
849  JfexTriggerTowerInfo ttInfo( mapping.getTriggerTowerInfo() );
850 
851  if ( region.getValidity() && hwInfo.getValidity() ) {
852  int layer = (region.getLayer() == L1CaloDetectorRegion::Electromagnetic) ? 0 : 1;
853  int localEta = region.getEtaIndex() - moduleEta;
854  int localPhi = region.getPhiIndex();
855 
856  L1CaloRdoJfexTower newOne( shelfNumber, jfexNumber, localEta, localPhi, layer, region );
857  newOne.setRodInfo( rodInfo );
858  L1CaloRdoJfexTower& rdo = L1CaloBsDecoderUtil::findRdo( newOne, tower );
859 
860  rdo.setHardwareInfo( procNumber, chanNumber, iTower,
861  hwInfo.getAvr(), hwInfo.getFibreNumber(),
862  ttInfo.isCore() );
863  rdo.setValue( towerEt );
864  rdo.setFlag( errorMask );
865 
866  if ( m_verbosity > 0 )
867  {
868  std::cout << "L1CaloBsDecoderRun3::decodeJfexDataChan: "
869  << "module=" << jfexNumber
870  << std::hex << ", Et=0x" << towerEt << ", flag=0x" << errorMask
871  << std::dec << std::endl;
872  }
873  //std::cout << "L1CaloBsDecoderRun3::addJfexTower: fpga=" << fpgaNumber
874  // << ", chan=" << chanNumber << ", word=" << iTower
875  // << ", unit=" << unitNumber
876  // << ", mpod=" << hwInfo.getAvr()
877  // << ", modFibre=" << hwInfo.getFibreNumber()
878  // << ", mgtFibre=" << mgtFibreNumber
879  // << ", regionEta=" << localEta
880  // << ", regionPhi=" << localPhi
881  // << ", layer=" << layer
882  // << ", phiFpga=" << (localPhi/16)
883  // << ", hwFpga=" << hwInfo.getFpgaNumber()
884  // << ", validity=" << region.getValidity()
885  // << ", Et=" << towerEt
886  // << ", errors=0x" << std::hex << errorMask << std::dec
887  // << std::endl;
888  }
889  }
890  }
891 
892  return errorBits;
893 }

◆ decodeJfexTobs()

void L1CaloBsDecoderRun3::decodeJfexTobs ( const uint32_t *  beg,
const uint32_t *  end,
std::list< L1CaloRdoJfexTob > &  tob,
std::list< L1CaloRdoRodInfo >::const_iterator  rodInfo 
)

Decode jFEX TOBs and XTOBs.

The RDO value encodes the cluster Et in the value field and the isolation bits and other information in the flag.

Parameters
begpointer to start of rod data payload
endpointer to end of rod data payload
toblist of RDO to be filled
rodInfoiterator to ROD information for this block

Definition at line 905 of file L1CaloBsDecoderRun3.cxx.

908 {
909  const uint32_t* payload( beg );
910  const size_t fragmentSize = end - beg;
911 
912  // The data block is optimised for production by firmware as a set
913  // of nested blocks with the lengths at the end. So we need to find
914  // the end and work backwards.
915 
916  if ( fragmentSize < 2 ) {
917  LOG_ERROR("decodeJfexTobs","",": fragment size " << fragmentSize
918  << " is too small for the ROD trailer");
919  return;
920  }
921 
922  size_t index = fragmentSize;
923  const uint32_t rodTrailer2 = payload[--index];
924  const uint32_t rodTrailer1 = payload[--index];
925 
926  const uint32_t rodErrors = rodTrailer2 & 0x7f;
927  const size_t payloadSize = rodTrailer1 & 0xffff;
928  if ( (payloadSize + 2) != fragmentSize ) {
929  // Actual ROD fragment payload size does not match that claimed in the trailer.
930  LOG_ERROR("decodeJfexTobs","","payload size " << payloadSize
931  << " inconsistent with ROD fragment size " << fragmentSize);
932  return;
933  }
934  //??const uint32_t rodShelfNumber = (rodTrailer1 >> 18) & 0x3;
935 
936  // Loop looking backwards for jFEX FPGA blocks.
937  while ( index > 0 ) {
938  if ( index < 2 ) {
939  LOG_ERROR("decodeJfexTobs","","remaining block size " << index
940  << " is too small for the jFEX trailer");
941  return;
942  }
943  size_t fpgaIndex = index;
944  const uint32_t fpgaTrailer2 = payload[--fpgaIndex];
945  const uint32_t fpgaTrailer1 = payload[--fpgaIndex];
946  const size_t fpgaBlockSize = fpgaTrailer1 & 0xffff;
947  const uint32_t jfexNumber = (fpgaTrailer1 >> 20) & 0x7;
948  const uint32_t fpgaNumber = (fpgaTrailer1 >> 18) & 0x3;
949  const uint32_t numSlices = (fpgaTrailer1 >> 24) & 0xf;
950  const uint32_t sliceNumber = (fpgaTrailer1 >> 28) & 0xf;
951  const uint32_t fpgaErrors = fpgaTrailer2 & 0x3f;
952  if ( fpgaBlockSize > index ) {
953  LOG_ERROR("decodeJfexTobs","","jFEX FPGA block size " <<
954  fpgaBlockSize << " exceeds remaining data size " << index
955  << " (jFEX " << jfexNumber << " FPGA " << fpgaNumber << ")");
956  return;
957  }
958  // Update index to previous jFEX FPGA block (if any).
959  index = fpgaIndex - fpgaBlockSize;
960 
961  // Combine rod and jfex error fields.
962  const uint32_t errorMask = fpgaErrors | (rodErrors << 6);
963 
964  bool ret = this->decodeJfexTobSlice ( payload, fpgaBlockSize, fpgaIndex, jfexNumber, fpgaNumber,
965  sliceNumber, numSlices, errorMask, tob, rodInfo );
966  if ( ! ret ) {
967  return;
968  }
969  }
970 }

◆ decodeJfexTobSlice()

bool L1CaloBsDecoderRun3::decodeJfexTobSlice ( const uint32_t  payload[],
size_t  blockSize,
size_t &  index,
const uint32_t  jfexNumber,
const uint32_t  fpgaNumber,
const uint32_t  sliceNumber,
const uint32_t  numSlices,
const uint32_t  errorMask,
std::list< L1CaloRdoJfexTob > &  tob,
std::list< L1CaloRdoRodInfo >::const_iterator  rodInfo 
)
private

Decode one jFEX FPGA block of TOBs and XTOBs for one slice.

Parameters
payloadentire ROD fragment payload vector
indexjust past end of block for this slice (this method updates it to the start of the block)
jfexNumbernumber of this jFEX in its shelf
fpgaNumberFPGA number
sliceNumbernumber of this readout slice
numSlicestotal number of TOB slices read out in this event
errorMaskglobal error bits set for this ROD fragment
toblist of RDO to be filled
rodInfoiterator to ROD information for this block
Returns
whether decoding succeeded (false to abort decoding in which case the returned index is not valid)

Definition at line 988 of file L1CaloBsDecoderRun3.cxx.

994 {
995  if ( index < 2 ) {
996  return false;
997  }
998 
999  // **FIXME** TEMP Ignore jfex00 and jfex05 due to data corruption.
1000  if ( jfexNumber == 0 || jfexNumber == 5 ) {
1001  return true;
1002  }
1003 
1004  const uint32_t countTrailer1 = payload[index-2];
1005  const uint32_t countTrailer2 = payload[index-1];
1006 
1007  // **FIXME** Not sure if jFEX will send corrective trailers?
1008  const uint32_t corrective = 0;
1009  if ( corrective ) {
1010  // **FIXME** To be implemented if required.
1011  }
1012  else {
1013  const uint32_t safeMode = (countTrailer1 ) & 0x1;
1014  const uint32_t numSJetTobs = (countTrailer1 >> 1) & 0x3f;
1015  const uint32_t numLJetTobs = (countTrailer1 >> 7) & 0x3f;
1016  const uint32_t numTauTobs = (countTrailer1 >> 13) & 0x3f;
1017  const uint32_t numElecTobs = (countTrailer1 >> 19) & 0x3f;
1018  const uint32_t numSumEtTobs = (countTrailer1 >> 25) & 0x1;
1019  const uint32_t numMissEtTobs = (countTrailer1 >> 26) & 0x1;
1020  const uint32_t numSJetXtobs = (countTrailer2 >> 1) & 0x3f;
1021  const uint32_t numLJetXtobs = (countTrailer2 >> 7) & 0x3f;
1022  const uint32_t numTauXtobs = (countTrailer2 >> 13) & 0x3f;
1023  const uint32_t numElecXtobs = (countTrailer2 >> 19) & 0x3f;
1024 
1025  // Work out how long this block should be. For jFEX both TOBs
1026  // and XTOBs are one word. Apart from the counts of small jets,
1027  // large jets, taus and (forward) electrons there are two TOBs
1028  // for SumEt and MissingEt.
1029  // If the total is odd there should be an extra zero padding word.
1030  // However in safe mode all the TOBs and XTOBs are suppressed
1031  // and we only have the trailer with the counts.
1032 
1033  // For ease of later decoding, fill a vector with the end index
1034  // of each type of TOB/XTOB word.
1035  std::vector<size_t> end;
1036  end.push_back( 0 ) ;
1037  if ( !safeMode ) {
1038  end.push_back( end.back() + numSJetTobs );
1039  end.push_back( end.back() + numLJetTobs );
1040  end.push_back( end.back() + numTauTobs );
1041  end.push_back( end.back() + numElecTobs );
1042  end.push_back( end.back() + numSumEtTobs );
1043  end.push_back( end.back() + numMissEtTobs );
1044  end.push_back( end.back() + numSJetXtobs );
1045  end.push_back( end.back() + numLJetXtobs );
1046  end.push_back( end.back() + numTauXtobs );
1047  end.push_back( end.back() + numElecXtobs );
1048  }
1049 
1050  size_t tobSize = end.back(); // End of TOBs/XTOBs
1051  tobSize += (tobSize % 2); // Possible padding
1052  tobSize += 2; // Two count words
1053 
1054  if ( tobSize != blockSize ) {
1055  LOG_ERROR("decodeJfexTobSlice","",": TOB slice " << sliceNumber
1056  << " has block size " << blockSize << " expected TOBs+counts " << tobSize
1057  << " (jFEX " << jfexNumber << " FPGA " << fpgaNumber << ")");
1058  }
1059  if ( tobSize > index ) {
1060  LOG_ERROR("decodeJfexTobSlice","",": TOB size " << tobSize
1061  << " is larger than index " << index);
1062  return false;
1063  }
1064 
1065  size_t numTobs = (safeMode) ? 0 : end[6]; // End index of MissEt TOBs
1066  size_t totalTobs = (safeMode) ? 0 : end.back(); // End index of TOBs+XTOBs
1067 
1068  // Move index to start of this block.
1069  index -= tobSize;
1070 
1071  // Luxury, we can now work forwards inside the slice block!
1072  size_t sliceIndex = index;
1073  L1CaloRdoFexTob::TobType fexTobType;
1074  L1CaloRdoFexTob::TobSource fexTobSource;
1075  for (size_t iTOB = 0; iTOB < totalTobs; iTOB++) {
1076  // Small jets, taus and electron TOBs and XTOBs
1077  // all have similar structure so extract common
1078  // values and override for other TOB types.
1079  // TOBs and xTOBs now have identical formats
1080  // so first find the TOB type, then process
1081  // the values afterwards.
1082  const uint32_t tobWord = payload[sliceIndex++];
1083  uint32_t flagInfo = (tobWord >> 21) & 0xfff;
1084  uint32_t etValue = (tobWord >> 10) & 0x7ff;
1085  uint32_t tobPhi = (tobWord >> 1) & 0xf;
1086  uint32_t tobEta = (tobWord >> 5) & 0x1f;
1087  fexTobSource = (iTOB < numTobs)
1088  ? L1CaloRdoFexTob::TobSource::JfexTob
1089  : L1CaloRdoFexTob::TobSource::JfexXtob;
1090  if (iTOB < end[1]) {
1091  fexTobType = L1CaloRdoFexTob::TobType::SmallJet;
1092  } else if (iTOB < end[2]) {
1093  fexTobType = L1CaloRdoFexTob::TobType::LargeJet;
1094  } else if (iTOB < end[3]) {
1095  fexTobType = L1CaloRdoFexTob::TobType::Tau;
1096  } else if (iTOB < end[4]) {
1097  fexTobType = L1CaloRdoFexTob::TobType::EM;
1098  } else if (iTOB < end[6]) {
1099  fexTobType = L1CaloRdoFexTob::TobType::Energy;
1100  } else if (iTOB < end[7]) {
1101  fexTobType = L1CaloRdoFexTob::TobType::SmallJet;
1102  } else if (iTOB < end[8]) {
1103  fexTobType = L1CaloRdoFexTob::TobType::LargeJet;
1104  } else if (iTOB < end[9]) {
1105  fexTobType = L1CaloRdoFexTob::TobType::Tau;
1106  } else if (iTOB < end[10]) {
1107  fexTobType = L1CaloRdoFexTob::TobType::EM;
1108  } else {
1109  // Padding word: skip.
1110  continue;
1111  }
1112 
1113  if (fexTobType == L1CaloRdoFexTob::TobType::SmallJet) {
1114  flagInfo = 0; // None defined
1115  } else if (fexTobType == L1CaloRdoFexTob::TobType::LargeJet) {
1116  flagInfo = 0; // None defined
1117  etValue = (tobWord >> 10) & 0x1fff;
1118  } else if (fexTobType == L1CaloRdoFexTob::TobType::Energy) {
1119  // **FIXME** SumEt and MissEt to be implemented!
1120  flagInfo = (tobWord & 0x1) | (tobWord & 0x1000) >> 15;
1121  etValue = (tobWord & 0x7ffffffe) >> 1;
1122  tobPhi = 0;
1123  tobEta = 0;
1124  }
1125 
1126  // **FIXME** REMOVE THIS TEMPORARY HACK ASAP!!
1127  // **FIXME** Ignore & fix wrong slice numbers.
1128  uint32_t sliceNumberHacked = sliceNumber;
1129  if (numSlices == 1 && sliceNumber == 2) {
1130  sliceNumberHacked = 0;
1131  }
1132  //>>if ( sliceNumber >= numSlices ) {
1133  if ( sliceNumberHacked >= numSlices ) {
1134  LOG_ERROR("decodeJfexTobSlice","",": TOB slice " << sliceNumber
1135  << " exceeds number of slices " << numSlices << " in processor trailer");
1136  }
1137  else if ( etValue || flagInfo ) {
1138  // Should already be zero suppressed in the readout
1139  // but no harm in making doubly sure.
1140  // Add the error bits from the jFEX control FPGA (low 6 bits)
1141  // and the error bits from the ROD output packet (low 7 bits)
1142  // to the isolation bits (shifted up 16 bits).
1143  // This probably needs more sophisticated treatment.
1144  // The reported fpgaNumber is in the U1-U4 order but
1145  // we need the FPGAs ordered by increasing phi.
1146  // **FIXME** Check use of tobEta and adjusted tobPhi by FPGA.
1147  const uint32_t procNumber = JfexDefs::processorNumberToUnitNumber(fpgaNumber+1) - 1;
1148  const uint32_t modulePhi = tobPhi + 16 * procNumber;
1149  const uint32_t flagMask = (flagInfo << 16) | errorMask;
1150  const uint32_t shelfNumber = 0x22; // Hard code to P1 value (34)
1151  L1CaloRdoJfexTob newOne( shelfNumber, jfexNumber, tobEta, modulePhi,
1152  numSlices, fexTobType, fexTobSource );
1153  newOne.setRodInfo( rodInfo );
1154  L1CaloRdoJfexTob& rdo = L1CaloBsDecoderUtil::findRdo( newOne, tob );
1155  //>>rdo.setValue( etValue, sliceNumber );
1156  //>>rdo.setFlag( flagMask, sliceNumber );
1157  rdo.setValue( etValue, sliceNumberHacked );
1158  rdo.setFlag( flagMask, sliceNumberHacked );
1159  if ( m_verbosity > 0 )
1160  {
1161  std::cout << "L1CaloBsDecoderRun3::decodeJfexTobSlice: tobType=" << fexTobType
1162  << ", tobSource=" << fexTobSource << ", slice=" << sliceNumberHacked
1163  << ", module=" << jfexNumber << ", fpga=" << fpgaNumber
1164  << ", proc=" << procNumber << ", eta=" << tobEta << ", phi=" << modulePhi
1165  << std::hex << ", Et=0x" << etValue << ", flag=0x" << flagMask
1166  << std::dec << ", numSlices=" << numSlices << std::endl;
1167  }
1168  }
1169  }
1170  }
1171  return true;
1172 }

◆ decodeOneEfexTob()

void L1CaloBsDecoderRun3::decodeOneEfexTob ( const uint32_t  word[],
const uint32_t  shelfNumber,
const uint32_t  efexNumber,
const uint32_t  fpgaNumber,
const uint32_t  errorMask,
const uint32_t  numSlices,
const uint32_t  sliceNum,
L1CaloRdoFexTob::TobType  tobType,
L1CaloRdoFexTob::TobSource  tobSource,
std::list< L1CaloRdoEfexTob > &  tob,
std::list< L1CaloRdoRodInfo >::const_iterator  rodInfo 
) const
private

Decode word(s) for one eFEX TOB (or xTOB) and create one RDO.

FIXME Document other parameters when stable!

Parameters
toblist of RDO to be filled
rodInfoiterator to ROD information for this block

Definition at line 594 of file L1CaloBsDecoderRun3.cxx.

602 {
603  const uint32_t tobWord = word[0];
604  const uint32_t isolInfo = (tobWord ) & 0xffc000;
605  const uint32_t tobPhi = (tobWord >> 24) & 0x7;
606  const uint32_t tobEta = (tobWord >> 27) & 0x7;
607  const uint32_t tobFpga = (tobWord >> 30) & 0x3;
608 
609  uint32_t etValue(0);
610  if (tobSource == L1CaloRdoFexTob::TobSource::EfexXtob) {
611  // XTOB: Et from second TOB word.
612  etValue = word[1] & 0xffff;
613  }
614  else { // EfexTob or Ph1Topo
615  // TOB: Et from single TOB word.
616  etValue = tobWord & 0xfff;
617  }
618 
619  if ( sliceNum >= numSlices ) {
620  LOG_ERROR("decodeOneEfexTob s" << shelfNumber << "e" << efexNumber << "f" << fpgaNumber,
621  "excessive sliceNum",
622  "TOB slice " << sliceNum << " exceeds number of slices " << numSlices << " in processor trailer");
623  }
624  else if ( etValue ) {
625  // Should already be zero suppressed in the readout
626  // but no harm in making doubly sure.
627  // Add the error bits from the eFEX control FPGA (low 6 bits)
628  // and the error bits from the ROD output packet (low 7 bits)
629  // to the isolation bits (which have the low 14 bits unused).
630  // This probably needs more sophisticated treatment.
631  // The internal eta within one FPGA is in the range 0-5
632  // where 1-4 are the standard values and 0 & 5 are only
633  // used at the extreme eta, ie |eta| > 2.4.
634  // To get an eta within the module we use the range 0-17
635  // where 0 & 17 are only used at the extremes.
636  const uint32_t moduleEta = 1 + (tobEta - 1) + 4 * tobFpga;
637  const uint32_t flagMask = isolInfo | errorMask;
638  L1CaloRdoEfexTob newOne( shelfNumber, efexNumber, moduleEta, tobPhi,
639  numSlices, tobType, tobSource );
640  newOne.setRodInfo( rodInfo );
641  L1CaloRdoEfexTob& rdo = L1CaloBsDecoderUtil::findRdo( newOne, tob );
642  rdo.setValue( etValue, sliceNum );
643  rdo.setFlag( flagMask, sliceNum );
644 #ifdef OFFLINE_DECODER
645  // store the raw words - used in offline to construct the EDM objects
646  rdo.setWord0( word[0], sliceNum );
647  if(tobSource == L1CaloRdoFexTob::TobSource::EfexXtob) rdo.setWord1(word[1], sliceNum);
648 #endif
649  if ( m_verbosity > 0 )
650  {
651  std::cout << "L1CaloBsDecoderRun3::decodeOneEfexTob: tobType=" << tobType
652  << ", tobSource=" << tobSource << ", slice=" << sliceNum
653  << ", shelf=" << shelfNumber << ", module=" << efexNumber
654  << ", eta=" << moduleEta << ", phi=" << tobPhi
655  << std::hex << ", Et=0x" << etValue << ", flag=0x" << flagMask
656  << std::dec << ", numSlices=" << numSlices << std::endl;
657  }
658  }
659 }

◆ decodePh1TopoData()

void L1CaloBsDecoderRun3::decodePh1TopoData ( const uint32_t *  beg,
const uint32_t *  end,
std::list< L1CaloRdoEfexTob > &  etob,
std::list< L1CaloRdoJfexTob > &  jtob,
std::list< L1CaloRdoGfexTob > &  gtob,
std::list< L1CaloRdoMuonTob > &  mtob,
std::list< L1CaloRdoRodInfo >::const_iterator  rodInfo 
)

Decode Ph1Topo input data: these are TOBs from FEXes and MuCTPI.

We create one RDO per TOB using the value field for its Et. The flag field is used for status/error bits.

Parameters
begpointer to start of rod data payload
endpointer to end of rod data payload
etoblist of eFEX TOB RDOs to be filled
jtoblist of jFEX TOB RDOs to be filled
gtoblist of gFEX TOB RDOs to be filled
mtoblist of muon TOB RDOs to be filled
rodInfoiterator to ROD information for this block

Definition at line 1549 of file L1CaloBsDecoderRun3.cxx.

1555 {
1556  const uint32_t* payload( beg );
1557  const size_t fragmentSize = end - beg;
1558 
1559  // Fibre types of Ph1Topo inputs. These are defined in the VHDL at:
1560  // https://gitlab.cern.ch/atlas-l1calo/l1topo/ph1topo/-/blob/master/src/infr/topo_mapping_pkg.vhd#L27
1561  // For our purposes we only need to distinguish different formats
1562  // and ignore those that do not appear in the readout.
1563  enum TopoInputFibreTypes { Unknown=0x00, IPB=0x01, TTC=0x02, EM1=0x03, EM2=0x04,
1564  G1=0x05, G2=0x06, J1=0x07, J2=0x08, JF=0x09, JFXE=0x0a,
1565  M0A=0x0b, M0C=0x0c, M1A=0x0d, M1C=0x0e, M2A=0x0f, M2C=0x10,
1566  TAU1=0x11, TAU2=0x12, gJ1=0x13, gJ2=0x14 };
1567 
1568  // The data block is optimised for production by firmware with the length
1569  // in a trailer at the end. The SWROD concatenates a number of such blocks
1570  // (removing the 2 word header used to fill the ROD fragment header).
1571  // So we need to find the end and work backwards.
1572 
1573  //??size_t numTobs = tower.size();
1574  size_t index = fragmentSize;
1575 
1576  // Loop looking backwards for Ph1Topo processor input data blocks.
1577  while ( index > 0 ) {
1578  if ( index < 2 ) {
1579  LOG_ERROR("decodePh1TopoData","","remaining block size " << index
1580  << " is too small for the Ph1Topo FPGA trailer");
1581  return;
1582  }
1583  const uint32_t fpgaTrailer2 = payload[--index];
1584  const uint32_t fpgaTrailer1 = payload[--index];
1585 
1586  const uint32_t fpgaErrors = fpgaTrailer2 & 0x3f;
1587  //??const uint32_t sliceNum = (fpgaTrailer1 >> 28) & 0xf;
1588  //??const uint32_t numSlices = (fpgaTrailer1 >> 24) & 0xf;
1589  const uint32_t sliceNum = 0; // **FIXME** Temporarily hard code until set properly
1590  const uint32_t numSlices = 1; // **FIXME** Temporarily hard code until set properly
1591  //>>const uint32_t topoNumber = (fpgaTrailer1 >> 22) & 0x3;
1592  //>>const uint32_t fpgaNumber = (fpgaTrailer1 >> 21) & 0x1;
1593  //>>const uint32_t fwType = (fpgaTrailer1 >> 19) & 0x3; // 0: Mult, 1: Algo, 2: Beta
1594  const size_t payloadSize = (fpgaTrailer1 & 0xffff);
1595 
1596  if ( payloadSize > index ) {
1597  LOG_ERROR("decodePh1TopoData","","remaining Ph1Topo block size "
1598  << index << " is too small for the claimed payload size "
1599  << payloadSize);
1600  return;
1601  }
1602 
1603  // We can now work forwards from the start of this block
1604  // decoding each set of 8 words per input fibre channel.
1605  // In Ph1Topo the input data channels can be TOBs of many
1606  // different types. The type is identifed in the 8th word.
1607  // We then need the appropriate mapping to give us which
1608  // P1 FEX crate and module number is the source.
1609  // NB this may be incorrect for test rig setups.
1610  index -= payloadSize;
1611  size_t chanIndex = 0;
1612  uint32_t fexShelf = 0;
1613  uint32_t fexModule = 0;
1614  uint32_t fexFpga = 0;
1615  while ( chanIndex < payloadSize ) {
1616  if ( (payloadSize - chanIndex) < 8 ) {
1617  LOG_ERROR("decodePh1TopoData","","remaining Ph1Topo block size "
1618  << (payloadSize - chanIndex)
1619  << " is too small for one Ph1Topo input fibre block (8)");
1620  return;
1621  }
1622  //>>const uint32_t chanNumber = ( payload[7] ) & 0xff;
1623  const uint32_t fibreType = ( payload[7] >> 8 ) & 0x1f;
1624  //>>const uint32_t errorBits = ( payload[7] >> 30 ) & 0x3;
1625 
1626  L1CaloRdoFexTob::TobType tobType(L1CaloRdoFexTob::TobType::Invalid);
1627  L1CaloRdoFexTob::TobSource tobSource(L1CaloRdoFexTob::TobSource::Ph1Topo);
1628 
1629  // Most fibres have up to six TOBs, but jFEX fibres have seven.
1630  size_t numTobs = 6;
1631  if (fibreType == TopoInputFibreTypes::J1 || fibreType == TopoInputFibreTypes::JF ||
1632  fibreType == TopoInputFibreTypes::J2 || fibreType == TopoInputFibreTypes::JFXE) {
1633  numTobs = 7;
1634  }
1635 
1636  for (size_t iTob = 0; iTob < numTobs; iTob++) {
1637  // TOBs from eFEX.
1638  if (fibreType == TopoInputFibreTypes::EM1 || fibreType == TopoInputFibreTypes::TAU1 ||
1639  fibreType == TopoInputFibreTypes::EM2 || fibreType == TopoInputFibreTypes::TAU2) {
1640  tobType = (fibreType <= TopoInputFibreTypes::EM2) // Assumes enum order!
1643  // Need mapping!
1644  this->decodeOneEfexTob( &payload[index+chanIndex+iTob], fexShelf, fexModule, fexFpga,
1645  fpgaErrors, numSlices, sliceNum, tobType, tobSource,
1646  etob, rodInfo );
1647  }
1648  // Fibres from jFEX.
1649  /*
1650  else if () {
1651  }
1652  */
1653  }
1654  chanIndex += 8;
1655  }
1656  }
1657  //??if ( m_verbosity > 0 )
1658  //??{
1659  //?? std::cout << "L1CaloBsDecoderRun3::decodeJfexData: n.towers added="
1660  //?? << tower.size() - numTowers << std::endl;
1661  //??}
1662 }

◆ decodePh1TopoHits()

void L1CaloBsDecoderRun3::decodePh1TopoHits ( const uint32_t *  beg,
const uint32_t *  end,
std::list< L1CaloRdoPh1TopoHit > &  hit,
std::list< L1CaloRdoRodInfo >::const_iterator  rodInfo 
)

Decode Ph1Topo hit results.

The format is common to jFEX TOBs (and much like eFEX TOBs). So there could be better code reuse than this cut & paste job.

Parameters
begpointer to start of rod data payload
endpointer to end of rod data payload
toblist of RDO to be filled
rodInfoiterator to ROD information for this block

Definition at line 1674 of file L1CaloBsDecoderRun3.cxx.

1677 {
1678  const uint32_t* payload( beg );
1679  const size_t fragmentSize = end - beg;
1680 
1681  // The data block is optimised for production by firmware as a set
1682  // of nested blocks with the lengths at the end. So we need to find
1683  // the end and work backwards.
1684 
1685  if ( fragmentSize < 2 ) {
1686  LOG_ERROR("decodePh1TopoHits","","fragment size " << fragmentSize
1687  << " is too small for the ROD trailer");
1688  return;
1689  }
1690 
1691  size_t index = fragmentSize;
1692  const uint32_t rodTrailer2 = payload[--index];
1693  const uint32_t rodTrailer1 = payload[--index];
1694 
1695  const uint32_t rodErrors = rodTrailer2 & 0x7f;
1696  const size_t payloadSize = rodTrailer1 & 0xffff;
1697  if ( (payloadSize + 2) != fragmentSize ) {
1698  // Actual ROD fragment payload size does not match that claimed in the trailer.
1699  LOG_ERROR("decodePh1TopoHits","","payload size " << payloadSize
1700  << " inconsistent with ROD fragment size " << fragmentSize);
1701  return;
1702  }
1703 
1704  // Loop looking backwards for Ph1Topo FPGA blocks.
1705  while ( index > 0 ) {
1706  if ( index < 2 ) {
1707  LOG_ERROR("decodePh1TopoHits","","remaining block size " << index
1708  << " is too small for the Ph1Topo trailer");
1709  return;
1710  }
1711  size_t fpgaIndex = index;
1712  const uint32_t fpgaTrailer2 = payload[--fpgaIndex];
1713  const uint32_t fpgaTrailer1 = payload[--fpgaIndex];
1714  const size_t fpgaBlockSize = fpgaTrailer1 & 0xffff;
1715  const uint32_t topoNumber = (fpgaTrailer1 >> 20) & 0x7;
1716  const uint32_t fpgaNumber = (fpgaTrailer1 >> 18) & 0x3;
1717  const uint32_t numSlices = (fpgaTrailer1 >> 24) & 0xf;
1718  const uint32_t sliceNumber = (fpgaTrailer1 >> 28) & 0xf;
1719  const uint32_t fpgaErrors = fpgaTrailer2 & 0x3f;
1720  if ( fpgaBlockSize > index ) {
1721  LOG_ERROR("decodePh1TopoHits","","Ph1Topo FPGA block size "
1722  << fpgaBlockSize << " exceeds remaining data size " << index
1723  << " (Ph1Topo " << topoNumber << " FPGA " << fpgaNumber << ")");
1724  return;
1725  }
1726  // Update index to previous Ph1Topo FPGA block (if any).
1727  index = fpgaIndex - fpgaBlockSize;
1728 
1729  // Combine rod and topo error fields.
1730  const uint32_t errorMask = fpgaErrors | (rodErrors << 6);
1731 
1732  // There should always be six words.
1733  // All six are only used by Topo1 and they are all CTP hits.
1734  // Topo2 and Topo3 modules just use two words of the block,
1735  // one for the hits sent to CTP and one for the overflow flags.
1736  const size_t expectedBlockSize = 6;
1737  if ( fpgaBlockSize != expectedBlockSize ) {
1738  LOG_ERROR("decodePh1TopoHits","","Ph1Topo FPGA block size "
1739  << fpgaBlockSize << " is not the expected " << expectedBlockSize);
1740  return;
1741  }
1742  const uint32_t shelfNumber = 0x24; // Hard code to P1 value (36)
1743  const int idFlag = 0; // Not used for Ph1Topo
1744  L1CaloRdoHit::HitSource hitSource( L1CaloRdoHit::Result );
1745  size_t numWordsUsedPerFPGA = (topoNumber == 1) ? 6 : 2;
1746  size_t numHitWordsPerFPGA = (topoNumber == 1) ? 6 : 1;
1747  size_t numHitWordsPerModule = numHitWordsPerFPGA * 2;
1748 
1749  L1CaloRdoPh1TopoHit newOne( shelfNumber, topoNumber, idFlag, hitSource, numHitWordsPerModule, numSlices );
1750  newOne.setRodInfo( rodInfo );
1751  L1CaloRdoPh1TopoHit& rdo = L1CaloBsDecoderUtil::findRdo( newOne, hit );
1752  rdo.setFlag( errorMask, sliceNumber );
1753 
1754  size_t sliceIndex = index;
1755  for ( size_t k = 0; k < numWordsUsedPerFPGA; k++ ) {
1756  const uint32_t resultWord = payload[sliceIndex++];
1757  size_t wordNum = ( topoNumber == 1 ) ? k : 0;
1758  wordNum += fpgaNumber * numHitWordsPerFPGA;
1759  // Interpret this as hit or overflow?
1760  bool isOverflow = ( topoNumber != 1 ) && ( k != 0 );
1761  if ( isOverflow ) {
1762  rdo.setOverflows( resultWord, wordNum, sliceNumber );
1763  }
1764  else {
1765  rdo.setHits( resultWord, wordNum, sliceNumber );
1766  }
1767 
1768  if ( m_verbosity > 0 )
1769  {
1770  std::cout << "L1CaloBsDecoderRun3::decodePh1TopoHits: slice=" << sliceNumber
1771  << ", module=" << topoNumber << ", fpga=" << fpgaNumber
1772  << std::hex << ", result=0x" << resultWord << ", errors=0x" << errorMask
1773  << std::dec << ", numSlices=" << numSlices << ", numWords=" << numHitWordsPerModule
1774  << ", isOverflow=" << isOverflow << std::endl;
1775  }
1776  }
1777  }
1778 }

◆ setLogger()

void L1CaloBsDecoderRun3::setLogger ( std::unique_ptr< Logging > &&  logger)
inline

Definition at line 40 of file L1CaloBsDecoderRun3.h.

40 { m_logger = std::move(logger); }

◆ setVerbosity()

void L1CaloBsDecoderRun3::setVerbosity ( bool  verbosity)

Member Data Documentation

◆ m_logger

std::unique_ptr<Logging> L1CaloBsDecoderRun3::m_logger
private

Definition at line 136 of file L1CaloBsDecoderRun3.h.

◆ m_verbosity

int L1CaloBsDecoderRun3::m_verbosity
private

Definition at line 135 of file L1CaloBsDecoderRun3.h.


The documentation for this class was generated from the following files:
FexDefs::num32BitWordsPerFibre
static int num32BitWordsPerFibre()
Definition: FexDefs.h:17
L1CaloRdoEfexTower
Definition: L1CaloRdoEfexTower.h:10
RunTileCalibRec.cells
cells
Definition: RunTileCalibRec.py:271
GetLCDefs::Unknown
@ Unknown
Definition: GetLCDefs.h:21
plotBeamSpotCompare.x1
x1
Definition: plotBeamSpotCompare.py:216
data
char data[hepevt_bytes_allocation_ATLAS]
Definition: HepEvt.cxx:11
L1CaloBsDecoderRun3::m_logger
std::unique_ptr< Logging > m_logger
Definition: L1CaloBsDecoderRun3.h:136
L1CaloDetectorRegion::getLayer
LayerTypeEnum getLayer() const
Definition: L1CaloDetectorRegion.h:52
xAOD::uint32_t
setEventNumber uint32_t
Definition: EventInfo_v1.cxx:127
index
Definition: index.py:1
Energy
std::vector< double > Energy
Definition: CalibHitToCaloCell.h:23
L1CaloDetectorRegion::getValidity
bool getValidity() const
Definition: L1CaloDetectorRegion.h:50
L1CaloBsDecoderRun3::decodeJfexDataChan
uint32_t decodeJfexDataChan(const uint32_t payload[], const uint32_t jfexNumber, const uint32_t fpgaNumber, const uint32_t errorMask, std::list< L1CaloRdoJfexTower > &dat, std::list< L1CaloRdoRodInfo >::const_iterator rodInfo)
Decode the data from one jFEX input fibre (only ever one slice).
Definition: L1CaloBsDecoderRun3.cxx:766
Ringer::EM2
@ EM2
Definition: CaloRingsDefs.h:48
L1Topo::blockType
L1Topo::BlockTypes blockType(const uint32_t word, uint32_t offset=28, uint32_t size=0x0f)
Function to return the block type of a data word from L1Topo
Definition: BlockTypes.cxx:9
LOG_ERROR
#define LOG_ERROR(location, title, detail)
Definition: L1CaloBsDecoderRun3.cxx:40
L1CaloBsDecoderRun3::m_verbosity
int m_verbosity
Definition: L1CaloBsDecoderRun3.h:135
L1CaloRdoEfexTower::setSupercells
void setSupercells(std::vector< uint32_t > &supercells)
Definition: L1CaloRdoEfexTower.cxx:83
L1CaloRdo::setValue
void setValue(int val, size_t slice)
Definition: L1CaloRdo.cxx:226
L1CaloBsDecoderRun3::decodeOneEfexTob
void decodeOneEfexTob(const uint32_t word[], const uint32_t shelfNumber, const uint32_t efexNumber, const uint32_t fpgaNumber, const uint32_t errorMask, const uint32_t numSlices, const uint32_t sliceNum, L1CaloRdoFexTob::TobType tobType, L1CaloRdoFexTob::TobSource tobSource, std::list< L1CaloRdoEfexTob > &tob, std::list< L1CaloRdoRodInfo >::const_iterator rodInfo) const
Decode word(s) for one eFEX TOB (or xTOB) and create one RDO.
Definition: L1CaloBsDecoderRun3.cxx:594
find_tgc_unfilled_channelids.mapping
mapping
Definition: find_tgc_unfilled_channelids.py:17
EfexHardwareInfo
Definition: EfexHardwareInfo.h:4
mergePhysValFiles.end
end
Definition: DataQuality/DataQualityUtils/scripts/mergePhysValFiles.py:93
GenericCrc
Definition: GenericCrc.h:9
L1CaloRdoEfexTob
Definition: L1CaloRdoEfexTob.h:10
xAOD::saturated
setScaleOne setStatusOne saturated
Definition: gFexGlobalRoI_v1.cxx:51
L1CaloDetectorRegion::Electromagnetic
@ Electromagnetic
Definition: L1CaloDetectorRegion.h:23
L1CaloRdoEfexTower::setHardwareInfo
void setHardwareInfo(uint32_t fpga, uint32_t mgt, uint32_t word, uint32_t mpod, uint32_t fibre, uint32_t overlap)
Definition: L1CaloRdoEfexTower.cxx:89
Ringer::EM
@ EM
Definition: CaloRingsDefs.h:19
lumiFormat.i
int i
Definition: lumiFormat.py:92
ret
T ret(T t)
Definition: rootspy.cxx:260
Result
ICscStripFitter::Result Result
Definition: CalibCscStripFitter.cxx:13
TRT::Hit::layer
@ layer
Definition: HitInfo.h:79
L1CaloBsDecoderRun3::decodeGfexTobSlice
bool decodeGfexTobSlice(const uint32_t payload[], const uint32_t blockType, const uint32_t sliceNumber, const uint32_t numSlices, const uint32_t errorMask, std::list< L1CaloRdoGfexTob > &tob, std::list< L1CaloRdoRodInfo >::const_iterator rodInfo)
Decode one gFEX FPGA block of TOBs for one slice.
Definition: L1CaloBsDecoderRun3.cxx:1463
xAOD::uint64_t
uint64_t
Definition: EventInfo_v1.cxx:123
EfexTrexFibrePacker
Definition: EfexTrexFibrePacker.h:10
SCT_Monitoring::disabled
@ disabled
Definition: SCT_MonitoringNumbers.h:60
EfexLatomeFibrePacker::getUnpackedData
virtual std::vector< myDataWord > getUnpackedData(const std::vector< myDataWord > &encodedData, InputDataFrameType frameType) const override
Function unpacking the data from LATOME format, either standard or alignement frame.
Definition: EfexLatomeFibrePacker.cxx:168
L1CaloBsDecoderRun3::decodeJfexTobSlice
bool decodeJfexTobSlice(const uint32_t payload[], size_t blockSize, size_t &index, const uint32_t jfexNumber, const uint32_t fpgaNumber, const uint32_t sliceNumber, const uint32_t numSlices, const uint32_t errorMask, std::list< L1CaloRdoJfexTob > &tob, std::list< L1CaloRdoRodInfo >::const_iterator rodInfo)
Decode one jFEX FPGA block of TOBs and XTOBs for one slice.
Definition: L1CaloBsDecoderRun3.cxx:988
L1CaloRdoFexTob::TobSource
TobSource
Definition: L1CaloRdoFexTob.h:15
L1CaloDetectorRegion::getEtaIndex
int getEtaIndex() const
Definition: L1CaloDetectorRegion.h:44
EfexTrexFibrePacker::getUnpackedData
virtual std::vector< myDataWord > getUnpackedData(const std::vector< myDataWord > &encodedData, InputDataFrameType frameType) const override
Function unpacking the data from LATOME format, either standard or alignement frame.
Definition: EfexTrexFibrePacker.cxx:127
TRT::Hit::globalPhi
@ globalPhi
Definition: HitInfo.h:38
min
#define min(a, b)
Definition: cfImp.cxx:40
WriteBchToCool.beg
beg
Definition: WriteBchToCool.py:69
PayloadHelpers::dataSize
size_t dataSize(TDA::PayloadIterator start)
Size in bytes of the buffer that is needed to decode next fragment data content.
Definition: TriggerEDMDeserialiserAlg.cxx:188
L1CaloDetectorRegion
Definition: L1CaloDetectorRegion.h:8
PixelModuleFeMask_create_db.payload
string payload
Definition: PixelModuleFeMask_create_db.py:69
FibrePackerBase::InputDataFrameType
InputDataFrameType
type of input data frame
Definition: FibrePackerBase.h:37
L1CaloDetectorRegion::getPhiIndex
int getPhiIndex() const
Definition: L1CaloDetectorRegion.h:45
DeMoScan.index
string index
Definition: DeMoScan.py:362
RunTileMonitoring.towers
towers
Definition: RunTileMonitoring.py:133
L1CaloBsDecoderRun3::checkFibreCRC
bool checkFibreCRC(std::vector< uint32_t > &data) const
Check the CRC in an input fibre block of words.
Definition: L1CaloBsDecoderRun3.cxx:669
L1CaloBsDecoderRun3::decodeGfexDataChan
uint32_t decodeGfexDataChan(const uint32_t payload[], const uint32_t fpgaNumber, const uint32_t chanNumber, const uint32_t errorMask, std::list< L1CaloRdoGfexTower > &dat, std::list< L1CaloRdoRodInfo >::const_iterator rodInfo)
Decode the data from one gFEX input fibre (only ever one slice).
Definition: L1CaloBsDecoderRun3.cxx:1260
EfexLatomeFibrePacker
Definition: EfexLatomeFibrePacker.h:10
GenericCrc::crc9fibre
uint32_t crc9fibre(const std::vector< uint32_t > &inwords, size_t num_bits) const
Functions calculating CRC over input data.
Definition: GenericCrc.cxx:5
L1CaloRdo::setFlag
void setFlag(int flag, size_t slice)
Definition: L1CaloRdo.cxx:239
xAODType::Tau
@ Tau
The object is a tau (jet)
Definition: ObjectType.h:49
L1CaloBsDecoderUtil::findRdo
static Tar & findRdo(const Tar &target, Dat &data, Iter begin, Iter end)
Definition: L1CaloBsDecoderUtil.h:33
L1CaloBsDecoderRun3::decodeEfexDataChan
uint32_t decodeEfexDataChan(const uint32_t payload[], const uint32_t efexNumber, const uint32_t shelfNumber, const uint32_t errorMask, std::list< L1CaloRdoEfexTower > &dat, std::list< L1CaloRdoRodInfo >::const_iterator rodInfo) const
Decode the data from one eFEX input fibre (only ever one slice).
Definition: L1CaloBsDecoderRun3.cxx:187
EfexCellMapping
Definition: EfexCellMapping.h:14
merge.status
status
Definition: merge.py:17
CrateDefs::numAtcaFexSlots
static unsigned int numAtcaFexSlots()
Definition: CrateDefs.h:42
Ringer::EM1
@ EM1
Definition: CaloRingsDefs.h:47
L1CaloBsDecoderRun3::decodeEfexTobSlice
bool decodeEfexTobSlice(const uint32_t payload[], size_t &index, const uint32_t efexNumber, const uint32_t shelfNumber, const uint32_t numSlices, const uint32_t errorMask, std::list< L1CaloRdoEfexTob > &tob, std::list< L1CaloRdoRodInfo >::const_iterator rodInfo) const
Decode one eFEX FPGA block of TOBs and XTOBs for one slice.
Definition: L1CaloBsDecoderRun3.cxx:487
FibrePackerBase::InputDataFrameType::Normal
@ Normal
Standard data frame.
python.iconfTool.gui.pad.logger
logger
Definition: pad.py:14
EfexDefs::numInputFibresPerFpga
static int numInputFibresPerFpga()
Definition: EfexDefs.h:35
fitman.k
k
Definition: fitman.py:528
L1CaloRdoFexTob::TobType
TobType
Definition: L1CaloRdoFexTob.h:14