ATLAS Offline Software
Loading...
Searching...
No Matches
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
18namespace fs = std::filesystem;
19namespace {
20//check the filename exists and return it as a string, or return empty string.
21fs::path
22getFilename(const char * filenameArg);
23
24void
25decodeEventWord(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
29std::vector<std::string>
30decodeEventFlags(uint32_t flags);
31
32bool
33findNextEvent(uint32_t* &start, uint32_t* &finish, uint32_t *end, uint32_t startWord);
34
35void
36decodeEvent(uint32_t *buffer, int length);
37
38void
39decodeSubFragment(uint32_t *buffer, int length);
40}
41
42inline std::string
43str(const char * word){
44 return word ? word : "";
45}
46
47void
49 std::cout<< "'DecodeSCT' takes exactly one argument, the bytestream filename." <<std::endl;
50}
51
52
53int main(int argc, char **argv) {
54 if (argc < 2){
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];
77 uint32_t *begin = buffer;
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
89namespace {
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
void helpMessage()
Definition DecodeSCT.cxx:48
double length(const pvec &v)
char data[hepevt_bytes_allocation_ATLAS]
Definition HepEvt.cxx:11
static Double_t fs
int main()
Definition hello.cxx:18
Definition index.py:1
setWord1 uint16_t
setEventNumber uint32_t
TFile * file