Bug Summary

File:/home/sdobbs/work/clang/halld_recon/src/libraries/DAQ/JEventSource_EVIO.cc
Warning:line 4780, column 67
Dereference of null pointer

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -main-file-name JEventSource_EVIO.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/JEventSource_EVIO.cc
1// $Id$
2// $HeadURL$
3//
4// File: JEventSource_EVIO.cc
5// Created: Tue Aug 7 15:22:29 EDT 2012
6// Creator: davidl (on Darwin harriet.jlab.org 11.4.0 i386)
7//
8
9// See comments in JEventSource_EVIO.h for overview description
10
11#include <unistd.h>
12#include <stdint.h>
13
14#include <string>
15#include <cmath>
16#include <iomanip>
17using namespace std;
18
19
20// This flag allows us to switch back and forth from using HDEVIO and
21// the CODA-supplied EVIO
22#define USE_HDEVIO1 1
23
24//#define ENABLE_UPSAMPLING
25
26#ifdef HAVE_EVIO1
27
28#if USE_HDEVIO1 == 0
29#include <evioFileChannel.hxx>
30#endif
31
32extern "C" uint32_t *swap_int32_t(uint32_t *data, unsigned int length, uint32_t *dest);
33#endif // HAVE_EVIO
34
35#ifdef HAVE_ET
36//#include <evioETChannel.hxx>
37#include <et.h>
38#endif // HAVE_ET
39
40#include "JEventSourceGenerator_EVIO.h"
41//#include "JFactoryGenerator_DAQ.h"
42#include "JEventSource_EVIO.h"
43
44using namespace jana;
45
46#include <DANA/DStatusBits.h>
47#include <TTAB/DTranslationTable.h>
48#include <TTAB/DTranslationTable_factory.h>
49#include <DAQ/Df125EmulatorAlgorithm_factory.h>
50#include <DAQ/Df250EmulatorAlgorithm_factory.h>
51
52#define _DBG_DAQ(A)cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<":"<<
52<<" 0x"<<hex<<A<<" cntrl:0x"<<
(A&0xF0000000)<<dec<<" slot:"<<((A>>
22)&0x1F)<<endl
cerr<<__FILE__"libraries/DAQ/JEventSource_EVIO.cc"<<":"<<__LINE__52<<" 0x"<<hex<<A<<" cntrl:0x"<<(A&0xF0000000)<<dec<<" slot:"<<((A>>22)&0x1F)<<endl
53
54// Make us a plugin
55#include <JANA/JApplication.h>
56//extern "C"{
57// void InitPlugin(JApplication *app){
58// InitJANAPlugin(app);
59// app->AddEventSourceGenerator(new JEventSourceGenerator_EVIO());
60// app->AddFactoryGenerator(new JFactoryGenerator_DAQ());
61// }
62//} // "C"
63
64// if we don't find a run number in the file, then it's nice to let the user know
65static bool WARN_USER_RUN_FILENAME = false;
66
67set<uint32_t> ROCIDS_TO_PARSE;
68
69//:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
70// If EVIO support is not available, define dummy methods
71#ifndef HAVE_EVIO1
72JEventSource_EVIO::JEventSource_EVIO(const char* source_name):JEventSource(source_name){
73 cerr << endl;
74 cerr << "You are trying to use code requiring EVIO when support" << endl;
75 cerr << "for EVIO was not built into this binary. Set your" << endl;
76 cerr << "EVIOROOT *and* your ETROOT environment variables to" << endl;
77 cerr << "point to your EVIO installation and recompile." << endl;
78 cerr << endl;
79 exit(-1);
80}
81 JEventSource_EVIO::~JEventSource_EVIO(){}
82jerror_t JEventSource_EVIO::GetEvent(jana::JEvent &event){return NOERROR;}
83 void JEventSource_EVIO::FreeEvent(jana::JEvent &event){}
84jerror_t JEventSource_EVIO::GetObjects(jana::JEvent &event, jana::JFactory_base *factory){return NOERROR;}
85jerror_t JEventSource_EVIO::ReadEVIOEvent(uint32_t* &buf){return NOERROR;}
86//:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
87
88#else // HAVE_EVIO
89
90//----------------
91// Constructor
92//----------------
93JEventSource_EVIO::JEventSource_EVIO(const char* source_name):JEventSource(source_name)
94{
95 // Initialize connection objects and flags to NULL
96 Nunparsed = 0;
97 no_more_events_in_source = false;
98 et_connected = false;
99 //chan = NULL;
100 hdevio = NULL__null;
101 source_type = kNoSource;
102 quit_on_next_ET_timeout = false;
103
104 // Initialize dedicated JStreamLog used for debugging messages
105 evioout.SetTag("--- EVIO ---: ");
106 evioout.SetTimestampFlag();
107 evioout.SetThreadstampFlag();
108
109 // Define base set of status bits
110 if(japp) DStatusBits::SetStatusBitDescriptions(japp);
111
112 // Get configuration parameters
113 AUTODETECT_MODULE_TYPES = true;
114 DUMP_MODULE_MAP = false;
115 MAKE_DOM_TREE = true;
116 PARSE_EVIO_EVENTS = true;
117 PARSE_F250 = true;
118 PARSE_F125 = true;
119 PARSE_F1TDC = true;
120 PARSE_CAEN1290TDC = true;
121 PARSE_CONFIG = true;
122 PARSE_BOR = true;
123 PARSE_EPICS = true;
124 PARSE_EVENTTAG = true;
125 PARSE_TRIGGER = true;
126 BUFFER_SIZE = 20000000; // in bytes
127 ET_STATION_NEVENTS = 10;
128 ET_STATION_CREATE_BLOCKING = false;
129 ET_DEBUG_WORDS_TO_DUMP = 0;
130 LOOP_FOREVER = false;
131 VERBOSE = 0;
132 TIMEOUT = 2.0;
133 MODTYPE_MAP_FILENAME = "modtype.map";
134 ENABLE_DISENTANGLING = true;
135 EVIO_SPARSE_READ = false;
136 EVENT_MASK = "";
137
138 F125_EMULATION_MODE = kEmulationAuto;
139 F250_EMULATION_MODE = kEmulationAuto;
140
141 USER_RUN_NUMBER = 0;
142 F125PULSE_NUMBER_FILTER = 1000;
143 F250PULSE_NUMBER_FILTER = 1000;
144
145 if(gPARMS){
146 // JANA doesn't know about EmulationModeType so we use temporary variables
147 uint32_t f250_emulation_mode = F250_EMULATION_MODE;
148 uint32_t f125_emulation_mode = F125_EMULATION_MODE;
149
150 gPARMS->SetDefaultParameter("EVIO:AUTODETECT_MODULE_TYPES", AUTODETECT_MODULE_TYPES, "Try and guess the module type tag,num values for which there is no module map entry.");
151 gPARMS->SetDefaultParameter("EVIO:DUMP_MODULE_MAP", DUMP_MODULE_MAP, "Write module map used to file when source is destroyed. n.b. If more than one input file is used, the map file will be overwritten!");
152 gPARMS->SetDefaultParameter("EVIO:MAKE_DOM_TREE", MAKE_DOM_TREE, "Set this to 0 to disable generation of EVIO DOM Tree and parsing of event. (for benchmarking/debugging)");
153 gPARMS->SetDefaultParameter("EVIO:PARSE_EVIO_EVENTS", PARSE_EVIO_EVENTS, "Set this to 0 to disable parsing of event but still make the DOM tree, so long as MAKE_DOM_TREE isn't set to 0. (for benchmarking/debugging)");
154 gPARMS->SetDefaultParameter("EVIO:PARSE_F250", PARSE_F250, "Set this to 0 to disable parsing of data from F250 ADC modules (for benchmarking/debugging)");
155 gPARMS->SetDefaultParameter("EVIO:PARSE_F125", PARSE_F125, "Set this to 0 to disable parsing of data from F125 ADC modules (for benchmarking/debugging)");
156 gPARMS->SetDefaultParameter("EVIO:PARSE_F1TDC", PARSE_F1TDC, "Set this to 0 to disable parsing of data from F1TDC modules (for benchmarking/debugging)");
157 gPARMS->SetDefaultParameter("EVIO:PARSE_CAEN1290TDC", PARSE_CAEN1290TDC, "Set this to 0 to disable parsing of data from CAEN 1290 TDC modules (for benchmarking/debugging)");
158 gPARMS->SetDefaultParameter("EVIO:PARSE_CONFIG", PARSE_CONFIG, "Set this to 0 to disable parsing of ROC configuration data in the data stream (for benchmarking/debugging)");
159 gPARMS->SetDefaultParameter("EVIO:PARSE_BOR", PARSE_BOR, "Set this to 0 to disable parsing of BOR events from the data stream (for benchmarking/debugging)");
160 gPARMS->SetDefaultParameter("EVIO:PARSE_EPICS", PARSE_EPICS, "Set this to 0 to disable parsing of EPICS events from the data stream (for benchmarking/debugging)");
161 gPARMS->SetDefaultParameter("EVIO:PARSE_EVENTTAG", PARSE_EVENTTAG, "Set this to 0 to disable parsing of event tag data in the data stream (for benchmarking/debugging)");
162 gPARMS->SetDefaultParameter("EVIO:PARSE_TRIGGER", PARSE_TRIGGER, "Set this to 0 to disable parsing of the built trigger bank from CODA (for benchmarking/debugging)");
163
164 gPARMS->SetDefaultParameter("EVIO:BUFFER_SIZE", BUFFER_SIZE, "Size in bytes to allocate for holding a single EVIO event.");
165 gPARMS->SetDefaultParameter("EVIO:ET_STATION_NEVENTS", ET_STATION_NEVENTS, "Number of events to use if we have to create the ET station. Ignored if station already exists.");
166 gPARMS->SetDefaultParameter("EVIO:ET_STATION_CREATE_BLOCKING", ET_STATION_CREATE_BLOCKING, "Set this to 0 to create station in non-blocking mode (default is to create it in blocking mode). Ignored if station already exists.");
167 gPARMS->SetDefaultParameter("EVIO:ET_DEBUG_WORDS_TO_DUMP", ET_DEBUG_WORDS_TO_DUMP, "Number of words to dump to screen from ET buffer (useful for debugging only).");
168 gPARMS->SetDefaultParameter("EVIO:LOOP_FOREVER", LOOP_FOREVER, "If reading from EVIO file, keep re-opening file and re-reading events forever (only useful for debugging) If reading from ET, this is ignored.");
169 gPARMS->SetDefaultParameter("EVIO:VERBOSE", VERBOSE, "Set verbosity level for processing and debugging statements while parsing. 0=no debugging messages. 10=all messages");
170 gPARMS->SetDefaultParameter("ET:TIMEOUT", TIMEOUT, "Set the timeout in seconds for each attempt at reading from ET system (repeated attempts will still be made indefinitely until program quits or the quit_on_et_timeout flag is set.");
171 gPARMS->SetDefaultParameter("EVIO:MODTYPE_MAP_FILENAME", MODTYPE_MAP_FILENAME, "Optional module type conversion map for use with files generated with the non-standard module types");
172 gPARMS->SetDefaultParameter("EVIO:ENABLE_DISENTANGLING", ENABLE_DISENTANGLING, "Enable/disable disentangling of multi-block events. Enabled by default. Set to 0 to disable.");
173 gPARMS->SetDefaultParameter("EVIO:SPARSE_READ", EVIO_SPARSE_READ, "Set to true to enable sparse reading of the EVIO file. This will take some time to map out the entire file prior to event processing. It is typically only useful if the EVIO:EVENT_MASK variable is set.");
174 gPARMS->SetDefaultParameter("EVIO:EVENT_MASK", EVENT_MASK, "Commas separated list used to set the mask that selects the type of events to read in. Other types will be skipped. Valid values are EPICS,BOR and PHYSICS");
175
176 gPARMS->SetDefaultParameter("EVIO:F250_EMULATION_MODE", f250_emulation_mode, "Set f250 emulation mode. 0=no emulation, 1=always, 2=auto. Default is 2 (auto).");
177 gPARMS->SetDefaultParameter("EVIO:F125_EMULATION_MODE", f125_emulation_mode, "Set f125 emulation mode. 0=no emulation, 1=always, 2=auto. Default is 2 (auto).");
178
179 gPARMS->SetDefaultParameter("EVIO:RUN_NUMBER", USER_RUN_NUMBER, "User-supplied run number. Override run number from other sources with this.(will be ignored if set to zero)");
180 gPARMS->SetDefaultParameter("EVIO:F125PULSE_NUMBER_FILTER", F125PULSE_NUMBER_FILTER, "Ignore data for DF125XXX objects with a pulse number equal or greater than this.");
181 gPARMS->SetDefaultParameter("EVIO:F250PULSE_NUMBER_FILTER", F250PULSE_NUMBER_FILTER, "Ignore data for DF250XXX objects with a pulse number equal or greater than this.");
182
183 F250_EMULATION_MODE = (EmulationModeType)f250_emulation_mode;
184 F125_EMULATION_MODE = (EmulationModeType)f125_emulation_mode;
185 }
186
187 // Try to open the file.
188 try {
189
190 if(VERBOSE>0) evioout << "Attempting to open \""<<this->source_name<<"\" as EVIO file..." <<endl;
191
192#if USE_HDEVIO1
193 //---------- HDEVIO ------------
194 hdevio = new HDEVIO(this->source_name);
195 if( ! hdevio->is_open ) throw std::exception(); // throw exception if unable to open
196 if(EVENT_MASK.length()!=0) hdevio->SetEventMask(EVENT_MASK);
197 if(EVIO_SPARSE_READ) hdevio->PrintFileSummary();
198#else // USE_HDEVIO
199 //-------- CODA EVIO -----------
200 jerr << "You are attempting to use the CODA Channels library for reading" << endl;
201 jerr << "and EVIO file and this mechanism has been disabled from in the" << endl;
202 jerr << "DAQ library. Contact davidl@jlab.org if you need this to be" << endl;
203 jerr << "reinstated." << endl;
204 quit(0);
205 //chan = new evioFileChannel(this->source_name, "r", BUFFER_SIZE);
206 //chan->open(); // open the file. Throws exception if not successful
207
208#endif // USE_HDEVIO
209
210 source_type = kFileSource;
211
212 } catch (std::exception &e) {
213
214#ifdef HAVE_ET
215 // Could not open file. Check if name starts with "ET:"
216 //chan = NULL;
217 if(this->source_name.substr(0,3) == "ET:"){
218 if(VERBOSE>0) evioout << "Attempting to open \""<<this->source_name<<"\" as ET (network) source..." <<endl;
219 ConnectToET(source_name);
220 }
221
222 if(!et_connected) throw JException("Failed to open ET system: " + this->source_name);
223
224 // open the channel. Throws exception if not successful
225 // chan->open(); // evioETchannel no longer used
226 source_type = kETSource;
227
228#else // HAVE_ET
229
230 // No ET and the file didn't work so re-throw the exception
231 if(this->source_name.substr(0,3) == "ET:"){
232 cerr << endl;
233 cerr << "=== ERROR: ET source specified and this was compiled without ===" << endl;
234 cerr << "=== ET support. You need to install ET and set your ===" << endl;
235 cerr << "=== ETROOT environment variable appropriately before ===" << endl;
236 cerr << "=== recompiling. ===" << endl;
237 cerr << endl;
238 }
239 throw e;
240
241#endif // HAVE_ET
242 }
243 if(VERBOSE>0) evioout << "Success opening event source \"" << this->source_name << "\"!" <<endl;
244
245
246 // Create list of data types this event source can provide
247 // (must match what is returned by JObject::className() )
248 // n.b. there is an ugly hack down in GetObjects that will
249 // probably also need a line added for each data type added
250 // here.
251 event_source_data_types.insert("Df250Config");
252 event_source_data_types.insert("Df250PulseIntegral");
253 event_source_data_types.insert("Df250StreamingRawData");
254 event_source_data_types.insert("Df250WindowSum");
255 event_source_data_types.insert("Df250PulseRawData");
256 event_source_data_types.insert("Df250TriggerTime");
257 event_source_data_types.insert("Df250PulseTime");
258 event_source_data_types.insert("Df250PulsePedestal");
259 event_source_data_types.insert("Df250WindowRawData");
260 event_source_data_types.insert("Df125Config");
261 event_source_data_types.insert("Df125PulseIntegral");
262 event_source_data_types.insert("Df125TriggerTime");
263 event_source_data_types.insert("Df125PulseTime");
264 event_source_data_types.insert("Df125PulsePedestal");
265 event_source_data_types.insert("Df125WindowRawData");
266 event_source_data_types.insert("Df125CDCPulse");
267 event_source_data_types.insert("Df125FDCPulse");
268 event_source_data_types.insert("DF1TDCConfig");
269 event_source_data_types.insert("DF1TDCHit");
270 event_source_data_types.insert("DF1TDCTriggerTime");
271 event_source_data_types.insert("DCAEN1290TDCConfig");
272 event_source_data_types.insert("DCAEN1290TDCHit");
273 event_source_data_types.insert("DCODAEventInfo");
274 event_source_data_types.insert("DCODAROCInfo");
275 event_source_data_types.insert("DTSscalers");
276 event_source_data_types.insert("DEPICSvalue");
277 event_source_data_types.insert("DEventTag");
278 event_source_data_types.insert("DL1Info");
279 event_source_data_types.insert("Df250Scaler");
280 event_source_data_types.insert("Df250AsyncPedestal");
281 //event_source_data_types.insert("DVertex");
282
283 // Read in optional module type translation map if it exists
284 ReadOptionalModuleTypeTranslation();
285
286 last_run_number = 0;
287 filename_run_number = 0;
288 current_event_count = 0;
289
290 // Try extracting the run number from the filename. (This is
291 // only used if the run number is not found in the EVIO data.)
292 size_t pos2 = this->source_name.find_last_of('_');
293 if(pos2 != string::npos){
294 size_t pos1 = this->source_name.find_last_of('_', pos2-1);
295 if(pos1 != string::npos){
296 pos1++;
297 string runstr = this->source_name.substr(pos1, pos2-pos1);
298 if(runstr.length()>0) filename_run_number = atoi(runstr.c_str());
299 }
300 }
301
302 pthread_mutex_init(&evio_buffer_pool_mutex, NULL__null);
303 pthread_mutex_init(&stored_events_mutex, NULL__null);
304 pthread_mutex_init(&current_event_count_mutex, NULL__null);
305 pthread_rwlock_init(&BOR_lock, NULL__null);
306}
307
308//----------------
309// Destructor
310//----------------
311JEventSource_EVIO::~JEventSource_EVIO()
312{
313 // close event source here
314// if(chan){
315// if(VERBOSE>0) evioout << "Closing event source \"" << this->source_name << "\"" <<endl;
316// chan->close();
317// delete chan;
318// }
319
320#ifdef HAVE_ET
321 if(et_connected){
322 if(VERBOSE>0) evioout << "Closing ET connection \"" << this->source_name << "\"" <<endl;
323 et_close(sys_id);
324 et_connected = false;
325 }
326#endif
327
328 if(hdevio){
329 if(VERBOSE>0) evioout << "Closing hdevio event source \"" << this->source_name << "\"" <<endl;
330 hdevio->PrintStats();
331 delete hdevio;
332 }
333
334 // Release memory used for the event buffer pool
335 while(!evio_buffer_pool.empty()){
336 free(evio_buffer_pool.front());
337 evio_buffer_pool.pop_front();
338 }
339
340 // Delete any BOR config objects
341 for(uint32_t i=0; i<BORobjs.size(); i++) delete BORobjs[i];
342 BORobjs.clear();
343
344 // Optionally dump the module map
345 if(DUMP_MODULE_MAP)DumpModuleMap();
346}
347
348//---------------------------------
349// ReadOptionalModuleTypeTranslation
350//---------------------------------
351void JEventSource_EVIO::ReadOptionalModuleTypeTranslation(void)
352{
353 // Some data may be taken with bad ROLs or drivers that
354 // write module type values that are non-standard. This
355 // allows the user to specify a simple text file that
356 // can be read in to translate the types found in the
357 // file to another type so that they can be properly parsed.
358 ifstream ifs(MODTYPE_MAP_FILENAME.c_str());
359 if(!ifs.is_open()) return;
360
361 cout << "Opened JLab module type translation map: " << endl;
362 cout << " " << MODTYPE_MAP_FILENAME << endl;
363 while(ifs.good()){
364 char line[256];
365 ifs.getline(line, 256);
366 if(ifs.gcount() < 1) break;
367 if(line[0] == '#') continue;
368
369 stringstream ss(line);
370 uint32_t from=10000, to=10000;
371 ss >> from >> to; // from=evio to=TT
372 if( to==10000 ){
373 if( from!=10000){
374 cout << "unable to convert line:" << endl;
375 cout << " " << line;
376 }
377 }else{
378 modtype_translate[(MODULE_TYPE)from] = (MODULE_TYPE)to;
379 }
380 }
381 ifs.close();
382
383 cout << " Read " << modtype_translate.size() << " entries" << endl;
384 map<MODULE_TYPE,MODULE_TYPE>::iterator iter;
385 for(iter=modtype_translate.begin(); iter != modtype_translate.end(); iter++){
386 cout << " type " << iter->first << " -> type " << iter->second << endl;
387 }
388}
389
390//----------------
391// ConnectToET
392//----------------
393void JEventSource_EVIO::ConnectToET(const char* source_name)
394{
395#ifdef HAVE_ET
396
397 /// Format for ET source strings is:
398 ///
399 /// ET:session:station:host:port
400 ///
401 /// The session is used to form the filename of the ET
402 /// system. For example, if an session of "eb" is specified,
403 /// then a file named "/tmp/et_sys_eb" is assumed to be
404 /// what should be opened. If no session is specified (or
405 /// an empty session name) then "none" is used as the session.
406 ///
407 /// If the station name specified does not exist, it will
408 /// be created. If it does exist, the existing station will
409 /// be used. If no station is specified, then the station
410 /// name "DANA" will be used. Any station created will be
411 /// set to "blocking" *unless* the configuration paramter
412 /// EVIO:ET_STATION_CREATE_BLOCKING is set to "0"
413 /// in which case it will be set to non-blocking.
414 ///
415 /// If the host is specified, then an attempt will be made
416 /// to open that system. If it is not specified, then
417 /// it will attempt to open an ET system on the local machine.
418 ///
419 /// If port is specified, it is used as the TCP port number
420 /// on the remote host to attach to. If the host is not
421 /// specified (i.e. by having two colons and therefore
422 /// an empty string) then the port is ignored. If the
423 /// port is omitted or specified as "0", then the default
424 /// port is used.
425 ///
426
427 // Split source name into session, station, etc...
428 vector<string> fields;
429 string str = source_name;
430 size_t startpos=0, endpos=0;
431 while((endpos = str.find(":", startpos)) != str.npos){
432 size_t len = endpos-startpos;
433 fields.push_back(len==0 ? "":str.substr(startpos, len));
434 startpos = endpos+1;
435 }
436 if(startpos<str.length()) fields.push_back(str.substr(startpos, str.npos));
437
438 string session = fields.size()>1 ? fields[1]:"";
439 string station = fields.size()>2 ? fields[2]:"";
440 string host = fields.size()>3 ? fields[3]:"localhost";
441 int port = fields.size()>4 ? atoi(fields[4].c_str()):ET_SERVER_PORT;
442
443 if(session == "") session = "none";
444 if(station == "") station = "DANA";
445 if(host == "") host = "localhost";
446 string fname = session.at(0)=='/' ? session:(string("/tmp/et_sys_") + session);
447
448 // Report to user what we're doing
449 jout << " Opening ET system:" << endl;
450 if(session!=fname) jout << " session: " << session << endl;
451 jout << " station: " << station << endl;
452 jout << " system file: " << fname << endl;
453 jout << " host: " << host << endl;
454 if(port !=0) jout << " port: " << port << endl;
455
456 // connect to the ET system
457 et_openconfig openconfig;
458 et_open_config_init(&openconfig);
459 if(host != ""){
460 if(host.find("239.")==0){
461 cout<<__FILE__"libraries/DAQ/JEventSource_EVIO.cc"<<":"<<__LINE__461<<" Configuring input ET for multicast" << endl;
462 et_open_config_setcast(openconfig, ET_MULTICAST);
463 et_open_config_addmulticast(openconfig, host.c_str());
464 et_open_config_sethost(openconfig, ET_HOST_ANYWHERE);
465 et_open_config_setport(openconfig, port);
466 struct timespec tspec={5,5};
467 et_open_config_settimeout(openconfig, tspec);
468 et_open_config_setwait(openconfig, ET_OPEN_WAIT);
469 }else{
470 cout<<__FILE__"libraries/DAQ/JEventSource_EVIO.cc"<<":"<<__LINE__470<<" Configuring input ET for direct connection" << endl;
471 et_open_config_setcast(openconfig, ET_DIRECT);
472 et_open_config_setmode(openconfig, ET_HOST_AS_LOCAL); // ET_HOST_AS_LOCAL or ET_HOST_AS_REMOTE
473 et_open_config_sethost(openconfig, host.c_str());
474 et_open_config_setport(openconfig, ET_BROADCAST_PORT);
475 if(port != 0)et_open_config_setserverport(openconfig, port);
476 }
477 }
478 int err = et_open(&sys_id,fname.c_str(),openconfig);
479 if(err != ET_OK){
480 cerr << __FILE__"libraries/DAQ/JEventSource_EVIO.cc"<<":"<<__LINE__480<<" Problem opening ET system"<<endl;
481 cerr << et_perror(err);
482 return;
483 }
484
485 // create station config in case no station exists
486 et_statconfig et_station_config;
487 et_station_config_init(&et_station_config);
488 et_station_config_setblock(et_station_config, ET_STATION_CREATE_BLOCKING ? ET_STATION_BLOCKING:ET_STATION_NONBLOCKING);
489 et_station_config_setselect(et_station_config,ET_STATION_SELECT_ALL);
490 et_station_config_setuser(et_station_config,ET_STATION_USER_MULTI);
491 et_station_config_setrestore(et_station_config,ET_STATION_RESTORE_OUT);
492 et_station_config_setcue(et_station_config,ET_STATION_NEVENTS);
493 et_station_config_setprescale(et_station_config,1);
494 cout<<"ET station configured\n";
495
496 // create station if not already created
497 int status=et_station_create(sys_id,&sta_id,station.c_str(),et_station_config);
498 if((status!=ET_OK)&&(status!=ET_ERROR_EXISTS)) {
499 et_close(sys_id);
500 cerr << "Unable to create station " << station << endl;
501 cerr << et_perror(status);
502
503 // Check that the number of events in the ET system is not
504 // less than the number of events we specified for the station CUE.
505 int Nevents = 0;
506 et_system_getnumevents(sys_id, &Nevents);
507 if(Nevents <= ET_STATION_NEVENTS){
508 jerr << "NOTE: The number of events specified for the station cue is equal to" << endl;
509 jerr << "or greater than the number of events in the entire ET system:" << endl;
510 jerr << endl;
511 jerr << " " << ET_STATION_NEVENTS << " >= " << Nevents << endl;
512 jerr << endl;
513 jerr << "Try re-running with: " << endl;
514 jerr << endl;
515 jerr << " -PEVIO:ET_STATION_NEVENTS=" << (Nevents+1)/2 << endl;
516 jerr << endl;
517 }
518 return;
519 }
520 if(status==ET_ERROR_EXISTS){
521 jout << " Using existing ET station " << station << endl;
522 }else{
523 jout << " ET station " << station << " created\n";
524 }
525
526 // Attach to the ET station
527 status=et_station_attach(sys_id,sta_id,&att_id);
528 if(status!=ET_OK) {
529 et_close(sys_id);
530 jerr << "Unable to attach to station " << station << endl;
531 return;
532 }
533
534 jout << "...now connected to ET system: " << fname
535 << ", station: " << station << " (station id=" << sta_id << ", attach id=" << att_id <<")" << endl;
536
537 et_connected = true;
538 // chan = new evioETChannel(sys_id, att_id);
539
540 // Make sure the size of event buffers we will allocate are at least as big
541 // as the event size used in the ET system
542 size_t eventsize;
543 et_system_geteventsize(sys_id, &eventsize);
544 if((uint32_t)eventsize > BUFFER_SIZE){
545 jout<<" Events in ET system are larger than currently set buffer size:"<<endl;
546 jout<<" "<<eventsize<<" > "<<BUFFER_SIZE<<endl;
547 jout<<" Setting BUFFER_SIZE to "<<eventsize<<endl;
548 BUFFER_SIZE = (uint32_t)eventsize;
549 }else{
550 jout<<" ET system event size:"<<eventsize<<" JEventSource_EVIO.BUFFER_SIZE:"<<BUFFER_SIZE<<endl;
551 }
552
553#else
554 jerr << endl;
555 jerr << "You are attempting to connect to an ET system using a binary that" <<endl;
556 jerr << "was compiled without ET support. Please reconfigure and recompile" <<endl;
557 jerr << "To get ET support." << endl;
558 jerr << endl;
559 throw exception();
560#endif // HAVE_ET
561}
562
563//----------------
564// Cleanup
565//----------------
566void JEventSource_EVIO::Cleanup(void)
567{
568 /// This is called internally by the JEventSource_EVIO class
569 /// once all events have been read in. Its purpose is to
570 /// free the hidden memory in all of the container class
571 /// members of the JEventSource_EVIO class. This is needed
572 /// for jobs that process a lot of input files and therefore
573 /// create a lot JEventSource_EVIO objects. JANA does not delete
574 /// these objects until the end of the job so this tends to
575 /// act like a memory leak. The data used can be substantial
576 /// (nearly 1GB per JEventSource_EVIO object).
577 if(hdevio) delete hdevio;
578 hdevio = NULL__null;
579 //if(chan) delete chan;
580 //chan = NULL;
581#ifdef HAVE_ET
582 if(et_connected) et_close(sys_id);
583 et_connected = false;
584#endif // HAVE_ET
585
586 module_type.clear();
587 modtype_translate.clear();
588
589 for(uint32_t i=0; i<hit_objs.size(); i++) hit_objs[i].resize(0);
590 hit_objs.resize(0);
591
592 while(!stored_events.empty()){
593 delete stored_events.front();
594 stored_events.pop();
595 }
596 while(!evio_buffer_pool.empty()) {
597 delete evio_buffer_pool.back();
598 evio_buffer_pool.pop_back();
599 }
600 while(!event_source_data_types.empty()){
601 event_source_data_types.erase(event_source_data_types.begin());
602 }
603}
604
605//----------------
606// GetEvent
607//----------------
608jerror_t JEventSource_EVIO::GetEvent(JEvent &event)
609{
610 if(VERBOSE>1) evioout << "GetEvent called for &event = " << hex << &event << dec << endl;
611
612 // If we couldn't even open the source, then there's nothing to do
613 bool no_source = true;
614#if USE_HDEVIO1
615 if(source_type==kFileSource){
616 if(no_more_events_in_source)
617 no_source = false;
618 else if(hdevio->is_open) // n.b. hdevio may be NULL if no_more_events_in_source==true
619 no_source = false;
620 }
621#endif
622 if(source_type==kETSource && et_connected) no_source = false;
623 if(no_source)throw JException(string("Unable to open EVIO channel for \"") + source_name + "\"");
624
625
626 // This may not be a long term solution, but here goes:
627 // We need to write single events out in EVIO format, possibly
628 // with new information attached. The easiest way to do this
629 // is to keep the DOM tree when the event is read in and modify
630 // it if needed before writing it out. The complication comes
631 // in that entangled events will not have a dedicated DOM tree
632 // for every event. This is only an issue if disentangling is
633 // not done upstream. How this is handled now is that the DOM
634 // tree pointer is copied into the ObjList object for the first
635 // physics event found in the DAQ event. The DOM tree is freed
636 // in FreeEvent (if the pointer is non-NULL). Note that for
637 // single event blocks (i.e. already disentangled events) the
638 // stored_events list will always be empty so "evt" is always
639 // set.
640
641 // Check for event stored from parsing a previously read in
642 // DAQ event
643 ObjList *objs_ptr = NULL__null;
644 pthread_mutex_lock(&stored_events_mutex);
645 if(!stored_events.empty()){
646 objs_ptr = stored_events.front();
647 stored_events.pop();
648
649 // If this is a stored event then it almost certainly
650 // came from a multi-event block of physics events.
651 // Set the physics event status bit.
652 event.SetStatusBit(kSTATUS_PHYSICS_EVENT);
653 }
654 pthread_mutex_unlock(&stored_events_mutex);
655
656 // If no events are currently stored in the buffer, then
657 // read in another event block.
658 if(objs_ptr == NULL__null){
659
660 uint32_t *buff = NULL__null; // ReadEVIOEvent will allocate memory from pool for this
661 double t1 = GetTime();
662 jerror_t err = no_more_events_in_source ? NO_MORE_EVENTS_IN_SOURCE:ReadEVIOEvent(buff);
663 double t2 = GetTime();
664
665 // If there are no more events to read from the source but there are
666 // buffers yet to be parsed, then we need to give those buffers
667 // a chance to be parsed so we can return an event it may contain.
668 if(err == NO_MORE_EVENTS_IN_SOURCE){
669 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<669<<" "
<<endl<<"-- No more events in source. Waiting for all buffers to be parsed (" << Nunparsed<<") ..." << endl;
670 no_more_events_in_source = true;
671 while(Nunparsed>0 && !japp->GetQuittingStatus()) usleep(1000);
672 pthread_mutex_lock(&stored_events_mutex);
673 if(stored_events.empty()){
674 pthread_mutex_unlock(&stored_events_mutex);
675 return NO_MORE_EVENTS_IN_SOURCE;
676 }
677
678 objs_ptr = stored_events.front();
679 stored_events.pop();
680 event.SetStatusBit(kSTATUS_PHYSICS_EVENT);
681
682 pthread_mutex_unlock(&stored_events_mutex);
683
684 err = NOERROR;
685 }
686 if(err != NOERROR) return err;
687 if(objs_ptr == NULL__null){
688 if(buff == NULL__null) return MEMORY_ALLOCATION_ERROR;
689 uint32_t buff_size = ((*buff) + 1)*4; // first word in EVIO buffer is total bank size in words
690
691 objs_ptr = new ObjList();
692 objs_ptr->time_evio_read = t2 - t1;
693 objs_ptr->eviobuff = buff;
694 objs_ptr->eviobuff_size = buff_size;
695 objs_ptr->run_number = FindRunNumber(buff);
696 objs_ptr->event_number = FindEventNumber(buff);
697
698 // Increment counter that keeps track of how many buffers still
699 // need to be parsed (decremented in ParseEvents)
700 pthread_mutex_lock(&stored_events_mutex);
701 Nunparsed++;
702 pthread_mutex_unlock(&stored_events_mutex);
703
704 // Increment counter that keeps track of how many events
705 // are currently being processed (decremented in FreeEvent)
706 pthread_mutex_lock(&current_event_count_mutex);
707 current_event_count++;
708 pthread_mutex_unlock(&current_event_count_mutex);
709 }
710 }
711
712 // Store a pointer to the ObjList object for this event in the
713 // JEvent as the Reference value. Parsing will be done later
714 // in GetObjects() -> ParseEvents() using the eviobuff pointer.
715 event.SetJEventSource(this);
716 event.SetEventNumber((uint64_t)objs_ptr->event_number);
717 event.SetRunNumber(objs_ptr->run_number);
718 event.SetRef(objs_ptr);
719 event.SetStatusBit(kSTATUS_EVIO);
720 if( source_type == kFileSource ) event.SetStatusBit(kSTATUS_FROM_FILE);
721 if( source_type == kETSource ) event.SetStatusBit(kSTATUS_FROM_ET);
722 if(objs_ptr)
723 if(objs_ptr->eviobuff) FindEventType(objs_ptr->eviobuff, event);
724
725 // EPICS and BOR events are barrier events
726 if(event.GetStatusBit(kSTATUS_EPICS_EVENT) || event.GetStatusBit(kSTATUS_BOR_EVENT) ){
727 event.SetSequential();
728 }
729
730 Nevents_read++;
731
732 return NOERROR;
733}
734
735//----------------
736// FreeEvent
737//----------------
738void JEventSource_EVIO::FreeEvent(JEvent &event)
739{
740 if(VERBOSE>1) evioout << "FreeEvent called for event: " << event.GetEventNumber() << endl;
741
742 ObjList *objs_ptr = (ObjList*)event.GetRef();
743 if(objs_ptr){
744
745 // If a DAQ event was read in but GetObjects never called
746 // then the buffer will never have been parsed. Since the
747 // DAQ event could hold multiple Physics events, we parse
748 // it now to ensure all physics events are presented by
749 // the event source. The ParseEvents call will copy the
750 // first event's parameters into our objs_ptr object, but
751 // any additional ones will be placed in stored_events.
752 if(!objs_ptr->eviobuff_parsed) ParseEvents(objs_ptr);
753
754 if(objs_ptr->own_objects){
755
756 for(unsigned int i=0; i<objs_ptr->hit_objs.size(); i++){
757 delete objs_ptr->hit_objs[i];
758 }
759
760 for(unsigned int i=0; i<objs_ptr->config_objs.size(); i++){
761 delete objs_ptr->config_objs[i];
762 }
763
764 for(unsigned int i=0; i<objs_ptr->misc_objs.size(); i++){
765 delete objs_ptr->misc_objs[i];
766 }
767 }
768
769 if(objs_ptr->DOMTree != NULL__null) delete objs_ptr->DOMTree;
770 if(objs_ptr->eviobuff){
771
772 // If we have not already stopped reading events from
773 // the source then return this buffer to the pool. Otherwise,
774 // delete the buffer.
775 if(hdevio){
776 // Return EVIO buffer to pool for recycling
777 pthread_mutex_lock(&evio_buffer_pool_mutex);
778 evio_buffer_pool.push_front(objs_ptr->eviobuff);
779 pthread_mutex_unlock(&evio_buffer_pool_mutex);
780 }else{
781 free(objs_ptr->eviobuff);
782 }
783 }
784
785 delete objs_ptr;
786
787 // Decrement counter that keeps track of how many events
788 // are currently being processed.
789 pthread_mutex_lock(&current_event_count_mutex);
790 current_event_count--;
791 bool last_event = (hdevio==NULL__null) && (current_event_count==0);
792 pthread_mutex_unlock(&current_event_count_mutex);
793
794 // If we are the last event, then clean up as much memory as
795 // possible.
796 if(last_event) Cleanup();
797 }
798}
799
800//----------------
801// ParseEvents
802//----------------
803jerror_t JEventSource_EVIO::ParseEvents(ObjList *objs_ptr)
804{
805 /// This is the high-level entry point for parsing the
806 /// DAQ event in order to create one or more Physics
807 /// events. It will be called from either GetObjects
808 /// or FreeEvent, the latter being done only if needed
809 /// to ensure the event does eventually get parsed.
810 /// The grunt work of actually parsing the data starts
811 /// in ParseEVIOEvent().
812 ///
813 /// This method is here so that the DOM Tree creation
814 /// and data parsing can be deferred from the EventBuffer
815 /// thread (of which there is only one) to an event
816 /// processor thread (or which there may be many). Since
817 /// the DOM tree creating and data parsing represent the
818 /// larger time cost of getting the event into memory,
819 /// a siginificant performance increase can be gained
820 /// using this slightly more complicated method.
821
822 if(VERBOSE>2) evioout << " Entering ParseEvents() with objs_ptr=" << hex << objs_ptr << dec << endl;
823
824 // Double check that we're not re-parsing an event
825 if(objs_ptr->eviobuff_parsed){
826 jerr << " DAQ event already parsed!! Bug in code. Contact davidl@jlab.org" << endl;
827 return UNKNOWN_ERROR;
828 }
829
830 // Bomb-proof against getting a NULL buffer
831 uint32_t *buff = objs_ptr->eviobuff;
832 if(buff == NULL__null){
833 jerr << " Bad buffer pointer passed to JEventSource_EVIO::ParseEvent()!!" << endl;
834 return RESOURCE_UNAVAILABLE;
835 }
836
837 // This container will be used to hold all of the individual
838 // Physics (L1 triggered) events for this DAQ event. This includes
839 // both dientangling multi-event blocks and separating multi-event
840 // ET events.
841 list<ObjList*> full_events;
842
843 // Setup up iptr and iend to point to the start of the first event
844 // and the word just after the end of the last event respectively.
845 // Initialize them for the case of reading from a file and not a
846 // CODA-produced ET event
847 uint32_t *iptr = &buff[0];
848 uint32_t *iend = &buff[buff[0]+1]; // EVIO length word is exclusive so +1
849
850 // If the "event" was read from ET, then it may (and likely
851 // will) contain several DAQ events. (Each DAQ event may itself
852 // contain many L1 trigger events.) In addition, the ET event
853 // will have a Network Transport Header (NTH) that must be skipped
854 // but only if read from CODA. Events put into the ET system
855 // by other means will not include the NTH. To decide whether
856 // there is an NTH, we look at the magic word and the header length.
857 // Note that byteswapping should already have occured.
858 if(source_type==kETSource && buff[7]==0xc0da0100 && buff[2]==8){
859 // This buffer read from ET. Redefine iptr and iend
860 iptr = &buff[8];
861 iend = &buff[buff[0]]; // EVIO length word in NTH is inclusive so don't add 1
862 }
863
864 if(VERBOSE>5) evioout << " Looping event stack with " << *iptr << " words" << endl;
865
866 // Loop over events in buffer until entire buffer is parsed.
867 // When reading from a file, this loop should only get executed once.
868 int Nevents_in_stack=0;
869 while(iptr < iend){
870
871 double time_dom_tree = 0;
872 double time_evio_parse = 0;
873
874 // Make a evioDOMTree for this DAQ event
875 evioDOMTree *evt = NULL__null;
876 if(MAKE_DOM_TREE){
877 try{
878 double tstart = GetTime();
879 evt = new evioDOMTree(iptr);
880 time_dom_tree = GetTime() - tstart;
881 }catch(evioException &e){
882 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<882<<" "
<< "Problem creating EVIO DOM Tree!!" << endl;
883 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<883<<" "
<< e.what() << endl;
884 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<884<<" "
<< "Binary dump of first 160 words follows:" << endl;
885 DumpBinary(iptr, iend, 160);
886 exit(-1);
887 }
888 }
889
890 if(evt){
891 // Parse event, making other ObjList objects
892 list<ObjList*> my_full_events;
893 //bool skipped_parsing = true;
894 if(PARSE_EVIO_EVENTS){
895 try{
896 double tstart = GetTime();
897 ParseEVIOEvent(evt, my_full_events);
898 time_evio_parse = GetTime() - tstart;
899 }catch(JException &jexception){
900 jerr << "Exception thrown from ParseEVIOEvent!" << endl;
901 jerr << jexception.toString() << endl;
902 }
903 }
904
905 // Append physics events found for this DAQ event to the list of all physics events
906 if(!my_full_events.empty()) {
907 my_full_events.front()->DOMTree = evt; // keep DOMTree pointer with first event from this DAQ event
908 my_full_events.front()->time_dom_tree = time_dom_tree;
909 my_full_events.front()->time_evio_parse = time_evio_parse;
910 full_events.insert( full_events.end(), my_full_events.begin(), my_full_events.end() );
911 }else{
912 delete evt;
913 }
914 }else{
915 // No DOM tree made for this buffer. Insert an empty event into
916 // the list so we can keep track of the number of events seen
917 // even when DOMTree creation is turned off.
918 ObjList *objs = new ObjList;
919 full_events.push_back(objs);
920 }
921
922 // Advance pointer to next event in buffer
923 iptr += iptr[0]+1;
924 Nevents_in_stack++; // number of events processed in this buffer (for debugging)
925 }
926
927 if(VERBOSE>5) evioout << " Loop finished. " << full_events.size() << " events total found (" << Nevents_in_stack << " events in stack)" << endl;
928
929 // At this point, we have parsed the DAQ event and extracted all physics
930 // events into the full_events list. In the case of a prestart or go event
931 // read from an EVIO file, the full_events list may actually be empty at
932 // this point. For these cases, we need to add an empty event for the
933 // current thread to "process".
934 bool empty_event = full_events.empty();
935 if(empty_event) full_events.push_back(new ObjList());
936
937 // Whether we actually parsed the events or not, we mark them as being
938 // parsed since it is really just used as a flag to tell whether this
939 // method should be called or not.
940 list<ObjList*>::iterator iter = full_events.begin();
941 for( ; iter != full_events.end(); iter++ ) (*iter)->eviobuff_parsed = true;
942
943 // Copy the first event's objects obtained from parsing into this event's ObjList
944 ObjList *objs = full_events.front();
945 full_events.pop_front();
946 //objs_ptr->run_number = empty_event ? objs_ptr->run_number:objs->run_number;
947 objs_ptr->own_objects = objs->own_objects;
948 objs_ptr->hit_objs = objs->hit_objs;
949 objs_ptr->config_objs = objs->config_objs;
950 objs_ptr->misc_objs = objs->misc_objs;
951 objs_ptr->eviobuff_parsed = objs->eviobuff_parsed;
952 objs_ptr->time_dom_tree = objs->time_dom_tree;
953 objs_ptr->time_evio_parse = objs->time_evio_parse;
954 //objs_ptr->eviobuff = objs->eviobuff; // Don't copy this! (it causes memory leak)
955 //objs_ptr->eviobuff_size = objs->eviobuff_size;
956 objs_ptr->DOMTree = objs->DOMTree;
957 delete objs;
958
959 // Config objects come from banks that are created when a block
960 // of events is read out. Thus, a single set of config. objects
961 // will be created when parsing a multi-event block. Here, we duplicate
962 // all config objects for the first event for every other event in the
963 // block. To make this a little more compact and maintainable, we use a
964 // #define. This allows us to write the class type once and guarantee
965 // that it shows up the same in all places. For example, using
966 // CloneConfigObject(Df125Config) will expand to something like:
967 //
968 // if(confobj->className() == string("Df125Config")){
969 // c = new Df125Config(confobj->rocid,confobj->slot_mask);
970 // *((Df125Config*)c) = *((Df125Config*)confobj);
971 // }
972#define CloneConfigObject(T){ if(confobj->className() == string("T")){ c = new T(confobj
->rocid,confobj->slot_mask); *((T*)c) = *((T*)confobj);
} }
{ if(confobj->className() == string(#T)){ c = new T(confobj->rocid,confobj->slot_mask); *((T*)c) = *((T*)confobj);} }
973 list<ObjList*>::iterator feiter = full_events.begin();
974 for(; feiter!=full_events.end(); feiter++){
975 ObjList *objs = *feiter;
976 for(uint32_t j=0; j<objs_ptr->config_objs.size(); j++){
977 DDAQConfig *confobj = objs_ptr->config_objs[j];
978 DDAQConfig *c = NULL__null;
979 CloneConfigObject(Df250Config){ if(confobj->className() == string("Df250Config")){ c = new
Df250Config(confobj->rocid,confobj->slot_mask); *((Df250Config
*)c) = *((Df250Config*)confobj);} }
;
980 CloneConfigObject(Df125Config){ if(confobj->className() == string("Df125Config")){ c = new
Df125Config(confobj->rocid,confobj->slot_mask); *((Df125Config
*)c) = *((Df125Config*)confobj);} }
;
981 CloneConfigObject(DF1TDCConfig){ if(confobj->className() == string("DF1TDCConfig")){ c = new
DF1TDCConfig(confobj->rocid,confobj->slot_mask); *((DF1TDCConfig
*)c) = *((DF1TDCConfig*)confobj);} }
;
982 CloneConfigObject(DCAEN1290TDCConfig){ if(confobj->className() == string("DCAEN1290TDCConfig"))
{ c = new DCAEN1290TDCConfig(confobj->rocid,confobj->slot_mask
); *((DCAEN1290TDCConfig*)c) = *((DCAEN1290TDCConfig*)confobj
);} }
;
983 if(c)objs->config_objs.push_back(c);
984 }
985 }
986
987 // Copy remaining events into the stored_events container
988 pthread_mutex_lock(&stored_events_mutex);
989 while(!full_events.empty()){
990 objs = full_events.front();
991 full_events.pop_front();
992 stored_events.push(objs);
993
994 // Copy run number from first event
995 objs->run_number = objs_ptr->run_number;
996 }
997
998 // Decrement counter of how many event buffers are unparsed
999 Nunparsed--;
1000
1001 pthread_mutex_unlock(&stored_events_mutex);
1002
1003 if(VERBOSE>2) evioout << " Leaving ParseEvents()" << endl;
1004
1005 return NOERROR;
1006}
1007
1008//----------------
1009// GetPoolBuffer
1010//----------------
1011uint32_t* JEventSource_EVIO::GetPoolBuffer(void)
1012{
1013 // Get buffer from pool or allocate new one if needed
1014 uint32_t *buff = NULL__null;
1015 pthread_mutex_lock(&evio_buffer_pool_mutex);
1016 if(evio_buffer_pool.empty()){
1017 // Allocate new block of memory
1018 if(VERBOSE>5) evioout << " evio_buffer_pool empty. Allocating new buffer of size: " << BUFFER_SIZE << " bytes" << endl;
1019 buff = (uint32_t*)malloc(BUFFER_SIZE);
1020 }else{
1021 if(VERBOSE>5) evioout << " evio_buffer_pool not empty(size=" << evio_buffer_pool.size() << "). using buffer from pool" << endl;
1022 buff = evio_buffer_pool.front();
1023 evio_buffer_pool.pop_front();
1024 }
1025 pthread_mutex_unlock(&evio_buffer_pool_mutex);
1026
1027 return buff;
1028}
1029
1030//----------------
1031// ReadEVIOEvent
1032//----------------
1033jerror_t JEventSource_EVIO::ReadEVIOEvent(uint32_t* &buff)
1034{
1035 /// This method will read an event from the source (file or ET system)
1036 /// copying the data into "buff". No parsing of the data is done at
1037 /// this level except that if the event comes from ET and needs to be
1038 /// byte-swapped, the byte swapping is done during the copy.
1039 ///
1040 /// This is called from the GetEvent method and therefore run in
1041 /// the event reader thread. Events read from ET may contain several DAQ
1042 /// events in a single buffer (and each of those may contain several
1043 /// physics events if read in multi-event blocks). Separating the multiple
1044 /// DAQ events is left to the ParseEvents method which gets called later
1045 /// from the event processing threads to improve efficiency.
1046
1047 if(VERBOSE>1) evioout << " ReadEVIOEvent() called with &buff=" << hex << &buff << dec << endl;
1048
1049 try{
1050 if(source_type==kFileSource){
1051 if(VERBOSE>3) evioout << " attempting read from EVIO file source ..." << endl;
1052
1053#if USE_HDEVIO1
1054
1055 bool done = false;
1056 buff = GetPoolBuffer(); // Get (or allocate) a new buffer from the pool
1057 uint32_t buff_size = BUFFER_SIZE;
1058 while(!done){
1059 bool isok = true;
1060 if(EVIO_SPARSE_READ)
1061 isok= hdevio->readSparse(buff, buff_size);
1062 else
1063 isok= hdevio->read(buff, buff_size);
1064 if(isok){
1065 done = true;
1066 }else{
1067 string mess = hdevio->err_mess.str();
1068
1069 switch(hdevio->err_code){
1070 case HDEVIO::HDEVIO_OK:
1071 done = true;
1072 break;
1073 case HDEVIO::HDEVIO_USER_BUFFER_TOO_SMALL:
1074 if(VERBOSE>0) evioout << "EVIO buffer too small (" << buff_size << " bytes) . Reallocating to " << hdevio->last_event_len<< endl;
1075 if(buff) free(buff);
1076 buff_size = hdevio->last_event_len;
1077 buff = new uint32_t[buff_size];
1078 continue;
1079 break;
1080 case HDEVIO::HDEVIO_EVENT_BIGGER_THAN_BLOCK:
1081 case HDEVIO::HDEVIO_BANK_TRUNCATED:
1082 case HDEVIO::HDEVIO_UNKNOWN_BANK_TYPE:
1083 if(VERBOSE>0) cout << endl << mess << endl;
1084 continue;
1085 break;
1086 case HDEVIO::HDEVIO_EOF:
1087 if(hdevio) delete hdevio;
1088 hdevio = NULL__null;
1089 if(LOOP_FOREVER && Nevents_read>=1){
1090 cout << "LOOP_FOREVER: reopening " << this->source_name <<endl;
1091 hdevio = new HDEVIO(this->source_name);
1092 if( hdevio->is_open ) continue;
1093 }
1094 return NO_MORE_EVENTS_IN_SOURCE;
1095 break;
1096 default:
1097 cout << endl << "err_code=" << hdevio->err_code << endl;
1098 cout << endl << mess << endl;
1099 japp->SetExitCode(hdevio->err_code);
1100 if(hdevio) delete hdevio;
1101 hdevio = NULL__null;
1102 return NO_MORE_EVENTS_IN_SOURCE;
1103 break;
1104 }
1105 }
1106 } // while(!done)
1107
1108#else
1109 // ( removed old evio library code )
1110#endif // USE_HDEVIO
1111
1112 }else if(source_type==kETSource){
1113
1114#ifdef HAVE_ET
1115
1116 if(VERBOSE>3) evioout << " attempting read from EVIO ET source ..." << endl;
1117
1118
1119 // Loop until we get an event or are told to stop
1120 struct timespec timeout;
1121 timeout.tv_sec = (unsigned int)floor(TIMEOUT); // set ET timeout
1122 timeout.tv_nsec = (unsigned int)floor(1.0E9*(TIMEOUT-(float)timeout.tv_sec));
1123 et_event *pe=NULL__null;
1124 while(! japp->GetQuittingStatus() ){
1125 int err = et_event_get(sys_id, att_id, &pe, ET_TIMED , &timeout);
1126
1127 if( err == ET_OK && pe!=NULL__null) break; // got an event. break out of while loop
1128
1129 if( err == ET_OK && pe==NULL__null){
1130 evioout << " !!! ET returned no error, but event pointer is NULL!!!" << endl;
1131 return NO_MORE_EVENTS_IN_SOURCE;
1132 }
1133
1134 if( err==ET_ERROR_TIMEOUT ){
1135 if(quit_on_next_ET_timeout)return NO_MORE_EVENTS_IN_SOURCE;
1136 }else if( err!=ET_OK){
1137 evioout << " Error reading from ET. This probably means the ET" << endl;
1138 evioout << "system has gone away (possibly due to run ending or" << endl;
1139 evioout << "DAQ crashing). At any rate, we are quitting now as this" << endl;
1140 evioout << "error is currently unrecoverable." << endl;
1141 return NO_MORE_EVENTS_IN_SOURCE;
1142 }
1143
1144 usleep(10);
1145 }
1146
1147 if(japp->GetQuittingStatus() && pe==NULL__null) return NO_MORE_EVENTS_IN_SOURCE;
1148
1149 // Get pointer to event buffer in the ET-owned memory
1150 uint32_t *et_buff=NULL__null;
1151 et_event_getdata(pe, (void**)&et_buff);
1152 if(et_buff == NULL__null){
1153 jerr << " Got event from ET, but pointer to data is NULL!" << endl;
1154 return NO_MORE_EVENTS_IN_SOURCE;
1155 }
1156
1157 // If user specified to dump words from ET event, do it right away
1158 if(ET_DEBUG_WORDS_TO_DUMP) DumpBinary(et_buff, &et_buff[ET_DEBUG_WORDS_TO_DUMP], ET_DEBUG_WORDS_TO_DUMP, NULL__null);
1159
1160 // A single ET event may have multiple EVIO blocks in it
1161 // Each block may have several EVIO events in it.
1162 //
1163 // (note that "block" here is not the same as the CODA
1164 // "block number". That one determines the number of
1165 // entangled events within the EVIO event and is dealt
1166 // with later while parsing the EVIO event itself.)
1167 //
1168 // We need to loop over EVIO blocks in this ET event
1169 // and then loop over EVIO events within the block.
1170
1171 // Get total size of ET event
1172 size_t et_len=0;
1173 size_t et_idx=0;
1174 et_event_getlength(pe, &et_len);
1175 if(VERBOSE>3)evioout << " ET event length: " << et_len << " (=" << et_len/4 << " words)"<<endl;
1176
1177 // Loop over EVIO blocks in ET event
1178 vector<uint32_t*> buffs;
1179 while(et_idx < et_len/4){
1180
1181 // Pointer to start of EVIO block header
1182 if(VERBOSE>3)evioout << " Looking for EVIO block header at et_idx=" << et_idx << endl;
1183 uint32_t *evio_block = &et_buff[et_idx];
1184
1185 // Check byte order of event by looking at magic #
1186 bool swap_needed = false;
1187 uint32_t magic = evio_block[7];
1188 switch(magic){
1189 case 0xc0da0100: swap_needed = false; break;
1190 case 0x0001dac0: swap_needed = true; break;
1191 default:
1192 evioout << "EVIO magic word not present!" << endl;
1193 return NO_MORE_EVENTS_IN_SOURCE;
1194 }
1195 uint32_t len = evio_block[0];
1196 if(swap_needed) len = EVIO_SWAP32(len)( (((len) >> 24) & 0x000000FF) | (((len) >> 8
) & 0x0000FF00) | (((len) << 8) & 0x00FF0000) |
(((len) << 24) & 0xFF000000) )
;
1197 if(VERBOSE>3){
1198 evioout << "Swapping is " << (swap_needed ? "":"not ") << "needed" << endl;
1199 evioout << " Num. words in EVIO buffer: "<<len<<endl;
1200 }
1201
1202 bool is_last_evio_block = (evio_block[5]>>(9+8))&0x1;
1203 if(VERBOSE>3)evioout << " Is last EVIO block?: " << is_last_evio_block << endl;
1204
1205 // Loop over all evio events in ET event
1206 uint32_t idx = 8; // point to first EVIO event
1207 while(idx<len){
1208
1209 // Size of events in bytes
1210 uint32_t mylen = swap_needed ? EVIO_SWAP32(evio_block[idx])( (((evio_block[idx]) >> 24) & 0x000000FF) | (((evio_block
[idx]) >> 8) & 0x0000FF00) | (((evio_block[idx]) <<
8) & 0x00FF0000) | (((evio_block[idx]) << 24) &
0xFF000000) )
:evio_block[idx];
1211 uint32_t bufsize_bytes = (mylen+1)*sizeof(uint32_t); // +1 is for buffer length word
1212 if(bufsize_bytes > BUFFER_SIZE){
1213 jerr<<" ET event larger than our BUFFER_SIZE!!!"<<endl;
1214 jerr<<" " << bufsize_bytes << " > " << BUFFER_SIZE << endl;
1215 jerr<<" Will stop reading from this source now. Try restarting"<<endl;
1216 jerr<<" with -PEVIO:BUFFER_SIZE=X where X is greater than "<<bufsize_bytes<<endl;
1217 if(VERBOSE>3){
1218 evioout << "First few words in case you are trying to debug:" << endl;
1219 for(unsigned int j=0; j<3; j++){
1220 char str[512];
1221 for(unsigned int i=0; i<5; i++){
1222 sprintf(str, " %08x", evio_block[i+j*5]);
1223 evioout << str;
1224 }
1225 evioout << endl;
1226 }
1227 }
1228 return NO_MORE_EVENTS_IN_SOURCE;
1229 }
1230
1231 // Check that EVIO event length doesn't claim to
1232 // extend past ET buffer.
1233 if( (idx+mylen) > len ){
1234 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<1234<<" "
<< "Bad word count while swapping events in ET event stack!" << endl;
1235 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<1235<<" "
<< "idx="<<idx<<" mylen="<<mylen<<" len="<<len<<endl;
1236 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<1236<<" "
<< "This indicates a problem either with the DAQ system"<<endl;
1237 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<1237<<" "
<< "or this parser code! Contact davidl@jlab.org x5567 " <<endl;
1238 break;
1239 }
1240
1241 // Get new buffer for this EVIO event
1242 buff = GetPoolBuffer();
1243
1244 // Copy event into "buff", byte swapping if needed.
1245 // If no swapping is needed, we just copy it all over
1246 // in one go.
1247 if(!swap_needed){
1248 memcpy(buff, &evio_block[idx], bufsize_bytes);
1249 }else{
1250 swap_int32_t(&evio_block[idx], mylen+1, buff);
1251 }
1252
1253 // Update pointer to next EVIO event in stack (if any)
1254 idx += mylen+1;
1255 buffs.push_back(buff);
1256 }
1257
1258 // bump index to next EVIO block
1259 et_idx += idx;
1260 if(VERBOSE>3)evioout << " EVIO events found so far: " << buffs.size() << endl;
1261 if(is_last_evio_block){
1262 if(VERBOSE>3) evioout << " Block flagged as last in ET event. Ignoring last " << (et_len/4 - et_idx) << " words" <<endl;
1263 break;
1264 }
1265 }
1266
1267 // Put ET event back since we're done with it
1268 et_event_put(sys_id, att_id, pe);
1269
1270 if(VERBOSE>3) evioout << " Found " << buffs.size() << " events in the ET event stack." << endl;
1271
1272 // The first EVIO event should be returned via "buff".
1273 buff = buffs.empty() ? NULL__null:buffs[0];
1274
1275 // Additional EVIO events need to be placed in
1276 // the "stored_events" deque so they can be
1277 // used in subsequent calls to GetEvent()
1278 pthread_mutex_lock(&stored_events_mutex);
1279 for(uint32_t i=1; i<buffs.size(); i++){
1280 ObjList *objs = new ObjList();
1281 objs->eviobuff = buffs[i];
1282 objs->eviobuff_size = BUFFER_SIZE;
1283 objs->run_number = FindRunNumber(buffs[i]);
1284 objs->event_number = FindEventNumber(buffs[i]);
1285 stored_events.push(objs);
1286 }
1287 pthread_mutex_unlock(&stored_events_mutex);
1288
1289#else // HAVE_ET
1290
1291 japp->Quit();
1292 evioout << "Attempting to read from ET system using binary that" << endl;
1293 evioout << "does not have ET support built in! Try recompiling" << endl;
1294 evioout << "programs/Utilities/plugins/DAQ with ETROOT defined" << endl;
1295 evioout << "and pointing to an ET installation." << endl;
1296
1297#endif //HAVE_ET
1298
1299 }
1300 } catch (evioException &e) {
1301 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<1301<<" "
<<e.what()<<endl;
1302 if(e.type == S_EVFILE_TRUNC0x40730001){
1303 jerr << "-- Event buffer truncated --" <<endl;
1304 jerr << "---- this could be because the events are too large " << endl;
1305 jerr << "---- for the buffer provided (" << BUFFER_SIZE << " bytes)" <<endl;
1306 jerr << "---- you can try giving a larger buffer size by setting" << endl;
1307 jerr << "---- the EVIO:BUFFER_SIZE configuration parameter by " << endl;
1308 jerr << "---- adding this argument to your command line:" << endl;
1309 jerr << "---- -PEVIO:BUFFER_SIZE=X (where X is in bytes)" << endl;
1310 }
1311 }
1312
1313 if(VERBOSE>2) evioout << " Leaving ReadEVIOEvent()" << endl;
1314
1315 return NOERROR;
1316}
1317
1318//----------------
1319// GetObjects
1320//----------------
1321jerror_t JEventSource_EVIO::GetObjects(JEvent &event, JFactory_base *factory)
1322{
1323 if(VERBOSE>2) evioout << " GetObjects() called for &event = " << hex << &event << dec << endl;
1324
1325 // This will get called when the first object of the event is
1326 // requested (regardless of the type of object). Instead of
1327 // pulling out objects only of the type requested, we instead
1328 // take the data for all objects and copy them into the respective
1329 // factories. Subsequent requests for objects for this same
1330 // event will get them from the factories. Thus, this should
1331 // only get called once per event.
1332 // O.K. that is not actually true. If objects of a type we don't
1333 // supply are requested, then the corresponding factory's evnt_called
1334 // flag will not have been set and it will come here first to see
1335 // if the source can supply those objects. In those cases, we should
1336 // just return OBJECT_NOT_AVAILABLE so it can revert to the factory
1337 // algorithm. We use the "own_objects" flag here to test if we have
1338 // already copied the low-level objects to the factories and so
1339 // should return right away.
1340 ObjList *objs_ptr = (ObjList*)event.GetRef();
1341 if(!objs_ptr)return RESOURCE_UNAVAILABLE;
1342 if(!objs_ptr->own_objects) return OBJECT_NOT_AVAILABLE; // if objects were already copied ...
1343
1344 // If any translation tables exist, we will use them at the end of this
1345 // method. However, the TTab plugin has an option to specify parsing of
1346 // only certain detector systems. It does this by copying values into
1347 // this JEventSource_EVIO object via the AddROCIDtoParseList method
1348 // while in the brun method. The brun method won't get called until
1349 // we ask for the DTranslationTable objects, thus, we must ask for them
1350 // here, prior to calling ParseEvents.
1351 // Note that we have to use the GetFromFactory() method here since
1352 // if we just use Get() or GetSingle(), it will call us (the event
1353 // source) again in an infinite loop!
1354 // Also note that we use static_cast here instead of dynamic_cast
1355 // since the latter requires that the type_info structure for
1356 // the DTranslationTable_factory be present. It is not in this
1357 // plugin (it is in the TTab plugin). Thus, with dynamic_cast there
1358 // is an unresolved symbol error if the TTab plugin is not also
1359 // present. (Make sense?)
1360 vector<const DTranslationTable*> translationTables;
1361 JEventLoop *loop = event.GetJEventLoop();
1362 DTranslationTable_factory *ttfac = static_cast<DTranslationTable_factory*>(loop->GetFactory("DTranslationTable"));
1363 if(ttfac) ttfac->Get(translationTables);
1364
1365 // We use a deferred parsing scheme for efficiency. If the event
1366 // is not flagged as having already been parsed, then parse it
1367 // now, creating objects for one or more events. The first event's
1368 // parameters will be copied into our ObjList object and any additional
1369 // ones stored in the stored_events queue.
1370 if(!objs_ptr->eviobuff_parsed) ParseEvents(objs_ptr);
1371
1372 // Get name of class which is actually being requested by caller
1373 string dataClassName = (factory==NULL__null ? "N/A":factory->GetDataClassName());
1374
1375 // Make list of data(hit) types we have. Keep list of
1376 // pointers to hit objects of each type
1377 map<string, vector<JObject*> > hit_objs_by_type;
1378 vector<DDAQAddress*> &hit_objs = objs_ptr->hit_objs;
1379 for(unsigned int i=0; i<hit_objs.size(); i++){
1380 JObject *hit_obj = hit_objs[i];
1381 hit_objs_by_type[hit_obj->className()].push_back(hit_obj);
1382 }
1383
1384 // Make list of config objects of each type
1385 map<string, vector<JObject*> > config_objs_by_type;
1386 vector<DDAQConfig*> &config_objs = objs_ptr->config_objs;
1387 for(unsigned int i=0; i<config_objs.size(); i++){
1388 JObject *config_obj = config_objs[i];
1389 config_objs_by_type[config_obj->className()].push_back(config_obj);
1390 }
1391
1392 // Make list of misc objects of each type
1393 map<string, vector<JObject*> > misc_objs_by_type;
1394 vector<JObject*> &misc_objs = objs_ptr->misc_objs;
1395 for(unsigned int i=0; i<misc_objs.size(); i++){
1396 JObject *jobj = misc_objs[i];
1397 misc_objs_by_type[jobj->className()].push_back(jobj);
1398 }
1399
1400 // Associate any DDAQConfig objects with hit objects to which they should apply.
1401 // If the objects are emulated, we will add this association later.
1402 for(unsigned int j=0; j<config_objs.size(); j++){
1403 DDAQConfig *config = config_objs[j];
1404 for(unsigned int i=0; i<hit_objs.size(); i++){
1405 DDAQAddress *hit = hit_objs[i];
1406 if(hit->rocid != config->rocid) continue;
1407 if( (1<<hit->slot) & config->slot_mask){
1408 hit->AddAssociatedObject(config);
1409 }
1410 }
1411 }
1412
1413 // Copy pointers to BOR objects
1414 CopyBOR(loop, hit_objs_by_type);
1415
1416 // In order for the janadot plugin to properly display the callgraph, we need to
1417 // make entries for each of the object types that we generated from data in the file.
1418 // Actually, we need to do it for all of the data objects we supply, but if any objects
1419 // are emulated (e.g. Df250PulseIntegral) they need to be added differently so the correct
1420 // dependence is shown. The first step is to add entries for all of the hit objects we
1421 // actually did find in the file. Do that here.
1422 map<string, vector<JObject*> >::iterator hoiter;
1423 for(hoiter=hit_objs_by_type.begin(); hoiter!=hit_objs_by_type.end(); hoiter++){
1424 AddSourceObjectsToCallStack(loop, hoiter->first);
1425 }
1426
1427 // Get references to various objects
1428 vector<JObject*> &f250_wrd_objs = hit_objs_by_type["Df250WindowRawData"];
1429 vector<JObject*> &f250_pt_objs = hit_objs_by_type["Df250PulseTime"];
1430 vector<JObject*> &f250_pp_objs = hit_objs_by_type["Df250PulsePedestal"];
1431 vector<JObject*> &f250_pi_objs = hit_objs_by_type["Df250PulseIntegral"];
1432
1433 vector<JObject*> &f125_wrd_objs = hit_objs_by_type["Df125WindowRawData"];
1434 vector<JObject*> &f125_pt_objs = hit_objs_by_type["Df125PulseTime"];
1435 vector<JObject*> &f125_pp_objs = hit_objs_by_type["Df125PulsePedestal"];
1436 vector<JObject*> &f125_pi_objs = hit_objs_by_type["Df125PulseIntegral"];
1437 vector<JObject*> &f125_cp_objs = hit_objs_by_type["Df125CDCPulse"];
1438 vector<JObject*> &f125_fp_objs = hit_objs_by_type["Df125FDCPulse"];
1439
1440 // Firmware Emulation
1441
1442 if( F250_EMULATION_MODE != kEmulationNone ){
1443 EmulateDf250Firmware(event, f250_wrd_objs, f250_pt_objs, f250_pp_objs, f250_pi_objs);
1444 }
1445 // Repeat for f125
1446 if( F125_EMULATION_MODE != kEmulationNone ){
1447 EmulateDf125Firmware(event, f125_wrd_objs, f125_cp_objs, f125_fp_objs);
1448 }
1449
1450 // Make PulseTime, PulsePedstal, and PulseIntegral objects associated objects of one another
1451 vector<Df250PulseIntegral*> f250_ppi_objs;
1452 vector<Df250PulseTime*> f250_ppt_objs;
1453 vector<Df250PulsePedestal*> f250_ppp_objs;
1454 CopyContainerElementsWithCast(f250_pi_objs, f250_ppi_objs);
1455 CopyContainerElementsWithCast(f250_pt_objs, f250_ppt_objs);
1456 CopyContainerElementsWithCast(f250_pp_objs, f250_ppp_objs);
1457 LinkAssociationsWithPulseNumber(f250_ppt_objs, f250_ppi_objs);
1458 LinkAssociationsWithPulseNumber(f250_ppp_objs, f250_ppi_objs);
1459 LinkAssociationsWithPulseNumber(f250_ppp_objs, f250_ppt_objs);
1460
1461 vector<Df125WindowRawData*> f125_pwrd_objs;
1462 vector<Df125PulseIntegral*> f125_ppi_objs;
1463 vector<Df125PulseTime*> f125_ppt_objs;
1464 vector<Df125PulsePedestal*> f125_ppp_objs;
1465 vector<Df125CDCPulse*> f125_pcp_objs;
1466 vector<Df125FDCPulse*> f125_pfp_objs;
1467 CopyContainerElementsWithCast(f125_wrd_objs, f125_pwrd_objs);
1468 CopyContainerElementsWithCast(f125_pi_objs, f125_ppi_objs);
1469 CopyContainerElementsWithCast(f125_pt_objs, f125_ppt_objs);
1470 CopyContainerElementsWithCast(f125_pp_objs, f125_ppp_objs);
1471 CopyContainerElementsWithCast(f125_cp_objs, f125_pcp_objs);
1472 CopyContainerElementsWithCast(f125_fp_objs, f125_pfp_objs);
1473 LinkAssociationsWithPulseNumber(f125_ppt_objs, f125_ppi_objs);
1474 LinkAssociationsWithPulseNumber(f125_ppp_objs, f125_ppi_objs);
1475 LinkAssociationsWithPulseNumber(f125_ppp_objs, f125_ppt_objs);
1476 LinkAssociations(f125_pcp_objs, f125_pwrd_objs);
1477 LinkAssociations(f125_pfp_objs, f125_pwrd_objs);
1478
1479 // Add data objects to call stack for the classes we can provide, but for which
1480 // there are no objects for this event. Again, this is so janadot will display things
1481 // properly.
1482 set<string>::iterator siter;
1483 for(siter=event_source_data_types.begin(); siter!=event_source_data_types.end(); siter++){
1484 if(hit_objs_by_type.find(*siter) == hit_objs_by_type.end()){
1485 AddSourceObjectsToCallStack(loop, *siter);
1486 }
1487 }
1488
1489 // The f125 firmware used for the 2014 and Spring 2015 commissioning
1490 // data was hardwired to report pedestals that were an average of
1491 // 4 samples. Since only the average was reported, the number of
1492 // samples used for this data was always "1". For the firmware
1493 // implemented in late 2015, configuration parameters were introduced
1494 // to allow a different number of samples to be used for the pedestal
1495 // and a different divisor as well. Here, we need to replace the
1496 // nsamples field of the PulsePedestal objects (which should be set to
1497 // a default value of "1") with values determined by the config.
1498 // parameters. We use the value NPED which should be calculated in
1499 // the coda_config code on the ROCs when the data was taken.
1500 vector<JObject*> &vpp125 = hit_objs_by_type["Df125PulsePedestal"];
1501 for(unsigned int i=0; i<vpp125.size(); i++){
1502 Df125PulsePedestal *pp = (Df125PulsePedestal*)vpp125[i];
1503 if(!pp->emulated){
1504 const Df125Config*conf = NULL__null;
1505 pp->GetSingle(conf);
1506 if(conf!=NULL__null){
1507 if(conf->NPED != 0xFFFF){
1508 pp->nsamples = conf->NPED;
1509 }
1510 }
1511 }
1512 }
1513
1514 // Initially, the F250, F125 firmware does not include the
1515 // pedestal measurement in the pulse integral data
1516 // (it is an add-on Pulse Pedestal word) We want the
1517 // pedestal field of the Df250PulseIntegral objects
1518 // to contain the measured pedestals in both cases.
1519 // Check all Df250PulseIntegral objects for an associated
1520 // Df250PulsePedestal object. If it has one, copy the
1521 // pedestal from it into the Df250PulseIntegral.
1522 vector<JObject*> &vpi250 = hit_objs_by_type["Df250PulseIntegral"];
1523 for(unsigned int i=0; i<vpi250.size(); i++){
1524
1525 Df250PulseIntegral *pi = (Df250PulseIntegral*)vpi250[i];
1526 const Df250Config*conf = NULL__null;
1527 const Df250BORConfig*BORconf = NULL__null;
1528 const Df250PulsePedestal*pp = NULL__null;
1529 pi->GetSingle(conf);
1530 pi->GetSingle(BORconf);
1531 pi->GetSingle(pp);
1532
1533 // If a Df250PulsePedestal object is associated with this
1534 // then copy its pedestal into the pedestal member of this
1535 // pulse integral object. Furthermore, if the pedestal is
1536 // *not* emulated and we have a configuration parameter from
1537 // the datastream for the number of samples the pedestal
1538 // represents, then copy this into the nsamples_pedestal.
1539 if(pp){
1540 pi->pedestal = pp->pedestal;
1541 if(!pp->emulated){
1542 if(conf!=NULL__null){
1543 if(conf->NPED != 0xFFFF){
1544 pi->nsamples_pedestal = conf->NPED;
1545 }
1546 }
1547 }
1548 }
1549
1550 // If this pulse integral is *not* emulated AND there is
1551 // a configuration object from the data stream associated,
1552 // then copy the number of samples for the integral from it.
1553 if(!pi->emulated){
1554 if (BORconf!=NULL__null){
1555 uint16_t NSB = BORconf->adc_nsb & 0x7F;
1556 uint16_t NSA = BORconf->adc_nsa & 0x7F;
1557 pi->nsamples_integral = NSB + NSA;
1558 }
1559 else if(conf){
1560 pi->nsamples_integral = conf->NSA_NSB;
1561 }
1562 }
1563 }
1564 vector<JObject*> &vpi125 = hit_objs_by_type["Df125PulseIntegral"];
1565 for(unsigned int i=0; i<vpi125.size(); i++){
1566
1567 Df125PulseIntegral *pi = (Df125PulseIntegral*)vpi125[i];
1568 const Df125Config*conf = NULL__null;
1569 const Df125PulsePedestal*pp = NULL__null;
1570 pi->GetSingle(conf);
1571 pi->GetSingle(pp);
1572
1573 // If a Df125PulsePedestal object is associated with this
1574 // then copy its pedestal into the pedestal member of this
1575 // pulse integral object. Furthermore, if the pedestal is
1576 // *not* emulated then copy the number of pedestal samples.
1577 // (n.b. the value of nsamples should have been set based
1578 // on the configuration parameter in a separate loop over
1579 // Df125PulsePedestal objects above.)
1580 if(pp){
1581 pi->pedestal = pp->pedestal;
1582 if(!pp->emulated) pi->nsamples_pedestal = pp->nsamples;
1583 }
1584
1585 // If this pulse integral is *not* emulated AND there is
1586 // a configuration object from the data stream associated,
1587 // then copy the number of samples for the integral from it.
1588 if(!pi->emulated){
1589 if(conf){
1590 pi->nsamples_integral = conf->NSA_NSB;
1591 }
1592 }
1593 }
1594 vector<JObject*> &vcdcp125 = hit_objs_by_type["Df125CDCPulse"];
1595 for(unsigned int i=0; i<vcdcp125.size(); i++){
1596
1597 Df125CDCPulse *cdcp = (Df125CDCPulse*)vcdcp125[i];
1598 const Df125Config*conf = NULL__null;
1599 cdcp->GetSingle(conf);
1600
1601 // If this CDCpulse is *not* emulated AND there is
1602 // a configuration object from the data stream associated,
1603 // then copy the number of samples for the integral from it.
1604 if(!cdcp->emulated){
1605 if(conf){
1606
1607 int timesample = (int)cdcp->le_time/10;
1608 int END = ( (timesample + conf->IE) > (conf->NW - 20) ) ? (conf->NW - 20) : (timesample + conf->IE) ;
1609 int nsamp = END - timesample;
1610 if (nsamp>0){
1611 cdcp->nsamples_integral = nsamp;
1612 } else {
1613 cdcp->nsamples_integral = 0; //integral is 0 if timesample >= NW-20
1614 }
1615
1616 }
1617 }
1618 }
1619
1620 vector<JObject*> &vfdcp125 = hit_objs_by_type["Df125FDCPulse"];
1621 for(unsigned int i=0; i<vfdcp125.size(); i++){
1622
1623 Df125FDCPulse *fdcp = (Df125FDCPulse*)vfdcp125[i];
1624 const Df125Config*conf = NULL__null;
1625 fdcp->GetSingle(conf);
1626
1627 // If this FDCpulse is *not* emulated AND there is
1628 // a configuration object from the data stream associated,
1629 // then copy the number of samples for the integral from it.
1630 if(!fdcp->emulated){
1631 if(conf){
1632
1633 int timesample = (int)fdcp->le_time/10;
1634 int END = ( (timesample + conf->IE) > (conf->NW - 20) ) ? (conf->NW - 20) : (timesample + conf->IE) ;
1635 int nsamp = END - timesample;
1636
1637 if (nsamp>0){
1638 fdcp->nsamples_integral = nsamp;
1639 } else {
1640 fdcp->nsamples_integral = 0; //integral is 0 if timesample >= NW-20
1641 }
1642
1643 }
1644 }
1645 }
1646
1647 // Loop over types of config objects, copying to appropriate factory
1648 map<string, vector<JObject*> >::iterator config_iter = config_objs_by_type.begin();
1649 for(; config_iter!=config_objs_by_type.end(); config_iter++){
1650 JFactory_base *fac = loop->GetFactory(config_iter->first, "", false); // false= don't allow default tag replacement
1651 if(fac) fac->CopyTo(config_iter->second);
1652 }
1653
1654 // Loop over types of hit objects, copying to appropriate factory
1655 map<string, vector<JObject*> >::iterator iter = hit_objs_by_type.begin();
1656 for(; iter!=hit_objs_by_type.end(); iter++){
1657 JFactory_base *fac = loop->GetFactory(iter->first, "", false); // false= don't allow default tag replacement
1658 fac->CopyTo(iter->second);
1659 }
1660
1661 // Loop over types of misc objects, copying to appropriate factory
1662 map<string, vector<JObject*> >::iterator misc_iter = misc_objs_by_type.begin();
1663 for(; misc_iter!=misc_objs_by_type.end(); misc_iter++){
1664 JFactory_base *fac = loop->GetFactory(misc_iter->first, "", false); // false= don't allow default tag replacement
1665 fac->CopyTo(misc_iter->second);
1666 }
1667 objs_ptr->own_objects = false;
1668
1669 // Copy pointers to BOR objects
1670 //CopyBOR(loop, hit_objs_by_type);
1671
1672 // Returning OBJECT_NOT_AVAILABLE tells JANA that this source cannot
1673 // provide the type of object requested and it should try and generate
1674 // it via a factory algorithm. Returning NOERROR on the other hand
1675 // tells JANA that we can provide this type of object and any that
1676 // are present have already been copied into the appropriate factory.
1677 jerror_t err = OBJECT_NOT_AVAILABLE;
1678 if(strlen(factory->Tag()) == 0){ // We do not supply any tagged factory data here
1679 if(event_source_data_types.find(dataClassName) != event_source_data_types.end()) err = NOERROR;
1680 }
1681
1682 // If it turns out there are no objects of one of the types we supply
1683 // then the CopyTo method for that factory never gets called and subsequent
1684 // requests for that object type will end up calling this method again.
1685 // (For the case when this is done from the ApplyTranslationTable call
1686 // below, it results in an infinite loop!). To prevent this, we need to
1687 // mark all factories of the data types we supply as having had their
1688 // evnt method called.
1689 set<string>::iterator dtiter = event_source_data_types.begin();
1690 for(; dtiter!=event_source_data_types.end(); dtiter++){
1691 JFactory_base *fac = loop->GetFactory(*dtiter);
1692 if(fac) {
1693 // The DAQ_WRD2PI plugin wants to generate some objects from
1694 // the waveform data, overiding anything found in the file.
1695 // It this case, the factory's use_factory flag is set and
1696 // we should NOT mark the factory as having it's event method
1697 // called. Furthermore, we should delete any objects in the
1698 // factory.
1699 // Now, another complication is that the only way to check
1700 // the use_factory flag is to have a pointer to the JFactory
1701 // not the JFactory_base. This means we have to check the data
1702 // type of the factory and make the appropriate cast
1703 string dataClassName = fac->GetDataClassName();
1704 int checkSourceFirst = 1;
1705 if( dataClassName == "Df250Config") checkSourceFirst = ((JFactory<Df250Config >*)fac)->GetCheckSourceFirst();
1706 else if(dataClassName == "Df250PulseIntegral") checkSourceFirst = ((JFactory<Df250PulseIntegral >*)fac)->GetCheckSourceFirst();
1707 else if(dataClassName == "Df250StreamingRawData") checkSourceFirst = ((JFactory<Df250StreamingRawData>*)fac)->GetCheckSourceFirst();
1708 else if(dataClassName == "Df250WindowSum") checkSourceFirst = ((JFactory<Df250WindowSum >*)fac)->GetCheckSourceFirst();
1709 else if(dataClassName == "Df250PulseRawData") checkSourceFirst = ((JFactory<Df250PulseRawData >*)fac)->GetCheckSourceFirst();
1710 else if(dataClassName == "Df250TriggerTime") checkSourceFirst = ((JFactory<Df250TriggerTime >*)fac)->GetCheckSourceFirst();
1711 else if(dataClassName == "Df250PulseTime") checkSourceFirst = ((JFactory<Df250PulseTime >*)fac)->GetCheckSourceFirst();
1712 else if(dataClassName == "Df250PulsePedestal") checkSourceFirst = ((JFactory<Df250PulsePedestal >*)fac)->GetCheckSourceFirst();
1713 else if(dataClassName == "Df250WindowRawData") checkSourceFirst = ((JFactory<Df250WindowRawData >*)fac)->GetCheckSourceFirst();
1714 else if(dataClassName == "Df125Config") checkSourceFirst = ((JFactory<Df125Config >*)fac)->GetCheckSourceFirst();
1715 else if(dataClassName == "Df125PulseIntegral") checkSourceFirst = ((JFactory<Df125PulseIntegral >*)fac)->GetCheckSourceFirst();
1716 else if(dataClassName == "Df125TriggerTime") checkSourceFirst = ((JFactory<Df125TriggerTime >*)fac)->GetCheckSourceFirst();
1717 else if(dataClassName == "Df125PulseTime") checkSourceFirst = ((JFactory<Df125PulseTime >*)fac)->GetCheckSourceFirst();
1718 else if(dataClassName == "Df125PulsePedestal") checkSourceFirst = ((JFactory<Df125PulsePedestal >*)fac)->GetCheckSourceFirst();
1719 else if(dataClassName == "Df125WindowRawData") checkSourceFirst = ((JFactory<Df125WindowRawData >*)fac)->GetCheckSourceFirst();
1720 else if(dataClassName == "Df125CDCPulse") checkSourceFirst = ((JFactory<Df125CDCPulse >*)fac)->GetCheckSourceFirst();
1721 else if(dataClassName == "Df125FDCPulse") checkSourceFirst = ((JFactory<Df125FDCPulse >*)fac)->GetCheckSourceFirst();
1722 else if(dataClassName == "DF1TDCConfig") checkSourceFirst = ((JFactory<DF1TDCConfig >*)fac)->GetCheckSourceFirst();
1723 else if(dataClassName == "DF1TDCHit") checkSourceFirst = ((JFactory<DF1TDCHit >*)fac)->GetCheckSourceFirst();
1724 else if(dataClassName == "DF1TDCTriggerTime") checkSourceFirst = ((JFactory<DF1TDCTriggerTime >*)fac)->GetCheckSourceFirst();
1725 else if(dataClassName == "DCAEN1290TDCConfig") checkSourceFirst = ((JFactory<DCAEN1290TDCConfig >*)fac)->GetCheckSourceFirst();
1726 else if(dataClassName == "DCAEN1290TDCHit") checkSourceFirst = ((JFactory<DCAEN1290TDCHit >*)fac)->GetCheckSourceFirst();
1727 else if(dataClassName == "DCODAEventInfo") checkSourceFirst = ((JFactory<DCODAEventInfo >*)fac)->GetCheckSourceFirst();
1728 else if(dataClassName == "DCODAROCInfo") checkSourceFirst = ((JFactory<DCODAROCInfo >*)fac)->GetCheckSourceFirst();
1729 else if(dataClassName == "DTSscalers") checkSourceFirst = ((JFactory<DTSscalers >*)fac)->GetCheckSourceFirst();
1730 else if(dataClassName == "Df250BORConfig") checkSourceFirst = ((JFactory<Df250BORConfig >*)fac)->GetCheckSourceFirst();
1731 else if(dataClassName == "Df125BORConfig") checkSourceFirst = ((JFactory<Df125BORConfig >*)fac)->GetCheckSourceFirst();
1732 else if(dataClassName == "DF1TDCBORConfig") checkSourceFirst = ((JFactory<DF1TDCBORConfig >*)fac)->GetCheckSourceFirst();
1733 else if(dataClassName == "DCAEN1290TDCBORConfig") checkSourceFirst = ((JFactory<DCAEN1290TDCBORConfig>*)fac)->GetCheckSourceFirst();
1734
1735 if(checkSourceFirst) {
1736 fac->Set_evnt_called();
1737 }else{
1738 // Factory wants to generate these so delete any read
1739 // from source.
1740 fac->Reset();
1741 }
1742 }
1743 }
1744
1745 // If a translation table object is available, use it to create
1746 // detector hits from the low-level DAQ objects we just created.
1747 for(unsigned int i=0; i<translationTables.size(); i++){
1748 translationTables[i]->ApplyTranslationTable(loop);
1749 if(translationTables[i]->IsSuppliedType(dataClassName))
1750 if(strlen(factory->Tag()) == 0)err = NOERROR; // Don't allow tagged factories from Translation table
1751 }
1752
1753 if(VERBOSE>2) evioout << " Leaving GetObjects()" << endl;
1754
1755 return err;
1756}
1757
1758//----------------
1759// CopyBOR
1760//----------------
1761void JEventSource_EVIO::CopyBOR(JEventLoop *loop, map<string, vector<JObject*> > &hit_objs_by_type)
1762{
1763 /// Copy pointers to BOR (Beginning Of Run) objects into the
1764 /// appropriate factories for this event. The objects are flagged
1765 /// so that the factories won't delete them and the objects
1766 /// may be reused on subsequent events.
1767
1768 pthread_rwlock_rdlock(&BOR_lock);
1769
1770 // Make list of BOR objects of each type
1771 map<string, vector<JObject*> > bor_objs_by_type;
1772 for(unsigned int i=0; i<BORobjs.size(); i++){
1773 JObject *jobj = BORobjs[i];
1774 bor_objs_by_type[jobj->className()].push_back(jobj);
1775 }
1776
1777 // Loop over types of BOR objects, copying to appropriate factory
1778 map<string, vector<JObject*> >::iterator iter = bor_objs_by_type.begin();
1779 for(; iter!=bor_objs_by_type.end(); iter++){
1780 const string &bor_obj_name = iter->first;
1781 vector<JObject*> &bors = iter->second;
1782 JFactory_base *fac = loop->GetFactory(bor_obj_name, "", false); // false= don't allow default tag replacement
1783 if(fac){
1784 fac->CopyTo(bors);
1785 fac->SetFactoryFlag(JFactory_base::NOT_OBJECT_OWNER);
1786 }
1787
1788 // Associate with hit objects from this type of module
1789 if(bor_obj_name == "Df250BORConfig"){
1790 LinkAssociationsModuleOnlyWithCast<Df250BORConfig,Df250PulseIntegral>(bors, hit_objs_by_type["Df250PulseIntegral"]);
1791 LinkAssociationsModuleOnlyWithCast<Df250BORConfig,Df250PulsePedestal>(bors, hit_objs_by_type["Df250PulsePedestal"]);
1792 LinkAssociationsModuleOnlyWithCast<Df250BORConfig,Df250PulseTime>(bors, hit_objs_by_type["Df250PulseTime"]);
1793 LinkAssociationsModuleOnlyWithCast<Df250BORConfig,Df250WindowRawData>(bors, hit_objs_by_type["Df250WindowRawData"]);
1794 }
1795 if(bor_obj_name == "Df125BORConfig"){
1796 LinkAssociationsModuleOnlyWithCast<Df125BORConfig,Df125CDCPulse>(bors, hit_objs_by_type["Df125CDCPulse"]);
1797 LinkAssociationsModuleOnlyWithCast<Df125BORConfig,Df125FDCPulse>(bors, hit_objs_by_type["Df125FDCPulse"]);
1798 LinkAssociationsModuleOnlyWithCast<Df125BORConfig,Df125PulseIntegral>(bors, hit_objs_by_type["Df125PulseIntegral"]);
1799 LinkAssociationsModuleOnlyWithCast<Df125BORConfig,Df125PulsePedestal>(bors, hit_objs_by_type["Df125PulsePedestal"]);
1800 LinkAssociationsModuleOnlyWithCast<Df125BORConfig,Df125PulseTime>(bors, hit_objs_by_type["Df125PulseTime"]);
1801 LinkAssociationsModuleOnlyWithCast<Df125BORConfig,Df125WindowRawData>(bors, hit_objs_by_type["Df125WindowRawData"]);
1802 }
1803 if(bor_obj_name == "DF1TDCBORConfig"){
1804 LinkAssociationsModuleOnlyWithCast<DF1TDCBORConfig,Df250PulseIntegral>(bors, hit_objs_by_type["DF1TDCHit"]);
1805 }
1806 if(bor_obj_name == "DCAEN1290TDCBORConfig"){
1807 LinkAssociationsModuleOnlyWithCast<DCAEN1290TDCBORConfig,Df250PulseIntegral>(bors, hit_objs_by_type["DCAEN1290TDCHit"]);
1808 }
1809 }
1810
1811 pthread_rwlock_unlock(&BOR_lock);
1812}
1813
1814//----------------
1815// AddSourceObjectsToCallStack
1816//----------------
1817void JEventSource_EVIO::AddSourceObjectsToCallStack(JEventLoop *loop, string className)
1818{
1819 /// This is used to give information to JANA regarding the origin of objects
1820 /// that *should* come from the source. We add them in explicitly because
1821 /// the file may not have any, but factories may ask for them. We want those
1822 /// links to indicate that the "0" objects in the factory came from the source
1823 /// so that janadot draws these objects correctly.
1824
1825 JEventLoop::call_stack_t cs;
1826 cs.caller_name = "<ignore>"; // tells janadot this object wasn't actually requested by anybody
1827 cs.caller_tag = "";
1828 cs.callee_name = className;
1829 cs.callee_tag = "";
1830 cs.start_time = 0.0;
1831 cs.end_time = 0.0;
1832 cs.data_source = JEventLoop::DATA_FROM_SOURCE;
1833 loop->AddToCallStack(cs);
1834}
1835
1836//----------------
1837// AddEmulatedObjectsToCallStack
1838//----------------
1839void JEventSource_EVIO::AddEmulatedObjectsToCallStack(JEventLoop *loop, string caller, string callee)
1840{
1841 /// This is used to give information to JANA regarding the relationship and
1842 /// origin of some of these data objects. This is really just needed so that
1843 /// the janadot program can be used to produce the correct callgraph. Because
1844 /// of how this plugin works, JANA can't record the correct call stack (at
1845 /// least not easily!) Therefore, we have to give it a little help here.
1846
1847 JEventLoop::call_stack_t cs;
1848 cs.caller_name = caller;
1849 cs.callee_name = callee;
1850 cs.data_source = JEventLoop::DATA_FROM_SOURCE;
1851 loop->AddToCallStack(cs);
1852 cs.callee_name = cs.caller_name;
1853 cs.caller_name = "<ignore>";
1854 cs.data_source = JEventLoop::DATA_FROM_FACTORY;
1855 loop->AddToCallStack(cs);
1856}
1857
1858//----------------
1859// EmulateDf250Firmware
1860//----------------
1861void JEventSource_EVIO::EmulateDf250Firmware(JEvent &event, vector<JObject*> &wrd_objs, vector<JObject*> &pt_objs, vector<JObject*> &pp_objs, vector<JObject*> &pi_objs)
1862{
1863 // Cant emulate without the raw data
1864 if(wrd_objs.size() == 0) return;
1865 if(VERBOSE>3) evioout << " Entering EmulateDf250Firmware ..." <<endl;
1866
1867 vector <const Df250EmulatorAlgorithm*> f250Emulator_const;
1868 Df250EmulatorAlgorithm *f250Emulator = NULL__null;
1869 JEventLoop *loop = event.GetJEventLoop();
1870 Df250EmulatorAlgorithm_factory *f250EmFac = static_cast<Df250EmulatorAlgorithm_factory*>(loop->GetFactory("Df250EmulatorAlgorithm"));
1871 if (f250EmFac) {
1872 f250EmFac->Get(f250Emulator_const);
1873 // Drop const
1874 if (f250Emulator_const.size() != 0) {
1875 f250Emulator = const_cast<Df250EmulatorAlgorithm*>(f250Emulator_const[0]);
1876 } else {
1877 jerr << "Unable to load Df250EmulatorAlgorithm ! skipping emulation ..." << endl;
1878 return;
1879 }
1880 }
1881
1882 if(VERBOSE>3) evioout << " Looping over raw data ..." <<endl;
1883 // Loop over all window raw data objects
1884 for(unsigned int i=0; i<wrd_objs.size(); i++){
1885 const Df250WindowRawData *f250WindowRawData = (Df250WindowRawData*)wrd_objs[i];
1886 Df250PulseTime *f250PulseTime = NULL__null;
1887 Df250PulsePedestal *f250PulsePedestal = NULL__null;
1888 Df250PulseIntegral *f250PulseIntegral = NULL__null;
1889
1890 // When raw data exists, we will always do the emulation
1891 // Grab the existing Pulse data, up to three of each type
1892 // for each WindowRawData object.
1893 for(uint32_t j=0; j<pt_objs.size(); j++){
1894 Df250PulseTime *pt = (Df250PulseTime*)pt_objs[j];
1895 if(pt->rocid == f250WindowRawData->rocid){
1896 if(pt->slot == f250WindowRawData->slot){
1897 if(pt->channel == f250WindowRawData->channel){
1898 f250PulseTime = pt;
1899 f250PulseTime->AddAssociatedObject(f250WindowRawData);
1900 if(pt->emulated){
1901 jerr << "Emulating channel that already has emulated objects!" << endl;
1902 jerr << "This likely means there is a bug in JEventSource_EVIO.cc" <<endl;
1903 jerr << "PulseTime: rocid="<<pt->rocid<<" slot="<<pt->slot<<" channel="<<pt->channel<<endl;
1904 jerr << "please report error to davidl@jlab.org" << endl;
1905 exit(-1);
1906 }
1907 }
1908 }
1909 }
1910 }
1911
1912 // Ditto for pulse pedestal objects
1913 for(uint32_t j=0; j<pp_objs.size(); j++){
1914 Df250PulsePedestal *pp = (Df250PulsePedestal*)pp_objs[j];
1915 if(pp->rocid == f250WindowRawData->rocid){
1916 if(pp->slot == f250WindowRawData->slot){
1917 if(pp->channel == f250WindowRawData->channel){
1918 f250PulsePedestal = pp;
1919 f250PulsePedestal->AddAssociatedObject(f250WindowRawData);
1920 if(pp->emulated){
1921 jerr << "Emulating channel that already has emulated objects!" << endl;
1922 jerr << "This likely means there is a bug in JEventSource_EVIO.cc" <<endl;
1923 jerr << "PulsePedestal: rocid="<<pp->rocid<<" slot="<<pp->slot<<" channel="<<pp->channel<<endl;
1924 jerr << "please report error to davidl@jlab.org" << endl;
1925 exit(-1);
1926 }
1927 }
1928 }
1929 }
1930 }
1931
1932 // Ditto for pulse integral objects
1933 for(uint32_t j=0; j<pi_objs.size(); j++){
1934 Df250PulseIntegral *pi = (Df250PulseIntegral*)pi_objs[j];
1935 if(pi->rocid == f250WindowRawData->rocid){
1936 if(pi->slot == f250WindowRawData->slot){
1937 if(pi->channel == f250WindowRawData->channel){
1938 f250PulseIntegral = pi;
1939 f250PulseIntegral->AddAssociatedObject(f250WindowRawData);
1940 if(pi->emulated){
1941 jerr << "Emulating channel that already has emulated objects!" << endl;
1942 jerr << "This likely means there is a bug in JEventSource_EVIO.cc" <<endl;
1943 jerr << "PulseIntegral: rocid="<<pi->rocid<<" slot="<<pi->slot<<" channel="<<pi->channel<<endl;
1944 jerr << "please report error to davidl@jlab.org" << endl;
1945 exit(-1);
1946 }
1947 }
1948 }
1949 }
1950 }
1951
1952 // Emulate firmware
1953 uint32_t pt_emulated = pt_objs.size();
1954 uint32_t pp_emulated = pp_objs.size();
1955 uint32_t pi_emulated = pi_objs.size();
1956 if(VERBOSE>3) evioout << " Calling EmulateFirmware ..." << endl;
1957 f250Emulator->EmulateFirmware(f250WindowRawData, pt_objs, pp_objs, pi_objs);
1958
1959 // Find all new objects generated by emulation and match with hw originals, if any
1960 uint32_t pt_hardware = 0;
1961 for (uint32_t i = pt_emulated; i < pt_objs.size(); i++) {
1962 const Df250WindowRawData *rd;
1963 Df250PulseTime *pt_em = dynamic_cast<Df250PulseTime*>(pt_objs[i]);
1964 pt_em->GetSingle(rd);
1965 if (rd != f250WindowRawData) {
1966 jerr << "Emulated object found that does not belong to WindowRawData object!" << endl;
1967 jerr << "This likely means there is a bug in JEventSource_EVIO.cc PulseTime emulation." << endl;
1968 jerr << "rocid=" << pt_em->rocid << " slot=" << pt_em->slot << " channel=" << pt_em->channel << endl;
1969 jerr << "Please report error to davidl@jlab.org" << endl;
1970 exit(-1);
1971 }
1972 for (uint32_t j = pt_hardware; j < pt_emulated; j++) {
1973 Df250PulseTime *pt_hw = dynamic_cast<Df250PulseTime*>(pt_objs[j]);
1974 pt_hw->GetSingle(rd);
1975 if (rd == f250WindowRawData && pt_hw->pulse_number == pt_em->pulse_number) {
1976 pt_hardware = j + 1;
1977 if (F250_EMULATION_MODE == kEmulationAlways) {
1978 *pt_hw = *pt_em;
1979 }
1980 else {
1981 pt_hw->time_emulated = pt_em->time_emulated;
1982 pt_hw->quality_factor_emulated = pt_em->quality_factor_emulated;
1983 }
1984 if ((VERBOSE > 0 && pt_hw->time != pt_hw->time_emulated) || VERBOSE > 3) {
1985 // implement special exceptions for early pulse times in mode 8 data
1986 if (VERBOSE > 3 || !(pt_hw->time == 0 &&
1987 (pt_hw->time_emulated == 64 || pt_hw->time_emulated == 128 ||
1988 pt_hw->time_emulated == 192 || pt_hw->time_emulated == 256)) )
1989 {
1990 jout << " comparing f250 hw and emulation pulse times for ROC/slot/chan "
1991 << pt_hw->rocid << "/" << pt_hw->slot << "/" << pt_hw->channel << ": "
1992 << pt_hw->time << " vs " << pt_hw->time_emulated << endl;
1993 }
1994 }
1995 pt_objs.erase(pt_objs.begin() + i);
1996 delete pt_em;
1997 pt_em = 0;
1998 --i;
1999 break;
2000 }
2001 }
2002 if (pt_em != 0 && VERBOSE > 3) {
2003 jout << " new f250 emulation PulseTime generated for ROC/slot/chan "
2004 << pt_em->rocid << "/" << pt_em->slot << "/" << pt_em->channel << ": "
2005 << "pulse " << pt_em->pulse_number << ", time " << pt_em->time << endl;
2006 }
2007 }
2008
2009 uint32_t pp_hardware = 0;
2010 for (uint32_t i = pp_emulated; i < pp_objs.size(); i++) {
2011 Df250PulsePedestal *pp_em = dynamic_cast<Df250PulsePedestal*>(pp_objs[i]);
2012 const Df250WindowRawData *rd;
2013 pp_em->GetSingle(rd);
2014 if (rd != f250WindowRawData) {
2015 jerr << "Emulated object found that does not belong to WindowRawData object!" << endl;
2016 jerr << "This likely means there is a bug in JEventSource_EVIO.cc PulsePedestal emulation." << endl;
2017 jerr << "rocid=" << pp_em->rocid << " slot=" << pp_em->slot << " channel=" << pp_em->channel << endl;
2018 jerr << "Please report error to davidl@jlab.org" << endl;
2019 exit(-1);
2020 }
2021 for (uint32_t j=pp_hardware; j < pp_emulated; j++) {
2022 Df250PulsePedestal *pp_hw = dynamic_cast<Df250PulsePedestal*>(pp_objs[j]);
2023 pp_hw->GetSingle(rd);
2024 if (rd == f250WindowRawData && pp_hw->pulse_number == pp_em->pulse_number) {
2025 pp_hardware = j + 1;
2026 if (F250_EMULATION_MODE == kEmulationAlways) {
2027 *pp_hw = *pp_em;
2028 }
2029 else {
2030 pp_hw->pedestal_emulated = pp_em->pedestal_emulated;
2031 pp_hw->pulse_peak_emulated = pp_em->pulse_peak_emulated;
2032 }
2033 if ((VERBOSE > 0 && pp_hw->pulse_peak != pp_hw->pulse_peak_emulated) || VERBOSE > 3)
2034 jout << " comparing f250 hw and emulation pulse peaks for ROC/slot/chan "
2035 << pp_hw->rocid << "/" << pp_hw->slot << "/" << pp_hw->channel << ": "
2036 << pp_hw->pulse_peak << " vs " << pp_hw->pulse_peak_emulated << endl;
2037 pp_objs.erase(pp_objs.begin() + i);
2038 delete pp_em;
2039 pp_em = 0;
2040 --i;
2041 break;
2042 }
2043 }
2044 if (pp_em != 0 && VERBOSE > 3) {
2045 jout << " new f250 emulation PulsePedestal generated for ROC/slot/chan "
2046 << pp_em->rocid << "/" << pp_em->slot << "/" << pp_em->channel << ": "
2047 << "pulse " << pp_em->pulse_number << ", pedestal " << pp_em->pedestal
2048 << ", peak " << pp_em->pulse_peak << endl;
2049 }
2050 }
2051
2052 uint32_t pi_hardware = 0;
2053 for (uint32_t i = pi_emulated; i < pi_objs.size(); i++) {
2054 Df250PulseIntegral *pi_em = dynamic_cast<Df250PulseIntegral*>(pi_objs[i]);
2055 const Df250WindowRawData *rd;
2056 pi_em->GetSingle(rd);
2057 if (rd != f250WindowRawData) {
2058 jerr << "Emulated object found that does not belong to WindowRawData object!" << endl;
2059 jerr << "This likely means there is a bug in JEventSource_EVIO.cc PulseIntegral emulation." << endl;
2060 jerr << "rocid=" << pi_em->rocid << " slot=" << pi_em->slot << " channel=" << pi_em->channel << endl;
2061 jerr << "Please report error to davidl@jlab.org" << endl;
2062 exit(-1);
2063 }
2064 for (uint32_t j=pi_hardware; j < pi_emulated; j++) {
2065 Df250PulseIntegral *pi_hw = dynamic_cast<Df250PulseIntegral*>(pi_objs[j]);
2066 pi_hw->GetSingle(rd);
2067 if (rd == f250WindowRawData && pi_hw->pulse_number == pi_em->pulse_number) {
2068 pi_hardware = j + 1;
2069 if (F250_EMULATION_MODE == kEmulationAlways) {
2070 *pi_hw = *pi_em;
2071 }
2072 else {
2073 pi_hw->integral_emulated = pi_em->integral_emulated;
2074 pi_hw->pedestal_emulated = pi_em->pedestal_emulated;
2075 }
2076 if ((VERBOSE > 0 && pi_hw->integral != pi_hw->integral_emulated) || VERBOSE > 3)
2077 jout << " comparing f250 hw and emulation pulse integrals for ROC/slot/chan "
2078 << pi_hw->rocid << "/" << pi_hw->slot << "/" << pi_hw->channel << ": "
2079 << pi_hw->integral << " vs " << pi_hw->integral_emulated << endl;
2080 pi_objs.erase(pi_objs.begin() + i);
2081 delete pi_em;
2082 pi_em = 0;
2083 i--;
2084 break;
2085 }
2086 }
2087 if (pi_em != 0 && VERBOSE > 3) {
2088 jout << " new f250 emulation PulseIntegral generated for ROC/slot/chan "
2089 << pi_em->rocid << "/" << pi_em->slot << "/" << pi_em->channel << ": "
2090 << "pulse " << pi_em->pulse_number << ", integral " << pi_em->integral
2091 << ", pedestal " << pi_em->pedestal << endl;
2092 }
2093 }
2094 }
2095
2096 // PulseTime, PulsePedestal, PulseIntegral objects are associated to one another in GetObjects
2097 if(VERBOSE>3) evioout << " Leaving EmulateDf250Firmware" <<endl;
2098}
2099
2100//----------------
2101// EmulateDf125Firmware
2102//----------------
2103void JEventSource_EVIO::EmulateDf125Firmware( JEvent &event, vector<JObject*> &wrd_objs, vector<JObject*> &cp_objs, vector<JObject*> &fp_objs)
2104{
2105 /// This code implements an upsampling technique developed by Naomi Jarvis at
2106 /// CMU. This was not implemented in the firmware for the 2014-2015 commissioning
2107 /// run, but was implemented for later runs.
2108 ///
2109 /// Removed f250 style emulation of f125 firmware. Keep in mind if for some reason old
2110 /// mode 8 data is processed, it will return the new style words with 1/10
2111 /// sample resolution. It is doubtful anyone will be using these in the future so nbd. 3/18/2016 MS
2112
2113 if(wrd_objs.size() == 0) return; // Can't do anything without the raw data
2114 if(VERBOSE>3) evioout << " Entering EmulateDf125Firmware ..." <<endl;
2115
2116 vector <const Df125EmulatorAlgorithm*> f125Emulator_const;
2117 Df125EmulatorAlgorithm *f125Emulator = NULL__null;
2118 JEventLoop *loop = event.GetJEventLoop();
2119 Df125EmulatorAlgorithm_factory *f125EmFac = static_cast<Df125EmulatorAlgorithm_factory*>(loop->GetFactory("Df125EmulatorAlgorithm"));
2120 if (f125EmFac) {
2121 f125EmFac->Get(f125Emulator_const);
2122 // Drop const
2123 if (f125Emulator_const.size() != 0) {
2124 f125Emulator = const_cast<Df125EmulatorAlgorithm*>(f125Emulator_const[0]);
2125 } else {
2126 jerr << "Unable to load Df125EmulatorAlgorithm ! skipping emulation ..." << endl;
2127 return;
2128 }
2129 }
2130
2131 // Loop over all window raw data objects
2132 for(unsigned int i=0; i<wrd_objs.size(); i++){
2133 const Df125WindowRawData *f125WindowRawData = (Df125WindowRawData*)wrd_objs[i];
2134 Df125CDCPulse *f125CDCPulse = NULL__null;
2135 Df125FDCPulse *f125FDCPulse = NULL__null;
2136
2137 //search for existing CDCPulse
2138 for(uint32_t j=0; j<cp_objs.size(); j++){
2139 Df125CDCPulse *cp = (Df125CDCPulse*)cp_objs[j];
2140 if(cp->rocid == f125WindowRawData->rocid){
2141 if(cp->slot == f125WindowRawData->slot){
2142 if(cp->channel == f125WindowRawData->channel){
2143 f125CDCPulse = cp;
2144 f125CDCPulse->AddAssociatedObject(f125WindowRawData);
2145 break;
2146 }
2147 }
2148 }
2149 }
2150
2151 // search for existing FDCPulse
2152 for(uint32_t j=0; j<fp_objs.size(); j++){
2153 Df125FDCPulse *fp = (Df125FDCPulse*)fp_objs[j];
2154 if(fp->rocid == f125WindowRawData->rocid){
2155 if(fp->slot == f125WindowRawData->slot){
2156 if(fp->channel == f125WindowRawData->channel){
2157 f125FDCPulse = fp;
2158 f125FDCPulse->AddAssociatedObject(f125WindowRawData);
2159 break;
2160 }
2161 }
2162 }
2163 }
2164
2165 // If the the pulse objects do not exist, create new ones to go with our raw data
2166 // This should rarely happen since CDC_long and FDC_long have the raw data
2167 // along with the calculated quantities in a pulse word. Pure raw mode would be the only time
2168 // when this would not be the case. Since this is so infrequently used (if ever),
2169 // the ROCID check for CDC/FDC determination is hard coded...
2170 // ROCID CDC: 25-28
2171 // ROCID FDC Cathode: 52,53,55-62
2172
2173 if(f125CDCPulse == NULL__null && ( f125WindowRawData->rocid < 30 ) ){
2174 f125CDCPulse = new Df125CDCPulse;
2175 f125CDCPulse->rocid = f125WindowRawData->rocid;
2176 f125CDCPulse->slot = f125WindowRawData->slot;
2177 f125CDCPulse->channel = f125WindowRawData->channel;
2178 f125CDCPulse->emulated = true;
2179 f125CDCPulse->AddAssociatedObject(f125WindowRawData);
2180 cp_objs.push_back(f125CDCPulse);
2181 }
2182
2183 else if(f125FDCPulse == NULL__null && ( f125WindowRawData->rocid > 30 ) ){
2184 f125FDCPulse = new Df125FDCPulse;
2185 f125FDCPulse->rocid = f125WindowRawData->rocid;
2186 f125FDCPulse->slot = f125WindowRawData->slot;
2187 f125FDCPulse->channel = f125WindowRawData->channel;
2188 f125FDCPulse->emulated = true;
2189 f125FDCPulse->AddAssociatedObject(f125WindowRawData);
2190 cp_objs.push_back(f125FDCPulse);
2191 }
2192
2193 // Flag all objects as emulated and their values will be replaced with emulated quantities
2194 if (F125_EMULATION_MODE == kEmulationAlways){
2195 if(f125CDCPulse!=NULL__null) f125CDCPulse->emulated = 1;
2196 if(f125FDCPulse!=NULL__null) f125FDCPulse->emulated = 1;
2197 }
2198
2199 // Perform the emulation
2200 f125Emulator->EmulateFirmware(f125WindowRawData, f125CDCPulse, f125FDCPulse);
2201 }
2202
2203 if(VERBOSE>3) evioout << " Leaving EmulateDf125Firmware" <<endl;
2204}
2205
2206//----------------
2207// GetRunNumber
2208//----------------
2209int32_t JEventSource_EVIO::GetRunNumber(evioDOMTree *evt)
2210{
2211 // Note: This is currently not used. Preference is
2212 // now given to the run number found in FindRunNumber
2213 // which is called from GetEvent. This makes things
2214 // a little simpler and ensures the run number originally
2215 // presented to the processor/factory does not change.
2216 // 2/15/2016 DL
2217
2218 // This is called during event parsing to get the
2219 // run number for the event.
2220 // Look through event to try and extract the run number.
2221 // We do this by looking for all uint64_t nodes. Then
2222 // check for a parent with one of the magic values for
2223 // the tag indicating it has run number information.
2224 if(USER_RUN_NUMBER>0) return USER_RUN_NUMBER;
2225 if(!evt) return last_run_number;
2226
2227 evioDOMNodeListP bankList = evt->getNodeList(typeIs<uint64_t>());
2228 evioDOMNodeList::iterator iter = bankList->begin();
2229 const uint64_t *run_number_and_type = NULL__null;
2230 for(; iter!=bankList->end(); iter++){
2231 evioDOMNodeP bankPtr = *iter;
2232 evioDOMNodeP physics_event_built_trigger_bank = bankPtr->getParent();
2233 if(physics_event_built_trigger_bank == NULL__null) continue;
2234 uint32_t tag = physics_event_built_trigger_bank->tag;
2235 const vector<uint64_t> *vec;
2236 switch(tag){
2237 case 0xFF22:
2238 case 0xFF23:
2239 case 0xFF26:
2240 case 0xFF27:
2241 vec = bankPtr->getVector<uint64_t>();
2242 if(!vec) continue;
2243 if(vec->size()<1) continue;
2244 run_number_and_type = &((*vec)[vec->size()-1]);
2245 break;
2246 }
2247 if(run_number_and_type != NULL__null) break;
2248 }
2249
2250 if(run_number_and_type != NULL__null) last_run_number = (*run_number_and_type)>>32;
2251
2252 return last_run_number;
2253}
2254
2255//----------------
2256// FindRunNumber
2257//----------------
2258int32_t JEventSource_EVIO::FindRunNumber(uint32_t *iptr)
2259{
2260 /// This is called from GetEvent() to quickly look for the run number
2261 /// at the time the event is read in so it can be passed into
2262 /// JEvent. It is what will be used for accessing the CCDB.
2263 /// from this event. If a bank containing the run number is found,
2264 /// use it to provide the run number. Otherwise, return whatever run
2265 /// number we were able to extract from the file name.
2266
2267 if(VERBOSE>1) evioout << " .. Searching for run number ..." <<endl;
2268 if(USER_RUN_NUMBER>0){
2269 if(VERBOSE>1) evioout << " returning user-supplied run number: " << USER_RUN_NUMBER << endl;
2270 return last_run_number=USER_RUN_NUMBER;
2271 }
2272
2273 // Assume first word is number of words in bank
2274 uint32_t *iend = &iptr[*iptr - 1];
2275 if(*iptr > 2048) iend = &iptr[2048];
2276 bool has_timestamps = false;
2277 while(iptr<iend){
2278 iptr++;
2279
2280 // EPICS event
2281 if( (*iptr & 0xff000f) == 0x600001){
2282 if(VERBOSE>2) evioout << " Found EPICS header. Looking for HD:coda:daq:run_number ..." << endl;
2283 const char *cptr = (const char*)&iptr[1];
2284 const char *cend = (const char*)iend;
2285 const char *needle = "HD:coda:daq:run_number=";
2286 while(cptr<cend){
2287 if(VERBOSE>4) evioout << " \""<<cptr<<"\"" << endl;
2288 if(!strncmp(cptr, needle, strlen(needle))){
2289 if(VERBOSE>2) evioout << " Found it!" << endl;
2290 return last_run_number = atoi(&cptr[strlen(needle)]);
2291 }
2292 cptr+=4; // should only start on 4-byte boundary!
2293 }
2294 }
2295
2296 // BOR event
2297 if( (*iptr & 0xffffffff) == 0x00700E01){
2298 // OK, this looks like a BOR event which does not include the
2299 // run number. In this case, we have a couple of options:
2300 //
2301 // 1. If we are reading from a file then look further into
2302 // the file to see if we can find another event with the
2303 // run number in it.
2304 //
2305 // 2. Return the run number found from the filename.
2306 //
2307 if(source_type==kFileSource){
2308 int32_t run_number = EpicQuestForRunNumber();
2309 if(run_number != 0){
2310 if(VERBOSE>1) evioout << " Found run number " << run_number << " from Epic Quest." <<endl;
2311 return last_run_number = run_number;
2312 }
2313 }
2314 break; // return filename_run_number with warning message
2315 }
2316
2317 // PHYSICS event
2318 switch((*iptr)>>16){
2319 case 0xFF10:
2320 case 0xFF11:
2321 case 0xFF20:
2322 case 0xFF21:
2323 case 0xFF24:
2324 case 0xFF25:
2325 case 0xFF30:
2326 // These Trigger Bank Tag values have no run number info in them
2327 if(VERBOSE>2) evioout << " ... Trigger bank tag (0x" << hex << ((*iptr)>>16) << dec << ") does not contain run number" <<endl;
2328 if(!WARN_USER_RUN_FILENAME) {
2329 jout << "WARNING: setting run number " << filename_run_number << " based on file name" << endl;
2330 WARN_USER_RUN_FILENAME = true;
2331 }
2332 return last_run_number = filename_run_number;
2333 case 0xFF23:
2334 case 0xFF27:
2335 has_timestamps = true;
2336 case 0xFF22:
2337 case 0xFF26:
2338 if(VERBOSE>2) evioout << " ... Trigger bank tag (0x" << hex << ((*iptr)>>16) << dec << ") does contain run number" <<endl;
2339 // Nrocs = (*iptr) & 0x0F;
2340 break;
2341 default:
2342 continue;
2343 }
2344 iptr++;
2345 if( ((*iptr)&0x00FF0000) != 0x000A0000) { iptr--; continue; }
2346 uint32_t M = iptr[-3] & 0x000000FF; // Number of events from Physics Event header
2347 if(VERBOSE>2) evioout << " ... Trigger bank " << (has_timestamps ? "does":"doesn't") << " have timestamps. Nevents in block M=" << M <<endl;
2348 iptr++;
2349 uint64_t *iptr64 = (uint64_t*)iptr;
2350
2351 uint64_t event_num = *iptr64;
2352 if(source_type==kETSource) event_num = ((*iptr64)>>32) | ((*iptr64)<<32);
2353 if(VERBOSE>3) evioout << " .... Event num: " << event_num <<endl;
2354 iptr64++;
2355 if(has_timestamps) iptr64 = &iptr64[M]; // advance past timestamps
2356
2357 // I'm not sure I fully understand this, but if we read from
2358 // ET, then the run number is in the low 32 bits of *iptr64.
2359 // If we are reading from a file, it is in the high 32 bits.
2360 // No byte swapping is needed (it has already been done, though
2361 // perhaps incorrectly). We handle this here by checking if
2362 // this is an ET source or not.
2363 uint64_t run64 = (*iptr64)>>32;
2364 if(source_type==kETSource){
2365 run64 = (*iptr64)&0xffffffff;
2366 }
2367 int32_t run = (int32_t)run64;
2368 if(VERBOSE>1) evioout << " .. Found run number: " << run <<endl;
2369
2370 return last_run_number = run;
2371 }
2372
2373 // if we're not sure what else to do, try a more comprehensive search
2374 if(source_type==kFileSource){
2375 int32_t run_number = EpicQuestForRunNumber();
2376 if(run_number != 0){
2377 if(VERBOSE>1) evioout << " Found run number " << run_number << " from Epic Quest." <<endl;
2378 return last_run_number = run_number;
2379 }
2380 }
2381
2382 if(!WARN_USER_RUN_FILENAME) {
2383 jout << "WARNING: setting run number " << filename_run_number << " based on file name" << endl;
2384 WARN_USER_RUN_FILENAME = true;
2385 }
2386
2387 return last_run_number = filename_run_number;
2388}
2389
2390//----------------
2391// EpicQuestForRunNumber
2392//----------------
2393int32_t JEventSource_EVIO::EpicQuestForRunNumber(void)
2394{
2395 /// This is called when an event is encountered that does
2396 /// not have a run number in it. (e.g. a BOR event encountered
2397 /// in FindRunNumber() ). This is a last hope of finding the
2398 /// run number in the file by looking for other events that
2399 /// may contain it. Specifically, EPICS or PHYSICS events.
2400 /// This only works if it is a file source so that it can open
2401 /// the file and read in past the first event.
2402 ///
2403 /// Note that this is extremely inefficient so should not be
2404 /// called very often. As a precaution, this will look to see
2405 /// if last_run_number is not set to 0 first and will just
2406 /// return it if it is. Only if it is not will the epic quest
2407 /// commence.
2408
2409 if(source_type!=kFileSource) return 0;
2410 if(last_run_number != 0) return last_run_number;
2411
2412 uint32_t buff_len = 4000000;
2413 uint32_t *buff = new uint32_t[buff_len];
2414 HDEVIO *hdevio = new HDEVIO(source_name);
2415 while(hdevio->read(buff, buff_len)){
2416
2417 // Assume first word is number of words in bank
2418 uint32_t *iptr = buff;
2419 uint32_t *iend = &iptr[*iptr - 1];
2420 if(*iptr > 2048) iend = &iptr[2048];
2421 bool has_timestamps = false;
2422 while(iptr<iend){
2423 iptr++;
2424
2425 // EPICS event
2426 if( (*iptr & 0xff000f) == 0x600001){
2427 if(VERBOSE>2) evioout << " Found EPICS header. Looking for HD:coda:daq:run_number ..." << endl;
2428 const char *cptr = (const char*)&iptr[1];
2429 const char *cend = (const char*)iend;
2430 const char *needle = "HD:coda:daq:run_number=";
2431 while(cptr<cend){
2432 if(VERBOSE>4) evioout << " \""<<cptr<<"\"" << endl;
2433 if(!strncmp(cptr, needle, strlen(needle))){
2434 if(VERBOSE>2) evioout << " Found it!" << endl;
2435 int32_t run_number = atoi(&cptr[strlen(needle)]);
2436 if(hdevio) delete hdevio;
2437 if(buff) delete[] buff;
2438 return run_number;
2439 }
2440 cptr+=4; // should only start on 4-byte boundary!
2441 }
2442 }
2443
2444 // BOR event
2445 if( (*iptr & 0xffffffff) == 0x00700E01) continue;
2446
2447 // PHYSICS event
2448 bool not_in_this_buffer = false;
2449 switch((*iptr)>>16){
2450 case 0xFF10:
2451 case 0xFF11:
2452 case 0xFF20:
2453 case 0xFF21:
2454 case 0xFF24:
2455 case 0xFF25:
2456 case 0xFF30:
2457 not_in_this_buffer = true;
2458 break;
2459 case 0xFF23:
2460 case 0xFF27:
2461 has_timestamps = true;
2462 case 0xFF22:
2463 case 0xFF26:
2464 break;
2465 default:
2466 continue;
2467 }
2468
2469 if(not_in_this_buffer) break; // go to next EVIO buffer
2470
2471 iptr++;
2472 if( ((*iptr)&0x00FF0000) != 0x000A0000) { iptr--; continue; }
2473 uint32_t M = iptr[-3] & 0x000000FF; // Number of events from Physics Event header
2474 if(VERBOSE>2) evioout << " ...(epic quest) Trigger bank " << (has_timestamps ? "does":"doesn't") << " have timestamps. Nevents in block M=" << M <<endl;
2475 iptr++;
2476 uint64_t *iptr64 = (uint64_t*)iptr;
2477
2478 uint64_t event_num = *iptr64;
2479 if(source_type==kETSource) event_num = ((*iptr64)>>32) | ((*iptr64)<<32);
2480 if(VERBOSE>3) evioout << " ....(epic quest) Event num: " << event_num <<endl;
2481 iptr64++;
2482 if(has_timestamps) iptr64 = &iptr64[M]; // advance past timestamps
2483
2484 // I'm not sure I fully understand this, but if we read from
2485 // ET, then the run number is in the low 32 bits of *iptr64.
2486 // If we are reading from a file, it is in the high 32 bits.
2487 // No byte swapping is needed (it has already been done, though
2488 // perhaps incorrectly). We handle this here by checking if
2489 // this is an ET source or not.
2490 uint64_t run64 = (*iptr64)>>32;
2491 if(source_type==kETSource){
2492 run64 = (*iptr64)&0xffffffff;
2493 }
2494 int32_t run = (int32_t)run64;
2495 if(VERBOSE>1) evioout << " .. (epic quest) Found run number: " << run <<endl;
2496
2497 if(hdevio) delete hdevio;
2498 if(buff) delete[] buff;
2499 return run;
2500
2501 } // while(iptr<iend)
2502
2503 if(hdevio->Nevents > 500) break;
2504 } // while(hdevio->read(buff, buff_len))
2505
2506 if(hdevio) delete hdevio;
2507 if(buff) delete[] buff;
2508
2509 return 0;
2510}
2511
2512//----------------
2513// FindEventNumber
2514//----------------
2515uint64_t JEventSource_EVIO::FindEventNumber(uint32_t *iptr)
2516{
2517 /// This is called from GetEvent() to quickly look for the event number
2518 /// at the time the event is read in so it can be passed into JEvent.
2519 /// (See comments for FindRunNumber above.)
2520 if(VERBOSE>1) evioout << " .. Searching for event number ..." <<endl;
2521
2522 if(*iptr < 6){
2523 if(VERBOSE>1) evioout << " Word count(="<<*iptr<<")<6. Returning Nevents_read+1(=" << Nevents_read+1 << ") as event number" <<endl;
2524 return Nevents_read+1;
2525 }
2526
2527 // Check header of Trigger bank
2528 uint32_t mask = 0xFF202000;
2529 if( (iptr[3]&mask) != mask ){
2530 if(VERBOSE>1){
2531 evioout << " iptr[3]=" << hex << iptr[3] << " does not look like trigger bank tag (" << (iptr[3]&mask) << " != " << mask << ")" << dec <<endl;
2532 evioout << " Returning Nevents_read+1(=" << Nevents_read+1 << ") as event number" <<endl;
2533 }
2534 return Nevents_read+1;
2535 }
2536
2537 uint64_t loevent_num = iptr[5];
2538 uint64_t hievent_num = iptr[6];
2539 if(source_type==kETSource) {
2540 loevent_num = iptr[6];
2541 hievent_num = iptr[5];
2542 }
2543 uint64_t event_num = loevent_num + (hievent_num<<32);
2544 if(VERBOSE>1) evioout << " .. Found event number: " << event_num <<endl;
2545
2546 return event_num;
2547}
2548
2549//----------------
2550// FindEventType
2551//----------------
2552void JEventSource_EVIO::FindEventType(uint32_t *iptr, JEvent &event)
2553{
2554 /// This is called from GetEvent to quickly determine the type of
2555 /// event this is (Physics, EPICS, SYNC, BOR, ...)
2556 uint32_t head = iptr[1];
2557 if( (head & 0xff000f) == 0x600001){
2558 event.SetStatusBit(kSTATUS_EPICS_EVENT);
2559 }else if( (head & 0xffffffff) == 0x00700E01){
2560 event.SetStatusBit(kSTATUS_BOR_EVENT);
2561 }else if( (head & 0xffffff00) == 0xff501000){
2562 event.SetStatusBit(kSTATUS_PHYSICS_EVENT);
2563 }else if( (head & 0xffffff00) == 0xff701000){
2564 event.SetStatusBit(kSTATUS_PHYSICS_EVENT);
2565 }else if( (head & 0xfff000ff) == 0xffd00000){
2566 event.SetStatusBit(kSTATUS_CONTROL_EVENT);
2567 if( (head>>16) == 0xffd0 ) event.SetStatusBit(kSTATUS_SYNC_EVENT);
2568 }else{
2569 DumpBinary(iptr, &iptr[16]);
2570 }
2571}
2572
2573//----------------
2574// MergeObjLists
2575//----------------
2576void JEventSource_EVIO::MergeObjLists(list<ObjList*> &events1, list<ObjList*> &events2)
2577{
2578 if(VERBOSE>5) evioout << " Entering MergeObjLists(). "
2579 << " &events1=" << hex << &events1 << dec << "(" << events1.size() << " events) "
2580 << " &events2=" << hex << &events2 << dec << "(" << events2.size() << " events) " << endl;
2581
2582 /// Merge the events referenced in events2 into the events1 list.
2583 ///
2584 /// This will append the object lists for each type of data object
2585 /// stored in events2 onto the appropriate list in events1. It does this
2586 /// event-by-event. The idea being that each entry in the queue represents a
2587 /// partial list of the objects for the event. The two queues are most likely
2588 /// filled from different EVIO banks orginiating from different ROCs.
2589 ///
2590 /// Before the merging is done, it is checked that both lists either have the
2591 /// same number of events, or one list is empty. One list is allowed to be
2592 /// empty since it is possible it was "filled" from a bank that contains no
2593 /// data at all which may not neccessarily be an error. If both queues have
2594 /// at least one event, but they do not contain an equal number of events,
2595 /// then an exception is thrown.
2596 ///
2597 /// The contents of event2 will be erased before returning. Ownership of all
2598 /// ObjList objects pointed to by event2 upon entry should be considered
2599 /// owned by event1 upon return.
2600
2601 // Allow a list of 1 event with only config objects in test below
2602 bool justconfig = false;
2603 if(events1.size()==1){
2604 ObjList *objs1 = events1.front();
2605 justconfig = objs1->hit_objs.size()==0 && objs1->misc_objs.size()==0 && objs1->config_objs.size()!=0;
2606 }else if(events2.size()==1){
2607 ObjList *objs2 = events2.front();
2608 justconfig = objs2->hit_objs.size()==0 && objs2->misc_objs.size()==0 && objs2->config_objs.size()!=0;
2609 }
2610
2611 // Check number of events and throw exception if appropriate
2612 unsigned int Nevents1 = events1.size();
2613 unsigned int Nevents2 = events2.size();
2614 if(Nevents1>0 && Nevents2>0 && !justconfig){
2615 if(Nevents1 != Nevents2){
2616 evioout << "Mismatch of number of events passed to MergeObjLists. Throwing exception." << endl;
2617 evioout << "Nevents1="<<Nevents1<<" Nevents2="<<Nevents2<<endl;
2618 throw JException("Number of events in JEventSource_EVIO::MergeObjLists do not match!");
2619 }
2620 }
2621
2622 // Handle cases when one or both lists are empty
2623 if(Nevents1==0 && Nevents2==0)return;
2624 if(Nevents1==0){
2625 events1 = events2;
2626 events2.clear(); // clear queue
2627 return;
2628 }
2629 if(Nevents2==0)return;
2630
2631 // If we get here it means both events1 and events2 have events
2632 list<ObjList*>::iterator iter = events1.begin();
2633 for(; iter!=events1.end(); iter++){
2634 if(events2.empty()) break; // in case one has just config objects in a single event
2635 ObjList *objs1 = *iter;
2636 ObjList *objs2 = events2.front();
2637 events2.pop_front();
2638
2639 objs1->hit_objs.insert(objs1->hit_objs.end(), objs2->hit_objs.begin(), objs2->hit_objs.end());
2640 objs1->config_objs.insert(objs1->config_objs.end(), objs2->config_objs.begin(), objs2->config_objs.end());
2641 objs1->misc_objs.insert(objs1->misc_objs.end(), objs2->misc_objs.begin(), objs2->misc_objs.end());
2642
2643 // Delete the objs2 container
2644 delete objs2;
2645 }
2646
2647 // Clear out any references to objects in event2 (this should be redundant)
2648 events2.clear(); // clear queue
2649
2650 if(VERBOSE>5) evioout << " Leaving MergeObjLists(). &events1=" << hex << &events1 << " &events2=" << &events2 << dec << endl;
2651}
2652
2653//----------------
2654// ParseEVIOEvent
2655//----------------
2656void JEventSource_EVIO::ParseEVIOEvent(evioDOMTree *evt, list<ObjList*> &full_events)
2657{
2658 if(VERBOSE>5) evioout << " Entering ParseEVIOEvent() with evt=" << hex << evt << dec << endl;
1
Assuming field 'VERBOSE' is <= 5
2
Taking false branch
2659
2660 if(!evt)throw RESOURCE_UNAVAILABLE;
3
Assuming 'evt' is non-null
4
Taking false branch
2661
2662 // Since each bank contains parts of many events, have them fill in
2663 // the "tmp_events" list and then merge those into the "full_events".
2664 // It is done this way so each bank can grow tmp_events to the appropriate
2665 // size to hold the number of events it discovers in the bank. A check
2666 // can then be made that this is consistent with the number of event
2667 // fragments found in the other banks.
2668 //list<ObjList*> full_events;
2669 list<ObjList*> tmp_events;
2670
2671 // The Physics Event bank is the outermost bank of the event and
2672 // it is a bank of banks. One of those banks is the
2673 // "Built Trigger Bank" which is a bank of segments. The others
2674 // are the "Data Bank" banks which in turn contain the
2675 // "Data Block Bank" banks which hold the actual data. For the
2676 // mc2coda generated data files (and presumably the real data)
2677 // these Data Block Banks are banks of ints. More specifically,
2678 // uint32_t.
2679 //
2680 // The "Physics Event's Built Trigger Bank" is a bank of segments.
2681 // This contains 3 segments, one each of type uint64, uint16, and
2682 // unit32. The first two are "common data" which contains information
2683 // common to all rocs. The last (uint32) has information specific to each
2684 // event and for each ROC.
2685 //
2686 // For now, we skip parseing the Built Trigger Bank and just
2687 // look for Data Block Banks. We do this by getting a list of
2688 // all uint32_t banks in the enitries DOM Tree (at all levels
2689 // of the heirachy) and checking the parent banks for depth
2690 // and additional info.
2691
2692 // Loop over list of all EVIO banks at all levels of the tree and parse
2693 // them, creating data objects and adding them to the overall list.
2694 evioDOMNodeListP bankList = evt->getNodeList();
2695 evioDOMNodeList::iterator iter = bankList->begin();
2696 if(VERBOSE
4.1
Field 'VERBOSE' is <= 7
>7) evioout << " Looping over " << bankList->size() << " banks in EVIO event" << endl;
5
Taking false branch
2697 for(int ibank=1; iter!=bankList->end(); iter++, ibank++){ // ibank only used for debugging messages
6
Loop condition is true. Entering loop body
2698
2699 if(VERBOSE
6.1
Field 'VERBOSE' is <= 7
>7) evioout << " -------- bank " << ibank << "/" << bankList->size() << " --------" << endl;
7
Taking false branch
2700
2701 // The data banks we want should have exactly two parents:
2702 // - Data Bank bank <-- parent
2703 // - Physics Event bank <-- grandparent
2704 //
2705 // other types of events may be inserted in the datastream though so we
2706 // check for those first.
2707
2708 // BOR event
2709 // BOR events will have an outermost
2710 // bank with tag=0x70 and num=1. If this is the outermost bank of
2711 // a BOR event, then parse it. If it is a inner BOR bank then ignore it.
2712 evioDOMNodeP outermostBankPtr = *iter;
2713 while(outermostBankPtr->getParent()) outermostBankPtr = outermostBankPtr->getParent();
8
Loop condition is false. Execution continues on line 2714
2714 if(outermostBankPtr->tag==0x70 && outermostBankPtr->num==1){
9
Assuming field 'tag' is equal to 112
10
Assuming field 'num' is equal to 1
11
Taking true branch
2715 // This is a BOR bank
2716 if(VERBOSE
11.1
Field 'VERBOSE' is <= 9
>9) evioout << " bank is part of BOR event ... " << endl;
12
Taking false branch
2717 if(outermostBankPtr == *iter){
13
Assuming the condition is true
14
Taking true branch
2718 if(VERBOSE
14.1
Field 'VERBOSE' is <= 9
>9) evioout << " bank is outermost EVIO bank. Parsing BOR event ..." << endl;
15
Taking false branch
2719 ParseBORevent(outermostBankPtr);
16
Calling 'JEventSource_EVIO::ParseBORevent'
2720 }else{
2721 if(VERBOSE>9) evioout << " bank is not outermost EVIO bankin BOR event skipping ..." << endl;
2722 }
2723 continue; // no further processing of this bank is needed
2724 }
2725
2726 // EPICS event
2727 evioDOMNodeP bankPtr = *iter;
2728 evioDOMNodeP data_bank = bankPtr->getParent();
2729 if( data_bank==NULL__null ) {
2730
2731 if(VERBOSE>9) evioout << " bank has no parent. Checking if it's an EPICS event ... " << endl;
2732 if(bankPtr->tag==96 && bankPtr->num==1){
2733 // This looks like an EPICS event. Hand it over to EPICS parser
2734 ParseEPICSevent(bankPtr, full_events);
2735 }else{
2736 if(VERBOSE>9) evioout << " Not an EPICS event bank. skipping ... " << endl;
2737 }
2738
2739 continue;
2740 }
2741
2742 // Trigger Bank
2743 evioDOMNodeP physics_event_bank = data_bank->getParent();
2744
2745 // TS scalers for SYNC events. Currently us phys event tag
2746 // Don't use the parent tag in the future, to be checked
2747 if((physics_event_bank != NULL__null) && (bankPtr != NULL__null)){
2748 if( (physics_event_bank->tag == 0xff70) && (bankPtr->tag == 0xEE02)){
2749 const vector<uint32_t> *vec = bankPtr->getVector<uint32_t>();
2750 if(vec->size() < 102){
2751 evioout << " TS record for SYNC event is inconsistent. Don't parse " << endl;
2752 } else {
2753 ParseTSSync(bankPtr, full_events);
2754 // MergeObjLists(full_events, tmp_events);
2755 }
2756 }
2757 }
2758
2759
2760 if( physics_event_bank==NULL__null ){
2761 if(VERBOSE>6) evioout << " bank has no grandparent. Checking if this is a trigger bank ... " << endl;
2762
2763 // Check if this is a CODA Reserved Bank Tag. If it is, then
2764 // this probably is part of the built trigger bank and not
2765 // the ROC data we're looking to parse here.
2766 if((bankPtr->tag & 0xFF00) == 0xFF00){
2767 if(VERBOSE>6) evioout << " Bank tag="<<hex<<data_bank->tag<<dec<<" is in reserved CODA range and has correct lineage. Assuming it's a built trigger bank."<< endl;
2768 ParseBuiltTriggerBank(bankPtr, tmp_events);
2769 if(VERBOSE>5) evioout << " Merging objects in ParseEVIOEvent" << endl;
2770 MergeObjLists(full_events, tmp_events);
2771
2772 // Check if this is a DEventTag bank
2773 }else if(bankPtr->tag == 0x0056){
2774 const vector<uint32_t> *vec = bankPtr->getVector<uint32_t>();
2775 if(vec){
2776 const uint32_t *iptr = &(*vec)[0];
2777 const uint32_t *iend = &(*vec)[vec->size()];
2778 ParseEventTag(iptr, iend, tmp_events);
2779 if(VERBOSE>5) evioout << " Merging DEventTag objects in ParseEVIOEvent" << endl;
2780 MergeObjLists(full_events, tmp_events);
2781 }
2782 }
2783
2784 continue; // if this wasn't a trigger bank, then it has the wrong lineage to be a data bank
2785 }
2786 if( physics_event_bank->getParent() != NULL__null ){
2787 if(VERBOSE>9) evioout << " bank DOES have great-grandparent. skipping ... " << endl;
2788 continue; // physics event bank should have no parent!
2789 }
2790 if(VERBOSE>9){
2791 evioout << " Physics Event Bank: tag=" << hex << physics_event_bank->tag << " num=" << (int)physics_event_bank->num << dec << endl;
2792 evioout << " Data Bank: tag=" << hex << data_bank->tag << " num=" << (int)data_bank->num << dec << endl;
2793 }
2794
2795 if(VERBOSE>9) evioout << " bank lineage check OK. Continuing with parsing ... " << endl;
2796
2797 // Extract ROC id (crate number) from bank's parent
2798 uint32_t rocid = data_bank->tag & 0x0FFF;
2799
2800 // Get data from bank in the form of a vector of uint32_t
2801 const vector<uint32_t> *vec = bankPtr->getVector<uint32_t>();
2802 if(!vec){
2803 if(VERBOSE>6) evioout << " bank is not uint32_t. Skipping..." << endl;
2804 continue;
2805 }
2806 const uint32_t *iptr = &(*vec)[0];
2807 const uint32_t *iend = &(*vec)[vec->size()];
2808 if(VERBOSE>6) evioout << " uint32_t bank has " << vec->size() << " words" << endl;
2809
2810 // If there are rocid's specified that we wish to parse, make sure this one
2811 // is in the list. Otherwise, skip it.
2812 if(!ROCIDS_TO_PARSE.empty()){
2813 if(VERBOSE>4) evioout << " Skipping parsing of rocid="<<rocid<<" due to it being in ROCIDS_TO_PARSE set." << endl;
2814 if(ROCIDS_TO_PARSE.find(rocid) == ROCIDS_TO_PARSE.end()) continue;
2815 }
2816
2817 // Check if this is a CODA Reserved Bank Tag.
2818 if((data_bank->tag & 0xFF00) == 0xFF00){
2819 if(VERBOSE>6) evioout << " Data Bank tag="<<hex<<data_bank->tag<<dec<<" is in reserved CODA range. This is probably not ROC data"<< endl;
2820 continue;
2821 }
2822
2823 // Check if this is a TS Bank.
2824 if(bankPtr->tag == 0xEE02){
2825 if(VERBOSE>4) evioout << " TS bank tag="<<hex<<bankPtr->tag<<dec<< endl;
2826 ParseTSBank(rocid, iptr, iend, full_events);
2827 continue;
2828 }
2829
2830
2831 // Check if this is a f250 Pedestal Bank. Read out at SYNC events.
2832 if(bankPtr->tag == 0xEE05){
2833 if(VERBOSE>6) evioout << " SYNC event - f250 pedestals found " << endl;
2834 ParseFA250AsyncPedestals(bankPtr, full_events, rocid);
2835 continue;
2836 }
2837
2838
2839 // FADC 250 scalers. Read out at SYNC events
2840 if(bankPtr->tag == 0xEE10){
2841 if(VERBOSE>6) evioout << " SYNC event - f250 scalers found "<< endl;
2842 ParseFA250Scalers(bankPtr, full_events, rocid);
2843 continue;
2844 }
2845
2846 /*
2847 // Check if this bank stores DVertex data
2848 if(bankPtr->tag == 0x0D01){
2849 if(VERBOSE>4) evioout << " DVertex bank tag="<<hex<<bankPtr->tag<<dec<< endl;
2850 ParseDVertexBank(bankPtr, full_events);
2851 continue;
2852 }
2853 */
2854
2855 // The number of events in block is stored in lower 8 bits
2856 // of header word (aka the "num") of Data Bank. This should
2857 // be at least 1.
2858 uint32_t NumEvents = data_bank->num & 0xFF;
2859 if( NumEvents<1 ){
2860 if(VERBOSE>9) evioout << " bank has less than 1 event (Data Bank num or \"M\" = 0) skipping ... " << endl;
2861 continue;
2862 }
2863
2864 // At this point iptr and iend indicate the data that came
2865 // from the ROC itself (all CODA headers have been stripped
2866 // away). Here, we need to decide what type of data this
2867 // bank contains. All JLab modules have a common block
2868 // header format and so are handled in a common way. Other
2869 // modules (e.g. CAEN) will have to appear in their own
2870 // EVIO bank and should be identified by their own det_id
2871 // value in the Data Block Bank.
2872 //
2873 // Current, preliminary thinking includes writing the type
2874 // of data into the 12-bit detector id contained in the
2875 // Data Block Bank of the DAQ group's "Event Building EVIO
2876 // Scheme". (This is the lower 12 bits of the "tag"). We
2877 // use this to decide if it is JLab module data or somehting
2878 // else.
2879 uint32_t det_id = bankPtr->tag & 0x0FFF;
2880 // Call appropriate parsing method
2881 bool bank_parsed = true; // will be set to false if default case is entered
2882 switch(det_id){
2883 case 0:
2884 case 1:
2885 case 3:
2886 case 6: // flash 250 module, MMD 2014/2/4
2887 case 16: // flash 125 module (CDC), DL 2014/6/19
2888 case 26: // F1 TDC module (BCAL), MMD 2014-07-31
2889 ParseJLabModuleData(rocid, iptr, iend, tmp_events);
2890 break;
2891
2892 case 20:
2893 ParseCAEN1190(rocid, iptr, iend, tmp_events);
2894 break;
2895
2896 case 0x55:
2897 ParseModuleConfiguration(rocid, iptr, iend, tmp_events);
2898 break;
2899
2900 case 5:
2901 // Beni's original CDC ROL used for the stand-alone CDC DAQ
2902 // had the following for the TS readout list (used in the TI):
2903 // *dma_dabufp++ = 0xcebaf111;
2904 // *dma_dabufp++ = tsGetIntCount();
2905 // *dma_dabufp++ = 0xdead;
2906 // *dma_dabufp++ = 0xcebaf222;
2907 // We skip this here, but put in the case so that we avoid errors
2908 break;
2909
2910
2911 default:
2912 jerr<<"Unknown module type ("<<det_id<<") encountered for tag="<<bankPtr->tag<<" num="<< (int)bankPtr->num << endl;
2913 bank_parsed = false;
2914 if(VERBOSE>5){
2915 cerr << endl;
2916 cout << "----- First few words to help with debugging -----" << endl;
2917 cout.flush(); cerr.flush();
2918 int i=0;
2919 for(const uint32_t *iiptr = iptr; iiptr<iend; iiptr++, i++){
2920 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<2920<<" "
<< "0x" << hex << *iiptr << dec << endl;
2921 if(i>=8) break;
2922 }
2923
2924 }
2925 }
2926
2927 // Merge this bank's partial events into the full events
2928 if(bank_parsed){
2929 if(VERBOSE>5) evioout << " Merging objects in ParseEVIOEvent" << endl;
2930 MergeObjLists(full_events, tmp_events);
2931 }
2932 }
2933
2934 // The following disabled in preference for keeping the
2935 // run number found by FindRunNumber called from
2936 // GetEvent() 2/15/2016
2937
2938 // // Set the run number for all events
2939 // uint32_t run_number = GetRunNumber(evt);
2940 // list<ObjList*>::iterator evt_iter = full_events.begin();
2941 // for(; evt_iter!=full_events.end(); evt_iter++){
2942 // ObjList *objs = *evt_iter;
2943 // objs->run_number = run_number;
2944 // }
2945
2946 if(VERBOSE>5) evioout << " Leaving ParseEVIOEvent()" << endl;
2947}
2948
2949#if HAVE_EVIO1
2950//----------------
2951// ParseBuiltTriggerBank
2952//----------------
2953void JEventSource_EVIO::ParseBuiltTriggerBank(evioDOMNodeP trigbank, list<ObjList*> &events)
2954{
2955 if(!PARSE_TRIGGER) return;
2956
2957 if(VERBOSE>5) evioout << " Entering ParseBuiltTriggerBank()" << endl;
2958
2959 uint32_t Mevents = 1; // number of events in block (will be overwritten below)
2960 uint32_t Nrocs = (uint32_t)trigbank->num; // number of rocs providing data in this bank
2961 evioDOMNodeP physics_event_bank = trigbank->getParent();
2962 if(physics_event_bank) Mevents = (uint32_t)physics_event_bank->num;
2963
2964 if(VERBOSE>6) evioout << " Mevents=" << Mevents << " Nrocs=" << Nrocs << endl;
2965
2966 // Some values to fill in while parsing the banks that will be used later to create objects
2967 vector<uint64_t> avg_timestamps;
2968 uint32_t run_number = 0;
2969 uint32_t run_type = 0;
2970 uint64_t first_event_num = 1;
2971 vector<uint16_t> event_types;
2972 map<uint32_t, vector<DCODAROCInfo*> > rocinfos; // key=event (from 0 to Mevents-1)
2973 //vector<map<uint32_t, DCODAROCInfo*> > rocinfos; // key=rocid
2974
2975 // Loop over children of built trigger bank
2976 evioDOMNodeListP bankList = trigbank->getChildren();
2977 evioDOMNodeList::iterator iter = bankList->begin();
2978 for(int ibank=1; iter!=bankList->end(); iter++, ibank++){
2979
2980 if(VERBOSE>7) evioout << " Looking for data in child banks ..." << endl;
2981
2982 evioDOMNodeP bankPtr = *iter;
2983
2984 // The "Physics Event's Built Trigger Bank" is a bank of segments that
2985 // may contain banks of 3 data types: uint64_t, uint32_t, and uint16_t
2986 // The uint64_t contains the first event number, average timestamps, and
2987 // run number & types. The uint16_t contains the event type(s). The
2988 // uint32_t contains the optional ROC specific meta data starting with
2989 // the specific timestamp for each event. All of these have some options
2990 // on exactly what info is contained in the bank. The first check here is
2991 // on the data type the bank contains. At most, one of the following pointers
2992 // should be non-zero.
2993 vector<uint64_t> *vec64 = bankPtr->getVector<uint64_t>();
2994 vector<uint32_t> *vec32 = bankPtr->getVector<uint32_t>();
2995 vector<uint16_t> *vec16 = bankPtr->getVector<uint16_t>();
2996
2997 // unit64_t = common data (1st part)
2998 if(vec64){
2999
3000 if(VERBOSE>9) evioout << " found uint64_t data" << endl;
3001
3002 // In addition to the first event number (1st word) there are three
3003 // additional pieces of information that may be present:
3004 // t = average timestamp
3005 // r = run number and type
3006 // d = run specific data
3007 //
3008 // The last one ("d") comes in the form of multiple uint32_t banks
3009 // so is not included in vec64. The other two have their presence
3010 // signaled by bit 0(=t) and bit 1(=r) in the trigbank tag. (We can
3011 // also deduce this from the bank length.)
3012
3013 if(vec64->size() == 0) continue; // need debug message here!
3014
3015 first_event_num = (*vec64)[0];
3016
3017 // Hi and lo 32bit words in 64bit numbers seem to be
3018 // switched for events read from ET, but not read from
3019 // file. Not sure if this is in the swapping routine
3020 if(source_type==kETSource) first_event_num = (first_event_num>>32) | (first_event_num<<32);
3021
3022 uint32_t Ntimestamps = vec64->size()-1;
3023 if(Ntimestamps==0) continue; // no more words of interest
3024 if(trigbank->tag & 0x2) Ntimestamps--; // subtract 1 for run number/type word if present
3025 for(uint32_t i=0; i<Ntimestamps; i++) avg_timestamps.push_back((*vec64)[i+1]);
3026
3027 // run number and run type
3028 if(trigbank->tag & 0x02){
3029 run_number = (*vec64)[vec64->size()-1] >> 32;
3030 run_type = (*vec64)[vec64->size()-1] & 0xFFFFFFFF;
3031 }
3032 }
3033
3034 // uint16_t = common data (2nd part)
3035 if(vec16){
3036
3037 if(VERBOSE>9) evioout << " found uint16_t data" << endl;
3038
3039 for(uint32_t i=0; i<Mevents; i++){
3040 if(i>=vec16->size()) break;
3041 event_types.push_back((*vec16)[i]);
3042 }
3043 }
3044
3045 // uint32_t = inidivdual ROC timestamps and misc. roc-specfic data
3046 if(vec32){
3047
3048 if(VERBOSE>9) evioout << " found uint32_t data" << endl;
3049
3050 // Get pointer to DCODAROCInfo object for this rocid/event, instantiating it if necessary
3051 uint32_t rocid = (uint32_t)bankPtr->tag;
3052 uint32_t Nwords_per_event = vec32->size()/Mevents;
3053 if(vec32->size() != Mevents*Nwords_per_event){
3054 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<3054<<" "
<< "Number of ROC data words in Trigger Bank inconsistent with header" << endl;
3055 exit(-1);
3056 }
3057
3058 uint32_t *iptr = &(*vec32)[0];
3059 for(uint32_t ievent=0; ievent<Mevents; ievent++){
3060
3061 DCODAROCInfo *codarocinfo = new DCODAROCInfo;
3062 codarocinfo->rocid = rocid;
3063
3064 uint64_t ts_low = *iptr++;
3065 uint64_t ts_high = *iptr++;
3066 codarocinfo->timestamp = (ts_high<<32) + ts_low;
3067 for(uint32_t i=2; i<Nwords_per_event; i++) codarocinfo->misc.push_back(*iptr++);
3068
3069 if(VERBOSE>7) evioout << " Adding DCODAROCInfo for rocid="<<rocid<< " with timestamp " << codarocinfo->timestamp << endl;
3070 rocinfos[ievent].push_back(codarocinfo);
3071 }
3072 }
3073 }
3074
3075 // Check that we have agreement on the number of events this data represents
3076 bool Nevent_mismatch = false;
3077 if(!avg_timestamps.empty()) Nevent_mismatch |= (avg_timestamps.size() != Mevents);
3078 if(!event_types.empty() ) Nevent_mismatch |= (event_types.size() != Mevents);
3079 if(!rocinfos.empty() ) Nevent_mismatch |= (rocinfos.size() != Mevents);
3080 if(Nevent_mismatch){
3081 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<3081<<" "
<<"Mismatch in number of events in Trigger Bank!"<<endl;
3082 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<3082<<" "
<<" Mevents="<<Mevents<<endl;
3083 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<3083<<" "
<<" avg_timestamps.size()="<<avg_timestamps.size()<<endl;
3084 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<3084<<" "
<<" event_types.size()="<<event_types.size()<<endl;
3085 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<3085<<" "
<<" rocinfos.size()="<<rocinfos.size()<<endl;
3086 exit(-1);
3087 }
3088
3089 // Copy all objects into events
3090 for(uint32_t i=0; i<Mevents; i++){
3091 while(events.size()<=i){
3092 if(!ENABLE_DISENTANGLING && !events.empty()) break;
3093 events.push_back(new ObjList);
3094 }
3095 ObjList *objs = events.back();
3096
3097 DCODAEventInfo *codaeventinfo = new DCODAEventInfo;
3098 codaeventinfo->run_number = run_number;
3099 codaeventinfo->run_type = run_type;
3100 codaeventinfo->event_number = first_event_num + i;
3101 codaeventinfo->event_type = event_types.empty() ? 0:event_types[i];
3102 codaeventinfo->avg_timestamp = avg_timestamps.empty() ? 0:avg_timestamps[i];
3103 objs->misc_objs.push_back(codaeventinfo);
3104 objs->event_number = codaeventinfo->event_number;
3105
3106 vector<DCODAROCInfo*> &codarocinfos = rocinfos[i];
3107 for(uint32_t i=0; i<codarocinfos.size(); i++) objs->misc_objs.push_back(codarocinfos[i]);
3108 }
3109
3110 if(VERBOSE>6) evioout << " Found "<<events.size()<<" events in Built Trigger Bank"<< endl;
3111 if(VERBOSE>5) evioout << " Leaving ParseBuiltTriggerBank()" << endl;
3112}
3113#endif // HAVE_EVIO
3114
3115//----------------
3116// ParseModuleConfiguration
3117//----------------
3118void JEventSource_EVIO::ParseModuleConfiguration(int32_t rocid, const uint32_t* &iptr, const uint32_t *iend, list<ObjList*> &events)
3119{
3120 if(!PARSE_CONFIG){ iptr = iend; return; }
3121
3122 if(VERBOSE>5) evioout << " Entering ParseModuleConfiguration() (events.size()="<<events.size()<<")" << endl;
3123
3124 /// Parse a bank of module configuration data. These are configuration values
3125 /// programmed into the module at the beginning of the run that may be needed
3126 /// in the offline. For example, the number of samples to sum in a FADC pulse
3127 /// integral.
3128 ///
3129 /// The bank has one or more sections, each describing parameters applicable
3130 /// to a number of modules as indicated by a 24bit slot mask.
3131 ///
3132 /// This bank should appear only once per DAQ event which, if in multi-event
3133 /// block mode, may have multiple L1 events. The parameters here will apply
3134 /// to all L1 events in the block. This method will put the config objects
3135 /// in the first event of "events", creating it if needed. The config objects
3136 /// are duplicated for all other events in the block later, after all event
3137 /// parsing is finished and the total number of events is known.
3138 /// (See the end of ParseEvents() .)
3139
3140 while(iptr < iend){
3141 uint32_t slot_mask = (*iptr) & 0xFFFFFF;
3142 uint32_t Nvals = ((*iptr) >> 24) & 0xFF;
3143 iptr++;
3144
3145 Df250Config *f250config = NULL__null;
3146 Df125Config *f125config = NULL__null;
3147 DF1TDCConfig *f1tdcconfig = NULL__null;
3148 DCAEN1290TDCConfig *caen1290tdcconfig = NULL__null;
3149
3150 // Loop over all parameters in this section
3151 for(uint32_t i=0; i< Nvals; i++){
3152 if( iptr >= iend){
3153 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<3153<<" "
<< "DAQ Configuration bank corrupt! slot_mask=0x" << hex << slot_mask << dec << " Nvals="<< Nvals << endl;
3154 exit(-1);
3155 }
3156
3157 daq_param_type ptype = (daq_param_type)((*iptr)>>16);
3158 uint16_t val = (*iptr) & 0xFFFF;
3159
3160 if(VERBOSE>6) evioout << " DAQ parameter of type: 0x" << hex << ptype << dec << " found with value: " << val << endl;
3161
3162 // Create config object of correct type if needed and copy
3163 // parameter value into it.
3164 switch(ptype>>8){
3165
3166 // f250
3167 case 0x05:
3168 if( !f250config ) f250config = new Df250Config(rocid, slot_mask);
3169 switch(ptype){
3170 case kPARAM250_NSA : f250config->NSA = val; break;
3171 case kPARAM250_NSB : f250config->NSB = val; break;
3172 case kPARAM250_NSA_NSB : f250config->NSA_NSB = val; break;
3173 case kPARAM250_NPED : f250config->NPED = val; break;
3174 default: _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<3174<<" "
<< "UNKNOWN DAQ Config Parameter type: 0x" << hex << ptype << dec << endl;
3175 }
3176 break;
3177
3178 // f125
3179 case 0x0F:
3180 if( !f125config ) f125config = new Df125Config(rocid, slot_mask);
3181 switch(ptype){
3182 case kPARAM125_NSA : f125config->NSA = val; break;
3183 case kPARAM125_NSB : f125config->NSB = val; break;
3184 case kPARAM125_NSA_NSB : f125config->NSA_NSB = val; break;
3185 case kPARAM125_NPED : f125config->NPED = val; break;
3186 case kPARAM125_WINWIDTH : f125config->WINWIDTH = val; break;
3187 case kPARAM125_PL : f125config->PL = val; break;
3188 case kPARAM125_NW : f125config->NW = val; break;
3189 case kPARAM125_NPK : f125config->NPK = val; break;
3190 case kPARAM125_P1 : f125config->P1 = val; break;
3191 case kPARAM125_P2 : f125config->P2 = val; break;
3192 case kPARAM125_PG : f125config->PG = val; break;
3193 case kPARAM125_IE : f125config->IE = val; break;
3194 case kPARAM125_H : f125config->H = val; break;
3195 case kPARAM125_TH : f125config->TH = val; break;
3196 case kPARAM125_TL : f125config->TL = val; break;
3197 case kPARAM125_IBIT : f125config->IBIT = val; break;
3198 case kPARAM125_ABIT : f125config->ABIT = val; break;
3199 case kPARAM125_PBIT : f125config->PBIT = val; break;
3200 default: _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<3200<<" "
<< "UNKNOWN DAQ Config Parameter type: 0x" << hex << ptype << dec << endl;
3201 }
3202 break;
3203
3204 // F1TDC
3205 case 0x06:
3206 if( !f1tdcconfig ) f1tdcconfig = new DF1TDCConfig(rocid, slot_mask);
3207 switch(ptype){
3208 case kPARAMF1_REFCNT : f1tdcconfig->REFCNT = val; break;
3209 case kPARAMF1_TRIGWIN : f1tdcconfig->TRIGWIN = val; break;
3210 case kPARAMF1_TRIGLAT : f1tdcconfig->TRIGLAT = val; break;
3211 case kPARAMF1_HSDIV : f1tdcconfig->HSDIV = val; break;
3212 case kPARAMF1_BINSIZE : f1tdcconfig->BINSIZE = val; break;
3213 case kPARAMF1_REFCLKDIV : f1tdcconfig->REFCLKDIV = val; break;
3214 default: _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<3214<<" "
<< "UNKNOWN DAQ Config Parameter type: 0x" << hex << ptype << dec << endl;
3215 }
3216 break;
3217
3218 // caen1290
3219 case 0x10:
3220 if( !caen1290tdcconfig ) caen1290tdcconfig = new DCAEN1290TDCConfig(rocid, slot_mask);
3221 switch(ptype){
3222 case kPARAMCAEN1290_WINWIDTH : caen1290tdcconfig->WINWIDTH = val; break;
3223 case kPARAMCAEN1290_WINOFFSET : caen1290tdcconfig->WINOFFSET = val; break;
3224 default: _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<3224<<" "
<< "UNKNOWN DAQ Config Parameter type: 0x" << hex << ptype << dec << endl;
3225 }
3226 break;
3227
3228 default:
3229 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<3229<<" "
<< "Unknown module type: 0x" << hex << (ptype>>8) << endl;
3230 exit(-1);
3231 }
3232
3233#if 0
3234 // Create config object of correct type if needed. (Only one type
3235 // should be created per section!)
3236 switch(ptype>>8){
3237 case 0x05: if(!f250config ) f250config = new Df250Config(rocid, slot_mask); break;
3238 case 0x0F: if(!f125config ) f125config = new Df125Config(rocid, slot_mask); break;
3239 case 0x06: if(!f1tdcconfig ) f1tdcconfig = new DF1TDCConfig(rocid, slot_mask); break;
3240 case 0x10: if(!caen1290tdcconfig) caen1290tdcconfig = new DCAEN1290TDCConfig(rocid, slot_mask); break;
3241 default:
3242 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<3242<<" "
<< "Unknown module type: 0x" << hex << (ptype>>8) << endl;
3243 exit(-1);
3244 }
3245
3246 // Copy parameter into config. object
3247 switch(ptype){
3248 case kPARAM250_NSA : f250config->NSA = val; break;
3249 case kPARAM250_NSB : f250config->NSB = val; break;
3250 case kPARAM250_NSA_NSB : f250config->NSA_NSB = val; break;
3251 case kPARAM250_NPED : f250config->NPED = val; break;
3252
3253 case kPARAM125_NSA : f125config->NSA = val; break;
3254 case kPARAM125_NSB : f125config->NSB = val; break;
3255 case kPARAM125_NSA_NSB : f125config->NSA_NSB = val; break;
3256 case kPARAM125_NPED : f125config->NPED = val; break;
3257 case kPARAM125_WINWIDTH : f125config->WINWIDTH = val; break;
3258 case kPARAM125_PL : f125config->PL = val; break;
3259 case kPARAM125_NW : f125config->NW = val; break;
3260 case kPARAM125_NPK : f125config->NPK = val; break;
3261 case kPARAM125_P1 : f125config->P1 = val; break;
3262 case kPARAM125_P2 : f125config->P2 = val; break;
3263 case kPARAM125_PG : f125config->PG = val; break;
3264 case kPARAM125_IE : f125config->IE = val; break;
3265 case kPARAM125_H : f125config->H = val; break;
3266 case kPARAM125_TH : f125config->TH = val; break;
3267 case kPARAM125_TL : f125config->TL = val; break;
3268 case kPARAM125_IBIT : f125config->IBIT = val; break;
3269 case kPARAM125_ABIT : f125config->ABIT = val; break;
3270 case kPARAM125_PBIT : f125config->PBIT = val; break;
3271
3272 case kPARAMF1_REFCNT : f1tdcconfig->REFCNT = val; break;
3273 case kPARAMF1_TRIGWIN : f1tdcconfig->TRIGWIN = val; break;
3274 case kPARAMF1_TRIGLAT : f1tdcconfig->TRIGLAT = val; break;
3275 case kPARAMF1_HSDIV : f1tdcconfig->HSDIV = val; break;
3276 case kPARAMF1_BINSIZE : f1tdcconfig->BINSIZE = val; break;
3277 case kPARAMF1_REFCLKDIV : f1tdcconfig->REFCLKDIV = val; break;
3278
3279 case kPARAMCAEN1290_WINWIDTH : caen1290tdcconfig->WINWIDTH = val; break;
3280 case kPARAMCAEN1290_WINOFFSET : caen1290tdcconfig->WINOFFSET = val; break;
3281
3282 default:
3283 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<3283<<" "
<< "UNKNOWN DAQ Config Parameter type: 0x" << hex << ptype << dec << endl;
3284 }
3285#endif
3286
3287 iptr++;
3288 }
3289
3290 // If we get here it means we didn't exit in the switch(ptype>>16) statement above
3291 // so there is at least one DDAQConfig object we need to store. Get pointer to
3292 // first event's ObjList, creating it if needed.
3293 if(events.empty()) events.push_back(new ObjList());
3294 ObjList *objs = *(events.begin());
3295
3296 if(f250config ) objs->config_objs.push_back(f250config );
3297 if(f125config ) objs->config_objs.push_back(f125config );
3298 if(f1tdcconfig ) objs->config_objs.push_back(f1tdcconfig );
3299 if(caen1290tdcconfig) objs->config_objs.push_back(caen1290tdcconfig);
3300 }
3301
3302 if(VERBOSE>5) evioout << " Leaving ParseModuleConfiguration()" << endl;
3303}
3304
3305//----------------
3306// ParseEventTag
3307//----------------
3308void JEventSource_EVIO::ParseEventTag(const uint32_t* &iptr, const uint32_t *iend, list<ObjList*> &events)
3309{
3310 if(!PARSE_EVENTTAG){ iptr = iend; return; }
3311
3312 if(VERBOSE>5) evioout << " Entering ParseEventTag() (events.size()="<<events.size()<<")" << endl;
3313
3314 // Make sure there is one event in the event container
3315 // and get pointer to it.
3316 if(events.empty()) events.push_back(new ObjList());
3317 ObjList *objs = *(events.begin());
3318
3319
3320 DEventTag *etag = new DEventTag;
3321
3322 // event_status
3323 uint64_t lo = *iptr++;
3324 uint64_t hi = *iptr++;
3325 etag->event_status = (hi<<32) + lo;
3326
3327 // L3_status
3328 lo = *iptr++;
3329 hi = *iptr++;
3330 etag->L3_status = (hi<<32) + lo;
3331
3332 // L3_decision
3333 etag->L3_decision = (DL3Trigger::L3_decision_t)*iptr++;
3334
3335 // L3_algorithm
3336 etag->L3_algorithm = *iptr++;
3337
3338 objs->misc_objs.push_back(etag);
3339
3340
3341 if(VERBOSE>5) evioout << " Leaving ParseEventTag()" << endl;
3342}
3343
3344//----------------
3345// ParseJLabModuleData
3346//----------------
3347void JEventSource_EVIO::ParseJLabModuleData(int32_t rocid, const uint32_t* &iptr, const uint32_t *iend, list<ObjList*> &events)
3348{
3349 if(VERBOSE>5) evioout << " Entering ParseJLabModuleData()" << endl;
3350
3351 /// Parse a bank of data coming from one or more JLab modules.
3352 /// The data are assumed to follow the standard JLab format for
3353 /// block headers. If multiple modules are read out in a single
3354 /// chain block transfer, then the data will all be placed in
3355 /// a single EVIO bank and this will loop over the modules.
3356 while(iptr < iend){
3357
3358 if(VERBOSE>9) evioout << "Parsing word: " << hex << *iptr << dec << endl;
3359
3360 // This was observed in some CDC data. Not sure where it came from ...
3361 if(*iptr == 0xF800FAFA){
3362 if(VERBOSE>9) evioout << " 0xf800fafa is a known extra word. Skipping it ..." << endl;
3363 iptr++;
3364 continue;
3365 }
3366
3367 // Get module type from next word (bits 18-21)
3368 uint32_t mod_id = ((*iptr) >> 18) & 0x000F;
3369
3370 // The enum defined in DModuleType.h MUST be kept in alignment
3371 // with the DAQ group's definitions for modules types!
3372 MODULE_TYPE type = (MODULE_TYPE)mod_id;
3373 if(VERBOSE>5) evioout << " Encountered module type: " << type << " (=" << DModuleType::GetModule(type).GetName() << ")" << endl;
3374
3375 if(modtype_translate.find(type) != modtype_translate.end()){
3376 type = modtype_translate[type];
3377 if(VERBOSE>5) evioout << " switched module type to: " << type << " (=" << DModuleType::GetModule(type).GetName() << ")" << endl;
3378 }
3379
3380 // Parse buffer depending on module type
3381 // (Note that each of the ParseXXX routines called below will
3382 // update the "iptr" variable to point to the next word
3383 // after the block it parsed.)
3384 list<ObjList*> tmp_events;
3385 const uint32_t *istart=iptr; // just for UNKNOWN case below
3386 bool module_parsed = true;
3387 switch(type){
3388 case DModuleType::FADC250:
3389 Parsef250Bank(rocid, iptr, iend, tmp_events);
3390 break;
3391
3392 case DModuleType::FADC125:
3393 Parsef125Bank(rocid, iptr, iend, tmp_events);
3394 break;
3395
3396 case DModuleType::F1TDC32:
3397 ParseF1TDCBank(rocid, iptr, iend, tmp_events);
3398 break;
3399
3400 case DModuleType::F1TDC48:
3401 ParseF1TDCBank(rocid, iptr, iend, tmp_events);
3402 break;
3403
3404 case DModuleType::JLAB_TS:
3405 //ParseTSBank(rocid, iptr, iend, tmp_events); // This is not used
3406 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<3406<<" "
<< "What the ? ! This data type isn't supposed to be here!!" << endl;
3407 break;
3408
3409 case DModuleType::TID:
3410 ParseTIBank(rocid, iptr, iend, tmp_events);
3411 break;
3412
3413 case DModuleType::UNKNOWN:
3414 default:
3415 jerr<<"Unknown module type ("<<mod_id<<") iptr=0x" << hex << iptr << dec << endl;
3416
3417 while(iptr<iend && ((*iptr) & 0xF8000000) != 0x88000000) iptr++; // Skip to JLab block trailer
3418 iptr++; // advance past JLab block trailer
3419 while(iptr<iend && *iptr == 0xF8000000) iptr++; // skip filler words after block trailer
3420 module_parsed = false;
3421 jerr<<"...skipping to 0x" << hex << iptr << dec << " (discarding " << (((uint64_t)iptr-(uint64_t)istart)/4) << " words)" << endl;
3422 break;
3423 }
3424
3425 if(VERBOSE>9) evioout << "Finished parsing (last word: " << hex << iptr[-1] << dec << ")" << endl;
3426
3427 if(module_parsed){
3428 if(VERBOSE>5) evioout << " Merging objects in ParseJLabModuleData" << endl;
3429 MergeObjLists(events, tmp_events);
3430 }
3431 }
3432
3433 if(VERBOSE>5) evioout << " Leaving ParseJLabModuleData()" << endl;
3434}
3435
3436//----------------
3437// Parsef250Bank
3438//----------------
3439void JEventSource_EVIO::Parsef250Bank(int32_t rocid, const uint32_t* &iptr, const uint32_t *iend, list<ObjList*> &events)
3440{
3441 /// Parse data from a single FADC250 module.
3442
3443 if(!PARSE_F250){ iptr = iend; return; }
3444
3445 // This will get updated to point to a newly allocated object when an
3446 // event header is encountered. The existing value (if non-NULL) is
3447 // added to the events queue first though so all events are kept.
3448 ObjList *objs = NULL__null;
3449
3450 // From the Block Header
3451 uint32_t slot=0;
3452 //uint32_t Nblock_events;
3453 //uint32_t iblock;
3454
3455 // From the Block Trailer
3456 //uint32_t slot_trailer;
3457 //uint32_t Nwords_in_block;
3458
3459 // From Event header
3460 //uint32_t slot_event_header;
3461 uint32_t itrigger = -1;
3462 uint32_t last_itrigger = -2;
3463
3464 // Loop over data words
3465 for(; iptr<iend; iptr++){
3466
3467 // Skip all non-data-type-defining words at this
3468 // level. When we do encounter one, the appropriate
3469 // case block below should handle parsing all of
3470 // the data continuation words and advance the iptr.
3471 if(((*iptr>>31) & 0x1) == 0)continue;
3472
3473 // Variables used inside of switch, but cannot be declared inside
3474 uint64_t t = 0L;
3475 uint32_t channel = 0;
3476 uint32_t sum = 0;
3477 uint32_t pulse_number = 0;
3478 uint32_t quality_factor = 0;
3479 uint32_t pulse_time = 0;
3480 uint32_t pedestal = 0;
3481 uint32_t pulse_peak = 0;
3482 uint32_t nsamples_integral = 0;
3483 uint32_t nsamples_pedestal = 0;
3484 bool overflow = false;
3485
3486 bool found_block_trailer = false;
3487 uint32_t data_type = (*iptr>>27) & 0x0F;
3488 switch(data_type){
3489 case 0: // Block Header
3490 slot = (*iptr>>22) & 0x1F;
3491 if(VERBOSE>7) evioout << " FADC250 Block Header: slot="<<slot<<" ("<<hex<<*iptr<<dec<<")"<<endl;
3492 //iblock= (*iptr>>8) & 0x03FF;
3493 //Nblock_events= (*iptr>>0) & 0xFF;
3494 break;
3495 case 1: // Block Trailer
3496 //slot_trailer = (*iptr>>22) & 0x1F;
3497 //Nwords_in_block = (*iptr>>0) & 0x3FFFFF;
3498 if(VERBOSE>7) evioout << " FADC250 Block Trailer"<<" ("<<hex<<*iptr<<dec<<")"<<endl;
3499 found_block_trailer = true;
3500 break;
3501 case 2: // Event Header
3502 //slot_event_header = (*iptr>>22) & 0x1F;
3503 itrigger = (*iptr>>0) & 0x3FFFFF;
3504 if(VERBOSE>7) evioout << " FADC250 Event Header: itrigger="<<itrigger<<" (objs=0x"<<hex<<objs<<dec<<", last_itrigger="<<last_itrigger<<", rocid="<<rocid<<", slot="<<slot<<")" <<" ("<<hex<<*iptr<<dec<<")" <<endl;
3505 if( (itrigger!=last_itrigger) || (objs==NULL__null) ){
3506 if(ENABLE_DISENTANGLING){
3507 if(objs){
3508 events.push_back(objs);
3509 objs = NULL__null;
3510 }
3511 }
3512 if(!objs) objs = new ObjList;
3513 last_itrigger = itrigger;
3514 }
3515 break;
3516 case 3: // Trigger Time
3517 t = ((*iptr)&0xFFFFFF)<<0;
3518 if(VERBOSE>7) evioout << " FADC250 Trigger Time: t="<<t<<" ("<<hex<<*iptr<<dec<<")"<<endl;
3519 iptr++;
3520 if(((*iptr>>31) & 0x1) == 0){
3521 t += ((*iptr)&0xFFFFFF)<<24; // from word on the street: second trigger time word is optional!!??
3522 if(VERBOSE>7) evioout << " Trigger time high word="<<(((*iptr)&0xFFFFFF))<<" ("<<hex<<*iptr<<dec<<")"<<endl;
3523 }else{
3524 iptr--;
3525 }
3526 if(objs) objs->hit_objs.push_back(new Df250TriggerTime(rocid, slot, itrigger, t));
3527 break;
3528 case 4: // Window Raw Data
3529 // iptr passed by reference and so will be updated automatically
3530 if(VERBOSE>7) evioout << " FADC250 Window Raw Data"<<" ("<<hex<<*iptr<<dec<<")"<<endl;
3531 MakeDf250WindowRawData(objs, rocid, slot, itrigger, iptr);
3532 break;
3533 case 5: // Window Sum
3534 channel = (*iptr>>23) & 0x0F;
3535 sum = (*iptr>>0) & 0x3FFFFF;
3536 overflow = (*iptr>>22) & 0x1;
3537 if(VERBOSE>7) evioout << " FADC250 Window Sum"<<" ("<<hex<<*iptr<<dec<<")"<<endl;
3538 if(objs) objs->hit_objs.push_back(new Df250WindowSum(rocid, slot, channel, itrigger, sum, overflow));
3539 break;
3540 case 6: // Pulse Raw Data
3541 // iptr passed by reference and so will be updated automatically
3542 if(VERBOSE>7) evioout << " FADC250 Pulse Raw Data"<<" ("<<hex<<*iptr<<dec<<")"<<endl;
3543 MakeDf250PulseRawData(objs, rocid, slot, itrigger, iptr);
3544 break;
3545 case 7: // Pulse Integral
3546 channel = (*iptr>>23) & 0x0F;
3547 pulse_number = (*iptr>>21) & 0x03;
3548 quality_factor = (*iptr>>19) & 0x03;
3549 sum = (*iptr>>0) & 0x7FFFF;
3550 nsamples_integral = 0; // must be overwritten later in GetObjects with value from Df125Config value
3551 nsamples_pedestal = 1; // The firmware returns an already divided pedestal
3552 pedestal = 0; // This will be replaced by the one from Df250PulsePedestal in GetObjects
3553 if(VERBOSE>7) evioout << " FADC250 Pulse Integral: chan="<<channel<<" pulse_number="<<pulse_number<<" sum="<<sum<<" ("<<hex<<*iptr<<dec<<")"<<endl;
3554 if( (objs!=NULL__null) && (pulse_number<F250PULSE_NUMBER_FILTER) ) {
3555 objs->hit_objs.push_back(new Df250PulseIntegral(rocid, slot, channel, itrigger, pulse_number,
3556 quality_factor, sum, pedestal, nsamples_integral, nsamples_pedestal));
3557 }
3558 break;
3559 case 8: // Pulse Time
3560 channel = (*iptr>>23) & 0x0F;
3561 pulse_number = (*iptr>>21) & 0x03;
3562 quality_factor = (*iptr>>19) & 0x03;
3563 pulse_time = (*iptr>>0) & 0x7FFFF;
3564 if(VERBOSE>7) evioout << " FADC250 Pulse Time: chan="<<channel<<" pulse_number="<<pulse_number<<" pulse_time="<<pulse_time<<" ("<<hex<<*iptr<<dec<<")"<<endl;
3565 if( (objs!=NULL__null) && (pulse_number<F250PULSE_NUMBER_FILTER) ) {
3566 objs->hit_objs.push_back(new Df250PulseTime(rocid, slot, channel, itrigger, pulse_number, quality_factor, pulse_time));
3567 }
3568 break;
3569 case 9: // Streaming Raw Data
3570 // This is marked "reserved for future implementation" in the current manual (v2).
3571 // As such, we don't try handling it here just yet.
3572 if(VERBOSE>7) evioout << " FADC250 Streaming Raw Data (unsupported)"<<" ("<<hex<<*iptr<<dec<<")"<<endl;
3573 break;
3574 case 10: // Pulse Pedestal
3575 channel = (*iptr>>23) & 0x0F;
3576 pulse_number = (*iptr>>21) & 0x03;
3577 pedestal = (*iptr>>12) & 0x1FF;
3578 pulse_peak = (*iptr>>0) & 0xFFF;
3579 if(VERBOSE>7) evioout << " FADC250 Pulse Pedestal chan="<<channel<<" pulse_number="<<pulse_number<<" pedestal="<<pedestal<<" pulse_peak="<<pulse_peak<<" ("<<hex<<*iptr<<dec<<")"<<endl;
3580 if( (objs!=NULL__null) && (pulse_number<F250PULSE_NUMBER_FILTER) ) {
3581 objs->hit_objs.push_back(new Df250PulsePedestal(rocid, slot, channel, itrigger, pulse_number, pedestal, pulse_peak));
3582 }
3583 break;
3584 case 13: // Event Trailer
3585 // This is marked "suppressed for normal readout – debug mode only" in the
3586 // current manual (v2). It does not contain any data so the most we could do here
3587 // is return early. I'm hesitant to do that though since it would mean
3588 // different behavior for debug mode data as regular data.
3589 case 14: // Data not valid (empty module)
3590 case 15: // Filler (non-data) word
3591 if(VERBOSE>7) evioout << " FADC250 Event Trailer, Data not Valid, or Filler word ("<<data_type<<")"<<" ("<<hex<<*iptr<<dec<<")"<<endl;
3592 break;
3593 }
3594
3595 // Once we find a block trailer, assume that is it for this module.
3596 if(found_block_trailer){
3597 iptr++; // iptr is still pointing to block trailer. Jump to next word.
3598 break;
3599 }
3600 }
3601
3602 // Chop off filler words
3603 for(; iptr<iend; iptr++){
3604 if(((*iptr)&0xf8000000) != 0xf8000000) break;
3605 }
3606
3607 // Add last event in block to list
3608 if(objs)events.push_back(objs);
3609
3610 // Here, we make object associations to link PulseIntegral, PulseTime, PulseRawData, etc
3611 // objects to each other so it is easier to get to these downstream without having to
3612 // make nested loops. This is the most efficient place to do it since the ObjList objects
3613 // in "event" contain only the objects from this EVIO block (i.e. at most one crate's
3614 // worth.)
3615 list<ObjList*>::iterator iter = events.begin();
3616 for(; iter!=events.end(); iter++){
3617
3618 // Sort list of objects into type-specific lists
3619 vector<DDAQAddress*> &hit_objs = (*iter)->hit_objs;
3620 vector<Df250TriggerTime*> vtrigt;
3621 vector<Df250WindowRawData*> vwrd;
3622 vector<Df250WindowSum*> vws;
3623 vector<Df250PulseRawData*> vprd;
3624 vector<Df250PulseIntegral*> vpi;
3625 vector<Df250PulseTime*> vpt;
3626 vector<Df250PulsePedestal*> vpp;
3627 for(unsigned int i=0; i<hit_objs.size(); i++){
3628 AddIfAppropriate(hit_objs[i], vtrigt);
3629 AddIfAppropriate(hit_objs[i], vwrd);
3630 AddIfAppropriate(hit_objs[i], vws);
3631 AddIfAppropriate(hit_objs[i], vprd);
3632 AddIfAppropriate(hit_objs[i], vpi);
3633 AddIfAppropriate(hit_objs[i], vpt);
3634 AddIfAppropriate(hit_objs[i], vpp);
3635 }
3636
3637 // Connect Df250PulseIntegral, Df250PulseTime, and
3638 // Df250PulsePedestal with Df250PulseRawData
3639 // (n.b. the associations between pi, pt, and pp are
3640 // done in GetObjects where emulated objects are
3641 // also available.)
3642 LinkAssociationsWithPulseNumber(vprd, vpi);
3643 LinkAssociationsWithPulseNumber(vprd, vpt);
3644 LinkAssociationsWithPulseNumber(vprd, vpp);
3645
3646 // Connect Df250WindowSum and Df250WindowRawData
3647 LinkAssociations(vwrd, vws);
3648
3649 // Connect Df250TriggerTime to everything
3650 LinkAssociationsModuleOnly(vtrigt, vwrd);
3651 LinkAssociationsModuleOnly(vtrigt, vws);
3652 LinkAssociationsModuleOnly(vtrigt, vprd);
3653 LinkAssociationsModuleOnly(vtrigt, vpi);
3654 LinkAssociationsModuleOnly(vtrigt, vpt);
3655 LinkAssociationsModuleOnly(vtrigt, vpp);
3656 }
3657}
3658
3659//----------------
3660// MakeDf250WindowRawData
3661//----------------
3662void JEventSource_EVIO::MakeDf250WindowRawData(ObjList *objs, uint32_t rocid, uint32_t slot, uint32_t itrigger, const uint32_t* &iptr)
3663{
3664 uint32_t channel = (*iptr>>23) & 0x0F;
3665 uint32_t window_width = (*iptr>>0) & 0x0FFF;
3666
3667 Df250WindowRawData *wrd = new Df250WindowRawData(rocid, slot, channel, itrigger);
3668
3669 for(uint32_t isample=0; isample<window_width; isample +=2){
3670
3671 // Advance to next word
3672 iptr++;
3673
3674 // Make sure this is a data continuation word, if not, stop here
3675 if(((*iptr>>31) & 0x1) != 0x0){
3676 iptr--; // calling method expects us to point to last word in block
3677 break;
3678 }
3679
3680 bool invalid_1 = (*iptr>>29) & 0x1;
3681 bool invalid_2 = (*iptr>>13) & 0x1;
3682 uint16_t sample_1 = 0;
3683 uint16_t sample_2 = 0;
3684 if(!invalid_1)sample_1 = (*iptr>>16) & 0x1FFF;
3685 if(!invalid_2)sample_2 = (*iptr>>0) & 0x1FFF;
3686
3687 // Sample 1
3688 wrd->samples.push_back(sample_1);
3689 wrd->invalid_samples |= invalid_1;
3690 wrd->overflow |= (sample_1>>12) & 0x1;
3691
3692 if((isample+2) == window_width && invalid_2)break; // skip last sample if flagged as invalid
3693
3694 // Sample 2
3695 wrd->samples.push_back(sample_2);
3696 wrd->invalid_samples |= invalid_2;
3697 wrd->overflow |= (sample_2>>12) & 0x1;
3698 }
3699
3700 // Due to how the calling function works, the value of "objs" passed to us may be NULL.
3701 // This will happen if a Window Raw Data block is encountered before an event header.
3702 // For these cases, we still want to try parsing the data so that the iptr is updated
3703 // but don't have an event to assign it to. If "objs" is non-NULL, add this object to
3704 // the list. Otherwise, delete it now.
3705 if(objs){
3706 objs->hit_objs.push_back(wrd);
3707 }else{
3708 delete wrd;
3709 }
3710}
3711
3712//----------------
3713// MakeDf250PulseRawData
3714//----------------
3715void JEventSource_EVIO::MakeDf250PulseRawData(ObjList *objs, uint32_t rocid, uint32_t slot, uint32_t itrigger, const uint32_t* &iptr)
3716{
3717 const uint32_t *istart = iptr;
3718 uint32_t channel = (*iptr>>23) & 0x0F;
3719 uint32_t pulse_number = (*iptr>>21) & 0x0003;
3720 uint32_t first_sample_number = (*iptr>>0) & 0x03FF;
3721
3722 if(VERBOSE>9) evioout << " DF250PulseRawData: iptr=0x" << hex << iptr << dec << " channel=" << channel << " pulse_number=" << pulse_number << " first_sample=" << first_sample_number << endl;
3723
3724 Df250PulseRawData *prd = new Df250PulseRawData(rocid, slot, channel, itrigger, pulse_number, first_sample_number);
3725
3726 // This loop needs to break when it hits a non-continuation word
3727 for(uint32_t isample=0; isample<1000; isample +=2){
3728
3729 // Advance to next word
3730 iptr++;
3731
3732 // Make sure this is a data continuation word, if not, stop here
3733 if(((*iptr>>31) & 0x1) != 0x0)break;
3734
3735 bool invalid_1 = (*iptr>>29) & 0x1;
3736 bool invalid_2 = (*iptr>>13) & 0x1;
3737 uint16_t sample_1 = 0;
3738 uint16_t sample_2 = 0;
3739 if(!invalid_1)sample_1 = (*iptr>>16) & 0x1FFF;
3740 if(!invalid_2)sample_2 = (*iptr>>0) & 0x1FFF;
3741
3742 // Sample 1
3743 prd->samples.push_back(sample_1);
3744 prd->invalid_samples |= invalid_1;
3745 prd->overflow |= (sample_1>>12) & 0x1;
3746
3747 bool last_word = (iptr[1]>>31) & 0x1;
3748 if(last_word && invalid_2)break; // skip last sample if flagged as invalid
3749
3750 // Sample 2
3751 prd->samples.push_back(sample_2);
3752 prd->invalid_samples |= invalid_2;
3753 prd->overflow |= (sample_2>>12) & 0x1;
3754 }
3755
3756 if(VERBOSE>9) evioout << " number of samples: " << prd->samples.size() << " words processed: " << iptr-istart << endl;
3757
3758 // When should get here because the loop above stopped when it found
3759 // a data defining word (bit 31=1). The method calling this one will
3760 // assume iptr is pointing to the last word of this block and it will
3761 // advance to the first word of the next block. We need to back up one
3762 // word so that it is pointing to the last word of this block.
3763 iptr--;
3764
3765 // Due to how the calling function works, the value of "objs" passed to us may be NULL.
3766 // This will happen if a Window Raw Data block is encountered before an event header.
3767 // For these cases, we still want to try parsing the data so that the iptr is updated
3768 // but don't have an event to assign it to. If "objs" is non-NULL, add this object to
3769 // the list. Otherwise, delete it now.
3770 if(objs){
3771 objs->hit_objs.push_back(prd);
3772 }else{
3773 delete prd;
3774 }
3775}
3776
3777//----------------
3778// Parsef125Bank
3779//----------------
3780void JEventSource_EVIO::Parsef125Bank(int32_t rocid, const uint32_t* &iptr, const uint32_t* iend, list<ObjList*> &events)
3781{
3782 /// Parse data from a single FADC125 module.
3783 /// This is currently written assuming that the Pulse Integral, Pulse Time, and Pulse Pedestal
3784 /// data formats follow what is in the file:
3785 /// https://halldweb1.jlab.org/wiki/index.php/File:FADC125_dataformat_250_modes.docx
3786
3787 if(!PARSE_F125){ iptr = iend; return; }
3788
3789 if(VERBOSE>6) evioout << " Entering Parsef125Bank for rocid=" << rocid << "..."<<endl;
3790
3791 // This will get updated to point to a newly allocated object when an
3792 // event header is encountered. The existing value (if non-NULL) is
3793 // added to the events queue first though so all events are kept.
3794 ObjList *objs = NULL__null;
3795
3796 // From the Block Header
3797 uint32_t slot=0;
3798 //uint32_t Nblock_events;
3799 //uint32_t iblock;
3800
3801 // From the Block Trailer
3802 //uint32_t slot_trailer;
3803 //uint32_t Nwords_in_block;
3804
3805 // From Event header
3806 //uint32_t slot_event_header;
3807 uint32_t itrigger = -1;
3808 uint32_t last_itrigger = -2;
3809 uint32_t last_pulse_time_channel=0;
3810 uint32_t last_slot = -1;
3811 uint32_t last_channel = -1;
3812
3813 // Loop over data words
3814 for(; iptr<iend; iptr++){
3815
3816 // Skip all non-data-type-defining words at this
3817 // level. When we do encounter one, the appropriate
3818 // case block below should handle parsing all of
3819 // the data continuation words and advance the iptr.
3820 if(((*iptr>>31) & 0x1) == 0)continue;
3821
3822 // Variables used inside of switch, but cannot be declared inside
3823 uint64_t t = 0L;
3824 uint32_t channel = 0;
3825 uint32_t sum = 0;
3826 uint32_t pulse_number = 0;
3827 uint32_t pulse_time = 0;
3828 uint32_t quality_factor = 0;
3829 uint32_t overflow_count = 0;
3830 uint32_t pedestal = 0;
3831 uint32_t pulse_peak = 0;
3832 uint32_t peak_time = 0;
3833 uint32_t nsamples_integral = 0;
3834 uint32_t nsamples_pedestal = 0;
3835 uint32_t word1=0;
3836 uint32_t word2=0;
3837
3838 bool found_block_trailer = false;
3839 uint32_t data_type = (*iptr>>27) & 0x0F;
3840 switch(data_type){
3841 case 0: // Block Header
3842 slot = (*iptr>>22) & 0x1F;
3843 if(VERBOSE>7) evioout << " FADC125 Block Header: slot="<<slot<<endl;
3844 //iblock= (*iptr>>8) & 0x03FF;
3845 //Nblock_events= (*iptr>>0) & 0xFF;
3846 break;
3847 case 1: // Block Trailer
3848 //slot_trailer = (*iptr>>22) & 0x1F;
3849 //Nwords_in_block = (*iptr>>0) & 0x3FFFFF;
3850 found_block_trailer = true;
3851 break;
3852 case 2: // Event Header
3853 //slot_event_header = (*iptr>>22) & 0x1F;
3854 itrigger = (*iptr>>0) & 0x3FFFFFF;
3855 if(VERBOSE>7) evioout << " FADC125 Event Header: itrigger="<<itrigger<<" (objs=0x"<<hex<<objs<<dec<<", last_itrigger="<<last_itrigger<<", rocid="<<rocid<<", slot="<<slot<<")" <<endl;
3856 if( (itrigger!=last_itrigger) || (objs==NULL__null) ){
3857 if(ENABLE_DISENTANGLING){
3858 if(objs){
3859 events.push_back(objs);
3860 objs = NULL__null;
3861 }
3862 }
3863 if(!objs) objs = new ObjList;
3864 last_itrigger = itrigger;
3865 }
3866 break;
3867 case 3: // Trigger Time
3868 t = ((*iptr)&0xFFFFFF)<<24; // n.b. Documentation is incorrect! This is opposite of f250 (see e-mail from Naomi/Cody on 4/28/2016)
3869 iptr++;
3870 if(((*iptr>>31) & 0x1) == 0){
3871 t += ((*iptr)&0xFFFFFF)<<0; // (see above)
3872 }else{
3873 iptr--;
3874 }
3875 if(VERBOSE>7) evioout << " FADC125 Trigger Time (t="<<t<<")"<<endl;
3876 if(objs) objs->hit_objs.push_back(new Df125TriggerTime(rocid, slot, itrigger, t));
3877 break;
3878 case 4: // Window Raw Data
3879 // iptr passed by reference and so will be updated automatically
3880 if(VERBOSE>7) evioout << " FADC125 Window Raw Data"<<endl;
3881 MakeDf125WindowRawData(objs, rocid, slot, itrigger, iptr);
3882 break;
3883
3884 case 5: // CDC pulse data (new) (GlueX-doc-2274-v8)
3885
3886 // Word 1:
3887 word1 = *iptr;
3888 channel = (*iptr>>20) & 0x7F;
3889 pulse_number = (*iptr>>15) & 0x1F;
3890 pulse_time = (*iptr>>4 ) & 0x7FF;
3891 quality_factor = (*iptr>>3 ) & 0x1; //time QF bit
3892 overflow_count = (*iptr>>0 ) & 0x7;
3893 if(VERBOSE>8) evioout << " FADC125 CDC Pulse Data word1: " << hex << (*iptr) << dec << endl;
3894 if(VERBOSE>7) evioout << " FADC125 CDC Pulse Data (chan="<<channel<<" pulse="<<pulse_number<<" time="<<pulse_time<<" QF="<<quality_factor<<" OC="<<overflow_count<<")"<<endl;
3895
3896 // Word 2:
3897 ++iptr;
3898 if(iptr>=iend){
3899 jerr << " Truncated f125 CDC hit (block ends before continuation word!)" << endl;
3900 continue;
3901 }
3902 if( ((*iptr>>31) & 0x1) != 0 ){
3903 jerr << " Truncated f125 CDC hit (missing continuation word!)" << endl;
3904 continue;
3905 }
3906 word2 = *iptr;
3907 pedestal = (*iptr>>23) & 0xFF;
3908 sum = (*iptr>>9 ) & 0x3FFF;
3909 pulse_peak = (*iptr>>0 ) & 0x1FF;
3910 if(VERBOSE>8) evioout << " FADC125 CDC Pulse Data word2: " << hex << (*iptr) << dec << endl;
3911 if(VERBOSE>7) evioout << " FADC125 CDC Pulse Data (pedestal="<<pedestal<<" sum="<<sum<<" peak="<<pulse_peak<<")"<<endl;
3912
3913 // Create hit objects
3914 nsamples_integral = 0; // must be overwritten later in GetObjects with value from Df125Config value
3915 nsamples_pedestal = 1; // The firmware pedestal divided by 2^PBIT where PBIT is a config. parameter
3916
3917 if( (objs!=NULL__null) && (pulse_number<F125PULSE_NUMBER_FILTER) ) {
3918 // n.b. This is were we might apply a check on whether we are
3919 // only producing emulated objects. If so, then we shouldn't
3920 // create the Df125CDCPulse. At this point in time though,
3921 // there are 3 config. parameters that control this because
3922 // the original firmware produced 3 separate data types as
3923 // opposed to the new firmware that puts the same infomation
3924 // into a single data type. The emulation framework is also
3925 // being revamped.
3926 objs->hit_objs.push_back( new Df125CDCPulse(rocid, slot, channel, itrigger
3927 , pulse_number // NPK
3928 , pulse_time // le_time
3929 , quality_factor // time_quality_bit
3930 , overflow_count // overflow_count
3931 , pedestal // pedestal
3932 , sum // integral
3933 , pulse_peak // first_max_amp
3934 , word1 // word1
3935 , word2 // word2
3936 , nsamples_pedestal // nsamples_pedestal
3937 , nsamples_integral // nsamples_integral
3938 , false) // emulated
3939 );
3940 }
3941
3942 // n.b. We don't record last_slot, last_channel, etc... here since those
3943 // are only used by data types corresponding to older firmware that did
3944 // not write out data type 5.
3945 break;
3946
3947 case 6: // FDC pulse data-integral (new) (GlueX-doc-2274-v8)
3948
3949 // Word 1:
3950 word1 = *iptr;
3951 channel = (*iptr>>20) & 0x7F;
3952 pulse_number = (*iptr>>15) & 0x1F;
3953 pulse_time = (*iptr>>4 ) & 0x7FF;
3954 quality_factor = (*iptr>>3 ) & 0x1; //time QF bit
3955 overflow_count = (*iptr>>0 ) & 0x7;
3956 if(VERBOSE>8) evioout << " FADC125 FDC Pulse Data(integral) word1: " << hex << (*iptr) << dec << endl;
3957 if(VERBOSE>7) evioout << " FADC125 FDC Pulse Data (chan="<<channel<<" pulse="<<pulse_number<<" time="<<pulse_time<<" QF="<<quality_factor<<" OC="<<overflow_count<<")"<<endl;
3958
3959 // Word 2:
3960 ++iptr;
3961 if(iptr>=iend){
3962 jerr << " Truncated f125 FDC hit (block ends before continuation word!)" << endl;
3963 continue;
3964 }
3965 if( ((*iptr>>31) & 0x1) != 0 ){
3966 jerr << " Truncated f125 FDC hit (missing continuation word!)" << endl;
3967 continue;
3968 }
3969 word2 = *iptr;
3970 pulse_peak = 0;
3971 sum = (*iptr>>19) & 0xFFF;
3972 peak_time = (*iptr>>11) & 0xFF;
3973 pedestal = (*iptr>>0 ) & 0x7FF;
3974 if(VERBOSE>8) evioout << " FADC125 FDC Pulse Data(integral) word2: " << hex << (*iptr) << dec << endl;
3975 if(VERBOSE>7) evioout << " FADC125 FDC Pulse Data (integral="<<sum<<" time="<<peak_time<<" pedestal="<<pedestal<<")"<<endl;
3976
3977 // Create hit objects
3978 nsamples_integral = 0; // must be overwritten later in GetObjects with value from Df125Config value
3979 nsamples_pedestal = 1; // The firmware pedestal divided by 2^PBIT where PBIT is a config. parameter
3980
3981 if( (objs!=NULL__null) && (pulse_number<F125PULSE_NUMBER_FILTER) ) {
3982 // n.b. This is were we might apply a check on whether we are
3983 // only producing emulated objects. If so, then we shouldn't
3984 // create the Df125FDCPulse. At this point in time though,
3985 // there are 3 config. parameters that control this because
3986 // the original firmware produced 3 separate data types as
3987 // opposed to the new firmware that puts the same infomation
3988 // into a single data type. The emulation framework is also
3989 // being revamped.
3990 objs->hit_objs.push_back( new Df125FDCPulse(rocid, slot, channel, itrigger
3991 , pulse_number // NPK
3992 , pulse_time // le_time
3993 , quality_factor // time_quality_bit
3994 , overflow_count // overflow_count
3995 , pedestal // pedestal
3996 , sum // integral
3997 , pulse_peak // peak_amp
3998 , peak_time // peak_time
3999 , word1 // word1
4000 , word2 // word2
4001 , nsamples_pedestal // nsamples_pedestal
4002 , nsamples_integral // nsamples_integral
4003 , false) // emulated
4004 );
4005 }
4006
4007 // n.b. We don't record last_slot, last_channel, etc... here since those
4008 // are only used by data types corresponding to older firmware that did
4009 // not write out data type 6.
4010 break;
4011
4012 case 7: // Pulse Integral
4013 if(VERBOSE>7) evioout << " FADC125 Pulse Integral"<<endl;
4014 channel = (*iptr>>20) & 0x7F;
4015 sum = (*iptr>>0) & 0xFFFFF;
4016 nsamples_integral = 0; // must be overwritten later in GetObjects with value from Df125Config value
4017 nsamples_pedestal = 1; // The firmware returns an already divided pedestal
4018 pedestal = 0; // This will be replaced by the one from Df250PulsePedestal in GetObjects
4019 if (last_slot == slot && last_channel == channel) pulse_number = 1;
4020 last_slot = slot;
4021 last_channel = channel;
4022 if( (objs!=NULL__null) && (pulse_number<F125PULSE_NUMBER_FILTER) ) {
4023 objs->hit_objs.push_back(new Df125PulseIntegral(rocid, slot, channel, itrigger, pulse_number,
4024 quality_factor, sum, pedestal, nsamples_integral, nsamples_pedestal));
4025 }
4026 break;
4027 case 8: // Pulse Time
4028 if(VERBOSE>7) evioout << " FADC125 Pulse Time"<<endl;
4029 channel = (*iptr>>20) & 0x7F;
4030 pulse_number = (*iptr>>18) & 0x03;
4031 pulse_time = (*iptr>>0) & 0xFFFF;
4032 if( (objs!=NULL__null) && (pulse_number<F125PULSE_NUMBER_FILTER) ) {
4033 objs->hit_objs.push_back(new Df125PulseTime(rocid, slot, channel, itrigger, pulse_number, quality_factor, pulse_time));
4034 }
4035 last_pulse_time_channel = channel;
4036 break;
4037
4038 case 9: // FDC pulse data-peak (new) (GlueX-doc-2274-v8)
4039
4040 // Word 1:
4041 word1 = *iptr;
4042 channel = (*iptr>>20) & 0x7F;
4043 pulse_number = (*iptr>>15) & 0x1F;
4044 pulse_time = (*iptr>>4 ) & 0x7FF;
4045 quality_factor = (*iptr>>3 ) & 0x1; //time QF bit
4046 overflow_count = (*iptr>>0 ) & 0x7;
4047 if(VERBOSE>8) evioout << " FADC125 FDC Pulse Data(peak) word1: " << hex << (*iptr) << dec << endl;
4048 if(VERBOSE>7) evioout << " FADC125 FDC Pulse Data (chan="<<channel<<" pulse="<<pulse_number<<" time="<<pulse_time<<" QF="<<quality_factor<<" OC="<<overflow_count<<")"<<endl;
4049
4050 // Word 2:
4051 ++iptr;
4052 if(iptr>=iend){
4053 jerr << " Truncated f125 FDC hit (block ends before continuation word!)" << endl;
4054 continue;
4055 }
4056 if( ((*iptr>>31) & 0x1) != 0 ){
4057 jerr << " Truncated f125 FDC hit (missing continuation word!)" << endl;
4058 continue;
4059 }
4060 word2 = *iptr;
4061 pulse_peak = (*iptr>>19) & 0xFFF;
4062 sum = 0;
4063 peak_time = (*iptr>>11) & 0xFF;
4064 pedestal = (*iptr>>0 ) & 0x7FF;
4065 if(VERBOSE>8) evioout << " FADC125 FDC Pulse Data(peak) word2: " << hex << (*iptr) << dec << endl;
4066 if(VERBOSE>7) evioout << " FADC125 FDC Pulse Data (integral="<<sum<<" time="<<peak_time<<" pedestal="<<pedestal<<")"<<endl;
4067
4068 // Create hit objects
4069 nsamples_integral = 0; // must be overwritten later in GetObjects with value from Df125Config value
4070 nsamples_pedestal = 1; // The firmware pedestal divided by 2^PBIT where PBIT is a config. parameter
4071
4072 if( (objs!=NULL__null) && (pulse_number<F125PULSE_NUMBER_FILTER) ) {
4073 // n.b. This is were we might apply a check on whether we are
4074 // only producing emulated objects. If so, then we shouldn't
4075 // create the Df125FDCPulse. At this point in time though,
4076 // there are 3 config. parameters that control this because
4077 // the original firmware produced 3 separate data types as
4078 // opposed to the new firmware that puts the same infomation
4079 // into a single data type. The emulation framework is also
4080 // being revamped.
4081
4082 // hard-cod destination object CDC/FDC based on rocid
4083
4084 if( rocid < 30 ){
4085
4086 objs->hit_objs.push_back( new Df125CDCPulse(rocid, slot, channel, itrigger
4087 , pulse_number // NPK
4088 , pulse_time // le_time
4089 , quality_factor // time_quality_bit
4090 , overflow_count // overflow_count
4091 , pedestal // pedestal
4092 , sum // integral
4093 , pulse_peak // peak_amp
4094 , word1 // word1
4095 , word2 // word2
4096 , nsamples_pedestal // nsamples_pedestal
4097 , nsamples_integral // nsamples_integral
4098 , false) // emulated
4099 );
4100
4101 }else{
4102
4103 objs->hit_objs.push_back( new Df125FDCPulse(rocid, slot, channel, itrigger
4104 , pulse_number // NPK
4105 , pulse_time // le_time
4106 , quality_factor // time_quality_bit
4107 , overflow_count // overflow_count
4108 , pedestal // pedestal
4109 , sum // integral
4110 , pulse_peak // peak_amp
4111 , peak_time // peak_time
4112 , word1 // word1
4113 , word2 // word2
4114 , nsamples_pedestal // nsamples_pedestal
4115 , nsamples_integral // nsamples_integral
4116 , false) // emulated
4117 );
4118 }
4119 }
4120
4121 // n.b. We don't record last_slot, last_channel, etc... here since those
4122 // are only used by data types corresponding to older firmware that did
4123 // not write out data type 6.
4124 break;
4125
4126 case 10: // Pulse Pedestal (consistent with Beni's hand-edited version of Cody's document)
4127 if(VERBOSE>7) evioout << " FADC125 Pulse Pedestal"<<endl;
4128 //channel = (*iptr>>20) & 0x7F;
4129 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")
4130 pulse_number = (*iptr>>21) & 0x03;
4131 pedestal = (*iptr>>12) & 0x1FF;
4132 pulse_peak = (*iptr>>0) & 0xFFF;
4133 nsamples_pedestal = 1; // The firmware returns an already divided pedestal
4134 if( (objs!=NULL__null) && (pulse_number<F125PULSE_NUMBER_FILTER) ) {
4135 objs->hit_objs.push_back(new Df125PulsePedestal(rocid, slot, channel, itrigger, pulse_number, pedestal, pulse_peak, nsamples_pedestal));
4136 }
4137 break;
4138
4139 case 13: // Event Trailer
4140 case 14: // Data not valid (empty module)
4141 case 15: // Filler (non-data) word
4142 if(VERBOSE>7) evioout << " FADC125 ignored data type: " << data_type <<endl;
4143 break;
4144 }
4145
4146 // Once we find a block trailer, assume that is it for this module.
4147 if(found_block_trailer){
4148 iptr++; // iptr is still pointing to block trailer. Jump to next word.
4149 break;
4150 }
4151 }
4152
4153 // Chop off filler words
4154 for(; iptr<iend; iptr++){
4155 if(((*iptr)&0xf8000000) != 0xf8000000) break;
4156 }
4157
4158 // Add last event in block to list
4159 if(objs)events.push_back(objs);
4160
4161 // Here, we make object associations to link PulseIntegral, PulseTime, PulseRawData, etc
4162 // objects to each other so it is easier to get to these downstream without having to
4163 // make nested loops. This is the most efficient place to do it since the ObjList objects
4164 // in "event" contain only the objects from this EVIO block (i.e. at most one crate's
4165 // worth.)
4166 list<ObjList*>::iterator iter = events.begin();
4167 for(; iter!=events.end(); iter++){
4168
4169 // Sort list of objects into type-specific lists
4170 vector<DDAQAddress*> &hit_objs = (*iter)->hit_objs;
4171 vector<Df125TriggerTime*> vtrigt;
4172 vector<Df125WindowRawData*> vwrd;
4173 vector<Df125PulseRawData*> vprd;
4174 vector<Df125PulseIntegral*> vpi;
4175 vector<Df125PulseTime*> vpt;
4176 vector<Df125PulsePedestal*> vpp;
4177 for(unsigned int i=0; i<hit_objs.size(); i++){
4178 AddIfAppropriate(hit_objs[i], vtrigt);
4179 AddIfAppropriate(hit_objs[i], vwrd);
4180 AddIfAppropriate(hit_objs[i], vprd);
4181 AddIfAppropriate(hit_objs[i], vpi);
4182 AddIfAppropriate(hit_objs[i], vpt);
4183 AddIfAppropriate(hit_objs[i], vpp);
4184 }
4185
4186 // Connect Df125PulseIntegral with Df125PulseTime
4187 LinkAssociationsWithPulseNumber(vprd, vpi);
4188 LinkAssociationsWithPulseNumber(vprd, vpt);
4189 LinkAssociationsWithPulseNumber(vprd, vpp);
4190 LinkAssociationsWithPulseNumber(vpi, vpt);
4191 LinkAssociationsWithPulseNumber(vpi, vpp);
4192 LinkAssociationsWithPulseNumber(vpt, vpp);
4193
4194 // Connect Df125TriggerTime to everything
4195 LinkAssociationsModuleOnly(vtrigt, vwrd);
4196 LinkAssociationsModuleOnly(vtrigt, vprd);
4197 LinkAssociationsModuleOnly(vtrigt, vpi);
4198 LinkAssociationsModuleOnly(vtrigt, vpt);
4199 LinkAssociationsModuleOnly(vtrigt, vpp);
4200 }
4201
4202 if(VERBOSE>6) evioout << " Leaving Parsef125Bank"<<endl;
4203}
4204
4205//----------------
4206// MakeDf125WindowRawData
4207//----------------
4208void JEventSource_EVIO::MakeDf125WindowRawData(ObjList *objs, uint32_t rocid, uint32_t slot, uint32_t itrigger, const uint32_t* &iptr)
4209{
4210 uint32_t channel = (*iptr>>20) & 0x7F;
4211 uint32_t window_width = (*iptr>>0) & 0x0FFF;
4212
4213 Df125WindowRawData *wrd = new Df125WindowRawData(rocid, slot, channel, itrigger);
4214
4215 for(uint32_t isample=0; isample<window_width; isample +=2){
4216
4217 // Advance to next word
4218 iptr++;
4219
4220 // Make sure this is a data continuation word, if not, stop here
4221 if(((*iptr>>31) & 0x1) != 0x0)break;
4222
4223 bool invalid_1 = (*iptr>>29) & 0x1;
4224 bool invalid_2 = (*iptr>>13) & 0x1;
4225 uint16_t sample_1 = 0;
4226 uint16_t sample_2 = 0;
4227 if(!invalid_1)sample_1 = (*iptr>>16) & 0x1FFF;
4228 if(!invalid_2)sample_2 = (*iptr>>0) & 0x1FFF;
4229
4230 // Sample 1
4231 wrd->samples.push_back(sample_1);
4232 wrd->invalid_samples |= invalid_1;
4233 wrd->overflow |= (sample_1>>12) & 0x1;
4234
4235 if((isample+2) == window_width && invalid_2)break; // skip last sample if flagged as invalid
4236
4237 // Sample 2
4238 wrd->samples.push_back(sample_2);
4239 wrd->invalid_samples |= invalid_2;
4240 wrd->overflow |= (sample_2>>12) & 0x1;
4241 }
4242
4243 if(VERBOSE>7) evioout << " FADC125 - " << wrd->samples.size() << " samples" << endl;
4244
4245 // Due to how the calling function works, the value of "objs" passed to us may be NULL.
4246 // This will happen if a Window Raw Data block is encountered before an event header.
4247 // For these cases, we still want to try parsing the data so that the iptr is updated
4248 // but don't have an event to assign it to. If "objs" is non-NULL, add this object to
4249 // the list. Otherwise, delete it now.
4250 if(objs){
4251 objs->hit_objs.push_back(wrd);
4252 }else{
4253 delete wrd;
4254 }
4255}
4256
4257//----------------
4258// MakeDf125PulseRawData
4259//----------------
4260void JEventSource_EVIO::MakeDf125PulseRawData(ObjList *objs, uint32_t rocid, uint32_t slot, uint32_t itrigger, const uint32_t* &iptr)
4261{
4262 uint32_t channel = (*iptr>>23) & 0x0F;
4263 uint32_t pulse_number = (*iptr>>21) & 0x000F;
4264 uint32_t first_sample_number = (*iptr>>0) & 0x03FF;
4265
4266 Df125PulseRawData *prd = new Df125PulseRawData(rocid, slot, channel, itrigger, pulse_number, first_sample_number);
4267
4268 // This loop needs to break when it hits a non-continuation word
4269 for(uint32_t isample=0; isample<1000; isample +=2){
4270
4271 // Advance to next word
4272 iptr++;
4273
4274 // Make sure this is a data continuation word, if not, stop here
4275 if(((*iptr>>31) & 0x1) != 0x0)break;
4276
4277 bool invalid_1 = (*iptr>>29) & 0x1;
4278 bool invalid_2 = (*iptr>>13) & 0x1;
4279 uint16_t sample_1 = 0;
4280 uint16_t sample_2 = 0;
4281 if(!invalid_1)sample_1 = (*iptr>>16) & 0x1FFF;
4282 if(!invalid_2)sample_2 = (*iptr>>0) & 0x1FFF;
4283
4284 // Sample 1
4285 prd->samples.push_back(sample_1);
4286 prd->invalid_samples |= invalid_1;
4287 prd->overflow |= (sample_1>>12) & 0x1;
4288
4289 bool last_word = (iptr[1]>>31) & 0x1;
4290 if(last_word && invalid_2)break; // skip last sample if flagged as invalid
4291
4292 // Sample 2
4293 prd->samples.push_back(sample_2);
4294 prd->invalid_samples |= invalid_2;
4295 prd->overflow |= (sample_2>>12) & 0x1;
4296 }
4297
4298
4299 // Due to how the calling function works, the value of "objs" passed to us may be NULL.
4300 // This will happen if a Window Raw Data block is encountered before an event header.
4301 // For these cases, we still want to try parsing the data so that the iptr is updated
4302 // but don't have an event to assign it to. If "objs" is non-NULL, add this object to
4303 // the list. Otherwise, delete it now.
4304 if(objs){
4305 objs->hit_objs.push_back(prd);
4306 }else{
4307 delete prd;
4308 }
4309}
4310
4311//----------------
4312// ParseF1TDCBank
4313//----------------
4314void JEventSource_EVIO::ParseF1TDCBank(int32_t rocid, const uint32_t* &iptr, const uint32_t* iend, list<ObjList*> &events)
4315{
4316 /// Parse data from a single F1TDCv2 (32 ch) or F1TDCv3 (48 ch) module.
4317 /// This code is based on the document F1TDC_V2_V3_4_29_14.pdf obtained from:
4318 /// https://coda.jlab.org/wiki/index.php/JLab_Module_Manuals
4319
4320 if(!PARSE_F1TDC){ iptr = iend; return; }
4321
4322 if(VERBOSE>6) evioout << " Entering ParseF1TDCBank (rocid=" << rocid << ")" << endl;
4323
4324 const uint32_t *istart = iptr;
4325
4326 // Some early data had a marker word at just before the actual F1 data
4327 if(*iptr == 0xf1daffff) iptr++;
4328
4329 // Block header word
4330 // Double check that block header is set
4331 if( ((*iptr) & 0xF8000000) != 0x80000000 ){
4332 throw JException("F1TDC Block header corrupt! (high 5 bits not set to 0x80000000!)");
4333 }
4334
4335 uint32_t slot_block_header = (*iptr)>>22 & 0x001F;
4336 uint32_t block_num = (*iptr)>> 8 & 0x03FF;
4337 uint32_t Nevents_block_header = (*iptr)>> 0 & 0x00FF;
4338 int modtype = (*iptr)>>18 & 0x000F; // should match a DModuleType::type_id_t
4339 if(VERBOSE>5) evioout << " F1 Block Header: slot=" << slot_block_header << " block_num=" << block_num << " Nevents=" << Nevents_block_header << endl;
4340
4341 // Advance to next word
4342 iptr++;
4343
4344 // Loop over events
4345 ObjList *objs = NULL__null;
4346 while(iptr<iend){
4347
4348 // Event header
4349 // Double check that event header is set
4350 if( ((*iptr) & 0xF8000000) != 0x90000000 ){
4351 if(VERBOSE>10){
4352 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<4352<<" "
<<"Corrupt F1TDC Event header! Data dump follows (\"*\" indicates bad header word):" <<endl;
4353 DumpBinary(istart, iend, 0, iptr);
4354 }
4355 throw JException("F1TDC Event header corrupt! (high 5 bits not set to 0x90000000!)");
4356 }
4357
4358 uint32_t slot_event_header = (*iptr)>>22 & 0x00000001F;
4359 uint32_t itrigger = (*iptr)>>0 & 0x0003FFFFF;
4360 if(VERBOSE>5) evioout << " F1 Event Header: slot=" << slot_block_header << " itrigger=" << itrigger << endl;
4361
4362 // Make sure slot number from event header matches block header
4363 if(slot_event_header != slot_block_header){
4364 char str[256];
4365 sprintf(str, "F1TDC slot from event header(%d) doesn't match block header(%d)", slot_event_header, slot_block_header);
4366 throw JException(str);
4367 }
4368
4369 // Advance to timestamp word
4370 iptr++;
4371 if(iptr>=iend) throw JException("F1TDC data corrupt! Block truncated before timestamp word!");
4372
4373 // The most recent documentation says that the first time stamp
4374 // word holds the low 24 bits and the second the high 16 bits. According to Dave A.,
4375 // the second word is optional.
4376 uint32_t trig_time = ((*iptr)&0xFFFFFF);
4377 if(VERBOSE>6) evioout << " F1 Trigger time: low 24 bits=" << trig_time << endl;
4378 iptr++;
4379 if(iptr>=iend) throw JException("F1TDC data corrupt! Block truncated before trailer word!");
4380 if(((*iptr>>31) & 0x1) == 0){
4381 trig_time += ((*iptr)&0xFFFF)<<24; // from word on the street: second trigger time word is optional!!??
4382 if(VERBOSE>6) evioout << " F1 Trigger time: high 16 bits=" << ((*iptr)&0xFFFF) << " total trig_time=" << trig_time << endl;
4383 }else{
4384 iptr--; // second time word not present, back up pointer
4385 }
4386
4387 // Create a new object list (i.e. new event)
4388 if(objs!=NULL__null && ENABLE_DISENTANGLING){
4389 events.push_back(objs);
4390 objs = NULL__null;
4391 }
4392 if(!objs) objs = new ObjList;
4393
4394 if(objs) objs->hit_objs.push_back(new DF1TDCTriggerTime(rocid, slot_block_header, itrigger, trig_time));
4395
4396 // Advance past last timestamp word to first data word (or rather, F1 chip header)
4397 iptr++;
4398
4399 // Loop over F1 data words
4400 uint32_t chip_f1header=0, chan_on_chip_f1header=0, itrigger_f1header=0, trig_time_f1header=0;
4401 while( iptr<iend && ((*iptr)>>31)==0x1 ){
4402
4403 bool done = false;
4404
4405 uint32_t chip, chan_on_chip, time;
4406 uint32_t channel;
4407 DF1TDCHit *hit=NULL__null;
4408 switch( (*iptr) & 0xF8000000 ){
4409 case 0xC0000000: // F1 Header
4410 chip_f1header = ((*iptr)>> 3) & 0x07;
4411 chan_on_chip_f1header = ((*iptr)>> 0) & 0x07; // this is always 7 in real data!
4412 itrigger_f1header = ((*iptr)>>16) & 0x3F;
4413 trig_time_f1header = ((*iptr)>> 7) & 0x1FF;
4414 if(VERBOSE>5) evioout << " Found F1 header: chip=" << chip_f1header << " chan=" << chan_on_chip_f1header << " itrig=" << itrigger_f1header << " trig_time=" << trig_time_f1header << endl;
4415 //if( itrigger_f1header != (itrigger & 0x3F)) throw JException("Trigger number in F1 header word does not match Event header word!");
4416 break;
4417 case 0xB8000000: // F1 Data
4418 chip = (*iptr>>19) & 0x07;
4419 chan_on_chip = (*iptr>>16) & 0x07;
4420 time = (*iptr>> 0) & 0xFFFF;
4421 if(VERBOSE>5) evioout << " Found F1 data : chip=" << chip << " chan=" << chan_on_chip << " time=" << time << " (header: chip=" << chip_f1header << ")" << endl;
4422 //if(chip!=chip_f1header) throw JException("F1 chip number in data does not match header!");
4423 channel = F1TDC_channel(chip, chan_on_chip, modtype);
4424 hit = new DF1TDCHit(rocid, slot_block_header, channel, itrigger, trig_time_f1header, time, *iptr, MODULE_TYPE(modtype));
4425 if(objs)objs->hit_objs.push_back(hit);
4426 break;
4427 case 0xF8000000: // Filler word
4428 if(VERBOSE>7) evioout << " Found F1 filler word" << endl;
4429 break;
4430 case 0x80000000: // JLab block header (handled in outer loop)
4431 case 0x88000000: // JLab block trailer (handled in outer loop)
4432 case 0x90000000: // JLab event header (handled in outer loop)
4433 case 0x98000000: // Trigger time (handled in outer loop)
4434 case 0xF0000000: // module has no valid data available for read out (how to handle this?)
4435 if(VERBOSE>5) evioout << " Found F1 break word: 0x" << hex << *iptr << dec << endl;
4436 done = true;
4437 break;
4438 default:
4439 cerr<<endl;
4440 cout.flush(); cerr.flush();
4441 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<4441<<" "
<<"Unknown data word in F1TDC block. Dumping for debugging:" << endl;
4442 for(const uint32_t *iiptr = istart; iiptr<iend; iiptr++){
4443 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<4443<<" "
<<"0x"<<hex<<*iiptr<<dec;
4444 if(iiptr == iptr)cerr<<" <----";
4445 switch( (*iiptr) & 0xF8000000 ){
4446 case 0x80000000: cerr << " F1 Block Header"; break;
4447 case 0x90000000: cerr << " F1 Event Header"; break;
4448 case 0x98000000: cerr << " F1 Trigger time"; break;
4449 case 0xC0000000: cerr << " F1 Header"; break;
4450 case 0xB8000000: cerr << " F1 Data"; break;
4451 case 0x88000000: cerr << " F1 Block Trailer"; break;
4452 case 0xF8000000: cerr << " Filler word"; break;
4453 case 0xF0000000: cerr << " <module has no valid data>"; break;
4454 default: break;
4455 }
4456 cerr<<endl;
4457 if(iiptr > (iptr+4)) break;
4458 }
4459
4460 throw JException("Unexpected word type in F1TDC block!");
4461 }
4462
4463 if(done)break;
4464
4465 // Advance to next data word
4466 iptr++;
4467
4468 } // end loop over data words in this event
4469
4470 // If the current word is a JLab block trailer, then we are done
4471 if( ((*iptr) & 0xF8000000) == 0x88000000) break;
4472
4473 } // end loop over events
4474
4475 // Add hits for last event to list of events.
4476 if(objs)events.push_back(objs);
4477
4478 if( ((*iptr) & 0xF8000000) != 0x88000000 ){
4479 throw JException("F1TDC Block Trailer corrupt! (high 5 bits not set to 0x88000000!)");
4480 }
4481
4482 // Advance past JLab block trailer
4483 iptr++;
4484
4485 // Skip filler words
4486 while(iptr<iend && (*iptr&0xF8000000)==0xF8000000)iptr++;
4487
4488 // Double check that we found all of the events we were supposed to
4489 if(!ENABLE_DISENTANGLING) Nevents_block_header=1;
4490 if(events.size() != Nevents_block_header){
4491 stringstream ss;
4492 ss << "F1TDC missing events in block! (found "<< events.size() <<" but should have found "<<Nevents_block_header<<")";
4493 DumpBinary(istart, iend, 128);
4494 throw JException(ss.str());
4495 }
4496
4497 if(VERBOSE>6) evioout << " Leaving ParseF1TDCBank (rocid=" << rocid << ")" << endl;
4498
4499}
4500
4501//----------------
4502// F1TDC_channel
4503//----------------
4504uint32_t JEventSource_EVIO::F1TDC_channel(uint32_t chip, uint32_t chan_on_chip, int modtype)
4505{
4506 /// Convert a F1TDC chip number and channel on the chip to the
4507 /// front panel channel number. This is based on "Input Channel Mapping"
4508 /// section at the very bottom of the document F1TDC_V2_V3_4_29_14.pdf
4509
4510 uint32_t channel_map[8] = {0, 0, 1, 1, 2, 2, 3, 3};
4511 switch(modtype){
4512 case DModuleType::F1TDC32:
4513 return (4 * chip) + channel_map[ chan_on_chip&0x7 ];
4514 case DModuleType::F1TDC48:
4515 return (chip <<3) | chan_on_chip;
4516 default:
4517 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<4517<<" "
<< "Calling F1TDC_channel for module type: " << DModuleType::GetName((DModuleType::type_id_t)modtype) << endl;
4518 throw JException("F1TDC_channel called for non-F1TDC module type");
4519 }
4520 return 1000000; // (should never get here)
4521}
4522
4523//----------------
4524// ParseTSBank
4525//----------------
4526void JEventSource_EVIO::ParseTSBank(int32_t rocid, const uint32_t* &iptr, const uint32_t* iend, list<ObjList*> &events)
4527{
4528 /// Parse data written to the TS roc data during sync events.
4529 /// This is written by the ts_scalers routine in the conf_utils.c
4530 /// file and called from ts_list.c
4531
4532 uint32_t Nwords = ((uint64_t)iend - (uint64_t)iptr)/sizeof(uint32_t);
4533 uint32_t Nwords_expected = (6+32+16+32+16);
4534 if(Nwords != Nwords_expected){
4535 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<4535<<" "
<< "TS bank size does not match expected!!" << endl;
4536 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<4536<<" "
<< "Found " << Nwords << " words. Expected " << Nwords_expected << endl;
4537
4538 }else{
4539 DTSscalers *s = new DTSscalers;
4540 s->nsync_event = *iptr++;
4541 s->int_count = *iptr++;
4542 s->live_time = *iptr++;
4543 s->busy_time = *iptr++;
4544 s->inst_livetime = *iptr++;
4545 s->time = *iptr++;
4546 for(uint32_t i=0; i<32; i++) s->gtp_scalers[i] = *iptr++;
4547 for(uint32_t i=0; i<16; i++) s->fp_scalers[i] = *iptr++;
4548 for(uint32_t i=0; i<32; i++) s->gtp_rate[i] = *iptr++;
4549 for(uint32_t i=0; i<16; i++) s->fp_rate[i] = *iptr++;
4550
4551 if(events.empty()) events.push_back(new ObjList);
4552 ObjList *objs = *(events.begin());
4553 objs->misc_objs.push_back(s);
4554 }
4555
4556 iptr = iend;
4557}
4558
4559//----------------
4560// ParseTIBank
4561//----------------
4562void JEventSource_EVIO::ParseTIBank(int32_t rocid, const uint32_t* &iptr, const uint32_t* iend, list<ObjList*> &events)
4563{
4564 while(iptr<iend && ((*iptr) & 0xF8000000) != 0x88000000) iptr++; // Skip to JLab block trailer
4565 iptr++; // advance past JLab block trailer
4566 while(iptr<iend && *iptr == 0xF8000000) iptr++; // skip filler words after block trailer
4567 //iptr = iend;
4568}
4569
4570//----------------
4571// ParseCAEN1190
4572//----------------
4573void JEventSource_EVIO::ParseCAEN1190(int32_t rocid, const uint32_t* &iptr, const uint32_t *iend, list<ObjList*> &events)
4574{
4575 /// Parse data from a CAEN 1190 or 1290 module
4576 /// (See ppg. 72-74 of V1290_REV15.pdf manual)
4577
4578 if(!PARSE_CAEN1290TDC){ iptr = iend; return; }
4579
4580 uint32_t slot = 0;
4581 uint32_t event_count = 0;
4582 uint32_t word_count = 0;
4583 uint32_t trigger_time_tag = 0;
4584 uint32_t tdc_num = 0;
4585 uint32_t event_id = 0;
4586 uint32_t bunch_id = 0;
4587
4588 // We need to accomodate multi-event blocks where
4589 // events are entangled (i.e. hits from event 1
4590 // are mixed inbetween those of event 2,3,4,
4591 // etc... With CAEN modules, we only know which
4592 // event a hit came from by looking at the event_id
4593 // in the TDC header. This value is only 12 bits
4594 // and could roll over within an event block. This
4595 // means we need to keep track of the order we
4596 // encounter them in so it is maintained in the
4597 // "events" container. The event_id order is kept
4598 // in the "event_id_order" vector.
4599 map<uint32_t, vector<DCAEN1290TDCHit*> > hits_by_event_id;
4600 vector<uint32_t> event_id_order;
4601
4602 while(iptr<iend){
4603
4604 // This word appears to be appended to the data.
4605 // Probably in the ROL. Ignore it if found.
4606 if(*iptr == 0xd00dd00d) {
4607 if(VERBOSE>7) evioout << " CAEN skipping 0xd00dd00d word" << endl;
4608 iptr++;
4609 continue;
4610 }
4611
4612 uint32_t type = (*iptr) >> 27;
4613 uint32_t edge = 0; // 1=trailing, 0=leading
4614 uint32_t channel = 0;
4615 uint32_t tdc = 0;
4616 uint32_t error_flags = 0;
4617 DCAEN1290TDCHit *caen1290tdchit = NULL__null;
4618 map<uint32_t, ObjList*>::iterator iter;
4619 switch(type){
4620 case 0b01000: // Global Header
4621 slot = (*iptr) & 0x1f;
4622 event_count = ((*iptr)>>5) & 0xffffff;
4623 if(VERBOSE>7) evioout << " CAEN TDC Global Header (slot=" << slot << " , event count=" << event_count << ")" << endl;
4624 break;
4625 case 0b10000: // Global Trailer
4626 slot = (*iptr) & 0x1f;
4627 word_count = ((*iptr)>>5) & 0x7ffff;
4628 if(VERBOSE>7) evioout << " CAEN TDC Global Trailer (slot=" << slot << " , word count=" << word_count << ")" << endl;
4629 slot = event_count = word_count = trigger_time_tag = tdc_num = event_id = bunch_id = 0;
4630 break;
4631 case 0b10001: // Global Trigger Time Tag
4632 trigger_time_tag = ((*iptr)>>5) & 0x7ffffff;
4633 if(VERBOSE>7) evioout << " CAEN TDC Global Trigger Time Tag (tag=" << trigger_time_tag << ")" << endl;
4634 break;
4635 case 0b00001: // TDC Header
4636 tdc_num = ((*iptr)>>24) & 0x03;
4637 event_id = ((*iptr)>>12) & 0x0fff;
4638 bunch_id = (*iptr) & 0x0fff;
4639 if( find(event_id_order.begin(), event_id_order.end(), event_id) == event_id_order.end()){
4640 event_id_order.push_back(event_id);
4641 }
4642 if(VERBOSE>7) evioout << " CAEN TDC TDC Header (tdc=" << tdc_num <<" , event id=" << event_id <<" , bunch id=" << bunch_id << ")" << endl;
4643 break;
4644 case 0b00000: // TDC Measurement
4645 edge = ((*iptr)>>26) & 0x01;
4646 channel = ((*iptr)>>21) & 0x1f;
4647 tdc = ((*iptr)>>0) & 0x1fffff;
4648 if(VERBOSE>7) evioout << " CAEN TDC TDC Measurement (" << (edge ? "trailing":"leading") << " , channel=" << channel << " , tdc=" << tdc << ")" << endl;
4649
4650 // Create DCAEN1290TDCHit object
4651 caen1290tdchit = new DCAEN1290TDCHit(rocid, slot, channel, 0, edge, tdc_num, event_id, bunch_id, tdc);
4652 hits_by_event_id[event_id].push_back(caen1290tdchit);
4653 break;
4654 case 0b00100: // TDC Error
4655 error_flags = (*iptr) & 0x7fff;
4656 if(VERBOSE>7) evioout << " CAEN TDC TDC Error (err flags=0x" << hex << error_flags << dec << ")" << endl;
4657 break;
4658 case 0b00011: // TDC Trailer
4659 tdc_num = ((*iptr)>>24) & 0x03;
4660 event_id = ((*iptr)>>12) & 0x0fff;
4661 word_count = ((*iptr)>>0) & 0x0fff;
4662 if(VERBOSE>7) evioout << " CAEN TDC TDC Trailer (tdc=" << tdc_num <<" , event id=" << event_id <<" , word count=" << word_count << ")" << endl;
4663 tdc_num = event_id = bunch_id = 0;
4664 break;
4665 case 0b11000: // Filler Word
4666 if(VERBOSE>7) evioout << " CAEN TDC Filler Word" << endl;
4667 break;
4668 default:
4669 evioout << "Unknown datatype: 0x" << hex << type << " full word: "<< *iptr << dec << endl;
4670 }
4671
4672 iptr++;
4673 }
4674
4675 // If disentagling is disabled, then lump all hits into single event
4676 if( (!ENABLE_DISENTANGLING) && (event_id_order.size()>1) ){
4677 if(VERBOSE>2) evioout << " Disentangling disabled. Merging all hits into single event" << endl;
4678 vector<DCAEN1290TDCHit*> &hits1 = hits_by_event_id[event_id_order[0]];
4679 for(uint32_t i=1; i<event_id_order.size(); i++){
4680 vector<DCAEN1290TDCHit*> &hits2 = hits_by_event_id[event_id_order[i]];
4681 hits1.insert(hits1.end(), hits2.begin(), hits2.end()); // copy hits into first event
4682 hits_by_event_id.erase(event_id_order[i]); // remove hits list for this event_id
4683 }
4684 }
4685
4686 // Add hits for each event to the events container, creating ObjList's as needed
4687 for(uint32_t i=0; i<event_id_order.size(); i++){
4688
4689 // Make sure there are enough event containers to hold this event
4690 while(events.size() <= i) events.push_back(new ObjList);
4691 list<ObjList*>::iterator it = events.begin();
4692 advance(it, i);
4693 ObjList *objs = *it;
4694
4695 vector<DCAEN1290TDCHit*> &hits = hits_by_event_id[event_id_order[i]];
4696 objs->hit_objs.insert(objs->hit_objs.end(), hits.begin(), hits.end());
4697
4698 if(VERBOSE>7) evioout << " Added " << hits.size() << " hits with event_id=" << event_id_order[i] << " to event " << i << endl;
4699 }
4700
4701}
4702
4703#if HAVE_EVIO1
4704//----------------
4705// ParseBORevent
4706//----------------
4707void JEventSource_EVIO::ParseBORevent(evioDOMNodeP bankPtr)
4708{
4709 if(!PARSE_BOR) return;
17
Assuming field 'PARSE_BOR' is true
18
Taking false branch
4710
4711 // This really shouldn't be needed
4712 pthread_rwlock_wrlock(&BOR_lock);
4713
4714 // Delete any existing BOR config objects. BOR events should
4715 // be flagged as sequential (or barrier) events so all threads
4716 // that were using these should be done with them now.
4717 for(uint32_t i=0; i<BORobjs.size(); i++) delete BORobjs[i];
19
Assuming the condition is false
20
Loop condition is false. Execution continues on line 4718
4718 BORobjs.clear();
4719
4720 evioDOMNodeListP bankList = bankPtr->getChildren();
4721 evioDOMNodeList::iterator iter = bankList->begin();
4722 if(VERBOSE>7) evioout << " Looping over " << bankList->size() << " banks in BOR event" << endl;
21
Assuming field 'VERBOSE' is <= 7
22
Taking false branch
4723 for(int ibank=1; iter!=bankList->end(); iter++, ibank++){ // ibank only used for debugging messages
23
Loop condition is true. Entering loop body
4724 evioDOMNodeP childBank = *iter;
4725
4726 if(childBank->tag==0x71){
24
Assuming field 'tag' is equal to 113
25
Taking true branch
4727 // uint32_t rocid = childBank->num;
4728 evioDOMNodeListP bankList = childBank->getChildren();
4729 evioDOMNodeList::iterator iter = bankList->begin();
4730 for(; iter!=bankList->end(); iter++){
26
Loop condition is true. Entering loop body
4731 evioDOMNodeP dataBank = *iter;
4732 // uint32_t slot = dataBank->tag>>5;
4733 uint32_t modType = dataBank->tag&0x1f;
4734
4735 const vector<uint32_t> *vec = dataBank->getVector<uint32_t>();
4736
4737 const uint32_t *src = &(*vec)[0];
4738 uint32_t *dest = NULL__null;
4739 uint32_t sizeof_dest = 0;
4740
4741 Df250BORConfig *f250conf = NULL__null;
4742 Df125BORConfig *f125conf = NULL__null;
4743 DF1TDCBORConfig *F1TDCconf = NULL__null;
4744 DCAEN1290TDCBORConfig *caen1190conf = NULL__null;
4745
4746 switch(modType){
27
'Default' branch taken. Execution continues on line 4777
4747 case DModuleType::FADC250: // f250
4748 f250conf = new Df250BORConfig;
4749 dest = (uint32_t*)&f250conf->rocid;
4750 sizeof_dest = sizeof(f250config);
4751 break;
4752 case DModuleType::FADC125: // f125
4753 f125conf = new Df125BORConfig;
4754 dest = (uint32_t*)&f125conf->rocid;
4755 sizeof_dest = sizeof(f125config);
4756 break;
4757
4758 case DModuleType::F1TDC32: // F1TDCv2
4759 case DModuleType::F1TDC48: // F1TDCv3
4760 F1TDCconf = new DF1TDCBORConfig;
4761 dest = (uint32_t*)&F1TDCconf->rocid;
4762 sizeof_dest = sizeof(F1TDCconfig);
4763 break;
4764
4765 case DModuleType::CAEN1190: // CAEN 1190 TDC
4766 case DModuleType::CAEN1290: // CAEN 1290 TDC
4767 caen1190conf = new DCAEN1290TDCBORConfig;
4768 dest = (uint32_t*)&caen1190conf->rocid;
4769 sizeof_dest = sizeof(caen1190config);
4770 break;
4771 }
4772
4773 // Check that the bank size and data structure size match.
4774 // If they do, then copy the data and add the object to
4775 // the event. If not, then delete the object and print
4776 // a warning message.
4777 if( vec->size() == (sizeof_dest/sizeof(uint32_t)) ){
28
Assuming the condition is true
29
Taking true branch
4778
4779 // Copy bank data, assuming format is the same
4780 for(uint32_t i=0; i<vec->size(); i++) *dest++ = *src++;
30
Assuming the condition is true
31
Loop condition is true. Entering loop body
32
Null pointer value stored to 'dest'
33
Dereference of null pointer
4781
4782 // Store object for use in this and subsequent events
4783 if(f250conf) BORobjs.push_back(f250conf);
4784 if(f125conf) BORobjs.push_back(f125conf);
4785 if(F1TDCconf) BORobjs.push_back(F1TDCconf);
4786 if(caen1190conf) BORobjs.push_back(caen1190conf);
4787
4788 }else if(sizeof_dest>0){
4789 if(f250conf) delete f250conf;
4790 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<4790<<" "
<< "BOR bank size does not match structure! " << vec->size() <<" != " << (sizeof_dest/sizeof(uint32_t)) << endl;
4791 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<4791<<" "
<< "sizeof(f250config)="<<sizeof(f250config)<<endl;
4792 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<4792<<" "
<< "sizeof(f125config)="<<sizeof(f125config)<<endl;
4793 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<4793<<" "
<< "sizeof(F1TDCconfig)="<<sizeof(F1TDCconfig)<<endl;
4794 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<4794<<" "
<< "sizeof(caen1190config)="<<sizeof(caen1190config)<<endl;
4795 }
4796 }
4797 }
4798 }
4799
4800 pthread_rwlock_unlock(&BOR_lock);
4801
4802}
4803
4804
4805//------------------
4806// ParseFA250Scalers
4807//------------------
4808// Read out fadc250 scalers at sync events
4809// for all boards in the crate.
4810// The data format: slot + 16 scalers
4811void JEventSource_EVIO::ParseFA250Scalers(evioDOMNodeP bankPtr, list<ObjList*> &events, uint32_t rocid){
4812
4813 const vector<uint32_t> *vec = bankPtr->getVector<uint32_t>();
4814
4815 if(vec->size() > 0){
4816 Df250Scaler *sc = new Df250Scaler;
4817
4818 sc->nsync = (*vec)[0];
4819 sc->trig_number = (*vec)[1];
4820 sc->version = (*vec)[2];
4821
4822 sc->crate = rocid;
4823
4824 for(uint32_t ii = 3; ii < vec->size(); ii++){
4825 sc->fa250_sc.push_back((*vec)[ii]);
4826 }
4827
4828 if(events.empty()){
4829 events.push_back(new ObjList());
4830 }
4831
4832 ObjList *objs = *(events.begin());
4833
4834 objs->misc_objs.push_back(sc);
4835 } else {
4836 evioout << " SYNC event: inconsistent format for FA250Scalers. Don't parse " << endl;
4837 }
4838
4839}
4840
4841//-------------------------
4842// ParseFA250AsyncPedestals
4843//-------------------------
4844// Read out fadc250 asynchronous pedestals at sync events
4845// for all boards in the crate.
4846// The data format: slot + 8 32-bit words (ped1, ped2)
4847void JEventSource_EVIO::ParseFA250AsyncPedestals(evioDOMNodeP bankPtr, list<ObjList*> &events, uint32_t rocid){
4848
4849
4850 const vector<uint32_t> *vec = bankPtr->getVector<uint32_t>();
4851
4852 if(vec->size() > 0){
4853
4854 Df250AsyncPedestal *ped = new Df250AsyncPedestal;
4855
4856 ped->nsync = (*vec)[0];
4857 ped->trig_number = (*vec)[1];
4858
4859 ped->crate = rocid;
4860
4861 for(uint32_t ii = 2; ii < vec->size(); ii++){
4862 ped->fa250_ped.push_back((*vec)[ii]);
4863 }
4864
4865 if(events.empty()){
4866 events.push_back(new ObjList());
4867 }
4868
4869 ObjList *objs = *(events.begin());
4870
4871 objs->misc_objs.push_back(ped);
4872 } else {
4873 evioout << " SYNC event: inconsistent format for FA250AsyncPedestals. Don't parse " << endl;
4874 }
4875
4876}
4877
4878
4879//----------------
4880// ParseTSSync event
4881//----------------
4882void JEventSource_EVIO::ParseTSSync(evioDOMNodeP bankPtr, list<ObjList*> &events)
4883{
4884
4885 DL1Info *trig_info = new DL1Info;
4886
4887 // cout << " INSIDE ParseTSSync " << endl;
4888
4889 if((bankPtr->tag & 0xFFFF) == 0xEE02){
4890 const vector<uint32_t> *vec = bankPtr->getVector<uint32_t>();
4891
4892
4893
4894 trig_info->nsync = (*vec)[0];
4895 trig_info->trig_number = (*vec)[1];
4896 trig_info->live_time = (*vec)[2];
4897 trig_info->busy_time = (*vec)[3];
4898 trig_info->live_inst = (*vec)[4];
4899 trig_info->unix_time = (*vec)[5];
4900
4901
4902
4903 // GTP scalers
4904 for(uint32_t ii = 6; ii < 38; ii++){
4905 trig_info->gtp_sc.push_back((*vec)[ii]);
4906 }
4907
4908 // FP scalers
4909 for(uint32_t ii = 38; ii < 54; ii++){
4910 trig_info->fp_sc.push_back((*vec)[ii]);
4911 }
4912
4913 // GTP rate
4914 for(uint32_t ii = 54; ii < 86; ii++){
4915 trig_info->gtp_rate.push_back((*vec)[ii]);
4916 }
4917
4918 // FP rate
4919 for(uint32_t ii = 86; ii < 102; ii++){
4920 trig_info->fp_rate.push_back((*vec)[ii]);
4921 }
4922 }
4923
4924
4925 if(events.empty()){
4926 events.push_back(new ObjList());
4927 // cout << " TSSync: Empty event " << endl;
4928 }
4929
4930 ObjList *objs = *(events.begin());
4931
4932 objs->misc_objs.push_back(trig_info);
4933
4934
4935}
4936
4937//----------------
4938// ParseDVertexBank
4939//----------------
4940void JEventSource_EVIO::ParseDVertexBank(evioDOMNodeP bankPtr, list<ObjList*> &events)
4941{
4942 const vector<uint32_t> *vec = bankPtr->getVector<uint32_t>();
4943
4944 if(vec->size() != 11) {
4945
4946 DVertex* the_vertex = new DVertex();
4947
4948 uint64_t lo_word = (*vec)[0];
4949 uint64_t hi_word = (*vec)[1];
4950 double vertex_x_pos = static_cast<double>( lo_word | (hi_word<<32) );
4951 lo_word = (*vec)[2];
4952 hi_word = (*vec)[3];
4953 double vertex_y_pos = static_cast<double>( lo_word | (hi_word<<32) );
4954 lo_word = (*vec)[4];
4955 hi_word = (*vec)[5];
4956 double vertex_z_pos = static_cast<double>( lo_word | (hi_word<<32) );
4957 lo_word = (*vec)[6];
4958 hi_word = (*vec)[7];
4959 double vertex_t = static_cast<double>( lo_word | (hi_word<<32) );
4960
4961 DVector3 vertex_position(vertex_x_pos, vertex_y_pos, vertex_z_pos);
4962 the_vertex->dSpacetimeVertex = DLorentzVector(vertex_position, vertex_t);
4963 the_vertex->dKinFitNDF = (*vec)[8];
4964
4965 lo_word = (*vec)[9];
4966 hi_word = (*vec)[10];
4967 the_vertex->dKinFitChiSq = static_cast<double>( lo_word | (hi_word<<32) );
4968
4969 if(events.empty()) {
4970 events.push_back(new ObjList());
4971 }
4972
4973 ObjList *objs = *(events.begin());
4974
4975 objs->misc_objs.push_back(the_vertex);
4976
4977 } else {
4978 evioout << " DVertex bank: inconsistent bank format. Don't parse " << endl;
4979 }
4980
4981}
4982
4983
4984//----------------
4985// ParseEPICSevent
4986//----------------
4987void JEventSource_EVIO::ParseEPICSevent(evioDOMNodeP bankPtr, list<ObjList*> &events)
4988{
4989 if(!PARSE_EPICS) return;
4990
4991 time_t timestamp=0;
4992
4993 ObjList *objs = NULL__null;
4994
4995 evioDOMNodeListP bankList = bankPtr->getChildren();
4996 evioDOMNodeList::iterator iter = bankList->begin();
4997 if(VERBOSE>7) evioout << " Looping over " << bankList->size() << " banks in EPICS event" << endl;
4998 for(int ibank=1; iter!=bankList->end(); iter++, ibank++){ // ibank only used for debugging messages
4999 evioDOMNodeP childBank = *iter;
5000
5001 if(childBank->tag == 97){
5002 // timestamp bank
5003 const vector<uint32_t> *vec = childBank->getVector<uint32_t>();
5004 if(vec) {
5005 timestamp = (time_t)(*vec)[0];
5006 if(VERBOSE>7) evioout << " timestamp: " << ctime(&timestamp);
5007 }
5008 }else if(childBank->tag==98){
5009 const vector<uint8_t> *vec = childBank->getVector<uint8_t>();
5010 if(vec){
5011 string nameval = (const char*)&((*vec)[0]);
5012 DEPICSvalue *epicsval = new DEPICSvalue(timestamp, nameval);
5013 if(VERBOSE>7) evioout << " " << nameval << endl;
5014
5015 if(!objs){
5016 if(events.empty()) events.push_back(new ObjList);
5017 objs = *(events.begin());
5018 }
5019 objs->misc_objs.push_back(epicsval);
5020 }
5021 }
5022 }
5023}
5024#endif // HAVE_EVIO
5025
5026//----------------
5027// DumpBinary
5028//----------------
5029void JEventSource_EVIO::DumpBinary(const uint32_t *iptr, const uint32_t *iend, uint32_t MaxWords, const uint32_t *imark)
5030{
5031 /// This is used for debugging. It will print to the screen the words
5032 /// starting at the address given by iptr and ending just before iend
5033 /// or for MaxWords words, whichever comes first. If iend is NULL,
5034 /// then MaxWords will be printed. If MaxWords is zero then it is ignored
5035 /// and only iend is checked. If both iend==NULL and MaxWords==0, then
5036 /// only the word at iptr is printed.
5037
5038 cout << "Dumping binary: istart=" << hex << iptr << " iend=" << iend << " MaxWords=" << dec << MaxWords << endl;
5039
5040 if(iend==NULL__null && MaxWords==0) MaxWords=1;
5041 if(MaxWords==0) MaxWords = (uint32_t)0xffffffff;
5042
5043 uint32_t Nwords=0;
5044 while(iptr!=iend && Nwords<MaxWords){
5045
5046 // line1 is hex and line2 is decimal
5047 stringstream line1, line2;
5048
5049 // print words in columns 8 words wide. First part is
5050 // reserved for word number
5051 uint32_t Ncols = 8;
5052 line1 << setw(5) << Nwords;
5053 line2 << string(5, ' ');
5054
5055 // Loop over columns
5056 for(uint32_t i=0; i<Ncols; i++, iptr++, Nwords++){
5057
5058 if(iptr == iend) break;
5059 if(Nwords>=MaxWords) break;
5060
5061 stringstream iptr_hex;
5062 iptr_hex << hex << "0x" << *iptr;
5063
5064 string mark = (iptr==imark ? "*":" ");
5065
5066 line1 << setw(12) << iptr_hex.str() << mark;
5067 line2 << setw(12) << *iptr << mark;
5068 }
5069
5070 cout << line1.str() << endl;
5071 cout << line2.str() << endl;
5072 cout << endl;
5073 }
5074}
5075
5076#endif // HAVE_EVIO
5077
5078#if 0
5079//----------------
5080// GuessModuleType
5081//----------------
5082MODULE_TYPE JEventSource_EVIO::GuessModuleType(const uint32_t* istart, const uint32_t* iend, evioDOMNodeP bankPtr)
5083{
5084 /// Try parsing through the information in the given data buffer
5085 /// to determine which type of module produced the data.
5086
5087 if(IsFADC250(istart, iend)) return DModuleType::FADC250;
5088 if(IsF125ADC(istart, iend)) return DModuleType::F125ADC;
5089 if(IsF1TDC(istart, iend)) return DModuleType::F1TDC;
5090 if(IsTS(istart, iend)) return DModuleType::JLAB_TS;
5091 if(IsTI(istart, iend)) return DModuleType::JLAB_TID;
5092
5093
5094 // Couldn't figure it out...
5095 return DModuleType::UNKNOWN;
5096}
5097
5098//----------------
5099// IsFADC250
5100//----------------
5101bool JEventSource_EVIO::IsFADC250(const uint32_t *istart, const uint32_t *iend)
5102{
5103 //---- Check for f250
5104 // This will check if the first word appears to be a block header.
5105 // If so, it loops over all words looking for a block trailer.
5106 // If the slot number in the block trailer matches that in the
5107 // block header AND the number of words in the block matches that
5108 // specified in the block trailer, then it is assumed to be a f250.
5109 if(((*istart>>31) & 0x1) == 1){
5110 uint32_t data_type = (*istart>>27) & 0x0F;
5111 if(data_type == 0){ // Block Header
5112 uint32_t slot_header = (*istart>>22) & 0x1F;
5113 uint32_t Nwords = 1;
5114 for(const uint32_t *iptr=istart; iptr<iend; iptr++, Nwords++){
5115 if(((*iptr>>31) & 0x1) == 1){
5116 uint32_t data_type = (*iptr>>27) & 0x0F;
5117 if(data_type == 1){ // Block Trailer
5118 uint32_t slot_trailer = (*iptr>>22) & 0x1F;
5119 uint32_t Nwords_trailer = (*iptr>>0) & 0x3FFFFF;
5120
5121 if( slot_header == slot_trailer && Nwords == Nwords_trailer ){
5122 return true;
5123 }else{
5124 return false;
5125 }
5126 }
5127 }
5128 }
5129 }
5130 }
5131
5132 // either first word was not a block header or no block trailer was found
5133 return false;
5134}
5135
5136//----------------
5137// IsF1TDC
5138//----------------
5139bool JEventSource_EVIO::IsF1TDC(const uint32_t *istart, const uint32_t *iend)
5140{
5141 //---- Check for F1TDC
5142 // This will check for consistency in the slot numbers for all words
5143 // in the buffer. The slot number of data words are checked against
5144 // the slot number of the most recently encountered header word.
5145 uint32_t slot_header = 1000;
5146 uint32_t slot_trailer = 1000;
5147
5148 const uint32_t *iptr=istart;
5149
5150 // skip first word which appears to be ROL marker for F1TDC data
5151 if(*istart == 0xf1daffff)iptr++
5152
5153 // There is no distinction between header and trailer
5154 // words other than the order that they appear. We keep
5155 // track by flipping this value
5156 bool looking_for_header = true;
5157
5158 // Keep track of the number of valid blocks of F1TDC data we find
5159 // (i.e. ones where the header and trailer words were found
5160 int Nvalid = 0;
5161
5162 for(; iptr<iend; iptr++){
5163
5164 // ROL end of data marker (only in test setup data)
5165 if(*iptr == 0xda0000ff)break;
5166
5167 uint32_t slot = (*iptr>>27) & 0x1F;
5168
5169 // if slot is 0 or 30, we are supposed to ignore the data.
5170 if(slot == 30 || slot ==0)continue;
5171
5172 if(((*iptr>>23) & 0x1) == 0){
5173 // header/trailer word
5174 if(looking_for_header){
5175 slot_header = slot;
5176 looking_for_header = false;
5177 }else{
5178 slot_trailer = slot;
5179 if(slot_trailer != slot_header)return false;
5180 looking_for_header = true;
5181 Nvalid++;
5182 }
5183 }else{
5184 // data word
5185
5186 // if we encounter a data word when we are expecting
5187 // a header word, then the current word is not from
5188 // an F1TDC. However, if we did find at least one valid
5189 // block at the begining, of the buffer, claim the buffer
5190 // points to F1TDC data. We check for as many valid F1TDC
5191 // blocks as possible to help ensure that is what the data
5192 // is.
5193 if(looking_for_header)return Nvalid>0;
5194
5195 // If the slot number does not match, then this is
5196 // not valid F1TDC data
5197 if(slot != slot_header)return false;
5198 }
5199 }
5200
5201 return Nvalid>0;
5202}
5203
5204//----------------
5205// DumpModuleMap
5206//----------------
5207void JEventSource_EVIO::DumpModuleMap(void)
5208{
5209 // Open output file
5210 string fname = "module_map.txt";
5211 ofstream ofs(fname.c_str());
5212 if(!ofs.is_open()){
5213 jerr<<"Unable to open file \""<<fname<<"\" for writing!"<<endl;
5214 return;
5215 }
5216
5217 jout<<"Writing module map to file \""<<fname<<"\""<<endl;
5218
5219 // Write header
5220 time_t now = time(NULL__null);
5221 ofs<<"# Autogenerated module map"<<endl;
5222 ofs<<"# Created: "<<ctime(&now);
5223 ofs<<"#"<<endl;
5224
5225 // Write known module types in header
5226 vector<DModuleType> modules;
5227 DModuleType::GetModuleList(modules);
5228 ofs<<"# Known module types:"<<endl;
5229 ofs<<"# ----------------------"<<endl;
5230 for(unsigned int i=0; i<modules.size(); i++){
5231 string name = modules[i].GetName();
5232 string space(12-name.size(), ' ');
5233 ofs << "# " << name << space << " - " << modules[i].GetDescription() <<endl;
5234 }
5235 ofs<<"#"<<endl;
5236 ofs<<"#"<<endl;
5237
5238 // Write module map
5239 ofs<<"# Format is:"<<endl;
5240 ofs<<"# tag num type"<<endl;
5241 ofs<<"#"<<endl;
5242
5243 map<tagNum, MODULE_TYPE>::iterator iter = module_type.begin();
5244 for(; iter!=module_type.end(); iter++){
5245
5246 tagNum tag_num = iter->first;
5247 MODULE_TYPE type = iter->second;
5248 ofs<<tag_num.first<<" "<<(int)tag_num.second<<" "<<DModuleType::GetName(type)<<endl;
5249 }
5250 ofs<<endl;
5251
5252 // Close output file
5253 ofs.close();
5254}
5255#endif