Line data Source code
1 :
2 : #include <vector>
3 : #include <string>
4 : #include <unordered_map>
5 : #include <map>
6 : #include <deque>
7 : #include <fstream>
8 :
9 : #include "mu2e_driver/mu2e_mmap_ioctl.h"
10 : // #include "artdaq-core-mu2e/Overlays/DTC_Types.h"
11 : #include "artdaq-core-mu2e/Overlays/DTC_Types/DTC_CharacterNotInTableError.h"
12 : #include "artdaq-core-mu2e/Overlays/DTC_Types/DTC_DCSOperationType.h"
13 : #include "artdaq-core-mu2e/Overlays/DTC_Types/DTC_DDRFlags.h"
14 : #include "artdaq-core-mu2e/Overlays/DTC_Types/DTC_DebugType.h"
15 : #include "artdaq-core-mu2e/Overlays/DTC_Types/DTC_EVBStatus.h"
16 : #include "artdaq-core-mu2e/Overlays/DTC_Types/DTC_EventMode.h"
17 : #include "artdaq-core-mu2e/Overlays/DTC_Types/DTC_EventWindowTag.h"
18 : #include "artdaq-core-mu2e/Overlays/DTC_Types/DTC_FIFOFullErrorFlags.h"
19 : #include "artdaq-core-mu2e/Overlays/DTC_Types/DTC_IICDDRBusAddress.h"
20 : #include "artdaq-core-mu2e/Overlays/DTC_Types/DTC_IICSERDESBusAddress.h"
21 : #include "artdaq-core-mu2e/Overlays/DTC_Types/DTC_LinkEnableMode.h"
22 : #include "artdaq-core-mu2e/Overlays/DTC_Types/DTC_LinkStatus.h"
23 : #include "artdaq-core-mu2e/Overlays/DTC_Types/DTC_Link_ID.h"
24 : #include "artdaq-core-mu2e/Overlays/DTC_Types/DTC_OscillatorType.h"
25 : #include "artdaq-core-mu2e/Overlays/DTC_Types/DTC_PLL_ID.h"
26 : #include "artdaq-core-mu2e/Overlays/DTC_Types/DTC_PRBSMode.h"
27 : #include "artdaq-core-mu2e/Overlays/DTC_Types/DTC_ROC_Emulation_Type.h"
28 : #include "artdaq-core-mu2e/Overlays/DTC_Types/DTC_RXBufferStatus.h"
29 : #include "artdaq-core-mu2e/Overlays/DTC_Types/DTC_RXStatus.h"
30 : #include "artdaq-core-mu2e/Overlays/DTC_Types/DTC_SerdesClockSpeed.h"
31 : #include "artdaq-core-mu2e/Overlays/DTC_Types/DTC_SERDESLoopbackMode.h"
32 : #include "artdaq-core-mu2e/Overlays/DTC_Types/DTC_SERDESRXDisparityError.h"
33 : #include "artdaq-core-mu2e/Overlays/DTC_Types/DTC_SimMode.h"
34 : #include "artdaq-core-mu2e/Overlays/DTC_Types/DTC_Subsystem.h"
35 : #include "artdaq-core-mu2e/Overlays/DTC_Types/Exceptions.h"
36 : #include "artdaq-core-mu2e/Overlays/DTC_Types/Utilities.h"
37 :
38 : #include "TRACE/tracemf.h"
39 : #define TRACE_NAME "binary_file_compare"
40 :
41 : typedef std::map<uint8_t, std::list<std::vector<uint8_t>>> roc_map;
42 : typedef std::map<uint8_t, roc_map> dtc_map;
43 : typedef std::map<uint8_t, dtc_map> subsystem_map;
44 : typedef std::map<uint64_t, subsystem_map> event_map;
45 :
46 0 : void printHelpMsg()
47 : {
48 0 : std::cout << "Compares DTC binary files to look for differences" << std::endl;
49 0 : std::cout << "Usage: DTC_binary_file_compare [options] file1 file2"
50 0 : << std::endl;
51 : std::cout
52 0 : << "Options are:" << std::endl
53 0 : << " -h, --help: This message." << std::endl
54 0 : << std::endl;
55 0 : exit(0);
56 : }
57 :
58 0 : uint8_t get_byte(mu2e_databuff_t& buf, size_t offset, size_t index)
59 : {
60 0 : return *(reinterpret_cast<uint8_t*>(reinterpret_cast<DataHeaderPacket*>(buf + offset) + 1) + index);
61 : }
62 :
63 0 : size_t add_to_map(event_map& map, mu2e_databuff_t& buf, size_t offset)
64 : {
65 0 : auto header = *reinterpret_cast<DataHeaderPacket*>(buf + offset);
66 0 : auto blockByteSize = header.s.TransferByteCount;
67 :
68 0 : uint64_t timestamp = header.s.ts10 + (static_cast<uint64_t>(header.s.ts32) << 16) + (static_cast<uint64_t>(header.s.ts54) << 32);
69 0 : auto bufSize = blockByteSize - 0x10;
70 :
71 : // TLOG(TLVL_DEBUG) << "Adding TS " << timestamp << " SS " << header.s.SubsystemID << " DTC " << header.s.DTCID << " ROC " << header.s.LinkID << " to map with size " << bufSize;
72 0 : map[timestamp][header.s.SubsystemID][header.s.DTCID][header.s.LinkID].push_back(std::vector<uint8_t>(bufSize));
73 0 : for (auto jj = 0; jj < bufSize; ++jj)
74 : {
75 0 : map[timestamp][header.s.SubsystemID][header.s.DTCID][header.s.LinkID].back()[jj] = get_byte(buf, offset, jj);
76 : }
77 :
78 0 : return blockByteSize;
79 : }
80 :
81 0 : int main(int argc, char* argv[])
82 : {
83 0 : std::vector<std::string> binaryFiles;
84 0 : for (auto optind = 1; optind < argc; ++optind)
85 : {
86 0 : if (argv[optind][0] == '-')
87 : {
88 0 : switch (argv[optind][1])
89 : {
90 0 : case '-': // Long option
91 : {
92 0 : auto option = DTCLib::Utilities::getLongOptionOption(&optind, &argv);
93 0 : if (option == "--help")
94 : {
95 0 : printHelpMsg();
96 : }
97 0 : break;
98 0 : }
99 0 : default:
100 0 : TLOG(TLVL_ERROR) << "Unknown option: " << argv[optind] << std::endl;
101 0 : printHelpMsg();
102 0 : break;
103 0 : case 'h':
104 0 : printHelpMsg();
105 0 : break;
106 : }
107 : }
108 : else
109 : {
110 0 : binaryFiles.push_back(std::string(argv[optind]));
111 : }
112 : }
113 :
114 0 : if (binaryFiles.size() < 2 || binaryFiles.size() > 2)
115 : {
116 0 : TLOG(TLVL_ERROR) << "You must specify two files to compare!";
117 0 : printHelpMsg();
118 0 : exit(1);
119 : }
120 :
121 : // Theory of comparison: Load first file into event_map, then go through second file, removing equivalent items from event_map. At the end, print the remainder of event_map, plus any disagreements.
122 0 : event_map first_file_contents;
123 0 : event_map second_file_disagreements;
124 :
125 0 : std::ifstream is(binaryFiles[0]);
126 0 : if (is.bad() || !is)
127 : {
128 0 : TLOG(TLVL_ERROR) << "Cannot read file " << binaryFiles[0];
129 0 : exit(2);
130 : }
131 0 : TLOG(TLVL_INFO) << "Reading binary file " << binaryFiles[0];
132 0 : uint64_t total_size_read = 0;
133 :
134 : mu2e_databuff_t buf;
135 :
136 0 : while (is)
137 : {
138 : uint64_t dmaWriteSize; // DMA Write buffer size
139 0 : is.read((char*)&dmaWriteSize, sizeof(dmaWriteSize));
140 0 : total_size_read += sizeof(dmaWriteSize);
141 :
142 : uint64_t dmaSize; // DMA buffer size
143 0 : is.read((char*)&dmaSize, sizeof(dmaSize));
144 0 : total_size_read += sizeof(dmaSize);
145 :
146 : // Check that size of all DataBlocks = DMA Buffer Size
147 0 : is.read((char*)buf, dmaSize);
148 0 : total_size_read += dmaSize;
149 :
150 0 : size_t offset = 0;
151 0 : while (offset < dmaSize)
152 : {
153 0 : offset += add_to_map(first_file_contents, buf, offset);
154 : }
155 : }
156 :
157 0 : TLOG(TLVL_INFO) << "Finished with file " << binaryFiles[0] << ", bytes read " << total_size_read;
158 :
159 0 : std::ifstream is2(binaryFiles[1]);
160 0 : if (is2.bad() || !is2)
161 : {
162 0 : TLOG(TLVL_ERROR) << "Cannot read file " << binaryFiles[1];
163 0 : exit(2);
164 : }
165 0 : TLOG(TLVL_INFO) << "Reading binary file " << binaryFiles[1];
166 0 : total_size_read = 0;
167 :
168 0 : while (is2)
169 : {
170 : uint64_t dmaWriteSize; // DMA Write buffer size
171 0 : is2.read((char*)&dmaWriteSize, sizeof(dmaWriteSize));
172 0 : total_size_read += sizeof(dmaWriteSize);
173 :
174 : uint64_t dmaSize; // DMA buffer size
175 0 : is2.read((char*)&dmaSize, sizeof(dmaSize));
176 0 : total_size_read += sizeof(dmaSize);
177 :
178 : // Check that size of all DataBlocks = DMA Buffer Size
179 0 : is2.read((char*)buf, dmaSize);
180 0 : total_size_read += dmaSize;
181 :
182 0 : size_t offset = 0;
183 0 : while (offset < dmaSize)
184 : {
185 0 : auto header = *reinterpret_cast<DataHeaderPacket*>(buf + offset);
186 0 : size_t blockByteSize = header.s.TransferByteCount;
187 :
188 0 : uint64_t timestamp = (static_cast<uint64_t>(header.s.ts10) << 32) + (static_cast<uint64_t>(header.s.ts32) << 16) + (static_cast<uint64_t>(header.s.ts54));
189 0 : size_t bufSize = blockByteSize - 0x10;
190 :
191 0 : if (first_file_contents.count(timestamp) && first_file_contents[timestamp].count(header.s.SubsystemID) && first_file_contents[timestamp][header.s.SubsystemID].count(header.s.DTCID) && first_file_contents[timestamp][header.s.SubsystemID][header.s.DTCID].count(header.s.LinkID))
192 : {
193 0 : auto agree_it = first_file_contents[timestamp][header.s.SubsystemID][header.s.DTCID][header.s.LinkID].end();
194 0 : auto ii = first_file_contents[timestamp][header.s.SubsystemID][header.s.DTCID][header.s.LinkID].begin();
195 0 : for (; ii != agree_it; ++ii)
196 : {
197 0 : if (ii->size() != bufSize) continue;
198 0 : bool this_agree = true;
199 0 : for (size_t jj = 0; jj < bufSize; ++jj)
200 : {
201 0 : if (ii->at(jj) != get_byte(buf, offset, jj))
202 : {
203 0 : TLOG(TLVL_WARNING) << "Disagreement found! TS " << timestamp << " SS " << header.s.SubsystemID << " DTC " << header.s.DTCID << " ROC " << header.s.LinkID << " byte " << jj << ": " << ii->at(jj) << " != " << get_byte(buf, offset, jj);
204 0 : this_agree = false;
205 0 : break;
206 : }
207 : }
208 0 : if (this_agree)
209 : {
210 0 : agree_it = ii;
211 0 : break;
212 : }
213 : }
214 0 : if (agree_it != first_file_contents[timestamp][header.s.SubsystemID][header.s.DTCID][header.s.LinkID].end())
215 : {
216 0 : first_file_contents[timestamp][header.s.SubsystemID][header.s.DTCID][header.s.LinkID].erase(agree_it);
217 0 : if (first_file_contents[timestamp][header.s.SubsystemID][header.s.DTCID][header.s.LinkID].size() == 0)
218 : {
219 0 : first_file_contents[timestamp][header.s.SubsystemID][header.s.DTCID]
220 0 : .erase(header.s.LinkID);
221 0 : if (first_file_contents[timestamp][header.s.SubsystemID][header.s.DTCID].size() == 0)
222 : {
223 0 : first_file_contents[timestamp][header.s.SubsystemID].erase(header.s.DTCID);
224 0 : if (first_file_contents[timestamp][header.s.SubsystemID].size() == 0)
225 : {
226 0 : first_file_contents[timestamp].erase(header.s.SubsystemID);
227 0 : if (first_file_contents[timestamp].size() == 0)
228 : {
229 0 : first_file_contents.erase(timestamp);
230 : }
231 : }
232 : }
233 : }
234 : }
235 : else
236 : {
237 0 : TLOG(TLVL_WARNING) << "Disagreement found! TS " << timestamp << " SS " << header.s.SubsystemID << " DTC " << header.s.DTCID << " ROC " << header.s.LinkID << " no matching entries found";
238 0 : add_to_map(second_file_disagreements, buf, offset);
239 : }
240 : }
241 : else
242 : {
243 0 : TLOG(TLVL_WARNING) << "Disagreement found! TS " << timestamp << " SS " << header.s.SubsystemID << " DTC " << header.s.DTCID << " ROC " << header.s.LinkID << " Not found in first file map!";
244 0 : add_to_map(second_file_disagreements, buf, offset);
245 : }
246 :
247 0 : offset += blockByteSize;
248 : }
249 : }
250 :
251 0 : TLOG(TLVL_INFO) << "Finished with file " << binaryFiles[1] << ", bytes read " << total_size_read;
252 0 : TLOG(TLVL_INFO) << "There are " << first_file_contents.size() << " events remaining from the first file. There are " << second_file_disagreements.size() << " events with different data in the second file.";
253 0 : for (auto& ts : first_file_contents)
254 : {
255 0 : TLOG(TLVL_TRACE) << "First file remainder: Event " << ts.first;
256 0 : for (auto& subsys : ts.second)
257 : {
258 0 : for (auto& dtc : subsys.second)
259 : {
260 0 : for (auto& roc : dtc.second)
261 : {
262 0 : TLOG(TLVL_TRACE) << "\tTS " << ts.first << " SS " << subsys.first << " DTC " << dtc.first << " ROC " << roc.first << ": sz: " << roc.second.size();
263 0 : for (auto& it : roc.second)
264 : {
265 0 : TLOG(TLVL_TRACE) << "\t\tByte vector sz=" << it.size();
266 : }
267 : }
268 : }
269 : }
270 : }
271 0 : for (auto& ts : second_file_disagreements)
272 : {
273 0 : TLOG(TLVL_TRACE) << "Second file disagreements: Event " << ts.first;
274 0 : for (auto& subsys : ts.second)
275 : {
276 0 : for (auto& dtc : subsys.second)
277 : {
278 0 : for (auto& roc : dtc.second)
279 : {
280 0 : TLOG(TLVL_TRACE) << "\tTS " << ts.first << " SS " << subsys.first << " DTC " << dtc.first << " ROC " << roc.first << ": sz: " << roc.second.size();
281 0 : for (auto& it : roc.second)
282 : {
283 0 : TLOG(TLVL_TRACE) << "\t\tByte vector sz=" << it.size();
284 : }
285 : }
286 : }
287 : }
288 : }
289 0 : }
|