ATLAS Offline Software
DecodeSCT.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
3 */
4 
5 #include <sys/mman.h> //PROT_READ, MAP_PRIVATE
6 #include <fcntl.h> //O_RDONLY
7 #include <unistd.h> //close
8 
9 #include <iostream>
10 #include <fstream>
11 #include <vector>
12 #include <string>
13 #include <utility>
14 #include <cstdint>
15 #include <filesystem>
16 
17 
18 namespace fs = std::filesystem;
19 namespace {
20 //check the filename exists and return it as a string, or return empty string.
22 getFilename(const char * filenameArg);
23 
24 void
25 decodeEventWord(uint16_t currWord, int errorType, bool &linkCondensed,
26  std::string &type, std::vector<std::pair<std::string, int> > &arguments,
27  std::vector<std::string> &errors);
28 
29 std::vector<std::string>
30 decodeEventFlags(uint32_t flags);
31 
32 bool
33 findNextEvent(uint32_t* &start, uint32_t* &finish, uint32_t *end, uint32_t startWord);
34 
35 void
36 decodeEvent(uint32_t *buffer, int length);
37 
38 void
39 decodeSubFragment(uint32_t *buffer, int length);
40 }
41 
42 inline std::string
43 str(const char * word){
44  return word ? word : "";
45 }
46 
47 void
49  std::cout<< "'DecodeSCT' takes exactly one argument, the bytestream filename." <<std::endl;
50 }
51 
52 
53 int main(int argc, char **argv) {
54  if (argc < 2){
55  helpMessage();
56  return 1;
57  }
58  fs::path input_file = getFilename(argv[1]);
59  if (input_file.empty()) {
60  std::cerr << argv[1] <<" does not exist."<<std::endl;
61  return 2;
62  }
63  auto length = fs::file_size(input_file);
64  printf("Length: %lu\n", length);
65  auto fd = open(input_file.c_str(), O_RDONLY);
66  if(fd<0) {
67  perror("File open failed");
68  return 3;
69  }
70  uint32_t *buffer = (uint32_t *) mmap(0, length, PROT_READ, MAP_PRIVATE, fd, 0);
71  if(buffer == MAP_FAILED) {
72  close(fd);
73  perror("mmap failed");
74  return 4;
75  }
76  uint32_t *endBuffer = &buffer[length/4];
78  uint32_t *end{};
79  while(findNextEvent(begin, end, endBuffer, 0xee1234ee)) {
80  //cppcheck-suppress invalidPrintfArgType_sint
81  printf("Event from %li to %li\n", begin-buffer, end-buffer);
82  int length = static_cast<int>(end - 1l - begin);
83  decodeEvent(begin, length);
84  }
85  munmap(buffer, length);
86  close(fd);
87 }
88 
89 namespace {
90 
91  bool findNextEvent(uint32_t* &start, uint32_t* &finish, uint32_t *end, uint32_t startWord) {
92  start ++;
93  if(start >= end) return false;
94  while(*start != startWord) {
95  start++;
96  if(start >= end) return false;
97  }
98  finish = start+1;
99  // ignore sub-ROD fragments
100  while((!( ((*finish & 0x00ffff00) == 0x00123400) || ((*finish & 0xffff0000) == 0x12340000))) || ((*finish) == 0xff1234ff)) {
101  // Last one, return length
102  if(finish >= end) break;
103  finish++;
104  }
105  return true;
106  }
107 
108  bool findNextSubFragment(uint32_t* &start, uint32_t* &finish, uint32_t *end) {
109  start ++;
110  if(start >= end) return false;
111  while(*start != 0xff1234ff) {
112  start++;
113  if(start >= end) return false;
114  }
115  finish = start+1;
116  while((!( ((*finish & 0x00ffff00) == 0x00123400) || ((*finish & 0xffff0000) == 0x12340000))) ) {
117  // Last one, return length
118  if(finish >= end) break;
119  finish++;
120  }
121  return true;
122  }
123 
124  inline uint32_t
125  eventWord(const uint32_t * const buffer, const int index, const int length) {
126  if (index > length) {
127  std::cout << "Attempt to read from the end of the buffer " << index << " " << length << std::endl;
128  return 0;
129  } else {
130  return buffer[index-1];
131  }
132  }
133 
134  void decodeEvent(uint32_t *frameBuffer, int length) {
135  if(frameBuffer[0] == 0xee1234ee) {
136  std::cout << "Valid header\n";
137  } else {
138  std::cout << "Bad check 0x" << std::hex << frameBuffer[0] << std::dec << "\n";
139  std::cout << "Skipping decode as SCT ROD fragment\n";
140  return;
141  }
142  uint32_t headerLength = 9; // Including bof
143  uint32_t trailerLength = 5; // Excluding eof
144  // The below assumes the old definition of headerLength (ie including 0xbof)
145  headerLength=10;
146  // 2 is to correct for the bof and eof that aren't in the s-link format
147  int eventLength = length - headerLength - trailerLength + 2;
148  uint32_t rawOffset = headerLength;
149  if(frameBuffer[1] != headerLength) {
150  std::cout << "Unknown header length (" << frameBuffer[1] << ")\n";
151  }
152  std::cout << "New formatter version:\n";
153  std::cout << "Version: 0x" << std::hex << eventWord(frameBuffer, 3, length) << std::dec
154  << " ID: 0x" <<std::hex << eventWord(frameBuffer, 4, length) <<std::dec
155  << " Run number = " << eventWord(frameBuffer, 5, length) << "\n";
156  std::cout << "L1ID = 0x" << std::hex << eventWord(frameBuffer, 6, length) << std::dec
157  << " BCID = 0x" << std::hex << eventWord(frameBuffer, 7, length) << std::dec
158  << " TType = " << eventWord(frameBuffer, 8, length)
159  << " det type = " << eventWord(frameBuffer, 9, length) << "\n";
160  uint32_t SubDetID = (eventWord(frameBuffer, 4, length) & 0xff0000) >> 16 ;
161  std::cout << "SubDetID = " << std::hex << SubDetID <<std::dec;
162  switch (SubDetID){
163  case 0x20:
164  case 0x21:
165  case 0x22:
166  case 0x23:
167  case 0x24:
168  {
169  std::cout << " Found SCT fragment [" << SubDetID << "]. Decoding...\n";
170 
171  // Something different to the first word
172  uint16_t lastWord = 1 + ((eventWord(frameBuffer, rawOffset, length) & 0xffff0000) >> 16);
173  uint32_t repeats = 0;
174 
175  bool linkCondensed = true;
176 
177  for(int i=0; i<eventLength * 2; i++) {
178  uint16_t currWord;
179  {
180  uint32_t rawWord = eventWord(frameBuffer, rawOffset + i/2, length);
181  if(i&1) {
182  currWord = rawWord & 0x00ffff;
183  } else {
184  currWord = (rawWord & 0xffff0000) >> 16;
185  }
186  }
187 
188  if(currWord == lastWord) {
189  repeats ++;
190  continue;
191  } else if(repeats) {
192  std::cout << " Repeated " << repeats << " times\n";
193  repeats = 0;
194  }
195  lastWord = currWord;
196  std::cout.width(4);
197  std::cout.fill('0');
198  std::cout << std::hex << currWord << std::dec;
199  std::cout.fill(' ');
200  std::string type;
201  std::vector<std::pair<std::string, int> > arguments;
202  std::vector<std::string> errors;
203  decodeEventWord(currWord, 0, linkCondensed,type, arguments, errors);
204  std::cout << " " << type << " ";
205  for(auto iter = arguments.begin();iter != arguments.end();++iter ) {
206  std::cout << " " << iter->first << ": " << iter->second;
207  }
208  if(errors.size() > 0) {
209  std::cout << " ERRORS: ";
210  }
211  for(auto iter = errors.begin();iter != errors.end();++iter) {
212  std::cout << " " << *iter;
213  }
214  std::cout << std::endl;
215  }
216  if(repeats) {
217  std::cout << " Repeated " << repeats << " times\n";
218  repeats = 0;
219  }
220  std::cout << "Error count = 0x" << std::hex << eventWord(frameBuffer, length-trailerLength + 2, length) << std::dec << "\n";
221  std::cout << "Error flags = 0x" << std::hex << eventWord(frameBuffer, length-trailerLength + 3, length) << std::dec << "\n";
222  int flags = eventWord(frameBuffer, length-trailerLength + 3, length);
223  std::vector<std::string> flagStrings = decodeEventFlags(flags);
224  for(auto iter = flagStrings.begin();iter != flagStrings.end();++iter) {
225  std::cout << *iter << " ";
226  }
227  if(flagStrings.size() > 0)
228  std::cout << std::endl;
229  std::cout << "nData = " << eventWord(frameBuffer, length-trailerLength + 5, length) << " words found = " << (length - (headerLength + trailerLength) + 2) << std::endl;
230  return;
231  }
232  case 0x70: {
233  std::cout << " TDAQ [" << SubDetID << "] beam crate fragment: " << std::endl;
234  uint32_t *endBuffer = &frameBuffer[length];
235  uint32_t *begin = frameBuffer;
236  uint32_t *end = frameBuffer;
237  bool found = findNextSubFragment(begin, end, endBuffer);
238  //cppcheck-suppress invalidPrintfArgType_sint
239  printf("SubFragment from %ld to %ld\n", begin-frameBuffer, end-frameBuffer);
240  while (found) {
241  const int extent = static_cast<int>(end-begin);
242  decodeSubFragment(begin, extent);
243  found = findNextSubFragment(begin, end, endBuffer);
244  //cppcheck-suppress invalidPrintfArgType_sint
245  if (found) printf("SubFragment from %ld to %ld\n", begin-frameBuffer, end-frameBuffer);
246  }
247  return;
248  }
249  case 0x30:
250  case 0x31:
251  case 0x32:
252  case 0x33:
253  case 0x34: {
254  std::cout << " TRT fragment [" << SubDetID << "] ... skipping" << std::endl;
255  return;
256  }
257  default: {
258  std::cout << " Not an known fragment [" << SubDetID << "] ... skipping" << std::endl;
259  return;
260  }
261  }
262  }
263 
264  void
265  decodeSubFragment(uint32_t *frameBuffer, int length) {
266  uint32_t SubFragID = eventWord(frameBuffer, 3, length) ;
267  std::cout << "SubFragmentID = " << SubFragID ;
268  std::cout << " Length = " << length;
269  std::string Type[8]={"data","res ","head","res ","eob ","res ","inv ","res "};
270  switch(SubFragID) {
271  case 0x1: {
272  std::cout << " Found TDC fragment. Decoding..."<< std::endl;
273  for (int i =0; i<length-3;i++) {
274  uint32_t data = eventWord(frameBuffer, i+4 ,length);
275  std::cout << "data[" << i << "]=0x" << std::hex <<(data&0xFFF) << std::dec << " ";
276  std::cout << "type=" << Type[(data>>24)&0x07] << " ";
277  std::cout << "chan=" << ((data>>16)&0x001f) << " ";
278  std::cout << "un=" << ((data>>13)&1) << " ";
279  std::cout << "ov=" << ((data>>12)&1) << " ";
280  std::cout << "value=" << ((data&0x0fff)) << " ";
281  std::cout << std::endl;
282  }
283  return;
284  }
285  case 0x2: {
286  std::cout << " Found ADC fragment. Decoding..." << std::endl;
287  for (int i =0; i<length-5;i++) {
288  uint32_t data = eventWord(frameBuffer, i+4 ,length);
289  std::cout << "data[" << i << "]=0x" << std::hex <<data << std::dec << " ";
290  std::cout << "type=" << Type[(data>>24)&0x07] << " ";
291  std::cout << "chan=" << ((data>>16)&0x001f) << " ";
292  std::cout << "un=" << ((data>>13)&1) << " ";
293  std::cout << "ov=" << ((data>>12)&1) << " ";
294  std::cout << "value=" << ((data&0x0fff)) << " ";
295  std::cout << std::endl;
296  }
297  return;
298  }
299  default: {
300  std::cout << " Not an known SubFragment [" << SubFragID << "] ... skipping" << std::endl;
301  return;
302  }
303  }
304  }
305 
306  void
307  decodeEventWord(uint16_t currWord, int errorType, bool &linkCondensed,
308  std::string &type, std::vector<std::pair<std::string, int> > &arguments,
309  std::vector<std::string> &errors) {
310  type = "UNKNOWN";
311  arguments.clear();
312  errors.clear();
313 
314  switch((currWord & 0xe000) >> 13) {
315  case 0:
316  {
317  if(currWord & 0x1f80)
318  type = "INVALID";
319  else {
320  // Flagged error
321  type = "Flagged error";
322  errors.push_back("FLAGGED");
323  arguments.push_back(std::make_pair("chip", (currWord & 0x78) >> 3));
324  arguments.push_back(std::make_pair("value", currWord & 0x7));
325  }
326  }
327  break;
328  case 1:
329  {
330  // Header
331  type = "Header";
332  if(errorType) {
333  // No indication of whether its condensed...??
334  arguments.push_back(std::make_pair("L1", ((currWord & 0x0f00) >> 8)));
335  arguments.push_back(std::make_pair("BCID", ((currWord & 0xff))));
336  if(currWord & 0x1000) {
337  errors.push_back("Preamble err");
338  }
339  } else {
340  int link = (currWord & 0x7f);
341  arguments.push_back(std::make_pair("Link", link));
342  if(currWord & 0x100) {
343  arguments.push_back(std::make_pair("Condensed mode", 1));
344  linkCondensed = true;
345  } else {
346  linkCondensed = false;
347  }
348  if(currWord & 0x200)
349  errors.push_back("BC err");
350  if(currWord & 0x400)
351  errors.push_back("L1 err");
352  if(currWord & 0x800)
353  errors.push_back("Time out err");
354  if(currWord & 0x1000)
355  errors.push_back("Preamble err");
356  }
357  }
358  break;
359  case 2:
360  {
361  if(currWord & 0x3ff)
362  type = "INVALID";
363  else {
364  // Trailer
365  type = "Trailer";
366  if(currWord & 0x400)
367  errors.push_back("Data overflow err");
368  if(currWord & 0x800)
369  errors.push_back("H/T limit err");
370  if(currWord & 0x1000)
371  errors.push_back("Trailer bit err");
372  }
373  }
374  break;
375  case 3:
376  {
377  if(currWord & 0x300)
378  type = "INVALID";
379  else {
380  // Raw data
381  type = "Raw";
382  int bits = ((currWord & 0x1c00) >> 10) + 1;
383  arguments.push_back(std::make_pair("bits", bits));
384  int value = ((currWord<<(8-bits)) & 0xff) >> (8-bits);
385  arguments.push_back(std::make_pair("value", value));
386  // Construct decimal number that looks like binary...
387  int binValue = 0;
388  for(int b=8-bits; b<8; b++) {
389  binValue = binValue * 10 + ((value>>(7-b)) & 1);
390  }
391  // Unfortunately leading zeros are supressed when it's printed as an int...
392  arguments.push_back(std::make_pair("binValue", binValue));
393  }
394  }
395  break;
396  default:
397  // Everything else (hits)
398  {
399  if((currWord & 0x2) == 0) {
400  // Check if it should be condensed
401  if(linkCondensed || errorType) {
402  arguments.push_back(std::make_pair("Chip", ((currWord & 0x7800) >> 11)));
403  arguments.push_back(std::make_pair("Channel", ((currWord & 0x7f0) >> 4)));
404  if(currWord & 1) {
405  type = "Condensed double hit";
406  if(currWord & 0x4) errors.push_back("Error in hit1");
407  if(currWord & 0x8) errors.push_back("Error in hit2");
408  } else {
409  type = "Condensed hit";
410  if(currWord & 0x4) errors.push_back("Error in hit");
411  }
412  }
413  }
414 
415  // Only check if expanded is a posibility
416  if(!linkCondensed || errorType) {
417  if((currWord & 0x8) == 0) {
418  type = "1st hit clust exp";
419  arguments.push_back(std::make_pair("Chip", ((currWord & 0x7800) >> 11)));
420  arguments.push_back(std::make_pair("Channel", ((currWord & 0x7f0) >> 4)));
421  arguments.push_back(std::make_pair("hits", currWord & 0x7));
422  } else {
423  if((currWord & 0x7f00) == 0) {
424  type = "Clust exp";
425  arguments.push_back(std::make_pair("hits", currWord & 0x7));
426  if(currWord & 0x80) {
427  arguments.push_back(std::make_pair("hits2", (currWord & 0x70) >> 4));
428  }
429  }
430  }
431  }
432  }
433  }
434  }
435 
436  std::vector<std::string>
437  decodeEventFlags(uint32_t flags) {
438  std::vector<std::string> result;
439  if(flags & 0x1) result.push_back("HEADER");
440  if(flags & 0x2) result.push_back("TRAILER");
441  if(flags & 0x4) result.push_back("FLAGGED");
442  if(flags & 0x8) result.push_back("\"HIT PATTERN\"");
443  if(flags & 0x10) result.push_back("SYNC");
444  if(flags & 0x20) result.push_back("L1ID");
445  if(flags & 0x40) result.push_back("BCID");
446  if(flags & 0x80) result.push_back("TIMEOUT");
447  if(flags & 0x100) result.push_back("\"ALMOST FULL\"");
448  if(flags & 0x200) result.push_back("OVERFLOW");
449  if(flags & 0x400) result.push_back("\"CHIP SEQ\"");
450  if(flags & 0x800) result.push_back("\"BAD CHIP\"");
451  return result;
452  }
453 
454  fs::path
455  getFilename(const char * filenameArg){
456  std::string result;
457  const fs::path file(filenameArg);
458  if (fs::exists(file)) result = filenameArg;
459  return fs::path(result);
460  }
461 } // Close null namespace
462 
plotBeamSpotCompare.x1
x1
Definition: plotBeamSpotCompare.py:216
data
char data[hepevt_bytes_allocation_ATLAS]
Definition: HepEvt.cxx:11
get_generator_info.result
result
Definition: get_generator_info.py:21
athena.path
path
python interpreter configuration --------------------------------------—
Definition: athena.py:128
xAOD::uint32_t
setEventNumber uint32_t
Definition: EventInfo_v1.cxx:127
index
Definition: index.py:1
AthenaPoolTestRead.flags
flags
Definition: AthenaPoolTestRead.py:8
mergePhysValFiles.start
start
Definition: DataQuality/DataQualityUtils/scripts/mergePhysValFiles.py:14
plotBeamSpotCompare.x2
x2
Definition: plotBeamSpotCompare.py:218
PlotCalibFromCool.begin
begin
Definition: PlotCalibFromCool.py:94
python.resample_meson.input_file
input_file
Definition: resample_meson.py:164
athena.value
value
Definition: athena.py:124
UploadAMITag.l
list l
Definition: UploadAMITag.larcaf.py:158
mergePhysValFiles.end
end
Definition: DataQuality/DataQualityUtils/scripts/mergePhysValFiles.py:93
TBReadH6BS_Calib_jobOptions.SubDetID
SubDetID
Definition: TBReadH6BS_Calib_jobOptions.py:32
createCoolChannelIdFile.buffer
buffer
Definition: createCoolChannelIdFile.py:12
xAOD::uint16_t
setWord1 uint16_t
Definition: eFexEMRoI_v1.cxx:88
lumiFormat.i
int i
Definition: lumiFormat.py:85
LArCellNtuple.argv
argv
Definition: LArCellNtuple.py:152
helpMessage
void helpMessage()
Definition: DecodeSCT.cxx:48
file
TFile * file
Definition: tile_monitor.h:29
DQHistogramMergeRegExp.argc
argc
Definition: DQHistogramMergeRegExp.py:20
xAODType
Definition: ObjectType.h:13
mergePhysValFiles.errors
list errors
Definition: DataQuality/DataQualityUtils/scripts/mergePhysValFiles.py:43
main
int main(int argc, char **argv)
Definition: DecodeSCT.cxx:53
ReadFromCoolCompare.fd
fd
Definition: ReadFromCoolCompare.py:196
plotBeamSpotMon.b
b
Definition: plotBeamSpotMon.py:77
Trk::open
@ open
Definition: BinningType.h:40
str
std::string str(const char *word)
Definition: DecodeSCT.cxx:43
CondAlgsOpts.found
int found
Definition: CondAlgsOpts.py:101
python.CaloScaleNoiseConfig.type
type
Definition: CaloScaleNoiseConfig.py:78
Herwig7_QED_EvtGen_ll.fs
dictionary fs
Definition: Herwig7_QED_EvtGen_ll.py:17
python.dummyaccess.exists
def exists(filename)
Definition: dummyaccess.py:9
length
double length(const pvec &v)
Definition: FPGATrackSimLLPDoubletHoughTransformTool.cxx:26