ATLAS Offline Software
EfexLatomeFibrePacker.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3 */
4 
6 
7 #include <iostream>
8 #include <cstdlib>
9 #include <cmath>
10 #include <map>
11 
12 
13 std::vector<FibrePackerBase::myDataWord> EfexLatomeFibrePacker::getPackedData(const std::vector<myDataWord>& inFrame,
14  myDataWord bcNumber,
15  InputDataFrameType frameType) const {
16 
17  std::vector<myDataWord> dataToLoad(FexDefs::num32BitWordsPerFibre(),0);
18  auto supercells = inFrame;
19 
20  switch(frameType){
21 
22  case InputDataFrameType::Normal: // Standard data pattern
23  {
24  for(auto& icell:supercells)
25  icell = icell & 0x3ff; // truncate to 10 bits
26 
27  myDataWord bcId = bcNumber & 0x7f ; // 7 bits from BCID
28 
29  myDataWord bcId02 = bcId & 0x7;
30  myDataWord bcId34 = (bcId >> 3) & 0x3;
31  myDataWord bcId56 = (bcId >> 5) & 0x3;
32 
33  dataToLoad.at(0) = (bcId56 << 8) | (supercells.at(0) <<10) |
34  (supercells.at(1) << 20) | (bcId34 << 30);
35  dataToLoad.at(1) = supercells.at(2) | (supercells.at(3) << 10) |
36  (supercells.at(4) << 20) | (((supercells.at(19) >>8) & 0x3) << 30);
37  dataToLoad.at(2) = supercells.at(5) | (supercells.at(6) << 10) |
38  (supercells.at(7) << 20) | (((supercells.at(19) >>6) & 0x3) << 30);
39  dataToLoad.at(3) = supercells.at(8) | (supercells.at(9) << 10) |
40  (supercells.at(10) << 20) | (((supercells.at(19) >>4) & 0x3) << 30);
41  dataToLoad.at(4) = supercells.at(11) | (supercells.at(12) << 10) |
42  (supercells.at(13) << 20) | (((supercells.at(19) >>2) & 0x3) << 30);
43  dataToLoad.at(5) = supercells.at(14) | (supercells.at(15) << 10) |
44  (supercells.at(16) << 20) | (((supercells.at(19) ) & 0x3) << 30);
45  dataToLoad.at(6) = supercells.at(17) | (supercells.at(18) << 10)| bcId02 << 20;
46 
47  // original code
48  // myDataWord tempCRC = crc9d32(dataToLoad,6l,true); // calculate CRC32 on first 6 words
49  // myDataWord myCRCReminder = crc9d23(dataToLoad[6],tempCRC,true); // CRC23 on the last word
50  // new code
51  myDataWord myCRCReminder = crc9full(dataToLoad,215); // 215 = 32*6+23
52 
53  dataToLoad.at(0) = K_28_5 | dataToLoad.at(0) ; // add K-character
54  dataToLoad[6] = dataToLoad[6] | ( myCRCReminder << 23) ; // add CRC check
55 
56  break;
57  }
58  case InputDataFrameType::Alignement: // Special pattern, LATOME alignement/mapping frame
59  {
60 
61  myDataWord latome_id = supercells.at(0) & 0xff; // 8b
62  myDataWord latome_src_id = supercells.at(1) & 0xffffffff; // 32b
63  myDataWord fiber_id = supercells.at(2) & 0x3f; // 6b
64  myDataWord bcId = bcNumber & 0xfff ; // 12 bits of BCID
65 
66  dataToLoad.at(0) = (fiber_id << 16) | (latome_id << 24);
67  dataToLoad.at(1) = latome_src_id;
68  dataToLoad.at(6) = bcId;
69 
70  dataToLoad.at(0) = (K_28_0 << 8) | dataToLoad.at(0) ; // add K_28_0, this is used for CRC calculation
71 
72  // original code
73  // myDataWord tempCRC = crc9d32(dataToLoad,6l,true); // calculate CRC32 on first 6 words
74  //myDataWord myCRCReminder = crc9d23(dataToLoad[6],tempCRC,true); // CRC23 on the last word
75  // new code
76  myDataWord myCRCReminder = crc9full(dataToLoad,215); // 215 = 32*6+23
77 
78  dataToLoad.at(0) = K_28_5 | dataToLoad.at(0) ; // add K_28_5, this is not used for CRC calculation
79  dataToLoad[6] = dataToLoad[6] | ( myCRCReminder << 23) ; // add CRC check to the famous last word
80 
81  break;
82  }
83  }
84 
85  return dataToLoad;
86 
87 }
88 
89 std::vector<FibrePackerBase::myDataWord> EfexLatomeFibrePacker::getPackedControl(const std::vector<myDataWord>& /*inFrame*/,
90  myDataWord /*bcNumber*/,
91  InputDataFrameType frameType) const {
92 
93  std::vector<myDataWord> controlWords(FexDefs::num32BitWordsPerFibre(),0);
94 
95  switch(frameType){
96 
97  case InputDataFrameType::Normal: // one K character in first data word
98  controlWords.at(0) = 0x1;
99  break;
100 
101  case InputDataFrameType::Alignement: // two K characters in first data word
102  controlWords.at(0) = 0x3;
103  break;
104 
105  }
106 
107  return controlWords;
108 }
109 
110 bool EfexLatomeFibrePacker::checkCRC(const std::vector<myDataWord>& encodedData,
111  InputDataFrameType frameType) const {
112 
113  auto inputData = encodedData;
114  myDataWord CRCCheck = 0;
115 
116  // Comment SJH: why do we need two cases here
117  // (may have been different originally, but not now?)
118  switch(frameType){
119 
120  case InputDataFrameType::Normal: // one K character in first data word
121  inputData.at(0) = inputData.at(0) & 0xffffff00;
122  // old code
123  // CRCCheck = crc9d32(inputData,7l,true); // calculate CRC32 on first 6 words
124  // new code
125  CRCCheck = crc9full(inputData,224); // calculate CRC on 224 bits = 7*32 bit words
126  break;
127 
128  case InputDataFrameType::Alignement: // two K characters in first data word, but zeroing only the first one
129  inputData.at(0) = inputData.at(0) & 0xffffff00;
130  // old code
131  // CRCCheck = crc9d32(inputData,7l,true); // calculate CRC32 on first 6 words
132  // new code
133  CRCCheck = crc9full(inputData,224); // calculate CRC on 224 bits = 7*32 bit words
134  break;
135 
136  }
137 
138  return (CRCCheck == 0);
139 }
140 
141 FibrePackerBase::myDataWord EfexLatomeFibrePacker::getBcNumber(const std::vector<myDataWord>& encodedData,
142  InputDataFrameType frameType) const {
143  myDataWord BcNumber =0;
144 
145  switch(frameType){
146 
148  {
149  myDataWord bcId02 = (encodedData.at(6) >> 20 ) & 0x7;
150  myDataWord bcId34 = (encodedData.at(0) >> 30 ) & 0x3;
151  myDataWord bcId56 = (encodedData.at(0) >> 8 ) & 0x3;
152 
153  BcNumber = bcId02 | (bcId34 << 3) | (bcId56 << 5);
154  break;
155  }
157  {
158  BcNumber = encodedData.at(6) & 0xfff;
159  break;
160  }
161  }
162 
163  return BcNumber;
164 }
165 
167  // BC number is just 7 bits for normal frames
168  // but the full 12 bits from align frames.
169  return (frameType == InputDataFrameType::Alignement) ? 0xfff : 0x07f;
170 }
171 
172 std::vector<FibrePackerBase::myDataWord> EfexLatomeFibrePacker::getUnpackedData(const std::vector<myDataWord>& encodedData,
173  InputDataFrameType frameType) const {
174  std::vector<myDataWord> unpackedData;
175 
176  switch(frameType){
177 
179  {
180  std::vector<myDataWord> supercells(EfexDefs::maxSuperCellsPerFibre(),0);
181 
182  // see: https://gitlab.cern.ch/atlas-l1calo-online/infraL1Calo/-/commit/1dc82d1ce21c14ca56d90e1af7d1af9bdb7990df#note_5865270
183  // 20 10-bit counts encoded in 7 32-bit words
184  // word 0 has 2, word 1-5 have 3 each (so 15 in total),
185  // word 6 has 2 more, and the last count is spread over the extra
186  // 2 bits in words 1-5
187 
188  supercells[0] = (encodedData[0] >> 10) & 0x3ff;
189  supercells[1] = (encodedData[0] >> 20) & 0x3ff;
190  supercells[2] = (encodedData[1] ) & 0x3ff;
191  supercells[3] = (encodedData[1] >> 10) & 0x3ff;
192  supercells[4] = (encodedData[1] >> 20) & 0x3ff;
193  supercells[5] = (encodedData[2] ) & 0x3ff;
194  supercells[6] = (encodedData[2] >> 10) & 0x3ff;
195  supercells[7] = (encodedData[2] >> 20) & 0x3ff;
196  supercells[8] = (encodedData[3] ) & 0x3ff;
197  supercells[9] = (encodedData[3] >> 10) & 0x3ff;
198  supercells[10] = (encodedData[3] >> 20) & 0x3ff;
199  supercells[11] = (encodedData[4] ) & 0x3ff;
200  supercells[12] = (encodedData[4] >> 10) & 0x3ff;
201  supercells[13] = (encodedData[4] >> 20) & 0x3ff;
202  supercells[14] = (encodedData[5] ) & 0x3ff;
203  supercells[15] = (encodedData[5] >> 10) & 0x3ff;
204  supercells[16] = (encodedData[5] >> 20) & 0x3ff;
205  supercells[17] = (encodedData.at(6) ) & 0x3ff;
206  supercells[18] = (encodedData[6] >> 10) & 0x3ff;
207  supercells.at(19) = ((encodedData[5] >> 30) & 0x3) |
208  ((encodedData[4] >> 30) & 0x3) << 2 |
209  ((encodedData[3] >> 30) & 0x3) << 4 |
210  ((encodedData[2] >> 30) & 0x3) << 6 |
211  ((encodedData[1] >> 30) & 0x3) << 8 ;
212  unpackedData=std::move(supercells);
213  break;
214  }
216  {
217  myDataWord latome_id = (encodedData.at(0) >> 24) & 0xff; // 8b
218  myDataWord latome_src_id = encodedData.at(1) & 0xffffffff; // 32b
219  myDataWord fiber_id = (encodedData.at(0) >> 16) & 0x3f; // 6b
220 
221  unpackedData.push_back(latome_id);
222  unpackedData.push_back(latome_src_id);
223  unpackedData.push_back(fiber_id);
224  break;
225  }
226  }
227 
228 
229  return unpackedData;
230 
231 }
232 
EfexLatomeFibrePacker::getBcMask
virtual myDataWord getBcMask(InputDataFrameType frameType) const override
Definition: EfexLatomeFibrePacker.cxx:166
FexDefs::num32BitWordsPerFibre
static int num32BitWordsPerFibre()
Definition: FexDefs.h:17
EfexLatomeFibrePacker.h
WriteCellNoiseToCool.icell
icell
Definition: WriteCellNoiseToCool.py:339
EfexLatomeFibrePacker::getPackedData
virtual std::vector< myDataWord > getPackedData(const std::vector< myDataWord > &inFrame, myDataWord bcNumber, InputDataFrameType frameType) const override
Function packing the data into the LATOME format, either standard or alignement frame.
Definition: EfexLatomeFibrePacker.cxx:13
FibrePackerBase::K_28_5
myDataWord K_28_5
Definition: FibrePackerBase.h:30
EfexLatomeFibrePacker::getPackedControl
virtual std::vector< myDataWord > getPackedControl(const std::vector< myDataWord > &inFrame, myDataWord bcNumber, InputDataFrameType frameType) const override
Function returning control words.
Definition: EfexLatomeFibrePacker.cxx:89
EfexLatomeFibrePacker::checkCRC
virtual bool checkCRC(const std::vector< myDataWord > &encodedData, InputDataFrameType frameType) const override
Definition: EfexLatomeFibrePacker.cxx:110
EfexLatomeFibrePacker::getBcNumber
virtual myDataWord getBcNumber(const std::vector< myDataWord > &encodedData, InputDataFrameType frameType) const override
Definition: EfexLatomeFibrePacker.cxx:141
EfexDefs::maxSuperCellsPerFibre
static int maxSuperCellsPerFibre()
Definition: EfexDefs.h:27
FibrePackerBase::crc9full
virtual myDataWord crc9full(const std::vector< myDataWord > &inwords, size_t num_bits) const
Functions calculating CRC over input data.
Definition: FibrePackerBase.cxx:11
FibrePackerBase::K_28_0
myDataWord K_28_0
Definition: FibrePackerBase.h:32
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:172
bcId
uint16_t bcId(uint32_t data)
Definition: TgcByteStreamData.h:326
FibrePackerBase::InputDataFrameType::Alignement
@ Alignement
Special mapping/alignement frame.
FibrePackerBase::InputDataFrameType
InputDataFrameType
type of input data frame
Definition: FibrePackerBase.h:37
FibrePackerBase::myDataWord
uint32_t myDataWord
Definition: FibrePackerBase.h:25
FibrePackerBase::InputDataFrameType::Normal
@ Normal
Standard data frame.