Bug Summary

File:/home/sdobbs/work/clang/halld_recon/src/libraries/DAQ/DEVIOWorkerThread.cc
Warning:line 1142, column 51
Although the value stored to 'trigger_time_tag' is used in the enclosing expression, the value is never actually read from 'trigger_time_tag'

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -main-file-name DEVIOWorkerThread.cc -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -tune-cpu generic -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /w/halld-scifs17exp/home/sdobbs/clang/llvm-project/install/lib/clang/12.0.0 -D HAVE_EVIO -D HAVE_TMVA=1 -I .Linux_CentOS7.7-x86_64-gcc4.8.5/libraries/DAQ -I libraries/DAQ -I . -I libraries -I libraries/include -I /w/halld-scifs17exp/home/sdobbs/clang/halld_recon/Linux_CentOS7.7-x86_64-gcc4.8.5/include -I libraries -I /group/halld/Software/builds/Linux_CentOS7.7-x86_64-gcc4.8.5/evio/evio-4.4.6/Linux-x86_64/include -I /w/halld-scifs17exp/halld2/home/sdobbs/Software/jana/jana_0.8.2/Linux_CentOS7.7-x86_64-gcc4.8.5/include -I /group/halld/Software/builds/Linux_CentOS7.7-x86_64-gcc4.8.5/root/root-6.08.06/include -internal-isystem /usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../include/c++/4.8.5 -internal-isystem /usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../include/c++/4.8.5/x86_64-redhat-linux -internal-isystem /usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../include/c++/4.8.5/backward -internal-isystem /usr/local/include -internal-isystem /w/halld-scifs17exp/home/sdobbs/clang/llvm-project/install/lib/clang/12.0.0/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -std=c++11 -fdeprecated-macro -fdebug-compilation-dir /home/sdobbs/work/clang/halld_recon/src -ferror-limit 19 -fgnuc-version=4.2.1 -fcxx-exceptions -fexceptions -vectorize-loops -vectorize-slp -analyzer-output=html -faddrsig -o /tmp/scan-build-2021-01-21-110224-160369-1 -x c++ libraries/DAQ/DEVIOWorkerThread.cc
1/// $Id$
2//
3// File: DEVIOWorkerThread.cc
4// Created: Mon Mar 28 07:40:07 EDT 2016
5// Creator: davidl (on Darwin harriet.jlab.org 13.4.0 i386)
6//
7
8#include <unistd.h>
9
10#include "DEVIOWorkerThread.h"
11#include "JEventSource_EVIOpp.h"
12#include "LinkAssociations.h"
13
14#include <swap_bank.h>
15#include <DANA/JExceptionDataFormat.h>
16
17using namespace std;
18using namespace std::chrono;
19
20
21
22//---------------------------------
23// DEVIOWorkerThread (Constructor)
24//---------------------------------
25DEVIOWorkerThread::DEVIOWorkerThread(
26 JEventSource_EVIOpp *event_source
27 ,list<DParsedEvent*> &parsed_events
28 ,uint32_t &MAX_PARSED_EVENTS
29 ,mutex &PARSED_EVENTS_MUTEX
30 ,condition_variable &PARSED_EVENTS_CV
31 ,set<uint32_t> &ROCIDS_TO_PARSE
32 ):
33 event_source(event_source)
34 ,parsed_events(parsed_events)
35 ,MAX_PARSED_EVENTS(MAX_PARSED_EVENTS)
36 ,PARSED_EVENTS_MUTEX(PARSED_EVENTS_MUTEX)
37 ,PARSED_EVENTS_CV(PARSED_EVENTS_CV)
38 ,ROCIDS_TO_PARSE(ROCIDS_TO_PARSE)
39 ,done(false)
40 ,thd(&DEVIOWorkerThread::Run,this)
41{
42 // n.b. in principal, the worker thread is started when the
43 // above constructor is hit and so may already be in Run()
44 // before executing anything below. The "done" variable is
45 // therefore initialized first to guarantee that if that
46 // happens, it gets to the cv.wait() call where it will wait
47 // for someone to notify it. That won't happen before this
48 // constructor completes so we do the remaining initializations
49 // below.
50
51 VERBOSE = 0;
52 Nrecycled = 0; // Incremented in JEventSource_EVIOpp::Dispatcher()
53 MAX_EVENT_RECYCLES = 1000; // In EVIO events (not L1 trigger events!) overwritten in JEventSource_EVIOpp constructor
54 MAX_OBJECT_RECYCLES = 1000; // overwritten in JEventSource_EVIOpp constructor
55 run_number_seed = 0; // Set in JEventSource_EVIOpp constructor
56
57 in_use = false;
58 jobtype = JOB_NONE;
59
60 buff_len = 100; // this will grow as needed
61 buff = new uint32_t[buff_len];
62
63 PARSE_F250 = true;
64 PARSE_F125 = true;
65 PARSE_F1TDC = true;
66 PARSE_CAEN1290TDC = true;
67 PARSE_CONFIG = true;
68 PARSE_BOR = true;
69 PARSE_EPICS = true;
70 PARSE_EVENTTAG = true;
71 PARSE_TRIGGER = true;
72 PARSE_SSP = true;
73 PARSE_GEMSRS = true;
74 NSAMPLES_GEMSRS = 9;
75
76 LINK_TRIGGERTIME = true;
77}
78
79//---------------------------------
80// ~DEVIOWorkerThread (Destructor)
81//---------------------------------
82DEVIOWorkerThread::~DEVIOWorkerThread()
83{
84 if(buff) delete[] buff;
85 for(auto pe : parsed_event_pool) delete pe;
86}
87
88//---------------------------------
89// Run
90//---------------------------------
91void DEVIOWorkerThread::Run(void)
92{
93 unique_lock<std::mutex> lck(mtx);
94
95 // Loop waiting for jobs or until told to quit
96 while(!done){
97
98 cv.wait_for(lck, std::chrono::milliseconds(1));
99
100 // In principle, in_use should never be false with a jobtype!=JOB_NONE
101 // In practice, this has happened, possibly due to compiler optimization
102 // reordering things in JEventSource_EVIOpp::Dispatcher. That led to
103 // attempting to process a buffer that was being written to. Avoid that
104 // condition by checking the in_use flag is really set.
105 if( !in_use ) continue;
106
107 try {
108
109 if( jobtype & JOB_SWAP ) swap_bank(buff, buff, swap32(buff[0])( (((buff[0]) >> 24) & 0x000000FF) | (((buff[0]) >>
8) & 0x0000FF00) | (((buff[0]) << 8) & 0x00FF0000
) | (((buff[0]) << 24) & 0xFF000000) )
+1 );
110
111 if( jobtype & JOB_FULL_PARSE ) MakeEvents();
112
113 if( jobtype & JOB_ASSOCIATE ) LinkAllAssociations();
114
115 if( !current_parsed_events.empty() ) PublishEvents();
116
117 } catch( JExceptionDataFormat &e ){
118 for(auto pe : parsed_event_pool) delete pe; // delete all parsed events any any objects they hold
119 parsed_event_pool.clear();
120 current_parsed_events.clear(); // (these are also in parsed_event_pool so were already deleted)
121 jerr << "Data format error exception caught" << endl;
122 jerr << "Stack trace follows:" << endl;
123 jerr << e.getStackTrace() << endl;
124 jerr << e.what() << endl;
125 japp->Quit(10);
126 } catch (exception &e) {
127 jerr << e.what() << endl;
128 for(auto pe : parsed_event_pool) delete pe; // delete all parsed events any any objects they hold
129 parsed_event_pool.clear();
130 current_parsed_events.clear(); // (these are also in parsed_event_pool so were already deleted)
131 japp->Quit(-1);
132 }
133
134 // Reset and mark us as available for use
135 jobtype = JOB_NONE;
136 in_use = false;
137
138 if( jobtype & JOB_QUIT ) break;
139 }
140
141 in_use = false;
142}
143
144//---------------------------------
145// Finish
146//---------------------------------
147void DEVIOWorkerThread::Finish(bool wait_to_complete)
148{
149 /// Set the done flag so that the worker thread
150 /// will exit once it is done processing its current
151 /// job. The thread is notified to wake up in case
152 /// it is currently idle. If the wait_to_complete
153 /// flag is set (default), then the worker thread is
154 /// joined to guarantee the current job's processing
155 /// is completed before returning.
156 done = true;
157 cv.notify_all();
158 if(wait_to_complete) {
159 thd.join();
160 } else {
161 thd.detach();
162 }
163}
164
165//---------------------------------
166// Prune
167//---------------------------------
168void DEVIOWorkerThread::Prune(void)
169{
170 /// Delete any DParsedEvent objects not currently in use.
171 /// If the DParsedEvent object pool and their internal
172 /// hit object pools are allowed to continuously grow, it
173 /// will appear as a though there is a memory leak. Occasional
174 /// pruning will reduce the average memory footprint.
175 /// This is called from MakeEvents() every MAX_EVENT_RECYCLES
176 /// EVIO events processed by this worker thread.
177 /// Note that this is in EVIO events (i.e. possibly a block
178 /// of events) not in L1 trigger events.
179 ///
180 /// NOTE: We currently do NOT reduce the size of buff
181 /// here if it is too big. We may wish to do that at some point!
182
183 // Delete extra parsed events
184 vector<DParsedEvent*> tmp_events = parsed_event_pool;
185 parsed_event_pool.clear();
186 for(auto pe : tmp_events) {
187 if(pe->in_use)
188 parsed_event_pool.push_back(pe);
189 else
190 delete pe;
191
192 }
193}
194
195//---------------------------------
196// MakeEvents
197//---------------------------------
198void DEVIOWorkerThread::MakeEvents(void)
199{
200
201 /// Make DParsedEvent objects from data currently in buff.
202 /// This will look at the begining of the EVIO event to see
203 /// how many L1 events are in it. It will then grab that many
204 /// DParsedEvent objects from this threads pool , or create
205 /// new ones and add them all to the current_parsed_events
206 /// vector. These are then filled out later as the data is
207 /// parsed.
208
209 if(!current_parsed_events.empty()) throw JException("Attempting call to DEVIOWorkerThread::MakeEvents when current_parsed_events not empty!!", __FILE__"libraries/DAQ/DEVIOWorkerThread.cc", __LINE__209);
210
211 uint32_t *iptr = buff;
212
213 uint32_t M = 1;
214 uint64_t event_num = 0;
215
216 iptr++;
217 uint32_t mask = 0xFF001000;
218 if( (*iptr)>>16 == 0xFF32){
219
220 // CDAQ BOR. Leave M=1
221
222 }else if( (*iptr)>>16 == 0xFF33){
223
224 // CDAQ Physics event
225 M = iptr[2]&0xFF;
226
227 // Event number taken from first ROC's trigger bank
228 uint64_t eventnum_lo = iptr[6];
229 uint64_t eventnum_hi = 0; // Only lower 32bits in ROC trigger info.
230 event_num = (eventnum_hi<<32) + (eventnum_lo);
231 }else if( ((*iptr)&mask) == mask ){
232 // CODA Physics event
233 M = *(iptr)&0xFF;
234 uint64_t eventnum_lo = iptr[4];
235 uint64_t eventnum_hi = iptr[5];
236 event_num = (eventnum_hi<<32) + (eventnum_lo);
237 }
238
239 // Try and get M DParsedEvent objects from this thread's pool.
240 for(auto pe : parsed_event_pool){
241 if(pe->in_use) continue;
242 current_parsed_events.push_back(pe);
243 if( current_parsed_events.size() >= M ) break;
244 }
245
246 // Create new DParsedEvent objects if needed
247 while( current_parsed_events.size() < M ){
248 DParsedEvent *pe = new DParsedEvent(MAX_OBJECT_RECYCLES);
249 current_parsed_events.push_back(pe);
250 parsed_event_pool.push_back(pe);
251 }
252
253 // Set indexes for the parsed event objects
254 // and flag them as being in use.
255 if( VERBOSE>3 ) cout << " Creating " << current_parsed_events.size() << " parsed events ..." << endl;
256 for(auto pe : current_parsed_events){
257
258 pe->Clear(); // return previous event's objects to pools and clear vectors
259 pe->buff_len = buff_len;
260 pe->istreamorder = istreamorder;
261 pe->run_number = run_number_seed;
262 pe->event_number = event_num++;
263 pe->sync_flag = false;
264 pe->in_use = true;
265 pe->copied_to_factories = false;
266 pe->event_status_bits = 0;
267 pe->borptrs = NULL__null; // may be set by either ParseBORbank or JEventSource_EVIOpp::GetEvent
268 }
269
270 // Parse data in buffer to create data objects
271 ParseBank();
272
273 // Occasionally prune extra DParsedEvent objects as well as objects
274 // from the existing pools to reduce average memory usage. We do
275 // this after parsing so that not everything is deleted (objects
276 // being used this event will be returned to the pools later.)
277 if(++Nrecycled%MAX_EVENT_RECYCLES == 0) Prune();
278 for(auto pe : current_parsed_events){
279 if( ++pe->Nrecycled%pe->MAX_RECYCLES == 0) pe->Prune();
280 }
281}
282
283//---------------------------------
284// PublishEvents
285//---------------------------------
286void DEVIOWorkerThread::PublishEvents(void)
287{
288 /// Copy our "current_parsed_events" pointers into the global "parsed_events"
289 /// list making them available for consumption.
290
291 // Lock mutex so other threads can't modify parsed_events
292 unique_lock<mutex> lck(PARSED_EVENTS_MUTEX);
293
294 // Make sure we don't exceed the maximum number of simultaneous
295 // parsed events. If the done flag is set, go ahead and add
296 // this regardless
297 while( ((current_parsed_events.size()+parsed_events.size())>=MAX_PARSED_EVENTS) && !done ){
298 event_source->NPARSER_STALLED++;
299 PARSED_EVENTS_CV.wait_for(lck, std::chrono::milliseconds(1));
300 }
301
302 // Loop over all elements of parsed_events and insert
303 // these based on istreamorder so that the front element
304 // is the most recent.
305 bool inserted = false;
306 for(auto it = parsed_events.begin(); it!=parsed_events.end(); it++){
307 if( istreamorder < (*it)->istreamorder ){
308 parsed_events.insert(it, current_parsed_events.begin(), current_parsed_events.end());
309 inserted = true;
310 break;
311 }
312 }
313
314 // In case this should go at end of list
315 if(!inserted) parsed_events.insert(parsed_events.end(), current_parsed_events.begin(), current_parsed_events.end());
316
317 lck.unlock();
318 PARSED_EVENTS_CV.notify_all();
319
320 // Any events should now be published
321 current_parsed_events.clear();
322}
323
324//---------------------------------
325// ParseBank
326//---------------------------------
327void DEVIOWorkerThread::ParseBank(void)
328{
329 uint32_t *iptr = buff;
330 uint32_t *iend = &buff[buff[0]+1];
331
332 while(iptr < iend){
333 uint32_t event_len = iptr[0];
334 uint32_t event_head = iptr[1];
335 uint32_t tag = (event_head >> 16) & 0xFFFF;
336
337//_DBG_ << "0x" << hex << (uint64_t)iptr << dec << ": event_len=" << event_len << "tag=" << hex << tag << dec << endl;
338
339 switch(tag){
340 case 0x0060: ParseEPICSbank(iptr, iend); break;
341 case 0x0070: ParseBORbank(iptr, iend); break;
342
343 case 0xFFD0:
344 case 0xFFD1:
345 case 0xFFD2:
346 case 0xFFD3:
347 case 0xFFD4: ParseControlEvent(iptr, iend); break;
348
349 case 0xFF58:
350 case 0xFF78: current_parsed_events.back()->sync_flag = true;
351 case 0xFF50:
352 case 0xFF70: ParsePhysicsBank(iptr, iend); break;
353 case 0xFF32:
354 case 0xFF33: ParseCDAQBank(iptr, iend); break;
355
356 default:
357 _DBG_std::cerr<<"libraries/DAQ/DEVIOWorkerThread.cc"<<
":"<<357<<" "
<< "Unknown outer EVIO bank tag: " << hex << tag << dec << endl;
358 iptr = &iptr[event_len+1];
359 if(event_len<1) iptr = iend;
360 }
361 }
362}
363
364//---------------------------------
365// ParseEventTagBank
366//---------------------------------
367void DEVIOWorkerThread::ParseEventTagBank(uint32_t* &iptr, uint32_t *iend)
368{
369 // skip the bank header
370 // EventTag is stored in a bank of banks with only 1 data bank
371 // so just skip the data bank header for now.
372
373 iptr++; // data bank length
374 iptr++; // data bank header
375
376 uint64_t evt_status_lo = *iptr++;
377 uint64_t evt_status_hi = *iptr++;
378 uint64_t l3_status_lo = *iptr++;
379 uint64_t l3_status_hi = *iptr++;
380 auto l3_decision = (DL3Trigger::L3_decision_t)*iptr++;
381 uint32_t l3_algorithm = *iptr++;
382 uint32_t mva_encoded = *iptr++;
383
384 uint64_t evt_status = evt_status_lo + (evt_status_hi<<32);
385 uint64_t l3_status = l3_status_lo + ( l3_status_hi<<32);
386
387 DParsedEvent *pe = current_parsed_events.front();
388 pe->NEW_DEventTag(evt_status, l3_decision, l3_status, l3_algorithm, mva_encoded);
389
390 iptr = iend;
391}
392
393//---------------------------------
394// ParseEPICSbank
395//---------------------------------
396void DEVIOWorkerThread::ParseEPICSbank(uint32_t* &iptr, uint32_t *iend)
397{
398 if(!PARSE_EPICS){ iptr = iend; return; }
399
400 time_t timestamp=0;
401
402 // Outer bank
403 uint32_t *istart = iptr;
404 uint32_t epics_bank_len = *iptr++;
405 if(epics_bank_len < 1){
406 _DBG_std::cerr<<"libraries/DAQ/DEVIOWorkerThread.cc"<<
":"<<406<<" "
<< "bank_len<1 in EPICS event!" << endl;
407 iptr = iend;
408 return;
409 }
410
411 uint32_t *iend_epics = &iptr[epics_bank_len];
412
413 // Advance to first daughter bank
414 iptr++;
415
416 // Get pointer to first DParsedEvent
417 DParsedEvent *pe = current_parsed_events.front();
418 pe->event_status_bits |= (1<<kSTATUS_EPICS_EVENT);
419
420 // Loop over daughter banks
421 while( iptr < iend_epics ){
422
423 uint32_t bank_len = (*iptr)&0xFFFF;
424 uint32_t tag = ((*iptr)>>24)&0xFF;
425 iptr++;
426
427 if(tag == 0x61){
428 // timestamp bank
429 timestamp = *iptr;
430 }else if(tag == 0x62){
431 // EPICS data value
432 string nameval = (const char*)iptr;
433 pe->NEW_DEPICSvalue(timestamp, nameval);
434 }else{
435 // Unknown tag. Bail
436 _DBG_std::cerr<<"libraries/DAQ/DEVIOWorkerThread.cc"<<
":"<<436<<" "
<< "Unknown tag 0x" << hex << tag << dec << " in EPICS event!" <<endl;
437 DumpBinary(istart, iend_epics, 32, &iptr[-1]);
438 throw JExceptionDataFormat("Unknown tag in EPICS bank", __FILE__"libraries/DAQ/DEVIOWorkerThread.cc", __LINE__438);
439 }
440
441 iptr = &iptr[bank_len];
442 }
443
444 iptr = iend_epics;
445}
446
447//---------------------------------
448// ParseBORbank
449//---------------------------------
450void DEVIOWorkerThread::ParseBORbank(uint32_t* &iptr, uint32_t *iend)
451{
452 /// Create BOR config objects from the EVIO bank and store them in
453 /// the event (should only be one since BOR events are not entangled).
454 /// These objects will eventually be inherited by the JEventSource_EVIOpp
455 /// object and passed to all subsequent events.
456
457 // Upon entry, iptr should point to length word of a bank of banks with tag=0x70
458 // indicating BOR event. Each bank contained within will represent one crate and
459 // will be a bank with tag=0x71 and num the rocid, containing tagsegments. Each tagsegment
460 // represents a single module with the tag containing the module type (bits 0-4) and
461 // slot (bits 5-10). The data in the tagsegments is uint32_t and maps to a data
462 // structure in bor_roc.h depending on the module type. Below is a summary of
463 // how this looks in memory:
464 //
465 // BOR event length
466 // BOR header
467 // crate bank length
468 // crate header
469 // module bank len/header
470 // module data ...
471 // module bank len/header
472 // module data ...
473 // ...
474 // crate bank length
475 // crate header
476 // ...
477
478 if(!PARSE_BOR){ iptr = &iptr[(*iptr) + 1]; return; }
479 if(VERBOSE>1) jout << "--- Parsing BOR Bank" << endl;
480
481 // Make sure there is exactly 1 event in current_parsed_events
482 if(current_parsed_events.size() != 1){
483 stringstream ss;
484 ss << "DEVIOWorkerThread::ParseBORbank called for EVIO event with " << current_parsed_events.size() << " events in it. (Should be exactly 1!)";
485 jerr << ss.str() << endl;
486 jerr << "EVIO length=" << hex << iptr[0] << " header=" << iptr[1] << endl;
487 throw JExceptionDataFormat(ss.str(), __FILE__"libraries/DAQ/DEVIOWorkerThread.cc", __LINE__487);
488 }
489
490 // Create new DBORptrs object and set pointer to it in DParsedEvent
491 // (see JEventSource_EVIOpp::GetEvent)
492 DParsedEvent *pe = current_parsed_events.front();
493 pe->event_status_bits |= (1<<kSTATUS_BOR_EVENT);
494 pe->borptrs = new DBORptrs();
495 DBORptrs* &borptrs = pe->borptrs;
496
497 // Make sure we have full event
498 uint32_t borevent_len = *iptr++;
499 uint32_t bank_len = (uint32_t)((uint64_t)iend - (uint64_t)iptr)/sizeof(uint32_t);
500 if(borevent_len > bank_len){
501 stringstream ss;
502 ss << "BOR: Size of bank doesn't match amount of data given (" << borevent_len << " > " << bank_len << ")";
503 throw JExceptionDataFormat(ss.str(), __FILE__"libraries/DAQ/DEVIOWorkerThread.cc", __LINE__503);
504 }
505 iend = &iptr[borevent_len]; // in case they give us too much data!
506
507 // Make sure BOR header word is right
508 // n.b. CODA writes bor_header = 0x700e01
509 // CDAQ replaces the last "01" with the number of crates.
510 // Prior to Fall 2019 this was 0x700e34 and then 2 more crates
511 // were added to make it 0x700e36. Now we just ignore those
512 // lower 8 bits so this doesn't break in the future.
513 uint32_t bor_header = *iptr++;
514// if( (bor_header!=0x700e01) && (bor_header!=0x700e34) ){
515 if( (bor_header>>8) != 0x700e ){
516 stringstream ss;
517 ss << "Bad BOR header: 0x" << hex << bor_header;
518 _DBG_std::cerr<<"libraries/DAQ/DEVIOWorkerThread.cc"<<
":"<<518<<" "
<< ss.str() << endl;
519 DumpBinary(&iptr[-4], iend, 32, iptr);
520 throw JExceptionDataFormat(ss.str(), __FILE__"libraries/DAQ/DEVIOWorkerThread.cc", __LINE__520);
521 }
522
523 // Loop over crates
524 while(iptr<iend){
525 uint32_t crate_len = *iptr++;
526 uint32_t *iend_crate = &iptr[crate_len]; // points to first word after this crate
527 uint32_t crate_header = *iptr++;
528// uint32_t rocid = crate_header&0xFF;
529
530 // Make sure crate tag is right
531 if( (crate_header>>16) != 0x71 ){
532 stringstream ss;
533 ss << "Bad BOR crate header: 0x" << hex << (crate_header>>16);
534 _DBG_std::cerr<<"libraries/DAQ/DEVIOWorkerThread.cc"<<
":"<<534<<" "
<< ss.str() << endl;
535 throw JExceptionDataFormat(ss.str(), __FILE__"libraries/DAQ/DEVIOWorkerThread.cc", __LINE__535);
536 }
537
538 // Loop over modules
539 while(iptr<iend_crate){
540 uint32_t module_header = *iptr++;
541 uint32_t module_len = module_header&0xFFFF;
542 uint32_t modType = (module_header>>20)&0x1f;
543// uint32_t slot = (module_header>>25);
544// uint32_t *iend_module = &iptr[module_len]; // points to first word after this module
545
546 uint32_t *src = iptr;
547 uint32_t *dest = NULL__null;
548 uint32_t sizeof_dest = 0;
549
550 Df250BORConfig *f250conf = NULL__null;
551 Df125BORConfig *f125conf = NULL__null;
552 DF1TDCBORConfig *F1TDCconf = NULL__null;
553 DCAEN1290TDCBORConfig *caen1190conf = NULL__null;
554 DTSGBORConfig *tsgconf = NULL__null;
555
556 switch(modType){
557 case DModuleType::FADC250: // f250
558 f250conf = new Df250BORConfig;
559 dest = (uint32_t*)&f250conf->rocid;
560 sizeof_dest = sizeof(f250config)/sizeof(uint32_t);
561 break;
562 case DModuleType::FADC125: // f125
563 f125conf = new Df125BORConfig;
564 dest = (uint32_t*)&f125conf->rocid;
565 sizeof_dest = sizeof(f125config)/sizeof(uint32_t);
566 break;
567
568 case DModuleType::F1TDC32: // F1TDCv2
569 case DModuleType::F1TDC48: // F1TDCv3
570 F1TDCconf = new DF1TDCBORConfig;
571 dest = (uint32_t*)&F1TDCconf->rocid;
572 sizeof_dest = sizeof(F1TDCconfig)/sizeof(uint32_t);
573 break;
574
575 case DModuleType::CAEN1190: // CAEN 1190 TDC
576 case DModuleType::CAEN1290: // CAEN 1290 TDC
577 caen1190conf = new DCAEN1290TDCBORConfig;
578 dest = (uint32_t*)&caen1190conf->rocid;
579 sizeof_dest = sizeof(caen1190config)/sizeof(uint32_t);
580 break;
581 case DModuleType::CDAQTSG: // TSG (from CDAQ)
582 tsgconf = new DTSGBORConfig;
583 // Accomodate variable number of words by copying here
584 tsgconf->rocid = 81; // rocid member must exist for LinkAssociations.h::SortByModule
585 tsgconf->slot = 1; // " " "
586 tsgconf->run_number = src[0];
587 tsgconf->unix_time = src[1];
588 for(uint32_t i=0; i<module_len; i++) tsgconf->misc_words.push_back(src[i]);
589
590 sizeof_dest = module_len; // prevent error from being thrown below
591 dest = src; // make copy benign. This allows us to keep mechansim used by other modules
592 break;
593
594 default:
595 {
596 stringstream ss;
597 ss << "Unknown BOR module type: " << modType << " (module_header=0x"<<hex<<module_header<<")";
598 jerr << ss.str() << endl;
599 throw JExceptionDataFormat(ss.str(), __FILE__"libraries/DAQ/DEVIOWorkerThread.cc", __LINE__599);
600 }
601 }
602
603 // Check that the bank size and data structure size match.
604 if( module_len > sizeof_dest ){
605 stringstream ss;
606 ss << "BOR module bank size does not match structure! " << module_len << " > " << sizeof_dest << " for modType " << modType;
607 _DBG_std::cerr<<"libraries/DAQ/DEVIOWorkerThread.cc"<<
":"<<607<<" "
<< ss.str() << endl;
608 throw JExceptionDataFormat(ss.str(), __FILE__"libraries/DAQ/DEVIOWorkerThread.cc", __LINE__608);
609 }
610
611 // Copy bank data, assuming format is the same
612 // Set extra words to "0" at end of structure
613 // in case we are processing data from older firmware
614 for(uint32_t i=0; i<sizeof_dest; i++) *dest++ = i<module_len ? (*src++):0;
615
616 // Extract certain derived values to fill in convenience members
617 if(f250conf ) f250conf->FillDerived();
618
619 // Store object for use in this and subsequent events
620 if(f250conf ) borptrs->vDf250BORConfig.push_back(f250conf);
621 if(f125conf ) borptrs->vDf125BORConfig.push_back(f125conf);
622 if(F1TDCconf ) borptrs->vDF1TDCBORConfig.push_back(F1TDCconf);
623 if(caen1190conf) borptrs->vDCAEN1290TDCBORConfig.push_back(caen1190conf);
624 if(tsgconf ) borptrs->vDTSGBORConfig.push_back(tsgconf);
625
626 iptr = &iptr[module_len];
627 }
628
629 iptr = iend_crate; // ensure we're pointing past this crate
630 }
631
632 // Sort the BOR config events now so we don't have to do it for every event
633 borptrs->Sort();
634}
635
636//---------------------------------
637// ParseTSscalerBank
638//---------------------------------
639void DEVIOWorkerThread::ParseTSscalerBank(uint32_t* &iptr, uint32_t *iend)
640{
641 uint32_t Nwords = ((uint64_t)iend - (uint64_t)iptr)/sizeof(uint32_t);
642 uint32_t Nwords_expected = (6+32+16+32+16);
643 if(Nwords != Nwords_expected){
644 _DBG_std::cerr<<"libraries/DAQ/DEVIOWorkerThread.cc"<<
":"<<644<<" "
<< "TS bank size does not match expected!!" << endl;
645 _DBG_std::cerr<<"libraries/DAQ/DEVIOWorkerThread.cc"<<
":"<<645<<" "
<< "Found " << Nwords << " words. Expected " << Nwords_expected << endl;
646 throw JExceptionDataFormat("TS bank size does not match expected", __FILE__"libraries/DAQ/DEVIOWorkerThread.cc", __LINE__646);
647 }else{
648 // n.b. Get the last event here since if this is a block
649 // of events, the last should be the actual sync event.
650 DParsedEvent *pe = current_parsed_events.back();
651 DL1Info *s = pe->NEW_DL1Info();
652 s->nsync = *iptr++;
653 s->trig_number = *iptr++;
654 s->live_time = *iptr++;
655 s->busy_time = *iptr++;
656 s->live_inst = *iptr++;
657 s->unix_time = *iptr++;
658 for(uint32_t i=0; i<32; i++) s->gtp_sc.push_back ( *iptr++ );
659 for(uint32_t i=0; i<16; i++) s->fp_sc.push_back ( *iptr++ );
660 for(uint32_t i=0; i<32; i++) s->gtp_rate.push_back( *iptr++ );
661 for(uint32_t i=0; i<16; i++) s->fp_rate.push_back ( *iptr++ );
662 }
663
664 iptr = iend;
665}
666
667//---------------------------------
668// Parsef250scalerBank
669//---------------------------------
670void DEVIOWorkerThread::Parsef250scalerBank(uint32_t rocid, uint32_t* &iptr, uint32_t *iend)
671{
672
673 uint32_t Nwords = ((uint64_t)iend - (uint64_t)iptr)/sizeof(uint32_t);
674
675 if(Nwords < 4){
676 _DBG_std::cerr<<"libraries/DAQ/DEVIOWorkerThread.cc"<<
":"<<676<<" "
<< "250Scaler bank size does not match expected!!" << endl;
677 _DBG_std::cerr<<"libraries/DAQ/DEVIOWorkerThread.cc"<<
":"<<677<<" "
<< "Found " << Nwords << endl;
678 throw JExceptionDataFormat("250scaler bank size does not match expected", __FILE__"libraries/DAQ/DEVIOWorkerThread.cc", __LINE__678);
679 } else {
680
681 DParsedEvent *pe = current_parsed_events.back();
682
683 Df250Scaler *sc = pe->NEW_Df250Scaler();
684
685 sc->nsync = *iptr++;
686 sc->trig_number = *iptr++;
687 sc->version = *iptr++;
688 sc->crate = rocid;
689
690 while(iptr < iend){
691 // cout << " " << *iptr << endl;
692 sc->fa250_sc.push_back(*iptr++);
693 }
694
695 }
696
697 iptr = iend;
698
699}
700
701//---------------------------------
702// ParseControlEvent
703//---------------------------------
704void DEVIOWorkerThread::ParseControlEvent(uint32_t* &iptr, uint32_t *iend)
705{
706
707 time_t t = (time_t)iptr[2];
708 string tstr = ctime(&t);
709 if(tstr.size()>1) tstr.erase(tstr.size()-1);
710
711 string type = "Control";
712 switch(iptr[1]>>16){
713 case 0XFFD0: type = "Sync"; break;
714 case 0XFFD1: type = "Prestart"; break;
715 case 0XFFD2: type = "Go"; break;
716 case 0XFFD3: type = "Pause"; break;
717 case 0XFFD4: type = "End"; break;
718 }
719
720 jout << "Control event: " << type << " - " << tstr << endl;
721
722 for(auto pe : current_parsed_events) {
723 pe->event_status_bits |= (1<<kSTATUS_CONTROL_EVENT);
724 auto controlevent = pe->NEW_DCODAControlEvent();
725 controlevent->event_type = iptr[1]>>16;
726 controlevent->unix_time = t;
727 for(auto p = iptr; p!=iend; p++) controlevent->words.push_back(*p);
728 }
729
730 iptr = &iptr[(*iptr) + 1];
731}
732
733//---------------------------------
734// ParsePhysicsBank
735//---------------------------------
736void DEVIOWorkerThread::ParsePhysicsBank(uint32_t* &iptr, uint32_t *iend)
737{
738
739 for(auto pe : current_parsed_events) pe->event_status_bits |= (1<<kSTATUS_PHYSICS_EVENT) + (1<<kSTATUS_CODA);
740
741 uint32_t physics_event_len = *iptr++;
742 uint32_t *iend_physics_event = &iptr[physics_event_len];
743 iptr++;
744
745 // Built Trigger Bank
746 uint32_t built_trigger_bank_len = *iptr;
747 uint32_t *iend_built_trigger_bank = &iptr[built_trigger_bank_len+1];
748 ParseBuiltTriggerBank(iptr, iend_built_trigger_bank);
749 iptr = iend_built_trigger_bank;
750
751 // Loop over Data banks
752 while( iptr < iend_physics_event ) {
753
754 uint32_t data_bank_len = *iptr;
755 uint32_t *iend_data_bank = &iptr[data_bank_len+1];
756
757 ParseDataBank(iptr, iend_data_bank);
758
759 iptr = iend_data_bank;
760 }
761
762 iptr = iend_physics_event;
763}
764
765//---------------------------------
766// ParseCDAQBank
767//---------------------------------
768void DEVIOWorkerThread::ParseCDAQBank(uint32_t* &iptr, uint32_t *iend)
769{
770
771 if(VERBOSE>1) jout << "-- Parsing CDAQ Event" << endl;
772
773 // Check if this is a BOR event
774 if( (iptr[1]&0xFFFF0000) == 0xFF320000 ){
775 iptr += 2;
776 try{
777 ParseBORbank(iptr, iend);
778 }catch(JException &e){
779 cerr << e.what();
780 }
781 return;
782 }
783
784 // Must be physics event(s)
785 for(auto pe : current_parsed_events) pe->event_status_bits |= (1<<kSTATUS_PHYSICS_EVENT) + (1<<kSTATUS_CDAQ);
786
787 // Set flag in JEventSource_EVIOpp that this is a CDAQ file
788 event_source->IS_CDAQ_FILE = true;
789
790 uint32_t physics_event_len = *iptr++;
791 uint32_t *iend_physics_event = &iptr[physics_event_len];
792 iptr++;
793
794 // Loop over Data banks
795 while( iptr < iend_physics_event ) {
796
797 uint32_t data_bank_len = *iptr;
798 uint32_t *iend_data_bank = &iptr[data_bank_len+1];
799
800 ParseDataBank(iptr, iend_data_bank);
801
802 iptr = iend_data_bank;
803 }
804
805 iptr = iend_physics_event;
806}
807
808//---------------------------------
809// ParseBuiltTriggerBank
810//---------------------------------
811void DEVIOWorkerThread::ParseBuiltTriggerBank(uint32_t* &iptr, uint32_t *iend)
812{
813 if(!PARSE_TRIGGER) return;
814
815 iptr++; // advance past length word
816 uint32_t mask = 0xFF202000;
817 if( ((*iptr) & mask) != mask ){
818 stringstream ss;
819 ss << "Bad header word in Built Trigger Bank: " << hex << *iptr;
820 throw JExceptionDataFormat(ss.str(), __FILE__"libraries/DAQ/DEVIOWorkerThread.cc", __LINE__820);
821 }
822
823 uint32_t tag = (*iptr)>>16; // 0xFF2X
824 uint32_t Nrocs = (*iptr++) & 0xFF;
825 uint32_t Mevents = current_parsed_events.size();
826
827 // sanity check:
828 if(Mevents == 0) {
829 stringstream ss;
830 ss << "DEVIOWorkerThread::ParseBuiltTriggerBank() called with zero events! "<<endl;
831 throw JExceptionDataFormat(ss.str(), __FILE__"libraries/DAQ/DEVIOWorkerThread.cc", __LINE__831);
832 }
833
834
835 //-------- Common data (64bit)
836 uint32_t common_header64 = *iptr++;
837 uint32_t common_header64_len = common_header64 & 0xFFFF;
838 uint64_t *iptr64 = (uint64_t*)iptr;
839 iptr = &iptr[common_header64_len];
840
841 // First event number
842 uint64_t first_event_num = *iptr64++;
843
844 // Hi and lo 32bit words in 64bit numbers seem to be
845 // switched for events read from ET, but not read from
846 // file. Not sure if this is in the swapping routine
847 if(event_source->source_type==event_source->kETSource) first_event_num = (first_event_num>>32) | (first_event_num<<32);
848
849 // Average timestamps
850 uint32_t Ntimestamps = (common_header64_len/2)-1;
851 if(tag & 0x2) Ntimestamps--; // subtract 1 for run number/type word if present
852 vector<uint64_t> avg_timestamps;
853 for(uint32_t i=0; i<Ntimestamps; i++) avg_timestamps.push_back(*iptr64++);
854
855 // run number and run type
856 uint32_t run_number = 0;
857 uint32_t run_type = 0;
858 if(tag & 0x02){
859 run_number = (*iptr64) >> 32;
860 run_type = (*iptr64) & 0xFFFFFFFF;
861 iptr64++;
862 }
863
864 //-------- Common data (16bit)
865 uint32_t common_header16 = *iptr++;
866 uint32_t common_header16_len = common_header16 & 0xFFFF;
867 uint16_t *iptr16 = (uint16_t*)iptr;
868 iptr = &iptr[common_header16_len];
869
870 vector<uint16_t> event_types;
871 for(uint32_t i=0; i<Mevents; i++) event_types.push_back(*iptr16++);
872
873 //-------- ROC data (32bit)
874 for(uint32_t iroc=0; iroc<Nrocs; iroc++){
875 uint32_t common_header32 = *iptr++;
876 uint32_t common_header32_len = common_header32 & 0xFFFF;
877 uint32_t rocid = common_header32 >> 24;
878
879 uint32_t Nwords_per_event = common_header32_len/Mevents;
880 for(auto pe : current_parsed_events){
881
882 DCODAROCInfo *codarocinfo = pe->NEW_DCODAROCInfo();
883 codarocinfo->rocid = rocid;
884
885 uint64_t ts_low = *iptr++;
886 uint64_t ts_high = *iptr++;
887 codarocinfo->timestamp = (ts_high<<32) + ts_low;
888 codarocinfo->misc.clear(); // could be recycled from previous event
889 for(uint32_t i=2; i<Nwords_per_event; i++) codarocinfo->misc.push_back(*iptr++);
890
891 if(iptr > iend){
892 throw JExceptionDataFormat("Bad data format in ParseBuiltTriggerBank!", __FILE__"libraries/DAQ/DEVIOWorkerThread.cc", __LINE__892);
893 }
894 }
895 }
896
897 //-------- Make DCODAEventInfo objects
898 uint64_t ievent = 0;
899 for(auto pe : current_parsed_events){
900
901 pe->run_number = run_number; // may be overwritten in JEventSource_EVIOpp::GetEvent()
902
903 DCODAEventInfo *codaeventinfo = pe->NEW_DCODAEventInfo();
904 codaeventinfo->run_number = run_number;
905 codaeventinfo->run_type = run_type;
906 codaeventinfo->event_number = first_event_num + ievent;
907 codaeventinfo->event_type = event_types.empty() ? 0:event_types[ievent];
908 codaeventinfo->avg_timestamp = avg_timestamps.empty() ? 0:avg_timestamps[ievent];
909 ievent++;
910 }
911}
912
913//---------------------------------
914// ParseRawTriggerBank
915//---------------------------------
916void DEVIOWorkerThread::ParseRawTriggerBank(uint32_t rocid, uint32_t* &iptr, uint32_t *iend)
917{
918 // CDAQ records the raw trigger bank rather than the built trigger bank.
919 // Create DCODAROCInfo objects for each of these.
920
921 if(!PARSE_TRIGGER) return;
922
923 // On entry, iptr points to word after the bank header (i.e. word after the one with 0xFF11)
924
925 // Loop over events. Should be one segment for each event
926 // suppress warning
927 // uint32_t ievent = 0;
928 for(auto pe : current_parsed_events){
929
930 uint32_t segment_header = *iptr++;
931 uint32_t segment_len = segment_header&0xFFFF;
932 uint32_t *iend_segment = &iptr[segment_len];
933
934 // suppress warning, remove assignment to unused variable but increment the pointer
935 // uint32_t event_number = *iptr++;
936 iptr++;
937 uint64_t ts_low = *iptr++;
938 uint64_t ts_high = *iptr++;
939
940 DCODAROCInfo *codarocinfo = pe->NEW_DCODAROCInfo();
941 codarocinfo->rocid = rocid;
942 codarocinfo->timestamp = (ts_high<<32) + ts_low;
943 codarocinfo->misc.clear(); // could be recycled from previous event
944
945 // rocid=1 is TS and produces 2 extra words for the trigger bits
946 for(uint32_t i=3; i<segment_len; i++) codarocinfo->misc.push_back(*iptr++);
947
948 if( iptr != iend_segment){
949 throw JExceptionDataFormat("Bad raw trigger bank format", __FILE__"libraries/DAQ/DEVIOWorkerThread.cc", __LINE__949);
950 }
951 }
952}
953
954//---------------------------------
955// ParseDataBank
956//---------------------------------
957void DEVIOWorkerThread::ParseDataBank(uint32_t* &iptr, uint32_t *iend)
958{
959 // Physics Event's Data Bank header
960 iptr++; // advance past data bank length word
961 uint32_t rocid = ((*iptr)>>16) & 0xFFF;
962 iptr++;
963
964 if(!ROCIDS_TO_PARSE.empty()){
965 if(ROCIDS_TO_PARSE.find(rocid) == ROCIDS_TO_PARSE.end()) return;
966 }
967
968 // Loop over Data Block Banks
969 while(iptr < iend){
970
971 uint32_t data_block_bank_len = *iptr++;
972 uint32_t *iend_data_block_bank = &iptr[data_block_bank_len];
973 uint32_t data_block_bank_header = *iptr++;
974
975 // Not sure where this comes from, but it needs to be skipped if present
976 while( (*iptr==0xF800FAFA) && (iptr<iend) ) iptr++;
977
978 uint32_t det_id = (data_block_bank_header>>16) & 0xFFF;
979 switch(det_id){
980
981 case 20:
982 if(VERBOSE>3) jout << " -- CAEN1190 rocid="<< rocid << endl;
983 ParseCAEN1190(rocid, iptr, iend_data_block_bank);
984 break;
985
986 case 0x55:
987 if(VERBOSE>3) jout <<" -- Module Configuration rocid="<< rocid << endl;
988 ParseModuleConfiguration(rocid, iptr, iend_data_block_bank);
989 break;
990
991 case 0x56:
992 if(VERBOSE>3) jout <<" -- Event Tag rocid="<< rocid << endl;
993 ParseEventTagBank(iptr, iend_data_block_bank);
994 break;
995
996 case 0:
997 case 1:
998 case 3:
999 case 6: // flash 250 module, MMD 2014/2/4
1000 case 16: // flash 125 module (CDC), DL 2014/6/19
1001 case 26: // F1 TDC module (BCAL), MMD 2014-07-31
1002 if(VERBOSE>3) jout <<" -- JLab Module rocid="<< rocid << endl;
1003 ParseJLabModuleData(rocid, iptr, iend_data_block_bank);
1004 break;
1005
1006 case 0x123:
1007 case 0x28:
1008 if(VERBOSE>3) jout <<" -- SSP rocid="<< rocid << endl;
1009 ParseSSPBank(rocid, iptr, iend_data_block_bank);
1010 break;
1011
1012 // These were implemented in the ROL for sync events
1013 // as 0xEE02 and 0xEE05. However, that violates the
1014 // spec. which reserves the top 4 bits as status bits
1015 // (the first "E" should really be a "1". We just check
1016 // other 12 bits here.
1017 case 0xE02:
1018 if(VERBOSE>3) jout <<" -- TSscaler rocid="<< rocid << endl;
1019 ParseTSscalerBank(iptr, iend);
1020 break;
1021 case 0xE05:
1022 // Parsef250scalerBank(iptr, iend);
1023 break;
1024 case 0xE10:
1025 Parsef250scalerBank(rocid, iptr, iend_data_block_bank);
1026 break;
1027
1028 // The CDAQ system leave the raw trigger info in the Physics event data
1029 // bank. Skip it for now.
1030 case 0xF11:
1031 if(VERBOSE>3) jout <<"Raw Trigger bank rocid="<< rocid << endl;
1032 ParseRawTriggerBank(rocid, iptr, iend_data_block_bank);
1033 break;
1034
1035 // When we write out single events in the offline, we also can save some
1036 // higher level data objects to save disk space and speed up
1037 // specialized processing (e.g. pi0 calibration)
1038 case 0xD01:
1039 ParseDVertexBank(iptr, iend_data_block_bank);
1040 break;
1041 case 0xD02:
1042 ParseDEventRFBunchBank(iptr, iend_data_block_bank);
1043 break;
1044
1045 case 5:
1046 // old ROL Beni used had this but I don't think its
1047 // been used for years. Run 10390 seems to have
1048 // this though (???)
1049 break;
1050
1051 case 0x11:
1052 // attempt at GEM SRS parsing
1053 ParseDGEMSRSBank(rocid, iptr, iend_data_block_bank);
1054 break;
1055
1056 default:
1057 jerr<<"Unknown module type ("<<det_id<<" = 0x" << hex << det_id << dec << " ) encountered" << endl;
1058// if(VERBOSE>5){
1059 cout << "----- First few words to help with debugging -----" << endl;
1060 cout.flush(); cerr.flush();
1061 DumpBinary(&iptr[-2], iend, 32, &iptr[-1]);
1062// }
1063 throw JExceptionDataFormat("Unknown bank type in EVIO", __FILE__"libraries/DAQ/DEVIOWorkerThread.cc", __LINE__1063);
1064
1065 }
1066
1067 iptr = iend_data_block_bank;
1068 }
1069
1070}
1071
1072//----------------
1073// ParseTIBank
1074//----------------
1075void DEVIOWorkerThread::ParseTIBank(uint32_t rocid, uint32_t* &iptr, uint32_t* iend)
1076{
1077 while(iptr<iend && ((*iptr) & 0xF8000000) != 0x88000000) iptr++; // Skip to JLab block trailer
1078 iptr++; // advance past JLab block trailer
1079 while(iptr<iend && *iptr == 0xF8000000) iptr++; // skip filler words after block trailer
1080 //iptr = iend;
1081}
1082
1083//----------------
1084// ParseCAEN1190
1085//----------------
1086void DEVIOWorkerThread::ParseCAEN1190(uint32_t rocid, uint32_t* &iptr, uint32_t *iend)
1087{
1088 if(!PARSE_CAEN1290TDC){ iptr = &iptr[(*iptr) + 1]; return; }
1089
1090 /// Parse data from a CAEN 1190 or 1290 module
1091 /// (See ppg. 72-74 of V1290_REV15.pdf manual)
1092
1093 uint32_t slot = 0;
1094 uint32_t event_count = 0;
1095 uint32_t word_count = 0;
1096 uint32_t trigger_time_tag = 0;
1097 uint32_t tdc_num = 0;
1098 uint32_t event_id = 0;
1099 uint32_t bunch_id = 0;
1100
1101 // We need to accomodate multi-event blocks where
1102 // events are entangled (i.e. hits from event 1
1103 // are mixed in between those of event 2,3,4,
1104 // etc... With CAEN modules, we only know which
1105 // event a hit came from by looking at the event_id
1106 // in the TDC header. This value is only 12 bits
1107 // and could roll over within an event block. This
1108 // means we need to keep track of the order we
1109 // encounter them in so it is maintained in the
1110 // "events" container. The event_id order is kept
1111 // in the "event_id_order" vector.
1112 map<uint32_t, DParsedEvent*> events_by_event_id;
1113
1114 auto pe_iter = current_parsed_events.begin();
1115 DParsedEvent *pe = NULL__null;
1116
1117 while(iptr<iend){
1118
1119 // This word appears to be appended to the data.
1120 // Probably in the ROL. Ignore it if found.
1121 if(*iptr == 0xd00dd00d) {
1122 if(VERBOSE>7) cout << " CAEN skipping 0xd00dd00d word" << endl;
1123 iptr++;
1124 continue;
1125 }
1126
1127 uint32_t type = (*iptr) >> 27;
1128 uint32_t edge = 0; // 1=trailing, 0=leading
1129 uint32_t channel = 0;
1130 uint32_t tdc = 0;
1131 uint32_t error_flags = 0;
1132 switch(type){
1133 case 0b01000: // Global Header
1134 slot = (*iptr) & 0x1f;
1135 event_count = ((*iptr)>>5) & 0xffffff;
1136 if(VERBOSE>7) cout << " CAEN TDC Global Header (slot=" << slot << " , event count=" << event_count << ")" << endl;
1137 break;
1138 case 0b10000: // Global Trailer
1139 slot = (*iptr) & 0x1f;
1140 word_count = ((*iptr)>>5) & 0x7ffff;
1141 if(VERBOSE>7) cout << " CAEN TDC Global Trailer (slot=" << slot << " , word count=" << word_count << ")" << endl;
1142 slot = event_count = word_count = trigger_time_tag = tdc_num = event_id = bunch_id = 0;
Although the value stored to 'trigger_time_tag' is used in the enclosing expression, the value is never actually read from 'trigger_time_tag'
1143 break;
1144 case 0b10001: // Global Trigger Time Tag
1145 trigger_time_tag = ((*iptr)>>5) & 0x7ffffff;
1146 if(VERBOSE>7) cout << " CAEN TDC Global Trigger Time Tag (tag=" << trigger_time_tag << ")" << endl;
1147 break;
1148 case 0b00001: // TDC Header
1149 tdc_num = ((*iptr)>>24) & 0x03;
1150 event_id = ((*iptr)>>12) & 0x0fff;
1151 bunch_id = (*iptr) & 0x0fff;
1152 if(events_by_event_id.find(event_id) == events_by_event_id.end()){
1153 if(pe_iter == current_parsed_events.end()){
1154 _DBG_std::cerr<<"libraries/DAQ/DEVIOWorkerThread.cc"<<
":"<<1154<<" "
<< "CAEN1290TDC parser sees more events than CODA header! (>" << current_parsed_events.size() << ")" << endl;
1155 for( auto p : events_by_event_id) cout << "id=" << p.first << endl;
1156 iptr = iend;
1157 throw JExceptionDataFormat("CAEN1290TDC parser sees more events than CODA header", __FILE__"libraries/DAQ/DEVIOWorkerThread.cc", __LINE__1157);
1158 }
1159 pe = *pe_iter++;
1160 events_by_event_id[event_id] = pe;
1161 }else{
1162 pe = events_by_event_id[event_id];
1163 }
1164 if(VERBOSE>7) cout << " CAEN TDC TDC Header (tdc=" << tdc_num <<" , event id=" << event_id <<" , bunch id=" << bunch_id << ")" << endl;
1165 break;
1166 case 0b00000: // TDC Measurement
1167 edge = ((*iptr)>>26) & 0x01;
1168 channel = ((*iptr)>>21) & 0x1f;
1169 tdc = ((*iptr)>>0) & 0x1fffff;
1170 if(VERBOSE>7) cout << " CAEN TDC TDC Measurement (" << (edge ? "trailing":"leading") << " , channel=" << channel << " , tdc=" << tdc << ")" << endl;
1171
1172 // Create DCAEN1290TDCHit object
1173 if(pe) pe->NEW_DCAEN1290TDCHit(rocid, slot, channel, 0, edge, tdc_num, event_id, bunch_id, tdc);
1174 break;
1175 case 0b00100: // TDC Error
1176 error_flags = (*iptr) & 0x7fff;
1177 if(VERBOSE>7) cout << " CAEN TDC TDC Error (err flags=0x" << hex << error_flags << dec << ")" << endl;
1178 break;
1179 case 0b00011: // TDC Trailer
1180 tdc_num = ((*iptr)>>24) & 0x03;
1181 event_id = ((*iptr)>>12) & 0x0fff;
1182 word_count = ((*iptr)>>0) & 0x0fff;
1183 if(VERBOSE>7) cout << " CAEN TDC TDC Trailer (tdc=" << tdc_num <<" , event id=" << event_id <<" , word count=" << word_count << ")" << endl;
1184 tdc_num = event_id = bunch_id = 0;
1185 break;
1186 case 0b11000: // Filler Word
1187 if(VERBOSE>7) cout << " CAEN TDC Filler Word" << endl;
1188 break;
1189 default:
1190 cout << "Unknown datatype: 0x" << hex << type << " full word: "<< *iptr << dec << endl;
1191 throw JExceptionDataFormat("Unknown data type for CAEN1190", __FILE__"libraries/DAQ/DEVIOWorkerThread.cc", __LINE__1191);
1192 }
1193
1194 iptr++;
1195 }
1196
1197}
1198
1199//----------------
1200// ParseModuleConfiguration
1201//----------------
1202void DEVIOWorkerThread::ParseModuleConfiguration(uint32_t rocid, uint32_t* &iptr, uint32_t *iend)
1203{
1204 if(!PARSE_CONFIG){ iptr = &iptr[(*iptr) + 1]; return; }
1205
1206 /// Parse a bank of module configuration data. These are configuration values
1207 /// programmed into the module at the beginning of the run that may be needed
1208 /// in the offline. For example, the number of samples to sum in a FADC pulse
1209 /// integral.
1210 ///
1211 /// The bank has one or more sections, each describing parameters applicable
1212 /// to a number of modules as indicated by a 24bit slot mask.
1213 ///
1214 /// This bank should appear only once per DAQ event which, if in multi-event
1215 /// block mode, may have multiple L1 events. The parameters here will apply
1216 /// to all L1 events in the block. This method will put the config objects
1217 /// into each event in current_parsed_events. The config objects are duplicated
1218 /// as needed so each event has its own, indepenent set of config object.
1219
1220 while(iptr < iend){
1221 uint32_t slot_mask = (*iptr) & 0xFFFFFF;
1222 uint32_t Nvals = ((*iptr) >> 24) & 0xFF;
1223 iptr++;
1224
1225 // Events will be created in the first event (i.e. using its pool)
1226 // but pointers are saved so we can use them to construct identical
1227 // objects in all other event later
1228 DParsedEvent *pe = current_parsed_events.front();
1229
1230 Df250Config *f250config = NULL__null;
1231 Df125Config *f125config = NULL__null;
1232 DF1TDCConfig *f1tdcconfig = NULL__null;
1233 DCAEN1290TDCConfig *caen1290tdcconfig = NULL__null;
1234
1235 // Loop over all parameters in this section
1236 for(uint32_t i=0; i< Nvals; i++){
1237 if( iptr >= iend){
1238 _DBG_std::cerr<<"libraries/DAQ/DEVIOWorkerThread.cc"<<
":"<<1238<<" "
<< "DAQ Configuration bank corrupt! slot_mask=0x" << hex << slot_mask << dec << " Nvals="<< Nvals << endl;
1239 throw JExceptionDataFormat("Corrupt DAQ config. bank", __FILE__"libraries/DAQ/DEVIOWorkerThread.cc", __LINE__1239);
1240 }
1241
1242 daq_param_type ptype = (daq_param_type)((*iptr)>>16);
1243 uint16_t val = (*iptr) & 0xFFFF;
1244
1245 if(VERBOSE>6) cout << " DAQ parameter of type: 0x" << hex << ptype << dec << " found with value: " << val << endl;
1246
1247 // Create config object of correct type if needed and copy
1248 // parameter value into it.
1249 switch(ptype>>8){
1250
1251 // f250
1252 case 0x05:
1253 if( !f250config ) f250config = pe->NEW_Df250Config(rocid, slot_mask);
1254 switch(ptype){
1255 case kPARAM250_NSA : f250config->NSA = val; break;
1256 case kPARAM250_NSB : f250config->NSB = val; break;
1257 case kPARAM250_NSA_NSB : f250config->NSA_NSB = val; break;
1258 case kPARAM250_NPED : f250config->NPED = val; break;
1259 default: _DBG_std::cerr<<"libraries/DAQ/DEVIOWorkerThread.cc"<<
":"<<1259<<" "
<< "UNKNOWN DAQ Config Parameter type: 0x" << hex << ptype << dec << endl;
1260 }
1261 break;
1262
1263 // f125
1264 case 0x0F:
1265 if( !f125config ) f125config = pe->NEW_Df125Config(rocid, slot_mask);
1266 switch(ptype){
1267 case kPARAM125_NSA : f125config->NSA = val; break;
1268 case kPARAM125_NSB : f125config->NSB = val; break;
1269 case kPARAM125_NSA_NSB : f125config->NSA_NSB = val; break;
1270 case kPARAM125_NPED : f125config->NPED = val; break;
1271 case kPARAM125_WINWIDTH : f125config->WINWIDTH = val; break;
1272 case kPARAM125_PL : f125config->PL = val; break;
1273 case kPARAM125_NW : f125config->NW = val; break;
1274 case kPARAM125_NPK : f125config->NPK = val; break;
1275 case kPARAM125_P1 : f125config->P1 = val; break;
1276 case kPARAM125_P2 : f125config->P2 = val; break;
1277 case kPARAM125_PG : f125config->PG = val; break;
1278 case kPARAM125_IE : f125config->IE = val; break;
1279 case kPARAM125_H : f125config->H = val; break;
1280 case kPARAM125_TH : f125config->TH = val; break;
1281 case kPARAM125_TL : f125config->TL = val; break;
1282 case kPARAM125_IBIT : f125config->IBIT = val; break;
1283 case kPARAM125_ABIT : f125config->ABIT = val; break;
1284 case kPARAM125_PBIT : f125config->PBIT = val; break;
1285 default: _DBG_std::cerr<<"libraries/DAQ/DEVIOWorkerThread.cc"<<
":"<<1285<<" "
<< "UNKNOWN DAQ Config Parameter type: 0x" << hex << ptype << dec << endl;
1286 }
1287 break;
1288
1289 // F1TDC
1290 case 0x06:
1291 if( !f1tdcconfig ) f1tdcconfig = pe->NEW_DF1TDCConfig(rocid, slot_mask);
1292 switch(ptype){
1293 case kPARAMF1_REFCNT : f1tdcconfig->REFCNT = val; break;
1294 case kPARAMF1_TRIGWIN : f1tdcconfig->TRIGWIN = val; break;
1295 case kPARAMF1_TRIGLAT : f1tdcconfig->TRIGLAT = val; break;
1296 case kPARAMF1_HSDIV : f1tdcconfig->HSDIV = val; break;
1297 case kPARAMF1_BINSIZE : f1tdcconfig->BINSIZE = val; break;
1298 case kPARAMF1_REFCLKDIV : f1tdcconfig->REFCLKDIV = val; break;
1299 default: _DBG_std::cerr<<"libraries/DAQ/DEVIOWorkerThread.cc"<<
":"<<1299<<" "
<< "UNKNOWN DAQ Config Parameter type: 0x" << hex << ptype << dec << endl;
1300 }
1301 break;
1302
1303 // caen1290
1304 case 0x10:
1305 if( !caen1290tdcconfig ) caen1290tdcconfig = pe->NEW_DCAEN1290TDCConfig(rocid, slot_mask);
1306 switch(ptype){
1307 case kPARAMCAEN1290_WINWIDTH : caen1290tdcconfig->WINWIDTH = val; break;
1308 case kPARAMCAEN1290_WINOFFSET : caen1290tdcconfig->WINOFFSET = val; break;
1309 default: _DBG_std::cerr<<"libraries/DAQ/DEVIOWorkerThread.cc"<<
":"<<1309<<" "
<< "UNKNOWN DAQ Config Parameter type: 0x" << hex << ptype << dec << endl;
1310 }
1311 break;
1312
1313 default:
1314 _DBG_std::cerr<<"libraries/DAQ/DEVIOWorkerThread.cc"<<
":"<<1314<<" "
<< "Unknown module type: 0x" << hex << (ptype>>8) << endl;
1315 throw JExceptionDataFormat("Unknown module type in configuration bank", __FILE__"libraries/DAQ/DEVIOWorkerThread.cc", __LINE__1315);
1316 }
1317
1318
1319 iptr++;
1320 }
1321
1322 // Make copies of all config objects for all other events
1323 for(auto tpe : current_parsed_events){
1324
1325 if(tpe == pe) continue; // first event already owns objects so skip it
1326
1327 if(f250config ) tpe->NEW_Df250Config(f250config);
1328 if(f125config ) tpe->NEW_Df125Config(f125config);
1329 if(f1tdcconfig ) tpe->NEW_DF1TDCConfig(f1tdcconfig);
1330 if(caen1290tdcconfig) tpe->NEW_DCAEN1290TDCConfig(caen1290tdcconfig);
1331 }
1332 }
1333}
1334
1335//----------------
1336// ParseJLabModuleData
1337//----------------
1338void DEVIOWorkerThread::ParseJLabModuleData(uint32_t rocid, uint32_t* &iptr, uint32_t *iend)
1339{
1340
1341 while(iptr<iend){
1342
1343 // Get module type from next word (bits 18-21)
1344 uint32_t mod_id = ((*iptr) >> 18) & 0x000F;
1345 MODULE_TYPE type = (MODULE_TYPE)mod_id;
1346 //cout << " rocid=" << rocid << " Encountered module type: " << type << " (=" << DModuleType::GetModule(type).GetName() << ") word=" << hex << (*iptr) << dec << endl;
1347
1348 switch(type){
1349 case DModuleType::FADC250:
1350 Parsef250Bank(rocid, iptr, iend);
1351 break;
1352
1353 case DModuleType::FADC125:
1354 Parsef125Bank(rocid, iptr, iend);
1355 break;
1356
1357 case DModuleType::F1TDC32:
1358 ParseF1TDCBank(rocid, iptr, iend);
1359 break;
1360
1361 case DModuleType::F1TDC48:
1362 ParseF1TDCBank(rocid, iptr, iend);
1363 break;
1364
1365 case DModuleType::TID:
1366 ParseTIBank(rocid, iptr, iend);
1367 /*
1368 // Ignore this data and skip over it
1369 while(iptr<iend && ((*iptr) & 0xF8000000) != 0x88000000) iptr++; // Skip to JLab block trailer
1370 iptr++; // advance past JLab block trailer
1371 while(iptr<iend && *iptr == 0xF8000000) iptr++; // skip filler words after block trailer
1372 break;
1373 */
1374 break;
1375
1376 case DModuleType::UNKNOWN:
1377 default:
1378 jerr<<"Unknown module type ("<<mod_id<<") iptr=0x" << hex << iptr << dec << endl;
1379
1380 while(iptr<iend && ((*iptr) & 0xF8000000) != 0x88000000) iptr++; // Skip to JLab block trailer
1381 iptr++; // advance past JLab block trailer
1382 while(iptr<iend && *iptr == 0xF8000000) iptr++; // skip filler words after block trailer
1383 throw JExceptionDataFormat("Unknown JLab module type", __FILE__"libraries/DAQ/DEVIOWorkerThread.cc", __LINE__1383);
1384 break;
1385 }
1386 }
1387
1388}
1389
1390//----------------
1391// Parsef250Bank
1392//----------------
1393void DEVIOWorkerThread::Parsef250Bank(uint32_t rocid, uint32_t* &iptr, uint32_t *iend)
1394{
1395 if(!PARSE_F250){ iptr = &iptr[(*iptr) + 1]; return; }
1396
1397 int continue_on_format_error = false;
1398
1399 auto pe_iter = current_parsed_events.begin();
1400 DParsedEvent *pe = NULL__null;
1401
1402 uint32_t slot = 0;
1403 uint32_t itrigger = -1;
1404
1405 uint32_t *istart_pulse_data = iptr;
1406
1407 // Loop over data words
1408 for(; iptr<iend; iptr++){
1409
1410 // Skip all non-data-type-defining words at this
1411 // level. When we do encounter one, the appropriate
1412 // case block below should handle parsing all of
1413 // the data continuation words and advance the iptr.
1414 if(((*iptr>>31) & 0x1) == 0)continue;
1415
1416 uint32_t data_type = (*iptr>>27) & 0x0F;
1417 switch(data_type){
1418 case 0: // Block Header
1419 slot = (*iptr>>22) & 0x1F;
1420 if(VERBOSE>7) cout << " FADC250 Block Header: slot="<<slot<<" (0x"<<hex<<*iptr<<dec<<")"<<endl;
1421 break;
1422 case 1: // Block Trailer
1423 pe_iter = current_parsed_events.begin();
1424 pe = NULL__null;
1425 if(VERBOSE>7) cout << " FADC250 Block Trailer"<<" (0x"<<hex<<*iptr<<dec<<") iptr=0x"<<hex<<iptr<<dec<<endl;
1426 break;
1427 case 2: // Event Header
1428 itrigger = (*iptr>>0) & 0x3FFFFF;
1429 pe = *pe_iter++;
1430 if(VERBOSE>7) cout << " FADC250 Event Header: itrigger="<<itrigger<<", rocid="<<rocid<<", slot="<<slot<<")" <<" (0x"<<hex<<*iptr<<dec<<")" <<endl;
1431 break;
1432 case 3: // Trigger Time
1433 {
1434 uint64_t t = ((*iptr)&0xFFFFFF)<<0;
1435 if(VERBOSE>7) cout << " FADC250 Trigger time low word="<<(((*iptr)&0xFFFFFF))<<" (0x"<<hex<<*iptr<<dec<<")"<<endl;
1436 iptr++;
1437 if(((*iptr>>31) & 0x1) == 0){
1438 t += ((*iptr)&0xFFFFFF)<<24; // from word on the street: second trigger time word is optional!!??
1439 if(VERBOSE>7) cout << " FADC250 Trigger time high word="<<(((*iptr)&0xFFFFFF))<<" (0x"<<hex<<*iptr<<dec<<") iptr=0x"<<hex<<iptr<<dec<<endl;
1440 }else{
1441 iptr--;
1442 }
1443 if(VERBOSE>7) cout << " FADC250 Trigger Time: t="<<t<<endl;
1444 if(pe) pe->NEW_Df250TriggerTime(rocid, slot, itrigger, t);
1445 }
1446 break;
1447 case 4: // Window Raw Data
1448 // iptr passed by reference and so will be updated automatically
1449 if(VERBOSE>7) cout << " FADC250 Window Raw Data"<<" (0x"<<hex<<*iptr<<dec<<")"<<endl;
1450 if(pe) MakeDf250WindowRawData(pe, rocid, slot, itrigger, iptr);
1451 break;
1452 case 5: // Window Sum
1453 {
1454 uint32_t channel = (*iptr>>23) & 0x0F;
1455 uint32_t sum = (*iptr>>0) & 0x3FFFFF;
1456 uint32_t overflow = (*iptr>>22) & 0x1;
1457 if(VERBOSE>7) cout << " FADC250 Window Sum"<<" (0x"<<hex<<*iptr<<dec<<")"<<endl;
1458 if(pe) pe->NEW_Df250WindowSum(rocid, slot, channel, itrigger, sum, overflow);
1459 }
1460 break;
1461 case 6: // Pulse Raw Data
1462// MakeDf250PulseRawData(objs, rocid, slot, itrigger, iptr);
1463 if(VERBOSE>7) cout << " FADC250 Pulse Raw Data"<<" (0x"<<hex<<*iptr<<dec<<")"<<endl;
1464 break;
1465 case 7: // Pulse Integral
1466 {
1467 uint32_t channel = (*iptr>>23) & 0x0F;
1468 uint32_t pulse_number = (*iptr>>21) & 0x03;
1469 uint32_t quality_factor = (*iptr>>19) & 0x03;
1470 uint32_t sum = (*iptr>>0) & 0x7FFFF;
1471 uint32_t nsamples_integral = 0; // must be overwritten later in GetObjects with value from Df125Config value
1472 uint32_t nsamples_pedestal = 1; // The firmware returns an already divided pedestal
1473 uint32_t pedestal = 0; // This will be replaced by the one from Df250PulsePedestal in GetObjects
1474 if(VERBOSE>7) cout << " FADC250 Pulse Integral: chan="<<channel<<" pulse_number="<<pulse_number<<" sum="<<sum<<" (0x"<<hex<<*iptr<<dec<<")"<<endl;
1475 if(pe) pe->NEW_Df250PulseIntegral(rocid, slot, channel, itrigger, pulse_number, quality_factor, sum, pedestal, nsamples_integral, nsamples_pedestal);
1476 }
1477 break;
1478 case 8: // Pulse Time
1479 {
1480 uint32_t channel = (*iptr>>23) & 0x0F;
1481 uint32_t pulse_number = (*iptr>>21) & 0x03;
1482 uint32_t quality_factor = (*iptr>>19) & 0x03;
1483 uint32_t pulse_time = (*iptr>>0) & 0x7FFFF;
1484 if(VERBOSE>7) cout << " FADC250 Pulse Time: chan="<<channel<<" pulse_number="<<pulse_number<<" pulse_time="<<pulse_time<<" (0x"<<hex<<*iptr<<dec<<")"<<endl;
1485 if(pe) pe->NEW_Df250PulseTime(rocid, slot, channel, itrigger, pulse_number, quality_factor, pulse_time);
1486 }
1487 break;
1488 case 9: // Pulse Data (firmware instroduce in Fall 2016)
1489 {
1490 // from word 1
1491 uint32_t event_number_within_block = (*iptr>>19) & 0xFF;
1492 uint32_t channel = (*iptr>>15) & 0x0F;
1493 bool QF_pedestal = (*iptr>>14) & 0x01;
1494 uint32_t pedestal = (*iptr>>0 ) & 0x3FFF;
1495 if(VERBOSE>7) cout << " FADC250 Pulse Data (0x"<<hex<<*iptr<<dec<<") channel=" << channel << " pedestal="<<pedestal << " event within block=" << event_number_within_block <<endl;
1496
1497 // event_number_within_block=0 indicates error
1498 if(event_number_within_block==0){
1499 _DBG_std::cerr<<"libraries/DAQ/DEVIOWorkerThread.cc"<<
":"<<1499<<" "
<<"event_number_within_block==0. This indicates a bug in firmware." << endl;
1500 exit(-1);
1501 }
1502
1503 // Event headers may be supressed so determine event from hit data
1504 if( (event_number_within_block > current_parsed_events.size()) ) { jerr << "Bad f250 event number for rocid="<<rocid<<" slot="<<slot<<" channel="<<channel<<endl; throw JException("Bad f250 event number", __FILE__"libraries/DAQ/DEVIOWorkerThread.cc", __LINE__1504);}
1505 pe_iter = current_parsed_events.begin();
1506 advance( pe_iter, event_number_within_block-1 );
1507 pe = *pe_iter++;
1508
1509 itrigger = event_number_within_block; // is this right?
1510 uint32_t pulse_number = 0;
1511
1512 while( (*++iptr>>31) == 0 ){
1513
1514 if( (*iptr>>30) != 0x01) {
1515 jerr << "Bad f250 Pulse Data for rocid="<<rocid<<" slot="<<slot<<" channel="<<channel<<endl;
1516 DumpBinary(istart_pulse_data, iend, ((uint64_t)&iptr[3]-(uint64_t)istart_pulse_data)/4, iptr);
1517 if (continue_on_format_error) {
1518 iptr = iend;
1519 return;
1520 }
1521 else
1522 throw JException("Bad f250 Pulse Data!", __FILE__"libraries/DAQ/DEVIOWorkerThread.cc", __LINE__1522);
1523 }
1524
1525 // from word 2
1526 uint32_t integral = (*iptr>>12) & 0x3FFFF;
1527 bool QF_NSA_beyond_PTW = (*iptr>>11) & 0x01;
1528 bool QF_overflow = (*iptr>>10) & 0x01;
1529 bool QF_underflow = (*iptr>>9 ) & 0x01;
1530 uint32_t nsamples_over_threshold = (*iptr>>0 ) & 0x1FF;
1531 if(VERBOSE>7) cout << " FADC250 Pulse Data word 2(0x"<<hex<<*iptr<<dec<<") integral="<<integral<<endl;
1532
1533 iptr++;
1534 if( (*iptr>>30) != 0x00){
1535 DumpBinary(istart_pulse_data, iend, 128, iptr);
1536 if (continue_on_format_error) {
1537 iptr = iend;
1538 return;
1539 }
1540 else
1541 throw JException("Bad f250 Pulse Data!", __FILE__"libraries/DAQ/DEVIOWorkerThread.cc", __LINE__1541);
1542 }
1543
1544 // from word 3
1545 uint32_t course_time = (*iptr>>21) & 0x1FF;//< 4 ns/count
1546 uint32_t fine_time = (*iptr>>15) & 0x3F;//< 0.0625 ns/count
1547 uint32_t pulse_peak = (*iptr>>3 ) & 0xFFF;
1548 bool QF_vpeak_beyond_NSA = (*iptr>>2 ) & 0x01;
1549 bool QF_vpeak_not_found = (*iptr>>1 ) & 0x01;
1550 bool QF_bad_pedestal = (*iptr>>0 ) & 0x01;
1551 if(VERBOSE>7) cout << " FADC250 Pulse Data word 3(0x"<<hex<<*iptr<<dec<<") course_time="<<course_time<<" fine_time="<<fine_time<<" pulse_peak="<<pulse_peak<<endl;
1552
1553 // FIRMWARE BUG: If pulse integral was zero, this is an invalid bad pulse;
1554 // skip over bogus repeated pulse time repeats, and ignore it altogether.
1555 // March 18, 2020 -rtj-
1556 if (integral == 0 && *iptr == *(iptr + 1)) {
1557 while (*(iptr + 1) == *iptr) {
1558 ++iptr;
1559 }
1560 jerr << "Bug #1: bad f250 Pulse Data for rocid="<<rocid<<" slot="<<slot<<" channel="<<channel<<endl;
1561 continue_on_format_error = true;
1562 break;
1563 }
1564
1565 if( pe ) {
1566 pe->NEW_Df250PulseData(rocid, slot, channel, itrigger
1567 , event_number_within_block
1568 , QF_pedestal
1569 , pedestal
1570 , integral
1571 , QF_NSA_beyond_PTW
1572 , QF_overflow
1573 , QF_underflow
1574 , nsamples_over_threshold
1575 , course_time
1576 , fine_time
1577 , pulse_peak
1578 , QF_vpeak_beyond_NSA
1579 , QF_vpeak_not_found
1580 , QF_bad_pedestal
1581 , pulse_number++);
1582 }
1583 }
1584 iptr--; // backup so when outer loop advances, it points to next data defining word
1585
1586 }
1587 break;
1588 case 10: // Pulse Pedestal
1589 {
1590 uint32_t channel = (*iptr>>23) & 0x0F;
1591 uint32_t pulse_number = (*iptr>>21) & 0x03;
1592 uint32_t pedestal = (*iptr>>12) & 0x1FF;
1593 uint32_t pulse_peak = (*iptr>>0) & 0xFFF;
1594 if(VERBOSE>7) cout << " FADC250 Pulse Pedestal chan="<<channel<<" pulse_number="<<pulse_number<<" pedestal="<<pedestal<<" pulse_peak="<<pulse_peak<<" (0x"<<hex<<*iptr<<dec<<")"<<endl;
1595 if(pe) pe->NEW_Df250PulsePedestal(rocid, slot, channel, itrigger, pulse_number, pedestal, pulse_peak);
1596 }
1597 break;
1598 case 13: // Event Trailer
1599 // This is marked "suppressed for normal readout – debug mode only" in the
1600 // current manual (v2). It does not contain any data so the most we could do here
1601 // is return early. I'm hesitant to do that though since it would mean
1602 // different behavior for debug mode data as regular data.
1603 case 14: // Data not valid (empty module)
1604 case 15: // Filler (non-data) word
1605 if(VERBOSE>7) cout << " FADC250 Event Trailer, Data not Valid, or Filler word ("<<data_type<<")"<<" (0x"<<hex<<*iptr<<dec<<")"<<endl;
1606 break;
1607 default:
1608 if(VERBOSE>7) cout << " FADC250 unknown data type ("<<data_type<<")"<<" (0x"<<hex<<*iptr<<dec<<")"<<endl;
1609 jerr << "FADC250 unknown data type (" << data_type << ") (0x" << hex << *iptr << dec << ")" << endl;
1610 // make additional debugging output for special error types
1611 if(data_type == 11) {
1612 cout << " FADC slot mask = "<<" 0x"<<hex<<*(iptr+1)<<dec<<endl;
1613 cout << " Token status = "<<" 0x"<<hex<<*(iptr+2)<<dec<<endl;
1614 cout << " Bus error status = "<<" 0x"<<hex<<*(iptr+3)<<dec<<endl;
1615 if(pe) {
1616 cout << " Associated with event number = "<<pe->event_number<<endl;
1617 }
1618 }
1619
1620 if (continue_on_format_error) {
1621 iptr = iend;
1622 return;
1623 }
1624 else
1625 throw JExceptionDataFormat("Unexpected word type in fADC250 block!", __FILE__"libraries/DAQ/DEVIOWorkerThread.cc", __LINE__1625);
1626 }
1627 }
1628
1629 // Chop off filler words
1630 for(; iptr<iend; iptr++){
1631 if(((*iptr)&0xf8000000) != 0xf8000000) break;
1632 }
1633}
1634
1635//----------------
1636// MakeDf250WindowRawData
1637//----------------
1638void DEVIOWorkerThread::MakeDf250WindowRawData(DParsedEvent *pe, uint32_t rocid, uint32_t slot, uint32_t itrigger, uint32_t* &iptr)
1639{
1640 uint32_t channel = (*iptr>>23) & 0x0F;
1641 uint32_t window_width = (*iptr>>0) & 0x0FFF;
1642
1643 Df250WindowRawData *wrd = pe->NEW_Df250WindowRawData(rocid, slot, channel, itrigger);
1644
1645 for(uint32_t isample=0; isample<window_width; isample +=2){
1646
1647 // Advance to next word
1648 iptr++;
1649
1650 // Make sure this is a data continuation word, if not, stop here
1651 if(((*iptr>>31) & 0x1) != 0x0){
1652 iptr--; // calling method expects us to point to last word in block
1653 break;
1654 }
1655
1656 bool invalid_1 = (*iptr>>29) & 0x1;
1657 bool invalid_2 = (*iptr>>13) & 0x1;
1658 uint16_t sample_1 = 0;
1659 uint16_t sample_2 = 0;
1660 if(!invalid_1)sample_1 = (*iptr>>16) & 0x1FFF;
1661 if(!invalid_2)sample_2 = (*iptr>>0) & 0x1FFF;
1662
1663 // Sample 1
1664 wrd->samples.push_back(sample_1);
1665 wrd->invalid_samples |= invalid_1;
1666 wrd->overflow |= (sample_1>>12) & 0x1;
1667
1668 if(((isample+2) == window_width) && invalid_2)break; // skip last sample if flagged as invalid
1669
1670 // Sample 2
1671 wrd->samples.push_back(sample_2);
1672 wrd->invalid_samples |= invalid_2;
1673 wrd->overflow |= (sample_2>>12) & 0x1;
1674 }
1675
1676 if(VERBOSE>7) cout << " FADC250 Window Raw Data: size from header=" << window_width << " Nsamples found=" << wrd->samples.size() << endl;
1677 if( window_width != wrd->samples.size() ){
1678 jerr <<" FADC250 Window Raw Data number of samples does not match header! (" <<wrd->samples.size() << " != " << window_width << ") for rocid=" << rocid << " slot=" << slot << " channel=" << channel << endl;
1679 }
1680}
1681
1682//----------------
1683// Parsef125Bank
1684//----------------
1685void DEVIOWorkerThread::Parsef125Bank(uint32_t rocid, uint32_t* &iptr, uint32_t *iend)
1686{
1687 if(!PARSE_F125){ iptr = &iptr[(*iptr) + 1]; return; }
1688
1689 auto pe_iter = current_parsed_events.begin();
1690 DParsedEvent *pe = NULL__null;
1691
1692 uint32_t slot=0;
1693 uint32_t itrigger = -1;
1694 uint32_t last_itrigger = -2;
1695 uint32_t last_pulse_time_channel=0;
1696 uint32_t last_slot = -1;
1697 uint32_t last_channel = -1;
1698
1699 // Loop over data words
1700 for(; iptr<iend; iptr++){
1701
1702 // Skip all non-data-type-defining words at this
1703 // level. When we do encounter one, the appropriate
1704 // case block below should handle parsing all of
1705 // the data continuation words and advance the iptr.
1706 if(((*iptr>>31) & 0x1) == 0)continue;
1707
1708 uint32_t data_type = (*iptr>>27) & 0x0F;
1709 switch(data_type){
1710 case 0: // Block Header
1711 slot = (*iptr>>22) & 0x1F;
1712 if(VERBOSE>7) cout << " FADC125 Block Header: slot="<<slot<<endl;
1713 break;
1714 case 1: // Block Trailer
1715 pe_iter = current_parsed_events.begin();
1716 pe = NULL__null;
1717 break;
1718 case 2: // Event Header
1719 //slot_event_header = (*iptr>>22) & 0x1F;
1720 itrigger = (*iptr>>0) & 0x3FFFFFF;
1721 pe = *pe_iter++;
1722 if(VERBOSE>7) cout << " FADC125 Event Header: itrigger="<<itrigger<<" last_itrigger="<<last_itrigger<<", rocid="<<rocid<<", slot="<<slot <<endl;
1723 break;
1724 case 3: // Trigger Time
1725 {
1726 uint64_t t = ((*iptr)&0xFFFFFF)<<0;
1727 iptr++;
1728 if(((*iptr>>31) & 0x1) == 0){
1729 t += ((*iptr)&0xFFFFFF)<<24; // from word on the street: second trigger time word is optional!!??
1730 }else{
1731 iptr--;
1732 }
1733 if(VERBOSE>7) cout << " FADC125 Trigger Time (t="<<t<<")"<<endl;
1734 if(pe) pe->NEW_Df125TriggerTime(rocid, slot, itrigger, t);
1735 }
1736 break;
1737 case 4: // Window Raw Data
1738 // iptr passed by reference and so will be updated automatically
1739 if(VERBOSE>7) cout << " FADC125 Window Raw Data"<<endl;
1740 if(pe) MakeDf125WindowRawData(pe, rocid, slot, itrigger, iptr);
1741 break;
1742
1743 case 5: // CDC pulse data (new) (GlueX-doc-2274-v8)
1744 {
1745 // Word 1:
1746 uint32_t word1 = *iptr;
1747 uint32_t channel = (*iptr>>20) & 0x7F;
1748 uint32_t pulse_number = (*iptr>>15) & 0x1F;
1749 uint32_t pulse_time = (*iptr>>4 ) & 0x7FF;
1750 uint32_t quality_factor = (*iptr>>3 ) & 0x1; //time QF bit
1751 uint32_t overflow_count = (*iptr>>0 ) & 0x7;
1752 if(VERBOSE>7){
1753 cout << " FADC125 CDC Pulse Data word1: " << hex << (*iptr) << dec << endl;
1754 cout << " FADC125 CDC Pulse Data (chan="<<channel<<" pulse="<<pulse_number<<" time="<<pulse_time<<" QF="<<quality_factor<<" OC="<<overflow_count<<")"<<endl;
1755 }
1756
1757 // Word 2:
1758 ++iptr;
1759 if(iptr>=iend){
1760 jerr << " Truncated f125 CDC hit (block ends before continuation word!)" << endl;
1761 continue;
1762 }
1763 if( ((*iptr>>31) & 0x1) != 0 ){
1764 jerr << " Truncated f125 CDC hit (missing continuation word!)" << endl;
1765 continue;
1766 }
1767 uint32_t word2 = *iptr;
1768 uint32_t pedestal = (*iptr>>23) & 0xFF;
1769 uint32_t sum = (*iptr>>9 ) & 0x3FFF;
1770 uint32_t pulse_peak = (*iptr>>0 ) & 0x1FF;
1771 if(VERBOSE>7){
1772 cout << " FADC125 CDC Pulse Data word2: " << hex << (*iptr) << dec << endl;
1773 cout << " FADC125 CDC Pulse Data (pedestal="<<pedestal<<" sum="<<sum<<" peak="<<pulse_peak<<")"<<endl;
1774 }
1775
1776 // Create hit objects
1777 uint32_t nsamples_integral = 0; // must be overwritten later in GetObjects with value from Df125Config value
1778 uint32_t nsamples_pedestal = 1; // The firmware pedestal divided by 2^PBIT where PBIT is a config. parameter
1779
1780 if( pe ) {
1781 pe->NEW_Df125CDCPulse(rocid, slot, channel, itrigger
1782 , pulse_number // NPK
1783 , pulse_time // le_time
1784 , quality_factor // time_quality_bit
1785 , overflow_count // overflow_count
1786 , pedestal // pedestal
1787 , sum // integral
1788 , pulse_peak // first_max_amp
1789 , word1 // word1
1790 , word2 // word2
1791 , nsamples_pedestal // nsamples_pedestal
1792 , nsamples_integral // nsamples_integral
1793 , false); // emulated
1794 }
1795 }
1796 break;
1797
1798 case 6: // FDC pulse data-integral (new) (GlueX-doc-2274-v8)
1799 {
1800 // Word 1:
1801 uint32_t word1 = *iptr;
1802 uint32_t channel = (*iptr>>20) & 0x7F;
1803 uint32_t pulse_number = (*iptr>>15) & 0x1F;
1804 uint32_t pulse_time = (*iptr>>4 ) & 0x7FF;
1805 uint32_t quality_factor = (*iptr>>3 ) & 0x1; //time QF bit
1806 uint32_t overflow_count = (*iptr>>0 ) & 0x7;
1807 if(VERBOSE>7){
1808 cout << " FADC125 FDC Pulse Data(integral) word1: " << hex << (*iptr) << dec << endl;
1809 cout << " FADC125 FDC Pulse Data (chan="<<channel<<" pulse="<<pulse_number<<" time="<<pulse_time<<" QF="<<quality_factor<<" OC="<<overflow_count<<")"<<endl;
1810 }
1811
1812 // Word 2:
1813 ++iptr;
1814 if(iptr>=iend){
1815 jerr << " Truncated f125 FDC hit (block ends before continuation word!)" << endl;
1816 continue;
1817 }
1818 if( ((*iptr>>31) & 0x1) != 0 ){
1819 jerr << " Truncated f125 FDC hit (missing continuation word!)" << endl;
1820 continue;
1821 }
1822 uint32_t word2 = *iptr;
1823 uint32_t pulse_peak = 0;
1824 uint32_t sum = (*iptr>>19) & 0xFFF;
1825 uint32_t peak_time = (*iptr>>11) & 0xFF;
1826 uint32_t pedestal = (*iptr>>0 ) & 0x7FF;
1827 if(VERBOSE>7){
1828 cout << " FADC125 FDC Pulse Data(integral) word2: " << hex << (*iptr) << dec << endl;
1829 cout << " FADC125 FDC Pulse Data (integral="<<sum<<" time="<<peak_time<<" pedestal="<<pedestal<<")"<<endl;
1830 }
1831
1832 // Create hit objects
1833 uint32_t nsamples_integral = 0; // must be overwritten later in GetObjects with value from Df125Config value
1834 uint32_t nsamples_pedestal = 1; // The firmware pedestal divided by 2^PBIT where PBIT is a config. parameter
1835
1836 if( pe ) {
1837 pe->NEW_Df125FDCPulse(rocid, slot, channel, itrigger
1838 , pulse_number // NPK
1839 , pulse_time // le_time
1840 , quality_factor // time_quality_bit
1841 , overflow_count // overflow_count
1842 , pedestal // pedestal
1843 , sum // integral
1844 , pulse_peak // peak_amp
1845 , peak_time // peak_time
1846 , word1 // word1
1847 , word2 // word2
1848 , nsamples_pedestal // nsamples_pedestal
1849 , nsamples_integral // nsamples_integral
1850 , false); // emulated
1851 }
1852 }
1853 break;
1854
1855 case 7: // Pulse Integral
1856 {
1857 if(VERBOSE>7) cout << " FADC125 Pulse Integral"<<endl;
1858 uint32_t channel = (*iptr>>20) & 0x7F;
1859 uint32_t sum = (*iptr>>0) & 0xFFFFF;
1860 uint32_t quality_factor = 0;
1861 uint32_t nsamples_integral = 0; // must be overwritten later in GetObjects with value from Df125Config value
1862 uint32_t nsamples_pedestal = 1; // The firmware returns an already divided pedestal
1863 uint32_t pedestal = 0; // This will be replaced by the one from Df250PulsePedestal in GetObjects
1864 uint32_t pulse_number = 0;
1865 if (last_slot == slot && last_channel == channel) pulse_number = 1;
1866 last_slot = slot;
1867 last_channel = channel;
1868 if( pe ) pe->NEW_Df125PulseIntegral(rocid, slot, channel, itrigger, pulse_number, quality_factor, sum, pedestal, nsamples_integral, nsamples_pedestal);
1869 }
1870 break;
1871 case 8: // Pulse Time
1872 {
1873 if(VERBOSE>7) cout << " FADC125 Pulse Time"<<endl;
1874 uint32_t channel = (*iptr>>20) & 0x7F;
1875 uint32_t pulse_number = (*iptr>>18) & 0x03;
1876 uint32_t pulse_time = (*iptr>>0) & 0xFFFF;
1877 uint32_t quality_factor = 0;
1878 if( pe ) pe->NEW_Df125PulseTime(rocid, slot, channel, itrigger, pulse_number, quality_factor, pulse_time);
1879 last_pulse_time_channel = channel;
1880 }
1881 break;
1882
1883 case 9: // FDC pulse data-peak (new) (GlueX-doc-2274-v8)
1884 {
1885 // Word 1:
1886 uint32_t word1 = *iptr;
1887 uint32_t channel = (*iptr>>20) & 0x7F;
1888 uint32_t pulse_number = (*iptr>>15) & 0x1F;
1889 uint32_t pulse_time = (*iptr>>4 ) & 0x7FF;
1890 uint32_t quality_factor = (*iptr>>3 ) & 0x1; //time QF bit
1891 uint32_t overflow_count = (*iptr>>0 ) & 0x7;
1892 if(VERBOSE>7){
1893 cout << " FADC125 FDC Pulse Data(peak) word1: " << hex << (*iptr) << dec << endl;
1894 cout << " FADC125 FDC Pulse Data (chan="<<channel<<" pulse="<<pulse_number<<" time="<<pulse_time<<" QF="<<quality_factor<<" OC="<<overflow_count<<")"<<endl;
1895 }
1896
1897 // Word 2:
1898 ++iptr;
1899 if(iptr>=iend){
1900 jerr << " Truncated f125 FDC hit (block ends before continuation word!)" << endl;
1901 continue;
1902 }
1903 if( ((*iptr>>31) & 0x1) != 0 ){
1904 jerr << " Truncated f125 FDC hit (missing continuation word!)" << endl;
1905 continue;
1906 }
1907 uint32_t word2 = *iptr;
1908 uint32_t pulse_peak = (*iptr>>19) & 0xFFF;
1909 uint32_t sum = 0;
1910 uint32_t peak_time = (*iptr>>11) & 0xFF;
1911 uint32_t pedestal = (*iptr>>0 ) & 0x7FF;
1912 if(VERBOSE>7){
1913 cout << " FADC125 FDC Pulse Data(peak) word2: " << hex << (*iptr) << dec << endl;
1914 cout << " FADC125 FDC Pulse Data (integral="<<sum<<" time="<<peak_time<<" pedestal="<<pedestal<<")"<<endl;
1915 }
1916
1917 // Create hit objects
1918 uint32_t nsamples_integral = 0; // must be overwritten later in GetObjects with value from Df125Config value
1919 uint32_t nsamples_pedestal = 1; // The firmware pedestal divided by 2^PBIT where PBIT is a config. parameter
1920
1921 if( pe ) {
1922
1923 // The following is a temporary fix. In late 2017 the CDC group started
1924 // using data type 9 (i.e. FDC pulse peak). This caused many conflicts
1925 // with plugins downstream that were built around there being a Df125CDCPulse
1926 // object associated with the DCDCDigiHit. In order to quickly solve
1927 // the issue as the run was starting, this fix was made to produce Df125CDCPulse
1928 // object from this data iff rocid<30 indicating the data came from the
1929 // CDC.
1930 if( rocid<30 ){
1931
1932 pe->NEW_Df125CDCPulse(rocid, slot, channel, itrigger
1933 , pulse_number // NPK
1934 , pulse_time // le_time
1935 , quality_factor // time_quality_bit
1936 , overflow_count // overflow_count
1937 , pedestal // pedestal
1938 , sum // integral
1939 , pulse_peak // peak_amp
1940 , word1 // word1
1941 , word2 // word2
1942 , nsamples_pedestal // nsamples_pedestal
1943 , nsamples_integral // nsamples_integral
1944 , false); // emulated
1945
1946 }else{
1947
1948 pe->NEW_Df125FDCPulse(rocid, slot, channel, itrigger
1949 , pulse_number // NPK
1950 , pulse_time // le_time
1951 , quality_factor // time_quality_bit
1952 , overflow_count // overflow_count
1953 , pedestal // pedestal
1954 , sum // integral
1955 , pulse_peak // peak_amp
1956 , peak_time // peak_time
1957 , word1 // word1
1958 , word2 // word2
1959 , nsamples_pedestal // nsamples_pedestal
1960 , nsamples_integral // nsamples_integral
1961 , false); // emulated
1962 }
1963 }
1964 }
1965 break;
1966
1967 case 10: // Pulse Pedestal (consistent with Beni's hand-edited version of Cody's document)
1968 {
1969 if(VERBOSE>7) cout << " FADC125 Pulse Pedestal"<<endl;
1970 //channel = (*iptr>>20) & 0x7F;
1971 uint32_t channel = last_pulse_time_channel; // not enough bits to hold channel number so rely on proximity to Pulse Time in data stream (see "FADC125 dataformat 250 modes.docx")
1972 uint32_t pulse_number = (*iptr>>21) & 0x03;
1973 uint32_t pedestal = (*iptr>>12) & 0x1FF;
1974 uint32_t pulse_peak = (*iptr>>0) & 0xFFF;
1975 uint32_t nsamples_pedestal = 1; // The firmware returns an already divided pedestal
1976 if( pe ) pe->NEW_Df125PulsePedestal(rocid, slot, channel, itrigger, pulse_number, pedestal, pulse_peak, nsamples_pedestal);
1977 }
1978 break;
1979
1980 case 13: // Event Trailer
1981 case 14: // Data not valid (empty module)
1982 case 15: // Filler (non-data) word
1983 if(VERBOSE>7) cout << " FADC125 ignored data type: " << data_type <<endl;
1984 break;
1985 default:
1986 if(VERBOSE>7) cout << " FADC125 unknown data type ("<<data_type<<")"<<" (0x"<<hex<<*iptr<<dec<<")"<<endl;
1987 throw JExceptionDataFormat("Unexpected word type in fADC125 block!", __FILE__"libraries/DAQ/DEVIOWorkerThread.cc", __LINE__1987);
1988
1989 }
1990 }
1991
1992 // Chop off filler words
1993 for(; iptr<iend; iptr++){
1994 if(((*iptr)&0xf8000000) != 0xf8000000) break;
1995 }
1996}
1997
1998//----------------
1999// MakeDf125WindowRawData
2000//----------------
2001void DEVIOWorkerThread::MakeDf125WindowRawData(DParsedEvent *pe, uint32_t rocid, uint32_t slot, uint32_t itrigger, uint32_t* &iptr)
2002{
2003 uint32_t channel = (*iptr>>20) & 0x7F;
2004 uint32_t window_width = (*iptr>>0) & 0x0FFF;
2005
2006 Df125WindowRawData *wrd = pe->NEW_Df125WindowRawData(rocid, slot, channel, itrigger);
2007
2008 for(uint32_t isample=0; isample<window_width; isample +=2){
2009
2010 // Advance to next word
2011 iptr++;
2012
2013 // Make sure this is a data continuation word, if not, stop here
2014 if(((*iptr>>31) & 0x1) != 0x0)break;
2015
2016 bool invalid_1 = (*iptr>>29) & 0x1;
2017 bool invalid_2 = (*iptr>>13) & 0x1;
2018 uint16_t sample_1 = 0;
2019 uint16_t sample_2 = 0;
2020 if(!invalid_1)sample_1 = (*iptr>>16) & 0x1FFF;
2021 if(!invalid_2)sample_2 = (*iptr>>0) & 0x1FFF;
2022
2023 // Sample 1
2024 wrd->samples.push_back(sample_1);
2025 wrd->invalid_samples |= invalid_1;
2026 wrd->overflow |= (sample_1>>12) & 0x1;
2027
2028 if((isample+2) == window_width && invalid_2)break; // skip last sample if flagged as invalid
2029
2030 // Sample 2
2031 wrd->samples.push_back(sample_2);
2032 wrd->invalid_samples |= invalid_2;
2033 wrd->overflow |= (sample_2>>12) & 0x1;
2034 }
2035}
2036
2037//----------------
2038// ParseF1TDCBank
2039//----------------
2040void DEVIOWorkerThread::ParseF1TDCBank(uint32_t rocid, uint32_t* &iptr, uint32_t *iend)
2041{
2042 if(!PARSE_F1TDC){ iptr = &iptr[(*iptr) + 1]; return; }
2043
2044 uint32_t *istart = iptr;
2045
2046 auto pe_iter = current_parsed_events.begin();
2047 DParsedEvent *pe = NULL__null;
2048
2049 uint32_t slot = 0;
2050 uint32_t modtype = 0;
2051 uint32_t itrigger = -1;
2052 uint32_t trig_time_f1header = 0;
2053
2054 // Some early data had a marker word at just before the actual F1 data
2055 if(*iptr == 0xf1daffff) iptr++;
2056
2057 // Loop over data words
2058 for(; iptr<iend; iptr++){
2059
2060 // Skip all non-data-type-defining words at this
2061 // level. When we do encounter one, the appropriate
2062 // case block below should handle parsing all of
2063 // the data continuation words and advance the iptr.
2064 if(((*iptr>>31) & 0x1) == 0)continue;
2065
2066 uint32_t data_type = (*iptr>>27) & 0x0F;
2067 switch(data_type){
2068 case 0: // Block Header
2069 slot = (*iptr)>>22 & 0x001F;
2070 modtype = (*iptr)>>18 & 0x000F; // should match a DModuleType::type_id_t
2071 if(VERBOSE>7) cout << " F1 Block Header: slot=" << slot << " modtype=" << modtype << endl;
2072 break;
2073
2074 case 1: // Block Trailer
2075 pe_iter = current_parsed_events.begin();
2076 pe = NULL__null;
2077 if(VERBOSE>7) cout << " F1 Block Trailer" << endl;
2078 break;
2079
2080 case 2: // Event Header
2081 {
2082 pe = *pe_iter++;
2083 itrigger = (*iptr)>>0 & 0x0003FFFFF;
2084 if(VERBOSE>7) {
2085 uint32_t slot_event_header = (*iptr)>>22 & 0x00000001F;
2086 cout << " F1 Event Header: slot=" << slot_event_header << " itrigger=" << itrigger << endl;
2087 }
2088 }
2089 break;
2090
2091 case 3: // Trigger time
2092 {
2093 uint64_t t = ((*iptr)&0xFFFFFF)<<0;
2094 iptr++;
2095 if(((*iptr>>31) & 0x1) == 0){
2096 t += ((*iptr)&0xFFFFFF)<<24; // from word on the street: second trigger time word is optional!!??
2097 }else{
2098 iptr--;
2099 }
2100 if(VERBOSE>7) cout << " F1TDC Trigger Time (t="<<t<<")"<<endl;
2101 if(pe) pe->NEW_DF1TDCTriggerTime(rocid, slot, itrigger, t);
2102 }
2103 break;
2104
2105 case 8: // F1 Chip Header
2106 trig_time_f1header = ((*iptr)>> 7) & 0x1FF;
2107 if(VERBOSE>7) {
2108 uint32_t chip_f1header = ((*iptr)>> 3) & 0x07;
2109 uint32_t chan_on_chip_f1header = ((*iptr)>> 0) & 0x07; // this is always 7 in real data!
2110 uint32_t itrigger_f1header = ((*iptr)>>16) & 0x3F;
2111 cout << " Found F1 header: chip=" << chip_f1header << " chan=" << chan_on_chip_f1header << " itrig=" << itrigger_f1header << " trig_time=" << trig_time_f1header << endl;
2112 }
2113 break;
2114
2115 case 7: // F1 Data
2116 {
2117 uint32_t chip = (*iptr>>19) & 0x07;
2118 uint32_t chan_on_chip = (*iptr>>16) & 0x07;
2119 uint32_t time = (*iptr>> 0) & 0xFFFF;
2120 uint32_t channel = F1TDC_channel(chip, chan_on_chip, modtype);
2121 if(VERBOSE>7) cout << " Found F1 data : chip=" << chip << " chan=" << chan_on_chip << " time=" << time << endl;
2122 if(pe){
2123 auto hit = pe->NEW_DF1TDCHit(rocid, slot, channel, itrigger, trig_time_f1header, time, *iptr, MODULE_TYPE(modtype));
2124 if(hit->res_status==0){
2125 static uint32_t Nwarnings=0;
2126 if(Nwarnings<10) jerr << "ERROR: F1 TDC chip \"unlocked\" flag set!" << ((++Nwarnings == 10) ? " -- last warning":"") << endl;
2127 }
2128 }
2129 }
2130 break;
2131
2132 case 15: // Filler word
2133 if(VERBOSE>7) cout << " F1 filler word" << endl;
2134 case 14: // Data not valid (how to handle this?)
2135 break;
2136
2137 default:
2138 cerr<<endl;
2139 cout.flush(); cerr.flush();
2140 _DBG_std::cerr<<"libraries/DAQ/DEVIOWorkerThread.cc"<<
":"<<2140<<" "
<<"Unknown data word in F1TDC block. Dumping for debugging:" << endl;
2141 for(const uint32_t *iiptr = istart; iiptr<iend; iiptr++){
2142 _DBG_std::cerr<<"libraries/DAQ/DEVIOWorkerThread.cc"<<
":"<<2142<<" "
<<"0x"<<hex<<*iiptr<<dec;
2143 if(iiptr == iptr)cerr<<" <----";
2144 switch( (*iiptr) & 0xF8000000 ){
2145 case 0x80000000: cerr << " F1 Block Header"; break;
2146 case 0x90000000: cerr << " F1 Event Header"; break;
2147 case 0x98000000: cerr << " F1 Trigger time"; break;
2148 case 0xC0000000: cerr << " F1 Header"; break;
2149 case 0xB8000000: cerr << " F1 Data"; break;
2150 case 0x88000000: cerr << " F1 Block Trailer"; break;
2151 case 0xF8000000: cerr << " Filler word"; break;
2152 case 0xF0000000: cerr << " <module has no valid data>"; break;
2153 default: break;
2154 }
2155 cerr<<endl;
2156 if(iiptr > (iptr+4)) break;
2157 }
2158 throw JExceptionDataFormat("Unexpected word type in F1TDC block!", __FILE__"libraries/DAQ/DEVIOWorkerThread.cc", __LINE__2158);
2159 break;
2160 }
2161 }
2162
2163 // Skip filler words
2164 while(iptr<iend && (*iptr&0xF8000000)==0xF8000000)iptr++;
2165}
2166
2167//----------------
2168// ParseSSPBank
2169//----------------
2170void DEVIOWorkerThread::ParseSSPBank(uint32_t rocid, uint32_t* &iptr, uint32_t *iend)
2171{
2172 if(!PARSE_SSP){ iptr = &iptr[(*iptr) + 1]; return; }
2173
2174 auto pe_iter = current_parsed_events.begin();
2175 DParsedEvent *pe = NULL__null;
2176
2177 uint32_t slot_bh = 0xFFFFFFFF; //< slot number from block header
2178 uint32_t slot = 0xFFFFFFFF; //< slot number from event header
2179 uint32_t itrigger = 0xFFFFFFFF;
2180 uint32_t dev_id = 0xFFFFFFFF;
2181 uint32_t ievent_cnt = 0xFFFFFFFF;
2182 //uint32_t last_itrigger = itrigger;
2183 for( ; iptr<iend; iptr++){
2184 if(((*iptr>>31) & 0x1) == 0)continue;
2185
2186 uint32_t data_type = (*iptr>>27) & 0x0F;
2187 switch(data_type){
2188 case 0: // Block Header
2189 {
2190 slot_bh = ((*iptr)>>22) & 0x1F;
2191 uint32_t block_num = ((*iptr)>> 8) & 0x3FF;
2192 uint32_t block_size = ((*iptr)>> 0) & 0xFF;
2193 if(VERBOSE>7) cout << " SSP/DIRC Block Header: slot=" << slot_bh << " block_num="<<block_num << " block_size=" << block_size << endl;
2194 }
2195 break;
2196 case 1: // Block Trailer
2197 pe_iter = current_parsed_events.begin();
2198 pe = NULL__null;
2199 if(VERBOSE>7) cout << " SSP/DIRC Block Trailer" << endl;
2200 break;
2201 case 2: // Event Header
2202 slot = ((*iptr)>>22) & 0x1F;
2203 itrigger = ((*iptr)>> 0) & 0x3FFFFF;
2204 pe = *pe_iter++;
2205 //if(itrigger != last_itrigger) pe = *pe_iter++;
2206 //last_itrigger = itrigger;
2207 if(VERBOSE>7) cout << " SSP/DIRC Event Header: slot=" << slot << " itrigger=" << itrigger << endl;
2208 if( slot != slot_bh ){
2209 jerr << "Slot from SSP/DIRC event header does not match slot from last block header (" <<slot<<" != " << slot_bh << ")" <<endl;
2210 }
2211 break;
2212 case 3: // Trigger Time
2213 {
2214 uint64_t t = ((*iptr)&0xFFFFFF)<<0;
2215 if(VERBOSE>7) cout << " SSP Trigger time low word="<<(((*iptr)&0xFFFFFF))<<" (0x"<<hex<<*iptr<<dec<<")"<<endl;
2216 iptr++;
2217 if(((*iptr>>31) & 0x1) == 0){ // Confirm that continuation word is present
2218 t += ((*iptr)&0xFFFFFF)<<24;
2219 if(VERBOSE>7) cout << " SSP Trigger time high word="<<(((*iptr)&0xFFFFFF))<<" (0x"<<hex<<*iptr<<dec<<") iptr=0x"<<hex<<iptr<<dec<<endl;
2220 }else{
2221 iptr--;
2222 }
2223 if(VERBOSE>7) cout << " SSP Trigger Time: t="<<t<<endl;
2224 if(pe) pe->NEW_DDIRCTriggerTime(rocid, slot, itrigger, t);
2225 }
2226 break;
2227 case 4: // Reserved
2228 case 5: // Reserved
2229 case 6: // Reserved
2230 case 10: // Reserved
2231 case 11: // Reserved
2232 case 12: // Reserved
2233 case 13: // Reserved
2234 if(VERBOSE>7) cout << " SSP/DIRC Reserved Word" << endl;
2235 break;
2236 case 7: // Device ID
2237 dev_id = ((*iptr)>>22) & 0x1F;
2238 ievent_cnt = ((*iptr)>>0 ) & 0x3FFFFF;
2239 if(VERBOSE>7) cout << " SSP/DIRC Device ID: dev_id=" << dev_id << " ievent_cnt=" << ievent_cnt << endl;
2240 break;
2241 case 8: // TDC Hit (single channel)
2242 {
2243 uint32_t edge = (*iptr>>26) & 0x01;
2244 uint32_t channel_fpga = (*iptr>>16) & 0xFF;
2245 uint32_t time = (*iptr>>0 ) & 0xFFFF;
2246 uint32_t channel = (dev_id<<8) + channel_fpga;
2247 if(VERBOSE>7) cout << " SSP/DIRC TDC Hit: edge=" << edge << "channel_fpga=" << channel_fpga << "time=" << time << " channel=" << channel << endl;
2248 if( pe ) pe->NEW_DDIRCTDCHit(rocid, slot, channel, itrigger, dev_id, ievent_cnt, channel_fpga, edge, time);
2249 }
2250 break;
2251 case 9: // ADC (64 channels, currently only used for bench testing and may not be supported by all firmware versions)
2252 {
2253 if(VERBOSE>7) cout << " SSP/DIRC ADC data"<<endl;
2254 uint32_t adc_hold2 = (*iptr>>16) & 0xFF;
2255 uint32_t adc_hold1 = (*iptr>>8 ) & 0xFF;
2256 uint32_t adc_max_bits = (*iptr>>4 ) & 0x0F;
2257 uint32_t maroc_id = (*iptr>>0 ) & 0x03;
2258 for(uint32_t i=0; i<32; i++){
2259 if(((*++iptr>>31) & 0x1) != 0){ iptr--; break;}
2260 uint32_t channel_lower = (dev_id<<8) + (maroc_id<<6) + (i*2 + 0); // ADC_LOWER
2261 uint32_t channel_upper = (dev_id<<8) + (maroc_id<<6) + (i*2 + 1); // ADC_UPPER
2262 uint32_t adc_lower = (*iptr>>0 ) & 0xFFF;
2263 uint32_t adc_upper = (*iptr>>16 ) & 0xFFF;
2264 switch(adc_max_bits){
2265 case 11:
2266 break;
2267 case 9:
2268 adc_lower >>= 2;
2269 adc_upper >>= 2;
2270 break;
2271 case 7:
2272 adc_lower >>= 4;
2273 adc_upper >>= 4;
2274 break;
2275 default:
2276 jerr << "Bad value for adc_max_bits (" << adc_max_bits << ") from SSP/DIRC with rocid=" << rocid << " slot=" << slot << "channel=" << channel_lower << "," << channel_upper << endl;
2277 break;
2278 }
2279 if( pe ) {
2280 pe->NEW_DDIRCADCHit(rocid, slot, channel_lower, itrigger, dev_id, ievent_cnt, adc_hold1, adc_hold2, adc_max_bits, maroc_id, adc_lower);
2281 pe->NEW_DDIRCADCHit(rocid, slot, channel_upper, itrigger, dev_id, ievent_cnt, adc_hold1, adc_hold2, adc_max_bits, maroc_id, adc_upper);
2282 }
2283 }
2284 }
2285 break;
2286 case 14: // Data not Valid
2287 if(VERBOSE>7) cout << " SSP/DIRC Data not Valid" << endl;
2288 break;
2289 case 15: // Filler Word
2290 if(VERBOSE>7) cout << " SSP/DIRC Filler Word" << endl;
2291 break;
2292 }
2293 }
2294
2295 iptr =iend;
2296}
2297
2298//----------------
2299// ParseGEMSRSBank
2300//----------------
2301void DEVIOWorkerThread::ParseDGEMSRSBank(uint32_t rocid, uint32_t* &iptr, uint32_t *iend)
2302{
2303 if(!PARSE_GEMSRS){ iptr = &iptr[(*iptr) + 1]; return; }
2304 if(VERBOSE>7) cout << "GEMSRS ROC " << rocid <<endl;
2305
2306 auto pe_iter = current_parsed_events.begin();
2307 DParsedEvent *pe = NULL__null;
2308
2309 // fictitious slot for TT, since SRS is a separate crate but read through ROC 76
2310 uint32_t slot = 24;
2311 uint32_t apv_id = 0xFFFFFFFF;
2312 uint32_t fec_id = 0xFFFFFFFF;
2313 uint32_t itrigger = 0xFFFFFFFF;
2314 //uint32_t ievent_cnt = 0xFFFFFFFF;
2315 //uint32_t last_itrigger = itrigger;
2316
2317 vector<int> rawData16bits;
2318
2319 iptr++; //skip first word? (no idata=0) used in GEMRawDecoder::Decode
2320
2321 while(true) { // while haven't reached event trailer
2322
2323 if(((*iptr>>8) & 0xffffff) == 0x414443) { // magic key for "Data Header" in ADC format
2324
2325 if(rawData16bits.size() > 0) {
2326 if(VERBOSE>7) cout<<"Previous channel: apv_id = "<<apv_id<<" fec_id = "<<fec_id<<" had "<<rawData16bits.size()<<" 16 bit words"<<endl;
2327
2328 if( pe ) MakeDGEMSRSWindowRawData(pe, rocid, slot, itrigger, apv_id, rawData16bits);
2329 }
2330 else { // for first APV in event initialize DParsedEvent
2331 pe = *pe_iter++;
2332 }
2333
2334 // initial word is "Data Header"
2335 apv_id = (*iptr) & 0xff; // equivalent to nadcCh in GEMRawDecoder::Decode
2336 iptr++; // next word is "Header Info" (reserved)
2337 fec_id = (*iptr>>16) & 0xff; // equivalent to nfecID in GEMRawDecoder::Decode
2338
2339 if(VERBOSE>7) cout<<"Data Header for APV = "<<apv_id<<" FEC = "<<fec_id<<endl;
2340
2341 // clear vector for raw data from this APV
2342 rawData16bits.clear();
2343 }
2344 else {
2345 unsigned int word32bit = *iptr;
2346 unsigned int word16bit1 = 0;
2347 unsigned int word16bit2 = 0;
2348
2349 unsigned int data1 = ( (word32bit)>>24 ) & 0xff;
2350 unsigned int data2 = ( (word32bit)>>16 ) & 0xff;
2351 unsigned int data3 = ( (word32bit)>>8 ) & 0xff;
2352 unsigned int data4 = (word32bit) & 0xff;
2353
2354 (word16bit1) = (data2 << 8) | data1;
2355 (word16bit2) = (data4 << 8) | data3;
2356 rawData16bits.push_back(word16bit1);
2357 rawData16bits.push_back(word16bit2);
2358 }
2359
2360 // trailer word (cleanup data from last APV?)
2361 if(*iptr == 0xfafafafa) {
2362
2363 // write last ADC channel out from rawData16bits vector
2364 if(rawData16bits.size() > 0) {
2365 if(VERBOSE>7) cout<<"Previous channel: apv_id = "<<apv_id<<" fec_id = "<<fec_id<<" had "<<rawData16bits.size()<<" 16 bit words"<<endl;
2366
2367 if( pe ) MakeDGEMSRSWindowRawData(pe, rocid, slot, itrigger, apv_id, rawData16bits);
2368 }
2369
2370 // reset DParsedEvent with event trailer?
2371 pe_iter = current_parsed_events.begin();
2372 pe = NULL__null;
2373 break;
2374 }
2375
2376 iptr++;
2377 }
2378
2379 iptr =iend;
2380}
2381
2382//-------------------------
2383// MakeDGEMSRSWindowRawData
2384//-------------------------
2385void DEVIOWorkerThread::MakeDGEMSRSWindowRawData(DParsedEvent *pe, uint32_t rocid, uint32_t slot, uint32_t itrigger, uint32_t apv_id, vector<int>rawData16bits)
2386{
2387 Int_t idata = 0, firstdata = 0, lastdata = 0;
2388 Int_t size = rawData16bits.size() ;
2389 vector<Float_t> rawDataTS, rawDataZS;
2390 rawDataTS.clear();
2391
2392 Int_t fAPVHeaderLevel = 1500;
2393 Int_t fNbOfTimeSamples = NSAMPLES_GEMSRS; // hard coded maximum number of time samples
2394
2395 uint8_t NCH = 128;
2396
2397 Int_t fStartData = 0;
2398 for(idata = 0; idata < size; idata++) {
2399 if (rawData16bits[idata] < fAPVHeaderLevel) {
2400 idata++ ;
2401 if (rawData16bits[idata] < fAPVHeaderLevel) {
2402 idata++ ;
2403 if (rawData16bits[idata] < fAPVHeaderLevel) {
2404 idata += 10;
2405 fStartData = idata ;
2406 idata = size ;
2407 }
2408 }
2409 }
2410 }
2411
2412 // set range for data
2413 firstdata = fStartData ;
2414 lastdata = firstdata + NCH;
2415
2416 ///////////////////////////////////////////////////////////////////////
2417 // loop over time bins and store samples in map for all APV channels //
2418 ///////////////////////////////////////////////////////////////////////
2419 //vector<uint16_t> windowDataAPV[NCH];
2420 std::shared_ptr< vector<uint16_t> > sptr_windowDataAPV( new vector<uint16_t>[NCH] );
2421 vector<uint16_t>* windowDataAPV = sptr_windowDataAPV.get();
2422 //for(int i=0; i<NCH; i++) windowDataAPV[i].resize(fNbOfTimeSamples);
2423
2424 for(Int_t timebin = 0; timebin < fNbOfTimeSamples; timebin++) {
2425 // EXTRACT APV25 DATA FOR A GIVEN TIME BIN
2426 rawDataTS.insert(rawDataTS.end(), &rawData16bits[firstdata], &rawData16bits[lastdata]);
2427 assert( rawDataTS.size() == 128 )((rawDataTS.size() == 128) ? static_cast<void> (0) : __assert_fail
("rawDataTS.size() == 128", "libraries/DAQ/DEVIOWorkerThread.cc"
, 2427, __PRETTY_FUNCTION__))
;
2428 for(Int_t chNo = 0; chNo < NCH; chNo++) {
2429 //windowDataAPV[chNo].at(timebin) = rawDataTS[chNo];
2430 windowDataAPV[chNo].push_back(rawDataTS[chNo]);
2431 }
2432
2433 firstdata = lastdata + 12 ;
2434 lastdata = firstdata + NCH;
2435 rawDataTS.clear() ;
2436
2437 // if next time sample beyond last word, break from loop
2438 if(lastdata > size) break;
2439 }
2440
2441 // write sample data to GEMSRS object
2442 for(int ichan=0; ichan<NCH; ichan++) {
2443 uint32_t channel = apv_id * 128 + ichan;
2444 DGEMSRSWindowRawData *windowRawData = pe->NEW_DGEMSRSWindowRawData(rocid, slot, channel, itrigger, apv_id, ichan);
2445 windowRawData->samples = windowDataAPV[ichan];
2446 }
2447}
2448
2449//----------------
2450// ParseDEventRFBunchBank
2451//----------------
2452void DEVIOWorkerThread::ParseDEventRFBunchBank(uint32_t* &iptr, uint32_t *iend)
2453{
2454 uint32_t Nwords = ((uint64_t)iend - (uint64_t)iptr)/sizeof(uint32_t);
2455 uint32_t Nwords_expected = 6;
2456 if(Nwords != Nwords_expected){
2457 _DBG_std::cerr<<"libraries/DAQ/DEVIOWorkerThread.cc"<<
":"<<2457<<" "
<< "RFTime size does not match expected!!" << endl;
2458 _DBG_std::cerr<<"libraries/DAQ/DEVIOWorkerThread.cc"<<
":"<<2458<<" "
<< "Found " << Nwords << " words. Expected " << Nwords_expected << endl;
2459 }else{
2460 DParsedEvent *pe = current_parsed_events.back();
2461 DEventRFBunch *the_rftime = pe->NEW_DEventRFBunch();
2462
2463 the_rftime->dTimeSource = static_cast<DetectorSystem_t>(*iptr++);
2464 the_rftime->dNumParticleVotes = *iptr++;
2465
2466 uint64_t in_word = *iptr++; // 1st word, lo word; 2nd word, hi word
2467 uint64_t in_word_hi = *iptr++;
2468 in_word |= in_word_hi<<32;
2469 double rftime;
2470 memcpy(&rftime, &in_word, sizeof(double));
2471 in_word = *iptr++; in_word_hi = *iptr++;
2472 in_word |= in_word_hi<<32;
2473 double rftime_var;
2474 memcpy(&rftime_var, &in_word, sizeof(double));
2475
2476 the_rftime->dTime = rftime;
2477 the_rftime->dTimeVariance = rftime_var;
2478 }
2479}
2480
2481
2482//----------------
2483// ParseDVertexBank
2484//----------------
2485void DEVIOWorkerThread::ParseDVertexBank(uint32_t* &iptr, uint32_t *iend)
2486{
2487 uint32_t Nwords = ((uint64_t)iend - (uint64_t)iptr)/sizeof(uint32_t);
2488 uint32_t Nwords_expected = 11;
2489 if(Nwords != Nwords_expected){
2490 _DBG_std::cerr<<"libraries/DAQ/DEVIOWorkerThread.cc"<<
":"<<2490<<" "
<< "DVertex size does not match expected!!" << endl;
2491 _DBG_std::cerr<<"libraries/DAQ/DEVIOWorkerThread.cc"<<
":"<<2491<<" "
<< "Found " << Nwords << " words. Expected " << Nwords_expected << endl;
2492 }else{
2493 DParsedEvent *pe = current_parsed_events.back();
2494 DVertex *the_vertex = pe->NEW_DVertex();
2495
2496 uint64_t in_word = *iptr++; // 1st word, lo word; 2nd word, hi word
2497 uint64_t in_word_hi = *iptr++;
2498 in_word |= in_word_hi<<32;
2499 //uint64_t hi_word = *iptr++;
2500 double vertex_x_pos;
2501 memcpy(&vertex_x_pos, &in_word, sizeof(double));
2502 in_word = *iptr++; in_word_hi = *iptr++;
2503 in_word |= in_word_hi<<32;
2504 double vertex_y_pos;
2505 memcpy(&vertex_y_pos, &in_word, sizeof(double));
2506 in_word = *iptr++; in_word_hi = *iptr++;
2507 in_word |= in_word_hi<<32;
2508 double vertex_z_pos;
2509 memcpy(&vertex_z_pos, &in_word, sizeof(double));
2510 in_word = *iptr++; in_word_hi = *iptr++;
2511 in_word |= in_word_hi<<32;
2512 double vertex_t;
2513 memcpy(&vertex_t, &in_word, sizeof(double));
2514
2515 DVector3 vertex_position(vertex_x_pos, vertex_y_pos, vertex_z_pos);
2516 the_vertex->dSpacetimeVertex = DLorentzVector(vertex_position, vertex_t);
2517 the_vertex->dKinFitNDF = *iptr++;
2518
2519 in_word = *iptr++; in_word_hi = *iptr++;
2520 in_word |= in_word_hi<<32;
2521 memcpy(&(the_vertex->dKinFitChiSq), &in_word, sizeof(double));
2522 }
2523}
2524
2525
2526//----------------
2527// LinkAllAssociations
2528//----------------
2529void DEVIOWorkerThread::LinkAllAssociations(void)
2530{
2531
2532 /// Find objects that should be linked as "associated objects"
2533 /// of one another and add to each other's list.
2534 for( auto pe : current_parsed_events){
2535
2536 //----------------- Sort hit objects
2537
2538 // fADC250 (n.b. Df250PulseData values overwritten in JEventSource_EVIOpp::LinkBORassociations)
2539 if(pe->vDf250PulseData.size()>1 ) sort(pe->vDf250PulseData.begin(), pe->vDf250PulseData.end(), SortByPulseNumber<Df250PulseData> );
2540 if(pe->vDf250PulseIntegral.size()>1) sort(pe->vDf250PulseIntegral.begin(), pe->vDf250PulseIntegral.end(), SortByPulseNumber<Df250PulseIntegral> );
2541 if(pe->vDf250PulseTime.size()>1 ) sort(pe->vDf250PulseTime.begin(), pe->vDf250PulseTime.end(), SortByPulseNumber<Df250PulseTime> );
2542 if(pe->vDf250PulsePedestal.size()>1) sort(pe->vDf250PulsePedestal.begin(), pe->vDf250PulsePedestal.end(), SortByPulseNumber<Df250PulsePedestal> );
2543 if(pe->vDf250WindowRawData.size()>1) sort(pe->vDf250WindowRawData.begin(), pe->vDf250WindowRawData.end(), SortByChannel<Df250WindowRawData> );
2544
2545 // fADC125
2546 if(pe->vDf125PulseIntegral.size()>1) sort(pe->vDf125PulseIntegral.begin(), pe->vDf125PulseIntegral.end(), SortByPulseNumber<Df125PulseIntegral> );
2547 if(pe->vDf125CDCPulse.size()>1 ) sort(pe->vDf125CDCPulse.begin(), pe->vDf125CDCPulse.end(), SortByChannel<Df125CDCPulse> );
2548 if(pe->vDf125FDCPulse.size()>1 ) sort(pe->vDf125FDCPulse.begin(), pe->vDf125FDCPulse.end(), SortByChannel<Df125FDCPulse> );
2549 if(pe->vDf125PulseTime.size()>1 ) sort(pe->vDf125PulseTime.begin(), pe->vDf125PulseTime.end(), SortByPulseNumber<Df125PulseTime> );
2550 if(pe->vDf125PulsePedestal.size()>1) sort(pe->vDf125PulsePedestal.begin(), pe->vDf125PulsePedestal.end(), SortByPulseNumber<Df125PulsePedestal> );
2551 if(pe->vDf125WindowRawData.size()>1) sort(pe->vDf125WindowRawData.begin(), pe->vDf125WindowRawData.end(), SortByChannel<Df125WindowRawData> );
2552
2553 // F1TDC
2554 if(pe->vDF1TDCHit.size()>1 ) sort(pe->vDF1TDCHit.begin(), pe->vDF1TDCHit.end(), SortByModule<DF1TDCHit> );
2555
2556 // CAEN1290TDC
2557 if(pe->vDCAEN1290TDCHit.size()>1 ) sort(pe->vDCAEN1290TDCHit.begin(), pe->vDCAEN1290TDCHit.end(), SortByModule<DCAEN1290TDCHit> );
2558
2559
2560 //----------------- Link hit objects
2561
2562 // Connect Df250 pulse objects
2563 LinkPulse(pe->vDf250PulseTime, pe->vDf250PulseIntegral);
2564 LinkPulsePedCopy(pe->vDf250PulsePedestal, pe->vDf250PulseIntegral);
2565
2566 // Connect Df125 pulse objects
2567 LinkPulse(pe->vDf125PulseTime, pe->vDf125PulseIntegral);
2568 LinkPulsePedCopy(pe->vDf125PulsePedestal, pe->vDf125PulseIntegral);
2569
2570 // Connect Df250 window raw data objects
2571 if(!pe->vDf250WindowRawData.empty()){
2572 LinkConfig(pe->vDf250Config, pe->vDf250WindowRawData);
2573 LinkModule(pe->vDf250TriggerTime, pe->vDf250WindowRawData);
2574 LinkChannel(pe->vDf250WindowRawData, pe->vDf250PulseIntegral);
2575 LinkChannel(pe->vDf250WindowRawData, pe->vDf250PulseTime);
2576 LinkChannel(pe->vDf250WindowRawData, pe->vDf250PulsePedestal);
2577 LinkChannel(pe->vDf250WindowRawData, pe->vDf250PulseData);
2578 }
2579
2580 // Connect Df125 window raw data objects
2581 if(!pe->vDf125WindowRawData.empty()){
2582 LinkConfig(pe->vDf125Config, pe->vDf125WindowRawData);
2583 LinkModule(pe->vDf125TriggerTime, pe->vDf125WindowRawData);
2584 LinkChannel(pe->vDf125WindowRawData, pe->vDf125PulseIntegral);
2585 LinkChannel(pe->vDf125WindowRawData, pe->vDf125PulseTime);
2586 LinkChannel(pe->vDf125WindowRawData, pe->vDf125PulsePedestal);
2587 LinkChannel(pe->vDf125WindowRawData, pe->vDf125CDCPulse);
2588 LinkChannel(pe->vDf125WindowRawData, pe->vDf125FDCPulse);
2589 }
2590
2591 //----------------- Optionally link config objects (on by default)
2592 if(LINK_CONFIG){
2593 if(pe->vDf250Config.size()>1 ) sort(pe->vDf250Config.begin(), pe->vDf250Config.end(), SortByROCID<Df250Config> );
2594 if(pe->vDf125Config.size()>1 ) sort(pe->vDf125Config.begin(), pe->vDf125Config.end(), SortByROCID<Df125Config> );
2595 if(pe->vDF1TDCConfig.size()>1 ) sort(pe->vDF1TDCConfig.begin(), pe->vDF1TDCConfig.end(), SortByROCID<DF1TDCConfig> );
2596 if(pe->vDCAEN1290TDCConfig.size()>1) sort(pe->vDCAEN1290TDCConfig.begin(), pe->vDCAEN1290TDCConfig.end(), SortByROCID<DCAEN1290TDCConfig> );
2597
2598 LinkConfigSamplesCopy(pe->vDf250Config, pe->vDf250PulseIntegral);
2599 LinkConfigSamplesCopy(pe->vDf250Config, pe->vDf250PulseData);
2600 LinkConfigSamplesCopy(pe->vDf125Config, pe->vDf125PulseIntegral);
2601 LinkConfigSamplesCopy(pe->vDf125Config, pe->vDf125CDCPulse);
2602 LinkConfigSamplesCopy(pe->vDf125Config, pe->vDf125FDCPulse);
2603 LinkConfig(pe->vDF1TDCConfig, pe->vDF1TDCHit);
2604 LinkConfig(pe->vDCAEN1290TDCConfig, pe->vDCAEN1290TDCHit);
2605 }
2606
2607 //----------------- Optionally link trigger time objects (off by default)
2608 if(LINK_TRIGGERTIME){
2609 if(pe->vDf250TriggerTime.size()>1 ) sort(pe->vDf250TriggerTime.begin(), pe->vDf250TriggerTime.end(), SortByModule<Df250TriggerTime> );
2610 if(pe->vDf125TriggerTime.size()>1 ) sort(pe->vDf125TriggerTime.begin(), pe->vDf125TriggerTime.end(), SortByModule<Df125TriggerTime> );
2611 if(pe->vDF1TDCTriggerTime.size()>1 ) sort(pe->vDF1TDCTriggerTime.begin(), pe->vDF1TDCTriggerTime.end(), SortByModule<DF1TDCTriggerTime> );
2612
2613 LinkModule(pe->vDf250TriggerTime, pe->vDf250PulseIntegral);
2614 LinkModule(pe->vDf125TriggerTime, pe->vDf125PulseIntegral);
2615 LinkModule(pe->vDf125TriggerTime, pe->vDf125CDCPulse);
2616 LinkModule(pe->vDf125TriggerTime, pe->vDf125FDCPulse);
2617 LinkModule(pe->vDF1TDCTriggerTime, pe->vDF1TDCHit);
2618 }
2619 }
2620
2621}
2622
2623//----------------
2624// DumpBinary
2625//----------------
2626void DEVIOWorkerThread::DumpBinary(const uint32_t *iptr, const uint32_t *iend, uint32_t MaxWords, const uint32_t *imark)
2627{
2628 /// This is used for debugging. It will print to the screen the words
2629 /// starting at the address given by iptr and ending just before iend
2630 /// or for MaxWords words, whichever comes first. If iend is NULL,
2631 /// then MaxWords will be printed. If MaxWords is zero then it is ignored
2632 /// and only iend is checked. If both iend==NULL and MaxWords==0, then
2633 /// only the word at iptr is printed.
2634
2635 cout << "Dumping binary: istart=" << hex << iptr << " iend=" << iend << " MaxWords=" << dec << MaxWords << endl;
2636
2637 if(iend==NULL__null && MaxWords==0) MaxWords=1;
2638 if(MaxWords==0) MaxWords = (uint32_t)0xffffffff;
2639
2640 uint32_t Nwords=0;
2641 while(iptr!=iend && Nwords<MaxWords){
2642
2643 // line1 is hex and line2 is decimal
2644 stringstream line1, line2;
2645
2646 // print words in columns 8 words wide. First part is
2647 // reserved for word number
2648 uint32_t Ncols = 8;
2649 line1 << setw(5) << Nwords;
2650 line2 << string(5, ' ');
2651
2652 // Loop over columns
2653 for(uint32_t i=0; i<Ncols; i++, iptr++, Nwords++){
2654
2655 if(iptr == iend) break;
2656 if(Nwords>=MaxWords) break;
2657
2658 stringstream iptr_hex;
2659 iptr_hex << hex << "0x" << *iptr;
2660
2661 string mark = (iptr==imark ? "*":" ");
2662
2663 line1 << setw(12) << iptr_hex.str() << mark;
2664 line2 << setw(12) << *iptr << mark;
2665 }
2666
2667 cout << line1.str() << endl;
2668 cout << line2.str() << endl;
2669 cout << endl;
2670 }
2671}
2672
2673