Bug Summary

File:libraries/DAQ/DEVIOWorkerThread.cc
Location:line 1215, column 31
Description:Called C++ object pointer is null

Annotated Source Code

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
16using namespace std;
17using namespace std::chrono;
18
19
20
21//---------------------------------
22// DEVIOWorkerThread (Constructor)
23//---------------------------------
24DEVIOWorkerThread::DEVIOWorkerThread(
25 JEventSource_EVIOpp *event_source
26 ,list<DParsedEvent*> &parsed_events
27 ,uint32_t &MAX_PARSED_EVENTS
28 ,mutex &PARSED_EVENTS_MUTEX
29 ,condition_variable &PARSED_EVENTS_CV
30 ):
31 event_source(event_source)
32 ,parsed_events(parsed_events)
33 ,MAX_PARSED_EVENTS(MAX_PARSED_EVENTS)
34 ,PARSED_EVENTS_MUTEX(PARSED_EVENTS_MUTEX)
35 ,PARSED_EVENTS_CV(PARSED_EVENTS_CV)
36 ,done(false)
37 ,thd(&DEVIOWorkerThread::Run,this)
38{
39 // n.b. in principal, the worker thread is started when the
40 // above constructor is hit and so may already be in Run()
41 // before executing anything below. The "done" variable is
42 // therefore initialized first to guarantee that if that
43 // happens, it gets to the cv.wait() call where it will wait
44 // for someone to notify it. That won't happen before this
45 // constructor completes so we do the remaining initializations
46 // below.
47
48 VERBOSE = 1;
49 Nrecycled = 0; // Incremented in JEventSource_EVIOpp::Dispatcher()
50 MAX_EVENT_RECYCLES = 1000; // In EVIO events (not L1 trigger events!) overwritten in JEventSource_EVIOpp constructor
51 MAX_OBJECT_RECYCLES = 1000; // overwritten in JEventSource_EVIOpp constructor
52 run_number_seed = 0; // Set in JEventSource_EVIOpp constructor
53
54 in_use = false;
55 jobtype = JOB_NONE;
56
57 buff_len = 100; // this will grow as needed
58 buff = new uint32_t[buff_len];
59
60 PARSE_F250 = true;
61 PARSE_F125 = true;
62 PARSE_F1TDC = true;
63 PARSE_CAEN1290TDC = true;
64 PARSE_CONFIG = true;
65 PARSE_BOR = true;
66 PARSE_EPICS = true;
67 PARSE_EVENTTAG = true;
68 PARSE_TRIGGER = true;
69
70}
71
72//---------------------------------
73// ~DEVIOWorkerThread (Destructor)
74//---------------------------------
75DEVIOWorkerThread::~DEVIOWorkerThread()
76{
77 if(buff) delete[] buff;
78 for(auto pe : parsed_event_pool) delete pe;
79}
80
81//---------------------------------
82// Run
83//---------------------------------
84void DEVIOWorkerThread::Run(void)
85{
86 unique_lock<std::mutex> lck(mtx);
87
88 // Loop waiting for jobs or until told to quit
89 while(!done){
90
91 cv.wait_for(lck, std::chrono::milliseconds(1));
92
93 // In principle, in_use should never be false with a jobtype!=JOB_NONE
94 // In practice, this has happened, possibly due to compiler optimization
95 // reordering things in JEventSource_EVIOpp::Dispatcher. That led to
96 // attempting to process a buffer that was being written to. Avoid that
97 // condition by checking the in_use flag is really set.
98 if( !in_use ) continue;
99
100 try {
101
102 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 );
103
104 if( jobtype & JOB_FULL_PARSE ) MakeEvents();
105
106 if( jobtype & JOB_ASSOCIATE ) LinkAllAssociations();
107
108 if( !current_parsed_events.empty() ) PublishEvents();
109
110 } catch (exception &e) {
111 jerr << e.what() << endl;
112 for(auto pe : parsed_event_pool) delete pe; // delete all parsed events any any objects they hold
113 parsed_event_pool.clear();
114 current_parsed_events.clear(); // (these are also in parsed_event_pool so were already deleted)
115 //exit(-1);
116 }
117
118 // Reset and mark us as available for use
119 jobtype = JOB_NONE;
120 in_use = false;
121
122 if( jobtype & JOB_QUIT ) break;
123 }
124
125 in_use = false;
126}
127
128//---------------------------------
129// Finish
130//---------------------------------
131void DEVIOWorkerThread::Finish(bool wait_to_complete)
132{
133 /// Set the done flag so that the worker thread
134 /// will exit once it is done processing its current
135 /// job. The thread is notified to wake up in case
136 /// it is currently idle. If the wait_to_complete
137 /// flag is set (default), then the worker thread is
138 /// joined to guarantee the current job's processing
139 /// is completed before returning.
140 done = true;
141 cv.notify_all();
142 if(wait_to_complete) {
143 thd.join();
144 } else {
145 thd.detach();
146 }
147}
148
149//---------------------------------
150// Prune
151//---------------------------------
152void DEVIOWorkerThread::Prune(void)
153{
154 /// Delete any DParsedEvent objects not currently in use.
155 /// If the DParsedEvent object pool and their internal
156 /// hit object pools are allowed to continuously grow, it
157 /// will appear as a though there is a memory leak. Occasional
158 /// pruning will reduce the average memory footprint.
159 /// This is called from MakeEvents() every MAX_EVENT_RECYCLES
160 /// EVIO events processed by this worker thread.
161 /// Note that this is in EVIO events (i.e. possibly a block
162 /// of events) not in L1 trigger events.
163 ///
164 /// NOTE: We currently do NOT reduce the size of buff
165 /// here if it is too big. We may wish to do that at some point!
166
167 // Delete extra parsed events
168 vector<DParsedEvent*> tmp_events = parsed_event_pool;
169 parsed_event_pool.clear();
170 for(auto pe : tmp_events) {
171 if(pe->in_use)
172 parsed_event_pool.push_back(pe);
173 else
174 delete pe;
175
176 }
177}
178
179//---------------------------------
180// MakeEvents
181//---------------------------------
182void DEVIOWorkerThread::MakeEvents(void)
183{
184
185 /// Make DParsedEvent objects from data currently in buff.
186 /// This will look at the begining of the EVIO event to see
187 /// how many L1 events are in it. It will then grab that many
188 /// DParsedEvent objects from this threads pool , or create
189 /// new ones and add them all to the current_parsed_events
190 /// vector. These are then filled out later as the data is
191 /// parsed.
192
193 if(!current_parsed_events.empty()) throw JException("Attempting call to DEVIOWorkerThread::MakeEvents when current_parsed_events not empty!!", __FILE__"libraries/DAQ/DEVIOWorkerThread.cc", __LINE__193);
194
195 uint32_t *iptr = buff;
196
197 uint32_t M = 1;
198 uint64_t event_num = 0;
199
200 iptr++;
201 uint32_t mask = 0xFF001000;
202 if( ((*iptr)&mask) == mask ){
203 // Physics event
204 M = *(iptr)&0xFF;
205 uint64_t eventnum_lo = iptr[4];
206 uint64_t eventnum_hi = iptr[5];
207 event_num = (eventnum_hi<<32) + (eventnum_lo);
208 }
209
210 // Try and get M DParsedEvent objects from this thread's pool.
211 for(auto pe : parsed_event_pool){
212 if(pe->in_use) continue;
213 current_parsed_events.push_back(pe);
214 if( current_parsed_events.size() >= M ) break;
215 }
216
217 // Create new DParsedEvent objects if needed
218 while( current_parsed_events.size() < M ){
219 DParsedEvent *pe = new DParsedEvent(MAX_OBJECT_RECYCLES);
220 current_parsed_events.push_back(pe);
221 parsed_event_pool.push_back(pe);
222 }
223
224 // Set indexes for the parsed event objects
225 // and flag them as being in use.
226 for(auto pe : current_parsed_events){
227
228 pe->Clear(); // return previous event's objects to pools and clear vectors
229 pe->istreamorder = istreamorder;
230 pe->run_number = run_number_seed;
231 pe->event_number = event_num++;
232 pe->sync_flag = false;
233 pe->in_use = true;
234 pe->copied_to_factories = false;
235 pe->event_status_bits = 0;
236 pe->borptrs = NULL__null; // may be set by either ParseBORbank or JEventSource_EVIOpp::GetEvent
237 }
238
239 // Parse data in buffer to create data objects
240 ParseBank();
241
242 // Occasionally prune extra DParsedEvent objects as well as objects
243 // from the existing pools to reduce average memory usage. We do
244 // this after parsing so that not everything is deleted (objects
245 // being used this event will be returned to the pools later.)
246 if(++Nrecycled%MAX_EVENT_RECYCLES == 0) Prune();
247 for(auto pe : current_parsed_events){
248 if( ++pe->Nrecycled%pe->MAX_RECYCLES == 0) pe->Prune();
249 }
250}
251
252//---------------------------------
253// PublishEvents
254//---------------------------------
255void DEVIOWorkerThread::PublishEvents(void)
256{
257 /// Copy our "current_parsed_events" pointers into the global "parsed_events"
258 /// list making them available for consumption.
259
260 // Lock mutex so other threads can't modify parsed_events
261 unique_lock<mutex> lck(PARSED_EVENTS_MUTEX);
262
263 // Make sure we don't exceed the maximum number of simultaneous
264 // parsed events. If the done flag is set, go ahead and add
265 // this regardless
266 while( ((current_parsed_events.size()+parsed_events.size())>=MAX_PARSED_EVENTS) && !done ){
267 PARSED_EVENTS_CV.wait_for(lck, std::chrono::milliseconds(1));
268 }
269
270 // Loop over all elements of parsed_events and insert
271 // these based on istreamorder so that the front element
272 // is the most recent.
273 bool inserted = false;
274 for(auto it = parsed_events.begin(); it!=parsed_events.end(); it++){
275 if( istreamorder < (*it)->istreamorder ){
276 parsed_events.insert(it, current_parsed_events.begin(), current_parsed_events.end());
277 inserted = true;
278 break;
279 }
280 }
281
282 // In case this should go at end of list
283 if(!inserted) parsed_events.insert(parsed_events.end(), current_parsed_events.begin(), current_parsed_events.end());
284
285 lck.unlock();
286 PARSED_EVENTS_CV.notify_all();
287
288 // Any events should now be published
289 current_parsed_events.clear();
290}
291
292//---------------------------------
293// ParseBank
294//---------------------------------
295void DEVIOWorkerThread::ParseBank(void)
296{
297
298 uint32_t *iptr = buff;
299 uint32_t *iend = &buff[buff[0]+1];
300
301 while(iptr < iend){
302 uint32_t event_len = iptr[0];
303 uint32_t event_head = iptr[1];
304 uint32_t tag = (event_head >> 16) & 0xFFFF;
305
306//_DBG_ << "tag=" << hex << tag << dec << endl;
307
308 switch(tag){
309 case 0x0056: ParseEventTagBank(iptr, iend); break;
310 case 0x0060: ParseEPICSbank(iptr, iend); break;
311 case 0x0070: ParseBORbank(iptr, iend); break;
312
313 case 0xFFD0:
314 case 0xFFD1:
315 case 0xFFD2:
316 case 0xFFD3: ParseControlEvent(iptr, iend); break;
317
318 case 0xFF58:
319 case 0xFF78: current_parsed_events.back()->sync_flag = true;
320 case 0xFF50:
321 case 0xFF70: ParsePhysicsBank(iptr, iend); break;
322
323 default:
324 _DBG_std::cerr<<"libraries/DAQ/DEVIOWorkerThread.cc"<<
":"<<324<<" "
<< "Unknown outer EVIO bank tag: " << hex << tag << dec << endl;
325 iptr = &iptr[event_len+1];
326 if(event_len<1) iptr = iend;
327 }
328 }
329}
330
331//---------------------------------
332// ParseEventTagBank
333//---------------------------------
334void DEVIOWorkerThread::ParseEventTagBank(uint32_t* &iptr, uint32_t *iend)
335{
336 iptr = &iptr[(*iptr) + 1];
337}
338
339//---------------------------------
340// ParseEPICSbank
341//---------------------------------
342void DEVIOWorkerThread::ParseEPICSbank(uint32_t* &iptr, uint32_t *iend)
343{
344 if(!PARSE_EPICS){ iptr = iend; return; }
345
346 time_t timestamp=0;
347
348 // Outer bank
349 uint32_t *istart = iptr;
350 uint32_t epics_bank_len = *iptr++;
351 if(epics_bank_len < 1){
352 _DBG_std::cerr<<"libraries/DAQ/DEVIOWorkerThread.cc"<<
":"<<352<<" "
<< "bank_len<1 in EPICS event!" << endl;
353 iptr = iend;
354 return;
355 }
356
357 uint32_t *iend_epics = &iptr[epics_bank_len];
358 if( iend_epics < iend ) iend = iend_epics;
359
360 // Advance to first daughter bank
361 iptr++;
362
363 // Get pointer to first DParsedEvent
364 DParsedEvent *pe = current_parsed_events.front();
365 pe->event_status_bits |= (1<<kSTATUS_EPICS_EVENT);
366
367 // Loop over daughter banks
368 while( iptr < iend_epics ){
369
370 uint32_t bank_len = (*iptr)&0xFFFF;
371 uint32_t tag = ((*iptr)>>24)&0xFF;
372 iptr++;
373
374 if(tag == 0x61){
375 // timestamp bank
376 timestamp = *iptr;
377 }else if(tag == 0x62){
378 // EPICS data value
379 string nameval = (const char*)iptr;
380 pe->NEW_DEPICSvalue(timestamp, nameval);
381 }else{
382 // Unknown tag. Bail
383 _DBG_std::cerr<<"libraries/DAQ/DEVIOWorkerThread.cc"<<
":"<<383<<" "
<< "Unknown tag 0x" << hex << tag << dec << " in EPICS event!" <<endl;
384 DumpBinary(istart, iend_epics, 32, &iptr[-1]);
385 }
386
387 iptr = &iptr[bank_len];
388 }
389
390 iptr = iend_epics;
391}
392
393//---------------------------------
394// ParseBORbank
395//---------------------------------
396void DEVIOWorkerThread::ParseBORbank(uint32_t* &iptr, uint32_t *iend)
397{
398 /// Create BOR config objects from the EVIO bank and store them in
399 /// the event (should only be one since BOR events are not entangled).
400 /// These objects will eventually be inherited by the JEventSource_EVIOpp
401 /// object and passed to all subsequent events.
402
403 // Upon entry, iptr should point to length word of a bank of banks with tag=0x70
404 // indicating BOR event. Each bank contained within will represent one crate and
405 // will be a bank with tag=0x71 and num the rocid, containing tagsegments. Each tagsegment
406 // represents a single module with the tag containing the module type (bits 0-4) and
407 // slot (bits 5-10). The data in the tagsegments is uint32_t and maps to a data
408 // structure in bor_roc.h depending on the module type. Below is a summary of
409 // how this looks in memory:
410 //
411 // BOR event length
412 // BOR header
413 // crate bank length
414 // crate header
415 // module bank len/header
416 // module data ...
417 // module bank len/header
418 // module data ...
419 // ...
420 // crate bank length
421 // crate header
422 // ...
423
424 if(!PARSE_BOR){ iptr = &iptr[(*iptr) + 1]; return; }
425
426 // Make sure there is exactly 1 event in current_parsed_events
427 if(current_parsed_events.size() != 1){
428 stringstream ss;
429 ss << "DEVIOWorkerThread::ParseBORbank called for EVIO event with " << current_parsed_events.size() << " events in it. (Should be exactly 1!)";
430 throw JException(ss.str(), __FILE__"libraries/DAQ/DEVIOWorkerThread.cc", __LINE__430);
431 }
432
433 // Create new DBORptrs object and set pointer to it in DParsedEvent
434 // (see JEventSource_EVIOpp::GetEvent)
435 DParsedEvent *pe = current_parsed_events.front();
436 pe->event_status_bits |= (1<<kSTATUS_BOR_EVENT);
437 pe->borptrs = new DBORptrs();
438 DBORptrs* &borptrs = pe->borptrs;
439
440 // Make sure we have full event
441 uint32_t borevent_len = *iptr++;
442 uint32_t bank_len = (uint32_t)((uint64_t)iend - (uint64_t)iptr)/sizeof(uint32_t);
443 if(borevent_len > bank_len){
444 stringstream ss;
445 ss << "BOR: Size of bank doesn't match amount of data given (" << borevent_len << " > " << bank_len << ")";
446 throw JException(ss.str(), __FILE__"libraries/DAQ/DEVIOWorkerThread.cc", __LINE__446);
447 }
448 iend = &iptr[borevent_len]; // in case they give us too much data!
449
450 // Make sure BOR header word is right
451 uint32_t bor_header = *iptr++;
452 if(bor_header != 0x700e01){
453 stringstream ss;
454 ss << "Bad BOR header: 0x" << hex << bor_header;
455 throw JException(ss.str(), __FILE__"libraries/DAQ/DEVIOWorkerThread.cc", __LINE__455);
456 }
457
458 // Loop over crates
459 while(iptr<iend){
460 uint32_t crate_len = *iptr++;
461 uint32_t *iend_crate = &iptr[crate_len]; // points to first word after this crate
462 uint32_t crate_header = *iptr++;
463// uint32_t rocid = crate_header&0xFF;
464
465 // Make sure crate tag is right
466 if( (crate_header>>16) != 0x71 ){
467 stringstream ss;
468 ss << "Bad BOR crate header: 0x" << hex << (crate_header>>16);
469 throw JException(ss.str(), __FILE__"libraries/DAQ/DEVIOWorkerThread.cc", __LINE__469);
470 }
471
472 // Loop over modules
473 while(iptr<iend_crate){
474 uint32_t module_header = *iptr++;
475 uint32_t module_len = module_header&0xFFFF;
476 uint32_t modType = (module_header>>20)&0x1f;
477// uint32_t slot = (module_header>>25);
478// uint32_t *iend_module = &iptr[module_len]; // points to first word after this module
479
480 uint32_t *src = iptr;
481 uint32_t *dest = NULL__null;
482 uint32_t sizeof_dest = 0;
483
484 Df250BORConfig *f250conf = NULL__null;
485 Df125BORConfig *f125conf = NULL__null;
486 DF1TDCBORConfig *F1TDCconf = NULL__null;
487 DCAEN1290TDCBORConfig *caen1190conf = NULL__null;
488
489 switch(modType){
490 case DModuleType::FADC250: // f250
491 f250conf = new Df250BORConfig;
492 dest = (uint32_t*)&f250conf->rocid;
493 sizeof_dest = sizeof(f250config);
494 break;
495 case DModuleType::FADC125: // f125
496 f125conf = new Df125BORConfig;
497 dest = (uint32_t*)&f125conf->rocid;
498 sizeof_dest = sizeof(f125config);
499 break;
500
501 case DModuleType::F1TDC32: // F1TDCv2
502 case DModuleType::F1TDC48: // F1TDCv3
503 F1TDCconf = new DF1TDCBORConfig;
504 dest = (uint32_t*)&F1TDCconf->rocid;
505 sizeof_dest = sizeof(F1TDCconfig);
506 break;
507
508 case DModuleType::CAEN1190: // CAEN 1190 TDC
509 case DModuleType::CAEN1290: // CAEN 1290 TDC
510 caen1190conf = new DCAEN1290TDCBORConfig;
511 dest = (uint32_t*)&caen1190conf->rocid;
512 sizeof_dest = sizeof(caen1190config);
513 break;
514
515 default:
516 {
517 stringstream ss;
518 ss << "Unknown BOR module type: " << modType << " (module_header=0x"<<hex<<module_header<<")";
519 jerr << ss.str() << endl;
520 throw JException(ss.str(), __FILE__"libraries/DAQ/DEVIOWorkerThread.cc", __LINE__520);
521 }
522 }
523
524 // Check that the bank size and data structure size match.
525 if( module_len != (sizeof_dest/sizeof(uint32_t)) ){
526 stringstream ss;
527 ss << "BOR module bank size does not match structure! " << module_len << " != " << (sizeof_dest/sizeof(uint32_t)) << " for modType " << modType;
528 throw JException(ss.str(), __FILE__"libraries/DAQ/DEVIOWorkerThread.cc", __LINE__528);
529 }
530
531 // Copy bank data, assuming format is the same
532 for(uint32_t i=0; i<module_len; i++) *dest++ = *src++;
533
534 // Store object for use in this and subsequent events
535 if(f250conf ) borptrs->vDf250BORConfig.push_back(f250conf);
536 if(f125conf ) borptrs->vDf125BORConfig.push_back(f125conf);
537 if(F1TDCconf ) borptrs->vDF1TDCBORConfig.push_back(F1TDCconf);
538 if(caen1190conf) borptrs->vDCAEN1290TDCBORConfig.push_back(caen1190conf);
539
540 iptr = &iptr[module_len];
541 }
542
543 iptr = iend_crate; // ensure we're pointing past this crate
544 }
545
546 // Sort the BOR config events now so we don't have to do it for every event
547 borptrs->Sort();
548
549}
550
551//---------------------------------
552// ParseTSscalerBank
553//---------------------------------
554void DEVIOWorkerThread::ParseTSscalerBank(uint32_t* &iptr, uint32_t *iend)
555{
556 iptr = &iptr[(*iptr) + 1];
557}
558
559//---------------------------------
560// Parsef250scalerBank
561//---------------------------------
562void DEVIOWorkerThread::Parsef250scalerBank(uint32_t* &iptr, uint32_t *iend)
563{
564 iptr = &iptr[(*iptr) + 1];
565}
566
567//---------------------------------
568// ParseControlEvent
569//---------------------------------
570void DEVIOWorkerThread::ParseControlEvent(uint32_t* &iptr, uint32_t *iend)
571{
572 for(auto pe : current_parsed_events) pe->event_status_bits |= (1<<kSTATUS_CONTROL_EVENT);
573
574 iptr = &iptr[(*iptr) + 1];
575}
576
577//---------------------------------
578// ParsePhysicsBank
579//---------------------------------
580void DEVIOWorkerThread::ParsePhysicsBank(uint32_t* &iptr, uint32_t *iend)
581{
582
583 for(auto pe : current_parsed_events) pe->event_status_bits |= (1<<kSTATUS_PHYSICS_EVENT);
584
585 uint32_t physics_event_len = *iptr++;
586 uint32_t *iend_physics_event = &iptr[physics_event_len];
587 iptr++;
588
589 // Built Trigger Bank
590 uint32_t built_trigger_bank_len = *iptr;
591 uint32_t *iend_built_trigger_bank = &iptr[built_trigger_bank_len+1];
592 ParseBuiltTriggerBank(iptr, iend_built_trigger_bank);
593 iptr = iend_built_trigger_bank;
594
595 // Loop over Data banks
596 while( iptr < iend_physics_event ) {
597
598 uint32_t data_bank_len = *iptr;
599 uint32_t *iend_data_bank = &iptr[data_bank_len+1];
600
601 ParseDataBank(iptr, iend_data_bank);
602
603 iptr = iend_data_bank;
604 }
605
606 iptr = iend_physics_event;
607}
608
609//---------------------------------
610// ParseBuiltTriggerBank
611//---------------------------------
612void DEVIOWorkerThread::ParseBuiltTriggerBank(uint32_t* &iptr, uint32_t *iend)
613{
614 if(!PARSE_TRIGGER) return;
615
616 iptr++; // advance past length word
617 uint32_t mask = 0xFF202000;
618 if( ((*iptr) & mask) != mask ){
619 stringstream ss;
620 ss << "Bad header word in Built Trigger Bank: " << hex << *iptr;
621 throw JException(ss.str(), __FILE__"libraries/DAQ/DEVIOWorkerThread.cc", __LINE__621);
622 }
623
624 uint32_t tag = (*iptr)>>16; // 0xFF2X
625 uint32_t Nrocs = (*iptr++) & 0xFF;
626 uint32_t Mevents = current_parsed_events.size();
627
628 //-------- Common data (64bit)
629 uint32_t common_header64 = *iptr++;
630 uint32_t common_header64_len = common_header64 & 0xFFFF;
631 uint64_t *iptr64 = (uint64_t*)iptr;
632 iptr = &iptr[common_header64_len];
633
634 // First event number
635 uint64_t first_event_num = *iptr64++;
636
637 // Hi and lo 32bit words in 64bit numbers seem to be
638 // switched for events read from ET, but not read from
639 // file. Not sure if this is in the swapping routine
640// if(source_type==kETSource) first_event_num = (first_event_num>>32) | (first_event_num<<32);
641
642 // Average timestamps
643 uint32_t Ntimestamps = (common_header64_len/2)-1;
644 if(tag & 0x2) Ntimestamps--; // subtract 1 for run number/type word if present
645 vector<uint64_t> avg_timestamps;
646 for(uint32_t i=0; i<Ntimestamps; i++) avg_timestamps.push_back(*iptr64++);
647
648 // run number and run type
649 uint32_t run_number = 0;
650 uint32_t run_type = 0;
651 if(tag & 0x02){
652 run_number = (*iptr64) >> 32;
653 run_type = (*iptr64) & 0xFFFFFFFF;
654 iptr64++;
655 }
656
657 //-------- Common data (16bit)
658 uint32_t common_header16 = *iptr++;
659 uint32_t common_header16_len = common_header16 & 0xFFFF;
660 uint16_t *iptr16 = (uint16_t*)iptr;
661 iptr = &iptr[common_header16_len];
662
663 vector<uint16_t> event_types;
664 for(uint32_t i=0; i<Mevents; i++) event_types.push_back(*iptr16++);
665
666 //-------- ROC data (32bit)
667 for(uint32_t iroc=0; iroc<Nrocs; iroc++){
668 uint32_t common_header32 = *iptr++;
669 uint32_t common_header32_len = common_header32 & 0xFFFF;
670 uint32_t rocid = common_header32 >> 24;
671
672 uint32_t Nwords_per_event = common_header32_len/Mevents;
673 for(auto pe : current_parsed_events){
674
675 DCODAROCInfo *codarocinfo = pe->NEW_DCODAROCInfo();
676 codarocinfo->rocid = rocid;
677
678 uint64_t ts_low = *iptr++;
679 uint64_t ts_high = *iptr++;
680 codarocinfo->timestamp = (ts_high<<32) + ts_low;
681 codarocinfo->misc.clear(); // could be recycled from previous event
682 for(uint32_t i=2; i<Nwords_per_event; i++) codarocinfo->misc.push_back(*iptr++);
683
684 if(iptr > iend){
685 throw JException("Bad data format in ParseBuiltTriggerBank!", __FILE__"libraries/DAQ/DEVIOWorkerThread.cc", __LINE__685);
686 }
687 }
688 }
689
690 //-------- Make DCODAEventInfo objects
691 uint64_t ievent = 0;
692 for(auto pe : current_parsed_events){
693
694 pe->run_number = run_number; // may be overwritten in JEventSource_EVIOpp::GetEvent()
695
696 DCODAEventInfo *codaeventinfo = pe->NEW_DCODAEventInfo();
697 codaeventinfo->run_number = run_number;
698 codaeventinfo->run_type = run_type;
699 codaeventinfo->event_number = first_event_num + ievent;
700 codaeventinfo->event_type = event_types.empty() ? 0:event_types[ievent];
701 codaeventinfo->avg_timestamp = avg_timestamps.empty() ? 0:avg_timestamps[ievent];
702 ievent++;
703 }
704}
705
706//---------------------------------
707// ParseDataBank
708//---------------------------------
709void DEVIOWorkerThread::ParseDataBank(uint32_t* &iptr, uint32_t *iend)
710{
711 // Physics Event's Data Bank header
712 iptr++; // advance past data bank length word
713 uint32_t rocid = ((*iptr)>>16) & 0xFFF;
714 iptr++;
715
716 // Loop over Data Block Banks
717 while(iptr < iend){
718
719 uint32_t data_block_bank_len = *iptr++;
720 uint32_t *iend_data_block_bank = &iptr[data_block_bank_len];
721 uint32_t data_block_bank_header = *iptr++;
722
723 // Not sure where this comes from, but it needs to be skipped if present
724 while( (*iptr==0xF800FAFA) && (iptr<iend) ) iptr++;
725
726 uint32_t det_id = (data_block_bank_header>>16) & 0xFFF;
727 switch(det_id){
728
729 case 20:
730 ParseCAEN1190(rocid, iptr, iend_data_block_bank);
731 break;
732
733 case 0x55:
734 ParseModuleConfiguration(rocid, iptr, iend_data_block_bank);
735 break;
736
737 case 0:
738 case 1:
739 case 3:
740 case 6: // flash 250 module, MMD 2014/2/4
741 case 16: // flash 125 module (CDC), DL 2014/6/19
742 case 26: // F1 TDC module (BCAL), MMD 2014-07-31
743 ParseJLabModuleData(rocid, iptr, iend_data_block_bank);
744 break;
745
746 // These were implemented in the ROL for sync events
747 // as 0xEE02 and 0xEE05. However, that violates the
748 // spec. which reserves the top 4 bits as status bits
749 // (the first "E" should really be a "1". We just check
750 // other 12 bits here.
751 case 0xE02:
752 ParseTSscalerBank(iptr, iend);
753 break;
754 case 0xE05:
755 Parsef250scalerBank(iptr, iend);
756 break;
757 case 0xE10: // really wish Sascha would share when he does this stuff!
758 Parsef250scalerBank(iptr, iend);
759 break;
760
761 case 5:
762 // old ROL Beni used had this but I don't think its
763 // been used for years. Run 10390 seems to have
764 // this though (???)
765 break;
766
767
768 default:
769 jerr<<"Unknown module type ("<<det_id<<" = " << hex << det_id << dec << " ) encountered" << endl;
770// if(VERBOSE>5){
771 cout << "----- First few words to help with debugging -----" << endl;
772 cout.flush(); cerr.flush();
773 DumpBinary(&iptr[-2], iend, 32, &iptr[-1]);
774// }
775 }
776
777 iptr = iend_data_block_bank;
778 }
779
780}
781
782//----------------
783// ParseCAEN1190
784//----------------
785void DEVIOWorkerThread::ParseCAEN1190(uint32_t rocid, uint32_t* &iptr, uint32_t *iend)
786{
787 if(!PARSE_CAEN1290TDC){ iptr = &iptr[(*iptr) + 1]; return; }
788
789 /// Parse data from a CAEN 1190 or 1290 module
790 /// (See ppg. 72-74 of V1290_REV15.pdf manual)
791
792 uint32_t slot = 0;
793 uint32_t event_count = 0;
794 uint32_t word_count = 0;
795 uint32_t trigger_time_tag = 0;
796 uint32_t tdc_num = 0;
797 uint32_t event_id = 0;
798 uint32_t bunch_id = 0;
799
800 // We need to accomodate multi-event blocks where
801 // events are entangled (i.e. hits from event 1
802 // are mixed in between those of event 2,3,4,
803 // etc... With CAEN modules, we only know which
804 // event a hit came from by looking at the event_id
805 // in the TDC header. This value is only 12 bits
806 // and could roll over within an event block. This
807 // means we need to keep track of the order we
808 // encounter them in so it is maintained in the
809 // "events" container. The event_id order is kept
810 // in the "event_id_order" vector.
811 map<uint32_t, DParsedEvent*> events_by_event_id;
812
813 auto pe_iter = current_parsed_events.begin();
814 DParsedEvent *pe = NULL__null;
815
816 while(iptr<iend){
817
818 // This word appears to be appended to the data.
819 // Probably in the ROL. Ignore it if found.
820 if(*iptr == 0xd00dd00d) {
821 if(VERBOSE>7) cout << " CAEN skipping 0xd00dd00d word" << endl;
822 iptr++;
823 continue;
824 }
825
826 uint32_t type = (*iptr) >> 27;
827 uint32_t edge = 0; // 1=trailing, 0=leading
828 uint32_t channel = 0;
829 uint32_t tdc = 0;
830 uint32_t error_flags = 0;
831 switch(type){
832 case 0b01000: // Global Header
833 slot = (*iptr) & 0x1f;
834 event_count = ((*iptr)>>5) & 0xffffff;
835 if(VERBOSE>7) cout << " CAEN TDC Global Header (slot=" << slot << " , event count=" << event_count << ")" << endl;
836 break;
837 case 0b10000: // Global Trailer
838 slot = (*iptr) & 0x1f;
839 word_count = ((*iptr)>>5) & 0x7ffff;
840 if(VERBOSE>7) cout << " CAEN TDC Global Trailer (slot=" << slot << " , word count=" << word_count << ")" << endl;
841 slot = event_count = word_count = trigger_time_tag = tdc_num = event_id = bunch_id = 0;
842 break;
843 case 0b10001: // Global Trigger Time Tag
844 trigger_time_tag = ((*iptr)>>5) & 0x7ffffff;
845 if(VERBOSE>7) cout << " CAEN TDC Global Trigger Time Tag (tag=" << trigger_time_tag << ")" << endl;
846 break;
847 case 0b00001: // TDC Header
848 tdc_num = ((*iptr)>>24) & 0x03;
849 event_id = ((*iptr)>>12) & 0x0fff;
850 bunch_id = (*iptr) & 0x0fff;
851 if(events_by_event_id.find(event_id) == events_by_event_id.end()){
852 if(pe_iter == current_parsed_events.end()){
853 _DBG_std::cerr<<"libraries/DAQ/DEVIOWorkerThread.cc"<<
":"<<853<<" "
<< "CAEN1290TDC parser sees more events than CODA header! (>" << current_parsed_events.size() << ")" << endl;
854 for( auto p : events_by_event_id) cout << "id=" << p.first << endl;
855 iptr = iend;
856 exit(-1); // should we exit, or try and continue??
857 return;
858 }
859 pe = *pe_iter++;
860 events_by_event_id[event_id] = pe;
861 }else{
862 pe = events_by_event_id[event_id];
863 }
864 if(VERBOSE>7) cout << " CAEN TDC TDC Header (tdc=" << tdc_num <<" , event id=" << event_id <<" , bunch id=" << bunch_id << ")" << endl;
865 break;
866 case 0b00000: // TDC Measurement
867 edge = ((*iptr)>>26) & 0x01;
868 channel = ((*iptr)>>21) & 0x1f;
869 tdc = ((*iptr)>>0) & 0x1fffff;
870 if(VERBOSE>7) cout << " CAEN TDC TDC Measurement (" << (edge ? "trailing":"leading") << " , channel=" << channel << " , tdc=" << tdc << ")" << endl;
871
872 // Create DCAEN1290TDCHit object
873 pe->NEW_DCAEN1290TDCHit(rocid, slot, channel, 0, edge, tdc_num, event_id, bunch_id, tdc);
874 break;
875 case 0b00100: // TDC Error
876 error_flags = (*iptr) & 0x7fff;
877 if(VERBOSE>7) cout << " CAEN TDC TDC Error (err flags=0x" << hex << error_flags << dec << ")" << endl;
878 break;
879 case 0b00011: // TDC Trailer
880 tdc_num = ((*iptr)>>24) & 0x03;
881 event_id = ((*iptr)>>12) & 0x0fff;
882 word_count = ((*iptr)>>0) & 0x0fff;
883 if(VERBOSE>7) cout << " CAEN TDC TDC Trailer (tdc=" << tdc_num <<" , event id=" << event_id <<" , word count=" << word_count << ")" << endl;
884 tdc_num = event_id = bunch_id = 0;
885 break;
886 case 0b11000: // Filler Word
887 if(VERBOSE>7) cout << " CAEN TDC Filler Word" << endl;
888 break;
889 default:
890 cout << "Unknown datatype: 0x" << hex << type << " full word: "<< *iptr << dec << endl;
891 }
892
893 iptr++;
894 }
895
896}
897
898//----------------
899// ParseModuleConfiguration
900//----------------
901void DEVIOWorkerThread::ParseModuleConfiguration(uint32_t rocid, uint32_t* &iptr, uint32_t *iend)
902{
903 if(!PARSE_CONFIG){ iptr = &iptr[(*iptr) + 1]; return; }
904
905 /// Parse a bank of module configuration data. These are configuration values
906 /// programmed into the module at the beginning of the run that may be needed
907 /// in the offline. For example, the number of samples to sum in a FADC pulse
908 /// integral.
909 ///
910 /// The bank has one or more sections, each describing parameters applicable
911 /// to a number of modules as indicated by a 24bit slot mask.
912 ///
913 /// This bank should appear only once per DAQ event which, if in multi-event
914 /// block mode, may have multiple L1 events. The parameters here will apply
915 /// to all L1 events in the block. This method will put the config objects
916 /// into each event in current_parsed_events. The config objects are duplicated
917 /// as needed so each event has its own, indepenent set of config object.
918
919 while(iptr < iend){
920 uint32_t slot_mask = (*iptr) & 0xFFFFFF;
921 uint32_t Nvals = ((*iptr) >> 24) & 0xFF;
922 iptr++;
923
924 // Events will be created in the first event (i.e. using its pool)
925 // but pointers are saved so we can use them to construct identical
926 // objects in all other event later
927 DParsedEvent *pe = current_parsed_events.front();
928
929 Df250Config *f250config = NULL__null;
930 Df125Config *f125config = NULL__null;
931 DF1TDCConfig *f1tdcconfig = NULL__null;
932 DCAEN1290TDCConfig *caen1290tdcconfig = NULL__null;
933
934 // Loop over all parameters in this section
935 for(uint32_t i=0; i< Nvals; i++){
936 if( iptr >= iend){
937 _DBG_std::cerr<<"libraries/DAQ/DEVIOWorkerThread.cc"<<
":"<<937<<" "
<< "DAQ Configuration bank corrupt! slot_mask=0x" << hex << slot_mask << dec << " Nvals="<< Nvals << endl;
938 exit(-1);
939 }
940
941 daq_param_type ptype = (daq_param_type)((*iptr)>>16);
942 uint16_t val = (*iptr) & 0xFFFF;
943
944 if(VERBOSE>6) cout << " DAQ parameter of type: 0x" << hex << ptype << dec << " found with value: " << val << endl;
945
946 // Create config object of correct type if needed and copy
947 // parameter value into it.
948 switch(ptype>>8){
949
950 // f250
951 case 0x05:
952 if( !f250config ) f250config = pe->NEW_Df250Config(rocid, slot_mask);
953 switch(ptype){
954 case kPARAM250_NSA : f250config->NSA = val; break;
955 case kPARAM250_NSB : f250config->NSB = val; break;
956 case kPARAM250_NSA_NSB : f250config->NSA_NSB = val; break;
957 case kPARAM250_NPED : f250config->NPED = val; break;
958 default: _DBG_std::cerr<<"libraries/DAQ/DEVIOWorkerThread.cc"<<
":"<<958<<" "
<< "UNKNOWN DAQ Config Parameter type: 0x" << hex << ptype << dec << endl;
959 }
960 break;
961
962 // f125
963 case 0x0F:
964 if( !f125config ) f125config = pe->NEW_Df125Config(rocid, slot_mask);
965 switch(ptype){
966 case kPARAM125_NSA : f125config->NSA = val; break;
967 case kPARAM125_NSB : f125config->NSB = val; break;
968 case kPARAM125_NSA_NSB : f125config->NSA_NSB = val; break;
969 case kPARAM125_NPED : f125config->NPED = val; break;
970 case kPARAM125_WINWIDTH : f125config->WINWIDTH = val; break;
971 case kPARAM125_PL : f125config->PL = val; break;
972 case kPARAM125_NW : f125config->NW = val; break;
973 case kPARAM125_NPK : f125config->NPK = val; break;
974 case kPARAM125_P1 : f125config->P1 = val; break;
975 case kPARAM125_P2 : f125config->P2 = val; break;
976 case kPARAM125_PG : f125config->PG = val; break;
977 case kPARAM125_IE : f125config->IE = val; break;
978 case kPARAM125_H : f125config->H = val; break;
979 case kPARAM125_TH : f125config->TH = val; break;
980 case kPARAM125_TL : f125config->TL = val; break;
981 case kPARAM125_IBIT : f125config->IBIT = val; break;
982 case kPARAM125_ABIT : f125config->ABIT = val; break;
983 case kPARAM125_PBIT : f125config->PBIT = val; break;
984 default: _DBG_std::cerr<<"libraries/DAQ/DEVIOWorkerThread.cc"<<
":"<<984<<" "
<< "UNKNOWN DAQ Config Parameter type: 0x" << hex << ptype << dec << endl;
985 }
986 break;
987
988 // F1TDC
989 case 0x06:
990 if( !f1tdcconfig ) f1tdcconfig = pe->NEW_DF1TDCConfig(rocid, slot_mask);
991 switch(ptype){
992 case kPARAMF1_REFCNT : f1tdcconfig->REFCNT = val; break;
993 case kPARAMF1_TRIGWIN : f1tdcconfig->TRIGWIN = val; break;
994 case kPARAMF1_TRIGLAT : f1tdcconfig->TRIGLAT = val; break;
995 case kPARAMF1_HSDIV : f1tdcconfig->HSDIV = val; break;
996 case kPARAMF1_BINSIZE : f1tdcconfig->BINSIZE = val; break;
997 case kPARAMF1_REFCLKDIV : f1tdcconfig->REFCLKDIV = val; break;
998 default: _DBG_std::cerr<<"libraries/DAQ/DEVIOWorkerThread.cc"<<
":"<<998<<" "
<< "UNKNOWN DAQ Config Parameter type: 0x" << hex << ptype << dec << endl;
999 }
1000 break;
1001
1002 // caen1290
1003 case 0x10:
1004 if( !caen1290tdcconfig ) caen1290tdcconfig = pe->NEW_DCAEN1290TDCConfig(rocid, slot_mask);
1005 switch(ptype){
1006 case kPARAMCAEN1290_WINWIDTH : caen1290tdcconfig->WINWIDTH = val; break;
1007 case kPARAMCAEN1290_WINOFFSET : caen1290tdcconfig->WINOFFSET = val; break;
1008 default: _DBG_std::cerr<<"libraries/DAQ/DEVIOWorkerThread.cc"<<
":"<<1008<<" "
<< "UNKNOWN DAQ Config Parameter type: 0x" << hex << ptype << dec << endl;
1009 }
1010 break;
1011
1012 default:
1013 _DBG_std::cerr<<"libraries/DAQ/DEVIOWorkerThread.cc"<<
":"<<1013<<" "
<< "Unknown module type: 0x" << hex << (ptype>>8) << endl;
1014 exit(-1);
1015 }
1016
1017
1018 iptr++;
1019 }
1020
1021 // Make copies of all config objects for all other events
1022 for(auto tpe : current_parsed_events){
1023
1024 if(tpe == pe) continue; // first event already owns objects so skip it
1025
1026 if(f250config ) tpe->NEW_Df250Config(f250config);
1027 if(f125config ) tpe->NEW_Df125Config(f125config);
1028 if(f1tdcconfig ) tpe->NEW_DF1TDCConfig(f1tdcconfig);
1029 if(caen1290tdcconfig) tpe->NEW_DCAEN1290TDCConfig(caen1290tdcconfig);
1030 }
1031 }
1032}
1033
1034//----------------
1035// ParseJLabModuleData
1036//----------------
1037void DEVIOWorkerThread::ParseJLabModuleData(uint32_t rocid, uint32_t* &iptr, uint32_t *iend)
1038{
1039
1040 while(iptr<iend){
1041
1042 // Get module type from next word (bits 18-21)
1043 uint32_t mod_id = ((*iptr) >> 18) & 0x000F;
1044 MODULE_TYPE type = (MODULE_TYPE)mod_id;
1045// cout << " rocid=" << rocid << " Encountered module type: " << type << " (=" << DModuleType::GetModule(type).GetName() << ") word=" << hex << (*iptr) << dec << endl;
1046
1047 switch(type){
1048 case DModuleType::FADC250:
1049 Parsef250Bank(rocid, iptr, iend);
1050 break;
1051
1052 case DModuleType::FADC125:
1053 Parsef125Bank(rocid, iptr, iend);
1054 break;
1055
1056 case DModuleType::F1TDC32:
1057 ParseF1TDCBank(rocid, iptr, iend);
1058 break;
1059
1060 case DModuleType::F1TDC48:
1061 ParseF1TDCBank(rocid, iptr, iend);
1062 break;
1063
1064 case DModuleType::TID:
1065// ParseTIBank(rocid, iptr, iend);
1066 break;
1067
1068 case DModuleType::UNKNOWN:
1069 default:
1070 jerr<<"Unknown module type ("<<mod_id<<") iptr=0x" << hex << iptr << dec << endl;
1071
1072 while(iptr<iend && ((*iptr) & 0xF8000000) != 0x88000000) iptr++; // Skip to JLab block trailer
1073 iptr++; // advance past JLab block trailer
1074 while(iptr<iend && *iptr == 0xF8000000) iptr++; // skip filler words after block trailer
1075 break;
1076 }
1077 }
1078
1079}
1080
1081//----------------
1082// Parsef250Bank
1083//----------------
1084void DEVIOWorkerThread::Parsef250Bank(uint32_t rocid, uint32_t* &iptr, uint32_t *iend)
1085{
1086 if(!PARSE_F250){ iptr = &iptr[(*iptr) + 1]; return; }
1
Taking false branch
1087
1088 auto pe_iter = current_parsed_events.begin();
1089 DParsedEvent *pe = NULL__null;
2
'pe' initialized to a null pointer value
1090
1091 uint32_t slot = 0;
1092 uint32_t itrigger = -1;
1093
1094 // Loop over data words
1095 for(; iptr<iend; iptr++){
3
Assuming 'iptr' is < 'iend'
4
Loop condition is true. Entering loop body
7
Loop condition is true. Entering loop body
10
Loop condition is true. Entering loop body
13
Loop condition is true. Entering loop body
1096
1097 // Skip all non-data-type-defining words at this
1098 // level. When we do encounter one, the appropriate
1099 // case block below should handle parsing all of
1100 // the data continuation words and advance the iptr.
1101 if(((*iptr>>31) & 0x1) == 0)continue;
5
Taking false branch
8
Taking false branch
11
Taking false branch
14
Taking false branch
1102
1103 uint32_t data_type = (*iptr>>27) & 0x0F;
1104 switch(data_type){
6
'Default' branch taken. Execution continues on line 1095
9
'Default' branch taken. Execution continues on line 1095
12
'Default' branch taken. Execution continues on line 1095
15
Control jumps to 'case 4:' at line 1133
1105 case 0: // Block Header
1106 slot = (*iptr>>22) & 0x1F;
1107 if(VERBOSE>7) cout << " FADC250 Block Header: slot="<<slot<<" ("<<hex<<*iptr<<dec<<")"<<endl;
1108 break;
1109 case 1: // Block Trailer
1110 pe_iter = current_parsed_events.begin();
1111 pe = NULL__null;
1112 if(VERBOSE>7) cout << " FADC250 Block Trailer"<<" ("<<hex<<*iptr<<dec<<")"<<endl;
1113 break;
1114 case 2: // Event Header
1115 itrigger = (*iptr>>0) & 0x3FFFFF;
1116 pe = *pe_iter++;
1117 if(VERBOSE>7) cout << " FADC250 Event Header: itrigger="<<itrigger<<", rocid="<<rocid<<", slot="<<slot<<")" <<" ("<<hex<<*iptr<<dec<<")" <<endl;
1118 break;
1119 case 3: // Trigger Time
1120 {
1121 uint64_t t = ((*iptr)&0xFFFFFF)<<0;
1122 iptr++;
1123 if(((*iptr>>31) & 0x1) == 0){
1124 t += ((*iptr)&0xFFFFFF)<<24; // from word on the street: second trigger time word is optional!!??
1125 if(VERBOSE>7) cout << " Trigger time high word="<<(((*iptr)&0xFFFFFF))<<" ("<<hex<<*iptr<<dec<<")"<<endl;
1126 }else{
1127 iptr--;
1128 }
1129 if(VERBOSE>7) cout << " FADC250 Trigger Time: t="<<t<<" ("<<hex<<*iptr<<dec<<")"<<endl;
1130 if(pe) pe->NEW_Df250TriggerTime(rocid, slot, itrigger, t);
1131 }
1132 break;
1133 case 4: // Window Raw Data
1134 // iptr passed by reference and so will be updated automatically
1135 if(VERBOSE>7) cout << " FADC250 Window Raw Data"<<" ("<<hex<<*iptr<<dec<<")"<<endl;
16
Taking false branch
1136 MakeDf250WindowRawData(pe, rocid, slot, itrigger, iptr);
17
Passing null pointer value via 1st parameter 'pe'
18
Calling 'DEVIOWorkerThread::MakeDf250WindowRawData'
1137 break;
1138 case 5: // Window Sum
1139 {
1140 uint32_t channel = (*iptr>>23) & 0x0F;
1141 uint32_t sum = (*iptr>>0) & 0x3FFFFF;
1142 uint32_t overflow = (*iptr>>22) & 0x1;
1143 if(VERBOSE>7) cout << " FADC250 Window Sum"<<" ("<<hex<<*iptr<<dec<<")"<<endl;
1144 if(pe) pe->NEW_Df250WindowSum(rocid, slot, channel, itrigger, sum, overflow);
1145 }
1146 break;
1147 case 6: // Pulse Raw Data
1148// MakeDf250PulseRawData(objs, rocid, slot, itrigger, iptr);
1149 if(VERBOSE>7) cout << " FADC250 Pulse Raw Data"<<" ("<<hex<<*iptr<<dec<<")"<<endl;
1150 break;
1151 case 7: // Pulse Integral
1152 {
1153 uint32_t channel = (*iptr>>23) & 0x0F;
1154 uint32_t pulse_number = (*iptr>>21) & 0x03;
1155 uint32_t quality_factor = (*iptr>>19) & 0x03;
1156 uint32_t sum = (*iptr>>0) & 0x7FFFF;
1157 uint32_t nsamples_integral = 0; // must be overwritten later in GetObjects with value from Df125Config value
1158 uint32_t nsamples_pedestal = 1; // The firmware returns an already divided pedestal
1159 uint32_t pedestal = 0; // This will be replaced by the one from Df250PulsePedestal in GetObjects
1160 if(VERBOSE>7) cout << " FADC250 Pulse Integral: chan="<<channel<<" pulse_number="<<pulse_number<<" sum="<<sum<<" ("<<hex<<*iptr<<dec<<")"<<endl;
1161 if(pe) pe->NEW_Df250PulseIntegral(rocid, slot, channel, itrigger, pulse_number, quality_factor, sum, pedestal, nsamples_integral, nsamples_pedestal);
1162 }
1163 break;
1164 case 8: // Pulse Time
1165 {
1166 uint32_t channel = (*iptr>>23) & 0x0F;
1167 uint32_t pulse_number = (*iptr>>21) & 0x03;
1168 uint32_t quality_factor = (*iptr>>19) & 0x03;
1169 uint32_t pulse_time = (*iptr>>0) & 0x7FFFF;
1170 if(VERBOSE>7) cout << " FADC250 Pulse Time: chan="<<channel<<" pulse_number="<<pulse_number<<" pulse_time="<<pulse_time<<" ("<<hex<<*iptr<<dec<<")"<<endl;
1171 if(pe) pe->NEW_Df250PulseTime(rocid, slot, channel, itrigger, pulse_number, quality_factor, pulse_time);
1172 }
1173 break;
1174 case 9: // Streaming Raw Data
1175 // This is marked "reserved for future implementation" in the current manual (v2).
1176 // As such, we don't try handling it here just yet.
1177 if(VERBOSE>7) cout << " FADC250 Streaming Raw Data (unsupported)"<<" ("<<hex<<*iptr<<dec<<")"<<endl;
1178 break;
1179 case 10: // Pulse Pedestal
1180 {
1181 uint32_t channel = (*iptr>>23) & 0x0F;
1182 uint32_t pulse_number = (*iptr>>21) & 0x03;
1183 uint32_t pedestal = (*iptr>>12) & 0x1FF;
1184 uint32_t pulse_peak = (*iptr>>0) & 0xFFF;
1185 if(VERBOSE>7) cout << " FADC250 Pulse Pedestal chan="<<channel<<" pulse_number="<<pulse_number<<" pedestal="<<pedestal<<" pulse_peak="<<pulse_peak<<" ("<<hex<<*iptr<<dec<<")"<<endl;
1186 if(pe) pe->NEW_Df250PulsePedestal(rocid, slot, channel, itrigger, pulse_number, pedestal, pulse_peak);
1187 }
1188 break;
1189 case 13: // Event Trailer
1190 // This is marked "suppressed for normal readout – debug mode only" in the
1191 // current manual (v2). It does not contain any data so the most we could do here
1192 // is return early. I'm hesitant to do that though since it would mean
1193 // different behavior for debug mode data as regular data.
1194 case 14: // Data not valid (empty module)
1195 case 15: // Filler (non-data) word
1196 if(VERBOSE>7) cout << " FADC250 Event Trailer, Data not Valid, or Filler word ("<<data_type<<")"<<" ("<<hex<<*iptr<<dec<<")"<<endl;
1197 break;
1198 }
1199 }
1200
1201 // Chop off filler words
1202 for(; iptr<iend; iptr++){
1203 if(((*iptr)&0xf8000000) != 0xf8000000) break;
1204 }
1205}
1206
1207//----------------
1208// MakeDf250WindowRawData
1209//----------------
1210void DEVIOWorkerThread::MakeDf250WindowRawData(DParsedEvent *pe, uint32_t rocid, uint32_t slot, uint32_t itrigger, uint32_t* &iptr)
1211{
1212 uint32_t channel = (*iptr>>23) & 0x0F;
1213 uint32_t window_width = (*iptr>>0) & 0x0FFF;
1214
1215 Df250WindowRawData *wrd = pe->NEW_Df250WindowRawData(rocid, slot, channel, itrigger);
19
Called C++ object pointer is null
1216
1217 for(uint32_t isample=0; isample<window_width; isample +=2){
1218
1219 // Advance to next word
1220 iptr++;
1221
1222 // Make sure this is a data continuation word, if not, stop here
1223 if(((*iptr>>31) & 0x1) != 0x0){
1224 iptr--; // calling method expects us to point to last word in block
1225 break;
1226 }
1227
1228 bool invalid_1 = (*iptr>>29) & 0x1;
1229 bool invalid_2 = (*iptr>>13) & 0x1;
1230 uint16_t sample_1 = 0;
1231 uint16_t sample_2 = 0;
1232 if(!invalid_1)sample_1 = (*iptr>>16) & 0x1FFF;
1233 if(!invalid_2)sample_2 = (*iptr>>0) & 0x1FFF;
1234
1235 // Sample 1
1236 wrd->samples.push_back(sample_1);
1237 wrd->invalid_samples |= invalid_1;
1238 wrd->overflow |= (sample_1>>12) & 0x1;
1239
1240 if(((isample+2) == window_width) && invalid_2)break; // skip last sample if flagged as invalid
1241
1242 // Sample 2
1243 wrd->samples.push_back(sample_2);
1244 wrd->invalid_samples |= invalid_2;
1245 wrd->overflow |= (sample_2>>12) & 0x1;
1246 }
1247}
1248
1249//----------------
1250// Parsef125Bank
1251//----------------
1252void DEVIOWorkerThread::Parsef125Bank(uint32_t rocid, uint32_t* &iptr, uint32_t *iend)
1253{
1254 if(!PARSE_F125){ iptr = &iptr[(*iptr) + 1]; return; }
1255
1256 auto pe_iter = current_parsed_events.begin();
1257 DParsedEvent *pe = NULL__null;
1258
1259 uint32_t slot=0;
1260 uint32_t itrigger = -1;
1261 uint32_t last_itrigger = -2;
1262 uint32_t last_pulse_time_channel=0;
1263 uint32_t last_slot = -1;
1264 uint32_t last_channel = -1;
1265
1266 // Loop over data words
1267 for(; iptr<iend; iptr++){
1268
1269 // Skip all non-data-type-defining words at this
1270 // level. When we do encounter one, the appropriate
1271 // case block below should handle parsing all of
1272 // the data continuation words and advance the iptr.
1273 if(((*iptr>>31) & 0x1) == 0)continue;
1274
1275 uint32_t data_type = (*iptr>>27) & 0x0F;
1276 switch(data_type){
1277 case 0: // Block Header
1278 slot = (*iptr>>22) & 0x1F;
1279 if(VERBOSE>7) cout << " FADC125 Block Header: slot="<<slot<<endl;
1280 break;
1281 case 1: // Block Trailer
1282 pe_iter = current_parsed_events.begin();
1283 pe = NULL__null;
1284 break;
1285 case 2: // Event Header
1286 //slot_event_header = (*iptr>>22) & 0x1F;
1287 itrigger = (*iptr>>0) & 0x3FFFFFF;
1288 pe = *pe_iter++;
1289 if(VERBOSE>7) cout << " FADC125 Event Header: itrigger="<<itrigger<<" last_itrigger="<<last_itrigger<<", rocid="<<rocid<<", slot="<<slot <<endl;
1290 break;
1291 case 3: // Trigger Time
1292 {
1293 uint64_t t = ((*iptr)&0xFFFFFF)<<0;
1294 iptr++;
1295 if(((*iptr>>31) & 0x1) == 0){
1296 t += ((*iptr)&0xFFFFFF)<<24; // from word on the street: second trigger time word is optional!!??
1297 }else{
1298 iptr--;
1299 }
1300 if(VERBOSE>7) cout << " FADC125 Trigger Time (t="<<t<<")"<<endl;
1301 if(pe) pe->NEW_Df125TriggerTime(rocid, slot, itrigger, t);
1302 }
1303 break;
1304 case 4: // Window Raw Data
1305 // iptr passed by reference and so will be updated automatically
1306 if(VERBOSE>7) cout << " FADC125 Window Raw Data"<<endl;
1307 MakeDf125WindowRawData(pe, rocid, slot, itrigger, iptr);
1308 break;
1309
1310 case 5: // CDC pulse data (new) (GlueX-doc-2274-v8)
1311 {
1312 // Word 1:
1313 uint32_t word1 = *iptr;
1314 uint32_t channel = (*iptr>>20) & 0x7F;
1315 uint32_t pulse_number = (*iptr>>15) & 0x1F;
1316 uint32_t pulse_time = (*iptr>>4 ) & 0x7FF;
1317 uint32_t quality_factor = (*iptr>>3 ) & 0x1; //time QF bit
1318 uint32_t overflow_count = (*iptr>>0 ) & 0x7;
1319 if(VERBOSE>7){
1320 cout << " FADC125 CDC Pulse Data word1: " << hex << (*iptr) << dec << endl;
1321 cout << " FADC125 CDC Pulse Data (chan="<<channel<<" pulse="<<pulse_number<<" time="<<pulse_time<<" QF="<<quality_factor<<" OC="<<overflow_count<<")"<<endl;
1322 }
1323
1324 // Word 2:
1325 ++iptr;
1326 if(iptr>=iend){
1327 jerr << " Truncated f125 CDC hit (block ends before continuation word!)" << endl;
1328 continue;
1329 }
1330 if( ((*iptr>>31) & 0x1) != 0 ){
1331 jerr << " Truncated f125 CDC hit (missing continuation word!)" << endl;
1332 continue;
1333 }
1334 uint32_t word2 = *iptr;
1335 uint32_t pedestal = (*iptr>>23) & 0xFF;
1336 uint32_t sum = (*iptr>>9 ) & 0x3FFF;
1337 uint32_t pulse_peak = (*iptr>>0 ) & 0x1FF;
1338 if(VERBOSE>7){
1339 cout << " FADC125 CDC Pulse Data word2: " << hex << (*iptr) << dec << endl;
1340 cout << " FADC125 CDC Pulse Data (pedestal="<<pedestal<<" sum="<<sum<<" peak="<<pulse_peak<<")"<<endl;
1341 }
1342
1343 // Create hit objects
1344 uint32_t nsamples_integral = 0; // must be overwritten later in GetObjects with value from Df125Config value
1345 uint32_t nsamples_pedestal = 1; // The firmware pedestal divided by 2^PBIT where PBIT is a config. parameter
1346
1347 if( pe ) {
1348 pe->NEW_Df125CDCPulse(rocid, slot, channel, itrigger
1349 , pulse_number // NPK
1350 , pulse_time // le_time
1351 , quality_factor // time_quality_bit
1352 , overflow_count // overflow_count
1353 , pedestal // pedestal
1354 , sum // integral
1355 , pulse_peak // first_max_amp
1356 , word1 // word1
1357 , word2 // word2
1358 , nsamples_pedestal // nsamples_pedestal
1359 , nsamples_integral // nsamples_integral
1360 , false); // emulated
1361 }
1362 }
1363 break;
1364
1365 case 6: // FDC pulse data-integral (new) (GlueX-doc-2274-v8)
1366 {
1367 // Word 1:
1368 uint32_t word1 = *iptr;
1369 uint32_t channel = (*iptr>>20) & 0x7F;
1370 uint32_t pulse_number = (*iptr>>15) & 0x1F;
1371 uint32_t pulse_time = (*iptr>>4 ) & 0x7FF;
1372 uint32_t quality_factor = (*iptr>>3 ) & 0x1; //time QF bit
1373 uint32_t overflow_count = (*iptr>>0 ) & 0x7;
1374 if(VERBOSE>7){
1375 cout << " FADC125 FDC Pulse Data(integral) word1: " << hex << (*iptr) << dec << endl;
1376 cout << " FADC125 FDC Pulse Data (chan="<<channel<<" pulse="<<pulse_number<<" time="<<pulse_time<<" QF="<<quality_factor<<" OC="<<overflow_count<<")"<<endl;
1377 }
1378
1379 // Word 2:
1380 ++iptr;
1381 if(iptr>=iend){
1382 jerr << " Truncated f125 FDC hit (block ends before continuation word!)" << endl;
1383 continue;
1384 }
1385 if( ((*iptr>>31) & 0x1) != 0 ){
1386 jerr << " Truncated f125 FDC hit (missing continuation word!)" << endl;
1387 continue;
1388 }
1389 uint32_t word2 = *iptr;
1390 uint32_t pulse_peak = 0;
1391 uint32_t sum = (*iptr>>19) & 0xFFF;
1392 uint32_t peak_time = (*iptr>>11) & 0xFF;
1393 uint32_t pedestal = (*iptr>>0 ) & 0x7FF;
1394 if(VERBOSE>7){
1395 cout << " FADC125 FDC Pulse Data(integral) word2: " << hex << (*iptr) << dec << endl;
1396 cout << " FADC125 FDC Pulse Data (integral="<<sum<<" time="<<peak_time<<" pedestal="<<pedestal<<")"<<endl;
1397 }
1398
1399 // Create hit objects
1400 uint32_t nsamples_integral = 0; // must be overwritten later in GetObjects with value from Df125Config value
1401 uint32_t nsamples_pedestal = 1; // The firmware pedestal divided by 2^PBIT where PBIT is a config. parameter
1402
1403 if( pe ) {
1404 pe->NEW_Df125FDCPulse(rocid, slot, channel, itrigger
1405 , pulse_number // NPK
1406 , pulse_time // le_time
1407 , quality_factor // time_quality_bit
1408 , overflow_count // overflow_count
1409 , pedestal // pedestal
1410 , sum // integral
1411 , pulse_peak // peak_amp
1412 , peak_time // peak_time
1413 , word1 // word1
1414 , word2 // word2
1415 , nsamples_pedestal // nsamples_pedestal
1416 , nsamples_integral // nsamples_integral
1417 , false); // emulated
1418 }
1419 }
1420 break;
1421
1422 case 7: // Pulse Integral
1423 {
1424 if(VERBOSE>7) cout << " FADC125 Pulse Integral"<<endl;
1425 uint32_t channel = (*iptr>>20) & 0x7F;
1426 uint32_t sum = (*iptr>>0) & 0xFFFFF;
1427 uint32_t quality_factor = 0;
1428 uint32_t nsamples_integral = 0; // must be overwritten later in GetObjects with value from Df125Config value
1429 uint32_t nsamples_pedestal = 1; // The firmware returns an already divided pedestal
1430 uint32_t pedestal = 0; // This will be replaced by the one from Df250PulsePedestal in GetObjects
1431 uint32_t pulse_number = 0;
1432 if (last_slot == slot && last_channel == channel) pulse_number = 1;
1433 last_slot = slot;
1434 last_channel = channel;
1435 if( pe ) pe->NEW_Df125PulseIntegral(rocid, slot, channel, itrigger, pulse_number, quality_factor, sum, pedestal, nsamples_integral, nsamples_pedestal);
1436 }
1437 break;
1438 case 8: // Pulse Time
1439 {
1440 if(VERBOSE>7) cout << " FADC125 Pulse Time"<<endl;
1441 uint32_t channel = (*iptr>>20) & 0x7F;
1442 uint32_t pulse_number = (*iptr>>18) & 0x03;
1443 uint32_t pulse_time = (*iptr>>0) & 0xFFFF;
1444 uint32_t quality_factor = 0;
1445 if( pe ) pe->NEW_Df125PulseTime(rocid, slot, channel, itrigger, pulse_number, quality_factor, pulse_time);
1446 last_pulse_time_channel = channel;
1447 }
1448 break;
1449
1450 case 9: // FDC pulse data-peak (new) (GlueX-doc-2274-v8)
1451 {
1452 // Word 1:
1453 uint32_t word1 = *iptr;
1454 uint32_t channel = (*iptr>>20) & 0x7F;
1455 uint32_t pulse_number = (*iptr>>15) & 0x1F;
1456 uint32_t pulse_time = (*iptr>>4 ) & 0x7FF;
1457 uint32_t quality_factor = (*iptr>>3 ) & 0x1; //time QF bit
1458 uint32_t overflow_count = (*iptr>>0 ) & 0x7;
1459 if(VERBOSE>7){
1460 cout << " FADC125 FDC Pulse Data(peak) word1: " << hex << (*iptr) << dec << endl;
1461 cout << " FADC125 FDC Pulse Data (chan="<<channel<<" pulse="<<pulse_number<<" time="<<pulse_time<<" QF="<<quality_factor<<" OC="<<overflow_count<<")"<<endl;
1462 }
1463
1464 // Word 2:
1465 ++iptr;
1466 if(iptr>=iend){
1467 jerr << " Truncated f125 FDC hit (block ends before continuation word!)" << endl;
1468 continue;
1469 }
1470 if( ((*iptr>>31) & 0x1) != 0 ){
1471 jerr << " Truncated f125 FDC hit (missing continuation word!)" << endl;
1472 continue;
1473 }
1474 uint32_t word2 = *iptr;
1475 uint32_t pulse_peak = (*iptr>>19) & 0xFFF;
1476 uint32_t sum = 0;
1477 uint32_t peak_time = (*iptr>>11) & 0xFF;
1478 uint32_t pedestal = (*iptr>>0 ) & 0x7FF;
1479 if(VERBOSE>7){
1480 cout << " FADC125 FDC Pulse Data(peak) word2: " << hex << (*iptr) << dec << endl;
1481 cout << " FADC125 FDC Pulse Data (integral="<<sum<<" time="<<peak_time<<" pedestal="<<pedestal<<")"<<endl;
1482 }
1483
1484 // Create hit objects
1485 uint32_t nsamples_integral = 0; // must be overwritten later in GetObjects with value from Df125Config value
1486 uint32_t nsamples_pedestal = 1; // The firmware pedestal divided by 2^PBIT where PBIT is a config. parameter
1487
1488 if( pe ) {
1489 pe->NEW_Df125FDCPulse(rocid, slot, channel, itrigger
1490 , pulse_number // NPK
1491 , pulse_time // le_time
1492 , quality_factor // time_quality_bit
1493 , overflow_count // overflow_count
1494 , pedestal // pedestal
1495 , sum // integral
1496 , pulse_peak // peak_amp
1497 , peak_time // peak_time
1498 , word1 // word1
1499 , word2 // word2
1500 , nsamples_pedestal // nsamples_pedestal
1501 , nsamples_integral // nsamples_integral
1502 , false); // emulated
1503 }
1504 }
1505 break;
1506
1507 case 10: // Pulse Pedestal (consistent with Beni's hand-edited version of Cody's document)
1508 {
1509 if(VERBOSE>7) cout << " FADC125 Pulse Pedestal"<<endl;
1510 //channel = (*iptr>>20) & 0x7F;
1511 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")
1512 uint32_t pulse_number = (*iptr>>21) & 0x03;
1513 uint32_t pedestal = (*iptr>>12) & 0x1FF;
1514 uint32_t pulse_peak = (*iptr>>0) & 0xFFF;
1515 uint32_t nsamples_pedestal = 1; // The firmware returns an already divided pedestal
1516 if( pe ) pe->NEW_Df125PulsePedestal(rocid, slot, channel, itrigger, pulse_number, pedestal, pulse_peak, nsamples_pedestal);
1517 }
1518 break;
1519
1520 case 13: // Event Trailer
1521 case 14: // Data not valid (empty module)
1522 case 15: // Filler (non-data) word
1523 if(VERBOSE>7) cout << " FADC125 ignored data type: " << data_type <<endl;
1524 break;
1525 }
1526 }
1527
1528 // Chop off filler words
1529 for(; iptr<iend; iptr++){
1530 if(((*iptr)&0xf8000000) != 0xf8000000) break;
1531 }
1532}
1533
1534//----------------
1535// MakeDf125WindowRawData
1536//----------------
1537void DEVIOWorkerThread::MakeDf125WindowRawData(DParsedEvent *pe, uint32_t rocid, uint32_t slot, uint32_t itrigger, uint32_t* &iptr)
1538{
1539 uint32_t channel = (*iptr>>20) & 0x7F;
1540 uint32_t window_width = (*iptr>>0) & 0x0FFF;
1541
1542 Df125WindowRawData *wrd = pe->NEW_Df125WindowRawData(rocid, slot, channel, itrigger);
1543
1544 for(uint32_t isample=0; isample<window_width; isample +=2){
1545
1546 // Advance to next word
1547 iptr++;
1548
1549 // Make sure this is a data continuation word, if not, stop here
1550 if(((*iptr>>31) & 0x1) != 0x0)break;
1551
1552 bool invalid_1 = (*iptr>>29) & 0x1;
1553 bool invalid_2 = (*iptr>>13) & 0x1;
1554 uint16_t sample_1 = 0;
1555 uint16_t sample_2 = 0;
1556 if(!invalid_1)sample_1 = (*iptr>>16) & 0x1FFF;
1557 if(!invalid_2)sample_2 = (*iptr>>0) & 0x1FFF;
1558
1559 // Sample 1
1560 wrd->samples.push_back(sample_1);
1561 wrd->invalid_samples |= invalid_1;
1562 wrd->overflow |= (sample_1>>12) & 0x1;
1563
1564 if((isample+2) == window_width && invalid_2)break; // skip last sample if flagged as invalid
1565
1566 // Sample 2
1567 wrd->samples.push_back(sample_2);
1568 wrd->invalid_samples |= invalid_2;
1569 wrd->overflow |= (sample_2>>12) & 0x1;
1570 }
1571}
1572
1573//----------------
1574// ParseF1TDCBank
1575//----------------
1576void DEVIOWorkerThread::ParseF1TDCBank(uint32_t rocid, uint32_t* &iptr, uint32_t *iend)
1577{
1578 if(!PARSE_F1TDC){ iptr = &iptr[(*iptr) + 1]; return; }
1579
1580 uint32_t *istart = iptr;
1581
1582 auto pe_iter = current_parsed_events.begin();
1583 DParsedEvent *pe = NULL__null;
1584
1585 uint32_t slot = 0;
1586 uint32_t modtype = 0;
1587 uint32_t itrigger = -1;
1588 uint32_t trig_time_f1header = 0;
1589
1590 // Some early data had a marker word at just before the actual F1 data
1591 if(*iptr == 0xf1daffff) iptr++;
1592
1593 // Loop over data words
1594 for(; iptr<iend; iptr++){
1595
1596 // Skip all non-data-type-defining words at this
1597 // level. When we do encounter one, the appropriate
1598 // case block below should handle parsing all of
1599 // the data continuation words and advance the iptr.
1600 if(((*iptr>>31) & 0x1) == 0)continue;
1601
1602 uint32_t data_type = (*iptr>>27) & 0x0F;
1603 switch(data_type){
1604 case 0: // Block Header
1605 slot = (*iptr)>>22 & 0x001F;
1606 modtype = (*iptr)>>18 & 0x000F; // should match a DModuleType::type_id_t
1607 if(VERBOSE>7) cout << " F1 Block Header: slot=" << slot << " modtype=" << modtype << endl;
1608 break;
1609
1610 case 1: // Block Trailer
1611 pe_iter = current_parsed_events.begin();
1612 pe = NULL__null;
1613 if(VERBOSE>7) cout << " F1 Block Trailer" << endl;
1614 break;
1615
1616 case 2: // Event Header
1617 {
1618 pe = *pe_iter++;
1619 itrigger = (*iptr)>>0 & 0x0003FFFFF;
1620 if(VERBOSE>7) {
1621 uint32_t slot_event_header = (*iptr)>>22 & 0x00000001F;
1622 cout << " F1 Event Header: slot=" << slot_event_header << " itrigger=" << itrigger << endl;
1623 }
1624 }
1625 break;
1626
1627 case 3: // Trigger time
1628 {
1629 uint64_t t = ((*iptr)&0xFFFFFF)<<0;
1630 iptr++;
1631 if(((*iptr>>31) & 0x1) == 0){
1632 t += ((*iptr)&0xFFFFFF)<<24; // from word on the street: second trigger time word is optional!!??
1633 }else{
1634 iptr--;
1635 }
1636 if(VERBOSE>7) cout << " F1TDC Trigger Time (t="<<t<<")"<<endl;
1637 if(pe) pe->NEW_DF1TDCTriggerTime(rocid, slot, itrigger, t);
1638 }
1639 break;
1640
1641 case 8: // F1 Chip Header
1642 trig_time_f1header = ((*iptr)>> 7) & 0x1FF;
1643 if(VERBOSE>7) {
1644 uint32_t chip_f1header = ((*iptr)>> 3) & 0x07;
1645 uint32_t chan_on_chip_f1header = ((*iptr)>> 0) & 0x07; // this is always 7 in real data!
1646 uint32_t itrigger_f1header = ((*iptr)>>16) & 0x3F;
1647 cout << " Found F1 header: chip=" << chip_f1header << " chan=" << chan_on_chip_f1header << " itrig=" << itrigger_f1header << " trig_time=" << trig_time_f1header << endl;
1648 }
1649 break;
1650
1651 case 7: // F1 Data
1652 {
1653 uint32_t chip = (*iptr>>19) & 0x07;
1654 uint32_t chan_on_chip = (*iptr>>16) & 0x07;
1655 uint32_t time = (*iptr>> 0) & 0xFFFF;
1656 uint32_t channel = F1TDC_channel(chip, chan_on_chip, modtype);
1657 if(VERBOSE>7) cout << " Found F1 data : chip=" << chip << " chan=" << chan_on_chip << " time=" << time << endl;
1658 if(pe) pe->NEW_DF1TDCHit(rocid, slot, channel, itrigger, trig_time_f1header, time, *iptr, MODULE_TYPE(modtype));
1659 }
1660 break;
1661
1662 case 15: // Filler word
1663 if(VERBOSE>7) cout << " F1 filler word" << endl;
1664 case 14: // Data not valid (how to handle this?)
1665 break;
1666
1667 default:
1668 cerr<<endl;
1669 cout.flush(); cerr.flush();
1670 _DBG_std::cerr<<"libraries/DAQ/DEVIOWorkerThread.cc"<<
":"<<1670<<" "
<<"Unknown data word in F1TDC block. Dumping for debugging:" << endl;
1671 for(const uint32_t *iiptr = istart; iiptr<iend; iiptr++){
1672 _DBG_std::cerr<<"libraries/DAQ/DEVIOWorkerThread.cc"<<
":"<<1672<<" "
<<"0x"<<hex<<*iiptr<<dec;
1673 if(iiptr == iptr)cerr<<" <----";
1674 switch( (*iiptr) & 0xF8000000 ){
1675 case 0x80000000: cerr << " F1 Block Header"; break;
1676 case 0x90000000: cerr << " F1 Event Header"; break;
1677 case 0x98000000: cerr << " F1 Trigger time"; break;
1678 case 0xC0000000: cerr << " F1 Header"; break;
1679 case 0xB8000000: cerr << " F1 Data"; break;
1680 case 0x88000000: cerr << " F1 Block Trailer"; break;
1681 case 0xF8000000: cerr << " Filler word"; break;
1682 case 0xF0000000: cerr << " <module has no valid data>"; break;
1683 default: break;
1684 }
1685 cerr<<endl;
1686 if(iiptr > (iptr+4)) break;
1687 }
1688 throw JException("Unexpected word type in F1TDC block!", __FILE__"libraries/DAQ/DEVIOWorkerThread.cc", __LINE__1688);
1689 break;
1690 }
1691 }
1692
1693 // Skip filler words
1694 while(iptr<iend && (*iptr&0xF8000000)==0xF8000000)iptr++;
1695}
1696
1697//----------------
1698// LinkAllAssociations
1699//----------------
1700void DEVIOWorkerThread::LinkAllAssociations(void)
1701{
1702 /// Find objects that should be linked as "associated objects"
1703 /// of one another and add to each other's list.
1704 for( auto pe : current_parsed_events){
1705
1706 //----------------- Sort all associations
1707 // fADC250
1708 if(pe->vDf250Config.size()>1 ) sort(pe->vDf250Config.begin(), pe->vDf250Config.end(), SortByROCID<Df250Config> );
1709 if(pe->vDf250TriggerTime.size()>1 ) sort(pe->vDf250TriggerTime.begin(), pe->vDf250TriggerTime.end(), SortByModule<Df250TriggerTime> );
1710 if(pe->vDf250PulseIntegral.size()>1) sort(pe->vDf250PulseIntegral.begin(), pe->vDf250PulseIntegral.end(), SortByPulseNumber<Df250PulseIntegral> );
1711 if(pe->vDf250PulseTime.size()>1 ) sort(pe->vDf250PulseTime.begin(), pe->vDf250PulseTime.end(), SortByPulseNumber<Df250PulseTime> );
1712 if(pe->vDf250PulsePedestal.size()>1) sort(pe->vDf250PulsePedestal.begin(), pe->vDf250PulsePedestal.end(), SortByPulseNumber<Df250PulsePedestal> );
1713
1714 // fADC125
1715 if(pe->vDf125Config.size()>1 ) sort(pe->vDf125Config.begin(), pe->vDf125Config.end(), SortByROCID<Df125Config> );
1716 if(pe->vDf125TriggerTime.size()>1 ) sort(pe->vDf125TriggerTime.begin(), pe->vDf125TriggerTime.end(), SortByModule<Df125TriggerTime> );
1717 if(pe->vDf125PulseIntegral.size()>1) sort(pe->vDf125PulseIntegral.begin(), pe->vDf125PulseIntegral.end(), SortByPulseNumber<Df125PulseIntegral> );
1718 if(pe->vDf125CDCPulse.size()>1 ) sort(pe->vDf125CDCPulse.begin(), pe->vDf125CDCPulse.end(), SortByChannel<Df125CDCPulse> );
1719 if(pe->vDf125FDCPulse.size()>1 ) sort(pe->vDf125FDCPulse.begin(), pe->vDf125FDCPulse.end(), SortByChannel<Df125FDCPulse> );
1720 if(pe->vDf125PulseTime.size()>1 ) sort(pe->vDf125PulseTime.begin(), pe->vDf125PulseTime.end(), SortByPulseNumber<Df125PulseTime> );
1721 if(pe->vDf125PulsePedestal.size()>1) sort(pe->vDf125PulsePedestal.begin(), pe->vDf125PulsePedestal.end(), SortByPulseNumber<Df125PulsePedestal> );
1722
1723 // F1TDC
1724 if(pe->vDF1TDCConfig.size()>1 ) sort(pe->vDF1TDCConfig.begin(), pe->vDF1TDCConfig.end(), SortByROCID<DF1TDCConfig> );
1725 if(pe->vDF1TDCTriggerTime.size()>1 ) sort(pe->vDF1TDCTriggerTime.begin(), pe->vDF1TDCTriggerTime.end(), SortByModule<DF1TDCTriggerTime> );
1726 if(pe->vDF1TDCHit.size()>1 ) sort(pe->vDF1TDCHit.begin(), pe->vDF1TDCHit.end(), SortByModule<DF1TDCHit> );
1727
1728 // CAEN1290TDC
1729 if(pe->vDCAEN1290TDCConfig.size()>1) sort(pe->vDCAEN1290TDCConfig.begin(), pe->vDCAEN1290TDCConfig.end(), SortByROCID<DCAEN1290TDCConfig> );
1730 if(pe->vDCAEN1290TDCHit.size()>1 ) sort(pe->vDCAEN1290TDCHit.begin(), pe->vDCAEN1290TDCHit.end(), SortByModule<DCAEN1290TDCHit> );
1731
1732
1733 //----------------- Link all associations
1734
1735 // Connect Df250Config objects
1736 LinkConfigSamplesCopy(pe->vDf250Config, pe->vDf250PulseIntegral);
1737
1738 // Connect Df125Config objects
1739 LinkConfigSamplesCopy(pe->vDf125Config, pe->vDf125PulseIntegral);
1740 LinkConfigSamplesCopy(pe->vDf125Config, pe->vDf125CDCPulse);
1741 LinkConfigSamplesCopy(pe->vDf125Config, pe->vDf125FDCPulse);
1742
1743 // Connect DF1TDCConfig objects
1744 LinkConfig(pe->vDF1TDCConfig, pe->vDF1TDCHit);
1745
1746 // Connect DCAEN1290TDCConfig objects
1747 LinkConfig(pe->vDCAEN1290TDCConfig, pe->vDCAEN1290TDCHit);
1748
1749 // Connect Df250TriggerTime objects
1750 LinkModule(pe->vDf250TriggerTime, pe->vDf250PulseIntegral);
1751
1752 // Connect Df125TriggerTime objects
1753 LinkModule(pe->vDf125TriggerTime, pe->vDf125PulseIntegral);
1754 LinkModule(pe->vDf125TriggerTime, pe->vDf125CDCPulse);
1755 LinkModule(pe->vDf125TriggerTime, pe->vDf125FDCPulse);
1756
1757 // Connect DF1TDCTriggerTime objects
1758 LinkModule(pe->vDF1TDCTriggerTime, pe->vDF1TDCHit);
1759
1760 // Connect Df250 pulse objects
1761 LinkPulse(pe->vDf250PulseTime, pe->vDf250PulseIntegral);
1762 LinkPulsePedCopy(pe->vDf250PulsePedestal, pe->vDf250PulseIntegral);
1763
1764 // Connect Df125 pulse objects
1765 LinkPulse(pe->vDf125PulseTime, pe->vDf125PulseIntegral);
1766 LinkPulsePedCopy(pe->vDf125PulsePedestal, pe->vDf125PulseIntegral);
1767
1768 // Connect Df250 window raw data objects
1769 if(!pe->vDf250WindowRawData.empty()){
1770 LinkConfig(pe->vDf250Config, pe->vDf250WindowRawData);
1771 LinkModule(pe->vDf250TriggerTime, pe->vDf250WindowRawData);
1772 LinkChannel(pe->vDf250WindowRawData, pe->vDf250PulseIntegral);
1773 LinkChannel(pe->vDf250WindowRawData, pe->vDf250PulseTime);
1774 LinkChannel(pe->vDf250WindowRawData, pe->vDf250PulsePedestal);
1775 }
1776
1777 // Connect Df125 window raw data objects
1778 if(!pe->vDf125WindowRawData.empty()){
1779 LinkConfig(pe->vDf125Config, pe->vDf125WindowRawData);
1780 LinkModule(pe->vDf125TriggerTime, pe->vDf125WindowRawData);
1781 LinkChannel(pe->vDf125WindowRawData, pe->vDf125PulseIntegral);
1782 LinkChannel(pe->vDf125WindowRawData, pe->vDf125PulseTime);
1783 LinkChannel(pe->vDf125WindowRawData, pe->vDf125PulsePedestal);
1784 LinkChannel(pe->vDf125WindowRawData, pe->vDf125CDCPulse);
1785 LinkChannel(pe->vDf125WindowRawData, pe->vDf125FDCPulse);
1786 }
1787
1788 }
1789
1790}
1791
1792//----------------
1793// DumpBinary
1794//----------------
1795void DEVIOWorkerThread::DumpBinary(const uint32_t *iptr, const uint32_t *iend, uint32_t MaxWords, const uint32_t *imark)
1796{
1797 /// This is used for debugging. It will print to the screen the words
1798 /// starting at the address given by iptr and ending just before iend
1799 /// or for MaxWords words, whichever comes first. If iend is NULL,
1800 /// then MaxWords will be printed. If MaxWords is zero then it is ignored
1801 /// and only iend is checked. If both iend==NULL and MaxWords==0, then
1802 /// only the word at iptr is printed.
1803
1804 cout << "Dumping binary: istart=" << hex << iptr << " iend=" << iend << " MaxWords=" << dec << MaxWords << endl;
1805
1806 if(iend==NULL__null && MaxWords==0) MaxWords=1;
1807 if(MaxWords==0) MaxWords = (uint32_t)0xffffffff;
1808
1809 uint32_t Nwords=0;
1810 while(iptr!=iend && Nwords<MaxWords){
1811
1812 // line1 is hex and line2 is decimal
1813 stringstream line1, line2;
1814
1815 // print words in columns 8 words wide. First part is
1816 // reserved for word number
1817 uint32_t Ncols = 8;
1818 line1 << setw(5) << Nwords;
1819 line2 << string(5, ' ');
1820
1821 // Loop over columns
1822 for(uint32_t i=0; i<Ncols; i++, iptr++, Nwords++){
1823
1824 if(iptr == iend) break;
1825 if(Nwords>=MaxWords) break;
1826
1827 stringstream iptr_hex;
1828 iptr_hex << hex << "0x" << *iptr;
1829
1830 string mark = (iptr==imark ? "*":" ");
1831
1832 line1 << setw(12) << iptr_hex.str() << mark;
1833 line2 << setw(12) << *iptr << mark;
1834 }
1835
1836 cout << line1.str() << endl;
1837 cout << line2.str() << endl;
1838 cout << endl;
1839 }
1840}
1841
1842