Bug Summary

File:libraries/DAQ/JEventSource_EVIO.cc
Location:line 1952, column 9
Description:Called C++ object pointer is null

Annotated Source Code

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) delete[] 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;
1
Taking false branch
1865 if(VERBOSE>3) evioout << " Entering EmulateDf250Firmware ..." <<endl;
2
Taking false branch
1866
1867 vector <const Df250EmulatorAlgorithm*> f250Emulator_const;
1868 Df250EmulatorAlgorithm *f250Emulator = NULL__null;
3
'f250Emulator' initialized to a null pointer value
1869 JEventLoop *loop = event.GetJEventLoop();
1870 Df250EmulatorAlgorithm_factory *f250EmFac = static_cast<Df250EmulatorAlgorithm_factory*>(loop->GetFactory("Df250EmulatorAlgorithm"));
1871 if (f250EmFac) {
4
Assuming 'f250EmFac' is null
5
Taking false branch
1872 f250EmFac->Get(f250Emulator_const);
1873 // Drop const
1874 if (f250Emulator_const.size() != 0) f250Emulator = const_cast<Df250EmulatorAlgorithm*>(f250Emulator_const[0]);
1875 }
1876
1877 if(VERBOSE>3) evioout << " Looping over raw data ..." <<endl;
6
Taking false branch
1878 // Loop over all window raw data objects
1879 for(unsigned int i=0; i<wrd_objs.size(); i++){
7
Loop condition is true. Entering loop body
1880 const Df250WindowRawData *f250WindowRawData = (Df250WindowRawData*)wrd_objs[i];
1881 Df250PulseTime *f250PulseTime = NULL__null;
1882 Df250PulsePedestal *f250PulsePedestal = NULL__null;
1883 Df250PulseIntegral *f250PulseIntegral = NULL__null;
1884
1885 // When raw data exists, we will always do the emulation
1886 // Grab the existing Pulse data, up to three of each type
1887 // for each WindowRawData object.
1888 for(uint32_t j=0; j<pt_objs.size(); j++){
8
Loop condition is false. Execution continues on line 1908
1889 Df250PulseTime *pt = (Df250PulseTime*)pt_objs[j];
1890 if(pt->rocid == f250WindowRawData->rocid){
1891 if(pt->slot == f250WindowRawData->slot){
1892 if(pt->channel == f250WindowRawData->channel){
1893 f250PulseTime = pt;
1894 f250PulseTime->AddAssociatedObject(f250WindowRawData);
1895 if(pt->emulated){
1896 jerr << "Emulating channel that already has emulated objects!" << endl;
1897 jerr << "This likely means there is a bug in JEventSource_EVIO.cc" <<endl;
1898 jerr << "PulseTime: rocid="<<pt->rocid<<" slot="<<pt->slot<<" channel="<<pt->channel<<endl;
1899 jerr << "please report error to davidl@jlab.org" << endl;
1900 exit(-1);
1901 }
1902 }
1903 }
1904 }
1905 }
1906
1907 // Ditto for pulse pedestal objects
1908 for(uint32_t j=0; j<pp_objs.size(); j++){
9
Loop condition is false. Execution continues on line 1928
1909 Df250PulsePedestal *pp = (Df250PulsePedestal*)pp_objs[j];
1910 if(pp->rocid == f250WindowRawData->rocid){
1911 if(pp->slot == f250WindowRawData->slot){
1912 if(pp->channel == f250WindowRawData->channel){
1913 f250PulsePedestal = pp;
1914 f250PulsePedestal->AddAssociatedObject(f250WindowRawData);
1915 if(pp->emulated){
1916 jerr << "Emulating channel that already has emulated objects!" << endl;
1917 jerr << "This likely means there is a bug in JEventSource_EVIO.cc" <<endl;
1918 jerr << "PulsePedestal: rocid="<<pp->rocid<<" slot="<<pp->slot<<" channel="<<pp->channel<<endl;
1919 jerr << "please report error to davidl@jlab.org" << endl;
1920 exit(-1);
1921 }
1922 }
1923 }
1924 }
1925 }
1926
1927 // Ditto for pulse integral objects
1928 for(uint32_t j=0; j<pi_objs.size(); j++){
10
Loop condition is false. Execution continues on line 1948
1929 Df250PulseIntegral *pi = (Df250PulseIntegral*)pi_objs[j];
1930 if(pi->rocid == f250WindowRawData->rocid){
1931 if(pi->slot == f250WindowRawData->slot){
1932 if(pi->channel == f250WindowRawData->channel){
1933 f250PulseIntegral = pi;
1934 f250PulseIntegral->AddAssociatedObject(f250WindowRawData);
1935 if(pi->emulated){
1936 jerr << "Emulating channel that already has emulated objects!" << endl;
1937 jerr << "This likely means there is a bug in JEventSource_EVIO.cc" <<endl;
1938 jerr << "PulseIntegral: rocid="<<pi->rocid<<" slot="<<pi->slot<<" channel="<<pi->channel<<endl;
1939 jerr << "please report error to davidl@jlab.org" << endl;
1940 exit(-1);
1941 }
1942 }
1943 }
1944 }
1945 }
1946
1947 // Emulate firmware
1948 uint32_t pt_emulated = pt_objs.size();
1949 uint32_t pp_emulated = pp_objs.size();
1950 uint32_t pi_emulated = pi_objs.size();
1951 if(VERBOSE>3) evioout << " Calling EmulateFirmware ..." << endl;
11
Taking false branch
1952 f250Emulator->EmulateFirmware(f250WindowRawData, pt_objs, pp_objs, pi_objs);
12
Called C++ object pointer is null
1953
1954 // Find all new objects generated by emulation and match with hw originals, if any
1955 uint32_t pt_hardware = 0;
1956 for (uint32_t i = pt_emulated; i < pt_objs.size(); i++) {
1957 const Df250WindowRawData *rd;
1958 Df250PulseTime *pt_em = dynamic_cast<Df250PulseTime*>(pt_objs[i]);
1959 pt_em->GetSingle(rd);
1960 if (rd != f250WindowRawData) {
1961 jerr << "Emulated object found that does not belong to WindowRawData object!" << endl;
1962 jerr << "This likely means there is a bug in JEventSource_EVIO.cc PulseTime emulation." << endl;
1963 jerr << "rocid=" << pt_em->rocid << " slot=" << pt_em->slot << " channel=" << pt_em->channel << endl;
1964 jerr << "Please report error to davidl@jlab.org" << endl;
1965 exit(-1);
1966 }
1967 for (uint32_t j = pt_hardware; j < pt_emulated; j++) {
1968 Df250PulseTime *pt_hw = dynamic_cast<Df250PulseTime*>(pt_objs[j]);
1969 pt_hw->GetSingle(rd);
1970 if (rd == f250WindowRawData && pt_hw->pulse_number == pt_em->pulse_number) {
1971 pt_hardware = j + 1;
1972 if (F250_EMULATION_MODE == kEmulationAlways) {
1973 *pt_hw = *pt_em;
1974 }
1975 else {
1976 pt_hw->time_emulated = pt_em->time_emulated;
1977 pt_hw->quality_factor_emulated = pt_em->quality_factor_emulated;
1978 }
1979 if ((VERBOSE > 0 && pt_hw->time != pt_hw->time_emulated) || VERBOSE > 3) {
1980 // implement special exceptions for early pulse times in mode 8 data
1981 if (VERBOSE > 3 || !(pt_hw->time == 0 &&
1982 (pt_hw->time_emulated == 64 || pt_hw->time_emulated == 128 ||
1983 pt_hw->time_emulated == 192 || pt_hw->time_emulated == 256)) )
1984 {
1985 jout << " comparing f250 hw and emulation pulse times for ROC/slot/chan "
1986 << pt_hw->rocid << "/" << pt_hw->slot << "/" << pt_hw->channel << ": "
1987 << pt_hw->time << " vs " << pt_hw->time_emulated << endl;
1988 }
1989 }
1990 pt_objs.erase(pt_objs.begin() + i);
1991 delete pt_em;
1992 pt_em = 0;
1993 --i;
1994 break;
1995 }
1996 }
1997 if (pt_em != 0 && VERBOSE > 3) {
1998 jout << " new f250 emulation PulseTime generated for ROC/slot/chan "
1999 << pt_em->rocid << "/" << pt_em->slot << "/" << pt_em->channel << ": "
2000 << "pulse " << pt_em->pulse_number << ", time " << pt_em->time << endl;
2001 }
2002 }
2003
2004 uint32_t pp_hardware = 0;
2005 for (uint32_t i = pp_emulated; i < pp_objs.size(); i++) {
2006 Df250PulsePedestal *pp_em = dynamic_cast<Df250PulsePedestal*>(pp_objs[i]);
2007 const Df250WindowRawData *rd;
2008 pp_em->GetSingle(rd);
2009 if (rd != f250WindowRawData) {
2010 jerr << "Emulated object found that does not belong to WindowRawData object!" << endl;
2011 jerr << "This likely means there is a bug in JEventSource_EVIO.cc PulsePedestal emulation." << endl;
2012 jerr << "rocid=" << pp_em->rocid << " slot=" << pp_em->slot << " channel=" << pp_em->channel << endl;
2013 jerr << "Please report error to davidl@jlab.org" << endl;
2014 exit(-1);
2015 }
2016 for (uint32_t j=pp_hardware; j < pp_emulated; j++) {
2017 Df250PulsePedestal *pp_hw = dynamic_cast<Df250PulsePedestal*>(pp_objs[j]);
2018 pp_hw->GetSingle(rd);
2019 if (rd == f250WindowRawData && pp_hw->pulse_number == pp_em->pulse_number) {
2020 pp_hardware = j + 1;
2021 if (F250_EMULATION_MODE == kEmulationAlways) {
2022 *pp_hw = *pp_em;
2023 }
2024 else {
2025 pp_hw->pedestal_emulated = pp_em->pedestal_emulated;
2026 pp_hw->pulse_peak_emulated = pp_em->pulse_peak_emulated;
2027 }
2028 if ((VERBOSE > 0 && pp_hw->pulse_peak != pp_hw->pulse_peak_emulated) || VERBOSE > 3)
2029 jout << " comparing f250 hw and emulation pulse peaks for ROC/slot/chan "
2030 << pp_hw->rocid << "/" << pp_hw->slot << "/" << pp_hw->channel << ": "
2031 << pp_hw->pulse_peak << " vs " << pp_hw->pulse_peak_emulated << endl;
2032 pp_objs.erase(pp_objs.begin() + i);
2033 delete pp_em;
2034 pp_em = 0;
2035 --i;
2036 break;
2037 }
2038 }
2039 if (pp_em != 0 && VERBOSE > 3) {
2040 jout << " new f250 emulation PulsePedestal generated for ROC/slot/chan "
2041 << pp_em->rocid << "/" << pp_em->slot << "/" << pp_em->channel << ": "
2042 << "pulse " << pp_em->pulse_number << ", pedestal " << pp_em->pedestal
2043 << ", peak " << pp_em->pulse_peak << endl;
2044 }
2045 }
2046
2047 uint32_t pi_hardware = 0;
2048 for (uint32_t i = pi_emulated; i < pi_objs.size(); i++) {
2049 Df250PulseIntegral *pi_em = dynamic_cast<Df250PulseIntegral*>(pi_objs[i]);
2050 const Df250WindowRawData *rd;
2051 pi_em->GetSingle(rd);
2052 if (rd != f250WindowRawData) {
2053 jerr << "Emulated object found that does not belong to WindowRawData object!" << endl;
2054 jerr << "This likely means there is a bug in JEventSource_EVIO.cc PulseIntegral emulation." << endl;
2055 jerr << "rocid=" << pi_em->rocid << " slot=" << pi_em->slot << " channel=" << pi_em->channel << endl;
2056 jerr << "Please report error to davidl@jlab.org" << endl;
2057 exit(-1);
2058 }
2059 for (uint32_t j=pi_hardware; j < pi_emulated; j++) {
2060 Df250PulseIntegral *pi_hw = dynamic_cast<Df250PulseIntegral*>(pi_objs[j]);
2061 pi_hw->GetSingle(rd);
2062 if (rd == f250WindowRawData && pi_hw->pulse_number == pi_em->pulse_number) {
2063 pi_hardware = j + 1;
2064 if (F250_EMULATION_MODE == kEmulationAlways) {
2065 *pi_hw = *pi_em;
2066 }
2067 else {
2068 pi_hw->integral_emulated = pi_em->integral_emulated;
2069 pi_hw->pedestal_emulated = pi_em->pedestal_emulated;
2070 }
2071 if ((VERBOSE > 0 && pi_hw->integral != pi_hw->integral_emulated) || VERBOSE > 3)
2072 jout << " comparing f250 hw and emulation pulse integrals for ROC/slot/chan "
2073 << pi_hw->rocid << "/" << pi_hw->slot << "/" << pi_hw->channel << ": "
2074 << pi_hw->integral << " vs " << pi_hw->integral_emulated << endl;
2075 pi_objs.erase(pi_objs.begin() + i);
2076 delete pi_em;
2077 pi_em = 0;
2078 i--;
2079 break;
2080 }
2081 }
2082 if (pi_em != 0 && VERBOSE > 3) {
2083 jout << " new f250 emulation PulseIntegral generated for ROC/slot/chan "
2084 << pi_em->rocid << "/" << pi_em->slot << "/" << pi_em->channel << ": "
2085 << "pulse " << pi_em->pulse_number << ", integral " << pi_em->integral
2086 << ", pedestal " << pi_em->pedestal << endl;
2087 }
2088 }
2089 }
2090
2091 // PulseTime, PulsePedestal, PulseIntegral objects are associated to one another in GetObjects
2092 if(VERBOSE>3) evioout << " Leaving EmulateDf250Firmware" <<endl;
2093}
2094
2095//----------------
2096// EmulateDf125Firmware
2097//----------------
2098void JEventSource_EVIO::EmulateDf125Firmware( JEvent &event, vector<JObject*> &wrd_objs, vector<JObject*> &cp_objs, vector<JObject*> &fp_objs)
2099{
2100 /// This code implements an upsampling technique developed by Naomi Jarvis at
2101 /// CMU. This was not implemented in the firmware for the 2014-2015 commissioning
2102 /// run, but was implemented for later runs.
2103 ///
2104 /// Removed f250 style emulation of f125 firmware. Keep in mind if for some reason old
2105 /// mode 8 data is processed, it will return the new style words with 1/10
2106 /// sample resolution. It is doubtful anyone will be using these in the future so nbd. 3/18/2016 MS
2107
2108 if(wrd_objs.size() == 0) return; // Can't do anything without the raw data
2109 if(VERBOSE>3) evioout << " Entering EmulateDf125Firmware ..." <<endl;
2110
2111 vector <const Df125EmulatorAlgorithm*> f125Emulator_const;
2112 Df125EmulatorAlgorithm *f125Emulator = NULL__null;
2113 JEventLoop *loop = event.GetJEventLoop();
2114 Df125EmulatorAlgorithm_factory *f125EmFac = static_cast<Df125EmulatorAlgorithm_factory*>(loop->GetFactory("Df125EmulatorAlgorithm"));
2115 if (f125EmFac) {
2116 f125EmFac->Get(f125Emulator_const);
2117 // Drop const
2118 if (f125Emulator_const.size() != 0) f125Emulator = const_cast<Df125EmulatorAlgorithm*>(f125Emulator_const[0]);
2119 }
2120
2121 // Loop over all window raw data objects
2122 for(unsigned int i=0; i<wrd_objs.size(); i++){
2123 const Df125WindowRawData *f125WindowRawData = (Df125WindowRawData*)wrd_objs[i];
2124 Df125CDCPulse *f125CDCPulse = NULL__null;
2125 Df125FDCPulse *f125FDCPulse = NULL__null;
2126
2127 //search for existing CDCPulse
2128 for(uint32_t j=0; j<cp_objs.size(); j++){
2129 Df125CDCPulse *cp = (Df125CDCPulse*)cp_objs[j];
2130 if(cp->rocid == f125WindowRawData->rocid){
2131 if(cp->slot == f125WindowRawData->slot){
2132 if(cp->channel == f125WindowRawData->channel){
2133 f125CDCPulse = cp;
2134 f125CDCPulse->AddAssociatedObject(f125WindowRawData);
2135 break;
2136 }
2137 }
2138 }
2139 }
2140
2141 // search for existing FDCPulse
2142 for(uint32_t j=0; j<fp_objs.size(); j++){
2143 Df125FDCPulse *fp = (Df125FDCPulse*)fp_objs[j];
2144 if(fp->rocid == f125WindowRawData->rocid){
2145 if(fp->slot == f125WindowRawData->slot){
2146 if(fp->channel == f125WindowRawData->channel){
2147 f125FDCPulse = fp;
2148 f125FDCPulse->AddAssociatedObject(f125WindowRawData);
2149 break;
2150 }
2151 }
2152 }
2153 }
2154
2155 // If the the pulse objects do not exist, create new ones to go with our raw data
2156 // This should rarely happen since CDC_long and FDC_long have the raw data
2157 // along with the calculated quantities in a pulse word. Pure raw mode would be the only time
2158 // when this would not be the case. Since this is so infrequently used (if ever),
2159 // the ROCID check for CDC/FDC determination is hard coded...
2160 // ROCID CDC: 25-28
2161 // ROCID FDC Cathode: 52,53,55-62
2162
2163 if(f125CDCPulse == NULL__null && ( f125WindowRawData->rocid < 30 ) ){
2164 f125CDCPulse = new Df125CDCPulse;
2165 f125CDCPulse->rocid = f125WindowRawData->rocid;
2166 f125CDCPulse->slot = f125WindowRawData->slot;
2167 f125CDCPulse->channel = f125WindowRawData->channel;
2168 f125CDCPulse->emulated = true;
2169 f125CDCPulse->AddAssociatedObject(f125WindowRawData);
2170 cp_objs.push_back(f125CDCPulse);
2171 }
2172
2173 else if(f125FDCPulse == NULL__null && ( f125WindowRawData->rocid > 30 ) ){
2174 f125FDCPulse = new Df125FDCPulse;
2175 f125FDCPulse->rocid = f125WindowRawData->rocid;
2176 f125FDCPulse->slot = f125WindowRawData->slot;
2177 f125FDCPulse->channel = f125WindowRawData->channel;
2178 f125FDCPulse->emulated = true;
2179 f125FDCPulse->AddAssociatedObject(f125WindowRawData);
2180 cp_objs.push_back(f125FDCPulse);
2181 }
2182
2183 // Flag all objects as emulated and their values will be replaced with emulated quantities
2184 if (F125_EMULATION_MODE == kEmulationAlways){
2185 if(f125CDCPulse!=NULL__null) f125CDCPulse->emulated = 1;
2186 if(f125FDCPulse!=NULL__null) f125FDCPulse->emulated = 1;
2187 }
2188
2189 // Perform the emulation
2190 f125Emulator->EmulateFirmware(f125WindowRawData, f125CDCPulse, f125FDCPulse);
2191 }
2192
2193 if(VERBOSE>3) evioout << " Leaving EmulateDf125Firmware" <<endl;
2194}
2195
2196//----------------
2197// GetRunNumber
2198//----------------
2199int32_t JEventSource_EVIO::GetRunNumber(evioDOMTree *evt)
2200{
2201 // Note: This is currently not used. Preference is
2202 // now given to the run number found in FindRunNumber
2203 // which is called from GetEvent. This makes things
2204 // a little simpler and ensures the run number originally
2205 // presented to the processor/factory does not change.
2206 // 2/15/2016 DL
2207
2208 // This is called during event parsing to get the
2209 // run number for the event.
2210 // Look through event to try and extract the run number.
2211 // We do this by looking for all uint64_t nodes. Then
2212 // check for a parent with one of the magic values for
2213 // the tag indicating it has run number information.
2214 if(USER_RUN_NUMBER>0) return USER_RUN_NUMBER;
2215 if(!evt) return last_run_number;
2216
2217 evioDOMNodeListP bankList = evt->getNodeList(typeIs<uint64_t>());
2218 evioDOMNodeList::iterator iter = bankList->begin();
2219 const uint64_t *run_number_and_type = NULL__null;
2220 for(; iter!=bankList->end(); iter++){
2221 evioDOMNodeP bankPtr = *iter;
2222 evioDOMNodeP physics_event_built_trigger_bank = bankPtr->getParent();
2223 if(physics_event_built_trigger_bank == NULL__null) continue;
2224 uint32_t tag = physics_event_built_trigger_bank->tag;
2225 const vector<uint64_t> *vec;
2226 switch(tag){
2227 case 0xFF22:
2228 case 0xFF23:
2229 case 0xFF26:
2230 case 0xFF27:
2231 vec = bankPtr->getVector<uint64_t>();
2232 if(!vec) continue;
2233 if(vec->size()<1) continue;
2234 run_number_and_type = &((*vec)[vec->size()-1]);
2235 break;
2236 }
2237 if(run_number_and_type != NULL__null) break;
2238 }
2239
2240 if(run_number_and_type != NULL__null) last_run_number = (*run_number_and_type)>>32;
2241
2242 return last_run_number;
2243}
2244
2245//----------------
2246// FindRunNumber
2247//----------------
2248int32_t JEventSource_EVIO::FindRunNumber(uint32_t *iptr)
2249{
2250 /// This is called from GetEvent() to quickly look for the run number
2251 /// at the time the event is read in so it can be passed into
2252 /// JEvent. It is what will be used for accessing the CCDB.
2253 /// from this event. If a bank containing the run number is found,
2254 /// use it to provide the run number. Otherwise, return whatever run
2255 /// number we were able to extract from the file name.
2256
2257 if(VERBOSE>1) evioout << " .. Searching for run number ..." <<endl;
2258 if(USER_RUN_NUMBER>0){
2259 if(VERBOSE>1) evioout << " returning user-supplied run number: " << USER_RUN_NUMBER << endl;
2260 return last_run_number=USER_RUN_NUMBER;
2261 }
2262
2263 // Assume first word is number of words in bank
2264 uint32_t *iend = &iptr[*iptr - 1];
2265 if(*iptr > 2048) iend = &iptr[2048];
2266 bool has_timestamps = false;
2267 while(iptr<iend){
2268 iptr++;
2269
2270 // EPICS event
2271 if( (*iptr & 0xff000f) == 0x600001){
2272 if(VERBOSE>2) evioout << " Found EPICS header. Looking for HD:coda:daq:run_number ..." << endl;
2273 const char *cptr = (const char*)&iptr[1];
2274 const char *cend = (const char*)iend;
2275 const char *needle = "HD:coda:daq:run_number=";
2276 while(cptr<cend){
2277 if(VERBOSE>4) evioout << " \""<<cptr<<"\"" << endl;
2278 if(!strncmp(cptr, needle, strlen(needle))){
2279 if(VERBOSE>2) evioout << " Found it!" << endl;
2280 return last_run_number = atoi(&cptr[strlen(needle)]);
2281 }
2282 cptr+=4; // should only start on 4-byte boundary!
2283 }
2284 }
2285
2286 // BOR event
2287 if( (*iptr & 0xffffffff) == 0x00700E01){
2288 // OK, this looks like a BOR event which does not include the
2289 // run number. In this case, we have a couple of options:
2290 //
2291 // 1. If we are reading from a file then look further into
2292 // the file to see if we can find another event with the
2293 // run number in it.
2294 //
2295 // 2. Return the run number found from the filename.
2296 //
2297 if(source_type==kFileSource){
2298 int32_t run_number = EpicQuestForRunNumber();
2299 if(run_number != 0){
2300 if(VERBOSE>1) evioout << " Found run number " << run_number << " from Epic Quest." <<endl;
2301 return last_run_number = run_number;
2302 }
2303 }
2304 break; // return filename_run_number with warning message
2305 }
2306
2307 // PHYSICS event
2308 switch((*iptr)>>16){
2309 case 0xFF10:
2310 case 0xFF11:
2311 case 0xFF20:
2312 case 0xFF21:
2313 case 0xFF24:
2314 case 0xFF25:
2315 case 0xFF30:
2316 // These Trigger Bank Tag values have no run number info in them
2317 if(VERBOSE>2) evioout << " ... Trigger bank tag (0x" << hex << ((*iptr)>>16) << dec << ") does not contain run number" <<endl;
2318 if(!WARN_USER_RUN_FILENAME) {
2319 jout << "WARNING: setting run number " << filename_run_number << " based on file name" << endl;
2320 WARN_USER_RUN_FILENAME = true;
2321 }
2322 return last_run_number = filename_run_number;
2323 case 0xFF23:
2324 case 0xFF27:
2325 has_timestamps = true;
2326 case 0xFF22:
2327 case 0xFF26:
2328 if(VERBOSE>2) evioout << " ... Trigger bank tag (0x" << hex << ((*iptr)>>16) << dec << ") does contain run number" <<endl;
2329 // Nrocs = (*iptr) & 0x0F;
2330 break;
2331 default:
2332 continue;
2333 }
2334 iptr++;
2335 if( ((*iptr)&0x00FF0000) != 0x000A0000) { iptr--; continue; }
2336 uint32_t M = iptr[-3] & 0x000000FF; // Number of events from Physics Event header
2337 if(VERBOSE>2) evioout << " ... Trigger bank " << (has_timestamps ? "does":"doesn't") << " have timestamps. Nevents in block M=" << M <<endl;
2338 iptr++;
2339 uint64_t *iptr64 = (uint64_t*)iptr;
2340
2341 uint64_t event_num = *iptr64;
2342 if(source_type==kETSource) event_num = ((*iptr64)>>32) | ((*iptr64)<<32);
2343 if(VERBOSE>3) evioout << " .... Event num: " << event_num <<endl;
2344 iptr64++;
2345 if(has_timestamps) iptr64 = &iptr64[M]; // advance past timestamps
2346
2347 // I'm not sure I fully understand this, but if we read from
2348 // ET, then the run number is in the low 32 bits of *iptr64.
2349 // If we are reading from a file, it is in the high 32 bits.
2350 // No byte swapping is needed (it has already been done, though
2351 // perhaps incorrectly). We handle this here by checking if
2352 // this is an ET source or not.
2353 uint64_t run64 = (*iptr64)>>32;
2354 if(source_type==kETSource){
2355 run64 = (*iptr64)&0xffffffff;
2356 }
2357 int32_t run = (int32_t)run64;
2358 if(VERBOSE>1) evioout << " .. Found run number: " << run <<endl;
2359
2360 return last_run_number = run;
2361 }
2362
2363 // if we're not sure what else to do, try a more comprehensive search
2364 if(source_type==kFileSource){
2365 int32_t run_number = EpicQuestForRunNumber();
2366 if(run_number != 0){
2367 if(VERBOSE>1) evioout << " Found run number " << run_number << " from Epic Quest." <<endl;
2368 return last_run_number = run_number;
2369 }
2370 }
2371
2372 if(!WARN_USER_RUN_FILENAME) {
2373 jout << "WARNING: setting run number " << filename_run_number << " based on file name" << endl;
2374 WARN_USER_RUN_FILENAME = true;
2375 }
2376
2377 return last_run_number = filename_run_number;
2378}
2379
2380//----------------
2381// EpicQuestForRunNumber
2382//----------------
2383int32_t JEventSource_EVIO::EpicQuestForRunNumber(void)
2384{
2385 /// This is called when an event is encountered that does
2386 /// not have a run number in it. (e.g. a BOR event encountered
2387 /// in FindRunNumber() ). This is a last hope of finding the
2388 /// run number in the file by looking for other events that
2389 /// may contain it. Specifically, EPICS or PHYSICS events.
2390 /// This only works if it is a file source so that it can open
2391 /// the file and read in past the first event.
2392 ///
2393 /// Note that this is extremely inefficient so should not be
2394 /// called very often. As a precaution, this will look to see
2395 /// if last_run_number is not set to 0 first and will just
2396 /// return it if it is. Only if it is not will the epic quest
2397 /// commence.
2398
2399 if(source_type!=kFileSource) return 0;
2400 if(last_run_number != 0) return last_run_number;
2401
2402 uint32_t buff_len = 4000000;
2403 uint32_t *buff = new uint32_t[buff_len];
2404 HDEVIO *hdevio = new HDEVIO(source_name);
2405 while(hdevio->read(buff, buff_len)){
2406
2407 // Assume first word is number of words in bank
2408 uint32_t *iptr = buff;
2409 uint32_t *iend = &iptr[*iptr - 1];
2410 if(*iptr > 2048) iend = &iptr[2048];
2411 bool has_timestamps = false;
2412 while(iptr<iend){
2413 iptr++;
2414
2415 // EPICS event
2416 if( (*iptr & 0xff000f) == 0x600001){
2417 if(VERBOSE>2) evioout << " Found EPICS header. Looking for HD:coda:daq:run_number ..." << endl;
2418 const char *cptr = (const char*)&iptr[1];
2419 const char *cend = (const char*)iend;
2420 const char *needle = "HD:coda:daq:run_number=";
2421 while(cptr<cend){
2422 if(VERBOSE>4) evioout << " \""<<cptr<<"\"" << endl;
2423 if(!strncmp(cptr, needle, strlen(needle))){
2424 if(VERBOSE>2) evioout << " Found it!" << endl;
2425 int32_t run_number = atoi(&cptr[strlen(needle)]);
2426 if(hdevio) delete hdevio;
2427 if(buff) delete[] buff;
2428 return run_number;
2429 }
2430 cptr+=4; // should only start on 4-byte boundary!
2431 }
2432 }
2433
2434 // BOR event
2435 if( (*iptr & 0xffffffff) == 0x00700E01) continue;
2436
2437 // PHYSICS event
2438 bool not_in_this_buffer = false;
2439 switch((*iptr)>>16){
2440 case 0xFF10:
2441 case 0xFF11:
2442 case 0xFF20:
2443 case 0xFF21:
2444 case 0xFF24:
2445 case 0xFF25:
2446 case 0xFF30:
2447 not_in_this_buffer = true;
2448 break;
2449 case 0xFF23:
2450 case 0xFF27:
2451 has_timestamps = true;
2452 case 0xFF22:
2453 case 0xFF26:
2454 break;
2455 default:
2456 continue;
2457 }
2458
2459 if(not_in_this_buffer) break; // go to next EVIO buffer
2460
2461 iptr++;
2462 if( ((*iptr)&0x00FF0000) != 0x000A0000) { iptr--; continue; }
2463 uint32_t M = iptr[-3] & 0x000000FF; // Number of events from Physics Event header
2464 if(VERBOSE>2) evioout << " ...(epic quest) Trigger bank " << (has_timestamps ? "does":"doesn't") << " have timestamps. Nevents in block M=" << M <<endl;
2465 iptr++;
2466 uint64_t *iptr64 = (uint64_t*)iptr;
2467
2468 uint64_t event_num = *iptr64;
2469 if(source_type==kETSource) event_num = ((*iptr64)>>32) | ((*iptr64)<<32);
2470 if(VERBOSE>3) evioout << " ....(epic quest) Event num: " << event_num <<endl;
2471 iptr64++;
2472 if(has_timestamps) iptr64 = &iptr64[M]; // advance past timestamps
2473
2474 // I'm not sure I fully understand this, but if we read from
2475 // ET, then the run number is in the low 32 bits of *iptr64.
2476 // If we are reading from a file, it is in the high 32 bits.
2477 // No byte swapping is needed (it has already been done, though
2478 // perhaps incorrectly). We handle this here by checking if
2479 // this is an ET source or not.
2480 uint64_t run64 = (*iptr64)>>32;
2481 if(source_type==kETSource){
2482 run64 = (*iptr64)&0xffffffff;
2483 }
2484 int32_t run = (int32_t)run64;
2485 if(VERBOSE>1) evioout << " .. (epic quest) Found run number: " << run <<endl;
2486
2487 if(hdevio) delete hdevio;
2488 if(buff) delete[] buff;
2489 return run;
2490
2491 } // while(iptr<iend)
2492
2493 if(hdevio->Nevents > 500) break;
2494 } // while(hdevio->read(buff, buff_len))
2495
2496 if(hdevio) delete hdevio;
2497 if(buff) delete[] buff;
2498
2499 return 0;
2500}
2501
2502//----------------
2503// FindEventNumber
2504//----------------
2505uint64_t JEventSource_EVIO::FindEventNumber(uint32_t *iptr)
2506{
2507 /// This is called from GetEvent() to quickly look for the event number
2508 /// at the time the event is read in so it can be passed into JEvent.
2509 /// (See comments for FindRunNumber above.)
2510 if(VERBOSE>1) evioout << " .. Searching for event number ..." <<endl;
2511
2512 if(*iptr < 6){
2513 if(VERBOSE>1) evioout << " Word count(="<<*iptr<<")<6. Returning Nevents_read+1(=" << Nevents_read+1 << ") as event number" <<endl;
2514 return Nevents_read+1;
2515 }
2516
2517 // Check header of Trigger bank
2518 uint32_t mask = 0xFF202000;
2519 if( (iptr[3]&mask) != mask ){
2520 if(VERBOSE>1){
2521 evioout << " iptr[3]=" << hex << iptr[3] << " does not look like trigger bank tag (" << (iptr[3]&mask) << " != " << mask << ")" << dec <<endl;
2522 evioout << " Returning Nevents_read+1(=" << Nevents_read+1 << ") as event number" <<endl;
2523 }
2524 return Nevents_read+1;
2525 }
2526
2527 uint64_t loevent_num = iptr[5];
2528 uint64_t hievent_num = iptr[6];
2529 if(source_type==kETSource) {
2530 loevent_num = iptr[6];
2531 hievent_num = iptr[5];
2532 }
2533 uint64_t event_num = loevent_num + (hievent_num<<32);
2534 if(VERBOSE>1) evioout << " .. Found event number: " << event_num <<endl;
2535
2536 return event_num;
2537}
2538
2539//----------------
2540// FindEventType
2541//----------------
2542void JEventSource_EVIO::FindEventType(uint32_t *iptr, JEvent &event)
2543{
2544 /// This is called from GetEvent to quickly determine the type of
2545 /// event this is (Physics, EPICS, SYNC, BOR, ...)
2546 uint32_t head = iptr[1];
2547 if( (head & 0xff000f) == 0x600001){
2548 event.SetStatusBit(kSTATUS_EPICS_EVENT);
2549 }else if( (head & 0xffffffff) == 0x00700E01){
2550 event.SetStatusBit(kSTATUS_BOR_EVENT);
2551 }else if( (head & 0xffffff00) == 0xff501000){
2552 event.SetStatusBit(kSTATUS_PHYSICS_EVENT);
2553 }else if( (head & 0xffffff00) == 0xff701000){
2554 event.SetStatusBit(kSTATUS_PHYSICS_EVENT);
2555 }else if( (head & 0xfff000ff) == 0xffd00000){
2556 event.SetStatusBit(kSTATUS_CONTROL_EVENT);
2557 if( (head>>16) == 0xffd0 ) event.SetStatusBit(kSTATUS_SYNC_EVENT);
2558 }else{
2559 DumpBinary(iptr, &iptr[16]);
2560 }
2561}
2562
2563//----------------
2564// MergeObjLists
2565//----------------
2566void JEventSource_EVIO::MergeObjLists(list<ObjList*> &events1, list<ObjList*> &events2)
2567{
2568 if(VERBOSE>5) evioout << " Entering MergeObjLists(). "
2569 << " &events1=" << hex << &events1 << dec << "(" << events1.size() << " events) "
2570 << " &events2=" << hex << &events2 << dec << "(" << events2.size() << " events) " << endl;
2571
2572 /// Merge the events referenced in events2 into the events1 list.
2573 ///
2574 /// This will append the object lists for each type of data object
2575 /// stored in events2 onto the appropriate list in events1. It does this
2576 /// event-by-event. The idea being that each entry in the queue represents a
2577 /// partial list of the objects for the event. The two queues are most likely
2578 /// filled from different EVIO banks orginiating from different ROCs.
2579 ///
2580 /// Before the merging is done, it is checked that both lists either have the
2581 /// same number of events, or one list is empty. One list is allowed to be
2582 /// empty since it is possible it was "filled" from a bank that contains no
2583 /// data at all which may not neccessarily be an error. If both queues have
2584 /// at least one event, but they do not contain an equal number of events,
2585 /// then an exception is thrown.
2586 ///
2587 /// The contents of event2 will be erased before returning. Ownership of all
2588 /// ObjList objects pointed to by event2 upon entry should be considered
2589 /// owned by event1 upon return.
2590
2591 // Allow a list of 1 event with only config objects in test below
2592 bool justconfig = false;
2593 if(events1.size()==1){
2594 ObjList *objs1 = events1.front();
2595 justconfig = objs1->hit_objs.size()==0 && objs1->misc_objs.size()==0 && objs1->config_objs.size()!=0;
2596 }else if(events2.size()==1){
2597 ObjList *objs2 = events2.front();
2598 justconfig = objs2->hit_objs.size()==0 && objs2->misc_objs.size()==0 && objs2->config_objs.size()!=0;
2599 }
2600
2601 // Check number of events and throw exception if appropriate
2602 unsigned int Nevents1 = events1.size();
2603 unsigned int Nevents2 = events2.size();
2604 if(Nevents1>0 && Nevents2>0 && !justconfig){
2605 if(Nevents1 != Nevents2){
2606 evioout << "Mismatch of number of events passed to MergeObjLists. Throwing exception." << endl;
2607 evioout << "Nevents1="<<Nevents1<<" Nevents2="<<Nevents2<<endl;
2608 throw JException("Number of events in JEventSource_EVIO::MergeObjLists do not match!");
2609 }
2610 }
2611
2612 // Handle cases when one or both lists are empty
2613 if(Nevents1==0 && Nevents2==0)return;
2614 if(Nevents1==0){
2615 events1 = events2;
2616 events2.clear(); // clear queue
2617 return;
2618 }
2619 if(Nevents2==0)return;
2620
2621 // If we get here it means both events1 and events2 have events
2622 list<ObjList*>::iterator iter = events1.begin();
2623 for(; iter!=events1.end(); iter++){
2624 if(events2.empty()) break; // in case one has just config objects in a single event
2625 ObjList *objs1 = *iter;
2626 ObjList *objs2 = events2.front();
2627 events2.pop_front();
2628
2629 objs1->hit_objs.insert(objs1->hit_objs.end(), objs2->hit_objs.begin(), objs2->hit_objs.end());
2630 objs1->config_objs.insert(objs1->config_objs.end(), objs2->config_objs.begin(), objs2->config_objs.end());
2631 objs1->misc_objs.insert(objs1->misc_objs.end(), objs2->misc_objs.begin(), objs2->misc_objs.end());
2632
2633 // Delete the objs2 container
2634 delete objs2;
2635 }
2636
2637 // Clear out any references to objects in event2 (this should be redundant)
2638 events2.clear(); // clear queue
2639
2640 if(VERBOSE>5) evioout << " Leaving MergeObjLists(). &events1=" << hex << &events1 << " &events2=" << &events2 << dec << endl;
2641}
2642
2643//----------------
2644// ParseEVIOEvent
2645//----------------
2646void JEventSource_EVIO::ParseEVIOEvent(evioDOMTree *evt, list<ObjList*> &full_events)
2647{
2648 if(VERBOSE>5) evioout << " Entering ParseEVIOEvent() with evt=" << hex << evt << dec << endl;
2649
2650 if(!evt)throw RESOURCE_UNAVAILABLE;
2651
2652 // Since each bank contains parts of many events, have them fill in
2653 // the "tmp_events" list and then merge those into the "full_events".
2654 // It is done this way so each bank can grow tmp_events to the appropriate
2655 // size to hold the number of events it discovers in the bank. A check
2656 // can then be made that this is consistent with the number of event
2657 // fragments found in the other banks.
2658 //list<ObjList*> full_events;
2659 list<ObjList*> tmp_events;
2660
2661 // The Physics Event bank is the outermost bank of the event and
2662 // it is a bank of banks. One of those banks is the
2663 // "Built Trigger Bank" which is a bank of segments. The others
2664 // are the "Data Bank" banks which in turn contain the
2665 // "Data Block Bank" banks which hold the actual data. For the
2666 // mc2coda generated data files (and presumably the real data)
2667 // these Data Block Banks are banks of ints. More specifically,
2668 // uint32_t.
2669 //
2670 // The "Physics Event's Built Trigger Bank" is a bank of segments.
2671 // This contains 3 segments, one each of type uint64, uint16, and
2672 // unit32. The first two are "common data" which contains information
2673 // common to all rocs. The last (uint32) has information specific to each
2674 // event and for each ROC.
2675 //
2676 // For now, we skip parseing the Built Trigger Bank and just
2677 // look for Data Block Banks. We do this by getting a list of
2678 // all uint32_t banks in the enitries DOM Tree (at all levels
2679 // of the heirachy) and checking the parent banks for depth
2680 // and additional info.
2681
2682 // Loop over list of all EVIO banks at all levels of the tree and parse
2683 // them, creating data objects and adding them to the overall list.
2684 evioDOMNodeListP bankList = evt->getNodeList();
2685 evioDOMNodeList::iterator iter = bankList->begin();
2686 if(VERBOSE>7) evioout << " Looping over " << bankList->size() << " banks in EVIO event" << endl;
2687 for(int ibank=1; iter!=bankList->end(); iter++, ibank++){ // ibank only used for debugging messages
2688
2689 if(VERBOSE>7) evioout << " -------- bank " << ibank << "/" << bankList->size() << " --------" << endl;
2690
2691 // The data banks we want should have exactly two parents:
2692 // - Data Bank bank <-- parent
2693 // - Physics Event bank <-- grandparent
2694 //
2695 // other types of events may be inserted in the datastream though so we
2696 // check for those first.
2697
2698 // BOR event
2699 // BOR events will have an outermost
2700 // bank with tag=0x70 and num=1. If this is the outermost bank of
2701 // a BOR event, then parse it. If it is a inner BOR bank then ignore it.
2702 evioDOMNodeP outermostBankPtr = *iter;
2703 while(outermostBankPtr->getParent()) outermostBankPtr = outermostBankPtr->getParent();
2704 if(outermostBankPtr->tag==0x70 && outermostBankPtr->num==1){
2705 // This is a BOR bank
2706 if(VERBOSE>9) evioout << " bank is part of BOR event ... " << endl;
2707 if(outermostBankPtr == *iter){
2708 if(VERBOSE>9) evioout << " bank is outermost EVIO bank. Parsing BOR event ..." << endl;
2709 ParseBORevent(outermostBankPtr);
2710 }else{
2711 if(VERBOSE>9) evioout << " bank is not outermost EVIO bankin BOR event skipping ..." << endl;
2712 }
2713 continue; // no further processing of this bank is needed
2714 }
2715
2716 // EPICS event
2717 evioDOMNodeP bankPtr = *iter;
2718 evioDOMNodeP data_bank = bankPtr->getParent();
2719 if( data_bank==NULL__null ) {
2720
2721 if(VERBOSE>9) evioout << " bank has no parent. Checking if it's an EPICS event ... " << endl;
2722 if(bankPtr->tag==96 && bankPtr->num==1){
2723 // This looks like an EPICS event. Hand it over to EPICS parser
2724 ParseEPICSevent(bankPtr, full_events);
2725 }else{
2726 if(VERBOSE>9) evioout << " Not an EPICS event bank. skipping ... " << endl;
2727 }
2728
2729 continue;
2730 }
2731
2732 // Trigger Bank
2733 evioDOMNodeP physics_event_bank = data_bank->getParent();
2734
2735 // TS scalers for SYNC events. Currently us phys event tag
2736 // Don't use the parent tag in the future, to be checked
2737 if((physics_event_bank != NULL__null) && (bankPtr != NULL__null)){
2738 if( (physics_event_bank->tag == 0xff70) && (bankPtr->tag == 0xEE02)){
2739 const vector<uint32_t> *vec = bankPtr->getVector<uint32_t>();
2740 if(vec->size() < 102){
2741 evioout << " TS record for SYNC event is inconsistent. Don't parse " << endl;
2742 } else {
2743 ParseTSSync(bankPtr, full_events);
2744 // MergeObjLists(full_events, tmp_events);
2745 }
2746 }
2747 }
2748
2749
2750 if( physics_event_bank==NULL__null ){
2751 if(VERBOSE>6) evioout << " bank has no grandparent. Checking if this is a trigger bank ... " << endl;
2752
2753 // Check if this is a CODA Reserved Bank Tag. If it is, then
2754 // this probably is part of the built trigger bank and not
2755 // the ROC data we're looking to parse here.
2756 if((bankPtr->tag & 0xFF00) == 0xFF00){
2757 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;
2758 ParseBuiltTriggerBank(bankPtr, tmp_events);
2759 if(VERBOSE>5) evioout << " Merging objects in ParseEVIOEvent" << endl;
2760 MergeObjLists(full_events, tmp_events);
2761
2762 // Check if this is a DEventTag bank
2763 }else if(bankPtr->tag == 0x0056){
2764 const vector<uint32_t> *vec = bankPtr->getVector<uint32_t>();
2765 if(vec){
2766 const uint32_t *iptr = &(*vec)[0];
2767 const uint32_t *iend = &(*vec)[vec->size()];
2768 ParseEventTag(iptr, iend, tmp_events);
2769 if(VERBOSE>5) evioout << " Merging DEventTag objects in ParseEVIOEvent" << endl;
2770 MergeObjLists(full_events, tmp_events);
2771 }
2772 }
2773
2774 continue; // if this wasn't a trigger bank, then it has the wrong lineage to be a data bank
2775 }
2776 if( physics_event_bank->getParent() != NULL__null ){
2777 if(VERBOSE>9) evioout << " bank DOES have great-grandparent. skipping ... " << endl;
2778 continue; // physics event bank should have no parent!
2779 }
2780 if(VERBOSE>9){
2781 evioout << " Physics Event Bank: tag=" << hex << physics_event_bank->tag << " num=" << (int)physics_event_bank->num << dec << endl;
2782 evioout << " Data Bank: tag=" << hex << data_bank->tag << " num=" << (int)data_bank->num << dec << endl;
2783 }
2784
2785 if(VERBOSE>9) evioout << " bank lineage check OK. Continuing with parsing ... " << endl;
2786
2787 // Extract ROC id (crate number) from bank's parent
2788 uint32_t rocid = data_bank->tag & 0x0FFF;
2789
2790 // Get data from bank in the form of a vector of uint32_t
2791 const vector<uint32_t> *vec = bankPtr->getVector<uint32_t>();
2792 if(!vec){
2793 if(VERBOSE>6) evioout << " bank is not uint32_t. Skipping..." << endl;
2794 continue;
2795 }
2796 const uint32_t *iptr = &(*vec)[0];
2797 const uint32_t *iend = &(*vec)[vec->size()];
2798 if(VERBOSE>6) evioout << " uint32_t bank has " << vec->size() << " words" << endl;
2799
2800 // If there are rocid's specified that we wish to parse, make sure this one
2801 // is in the list. Otherwise, skip it.
2802 if(!ROCIDS_TO_PARSE.empty()){
2803 if(VERBOSE>4) evioout << " Skipping parsing of rocid="<<rocid<<" due to it being in ROCIDS_TO_PARSE set." << endl;
2804 if(ROCIDS_TO_PARSE.find(rocid) == ROCIDS_TO_PARSE.end()) continue;
2805 }
2806
2807 // Check if this is a CODA Reserved Bank Tag.
2808 if((data_bank->tag & 0xFF00) == 0xFF00){
2809 if(VERBOSE>6) evioout << " Data Bank tag="<<hex<<data_bank->tag<<dec<<" is in reserved CODA range. This is probably not ROC data"<< endl;
2810 continue;
2811 }
2812
2813 // Check if this is a TS Bank.
2814 if(bankPtr->tag == 0xEE02){
2815 if(VERBOSE>4) evioout << " TS bank tag="<<hex<<bankPtr->tag<<dec<< endl;
2816 ParseTSBank(rocid, iptr, iend, full_events);
2817 continue;
2818 }
2819
2820
2821 // Check if this is a f250 Pedestal Bank. Read out at SYNC events.
2822 if(bankPtr->tag == 0xEE05){
2823 if(VERBOSE>6) evioout << " SYNC event - f250 pedestals found " << endl;
2824 ParseFA250AsyncPedestals(bankPtr, full_events, rocid);
2825 continue;
2826 }
2827
2828
2829 // FADC 250 scalers. Read out at SYNC events
2830 if(bankPtr->tag == 0xEE10){
2831 if(VERBOSE>6) evioout << " SYNC event - f250 scalers found "<< endl;
2832 ParseFA250Scalers(bankPtr, full_events, rocid);
2833 continue;
2834 }
2835
2836 /*
2837 // Check if this bank stores DVertex data
2838 if(bankPtr->tag == 0x0D01){
2839 if(VERBOSE>4) evioout << " DVertex bank tag="<<hex<<bankPtr->tag<<dec<< endl;
2840 ParseDVertexBank(bankPtr, full_events);
2841 continue;
2842 }
2843 */
2844
2845 // The number of events in block is stored in lower 8 bits
2846 // of header word (aka the "num") of Data Bank. This should
2847 // be at least 1.
2848 uint32_t NumEvents = data_bank->num & 0xFF;
2849 if( NumEvents<1 ){
2850 if(VERBOSE>9) evioout << " bank has less than 1 event (Data Bank num or \"M\" = 0) skipping ... " << endl;
2851 continue;
2852 }
2853
2854 // At this point iptr and iend indicate the data that came
2855 // from the ROC itself (all CODA headers have been stripped
2856 // away). Here, we need to decide what type of data this
2857 // bank contains. All JLab modules have a common block
2858 // header format and so are handled in a common way. Other
2859 // modules (e.g. CAEN) will have to appear in their own
2860 // EVIO bank and should be identified by their own det_id
2861 // value in the Data Block Bank.
2862 //
2863 // Current, preliminary thinking includes writing the type
2864 // of data into the 12-bit detector id contained in the
2865 // Data Block Bank of the DAQ group's "Event Building EVIO
2866 // Scheme". (This is the lower 12 bits of the "tag"). We
2867 // use this to decide if it is JLab module data or somehting
2868 // else.
2869 uint32_t det_id = bankPtr->tag & 0x0FFF;
2870 // Call appropriate parsing method
2871 bool bank_parsed = true; // will be set to false if default case is entered
2872 switch(det_id){
2873 case 0:
2874 case 1:
2875 case 3:
2876 case 6: // flash 250 module, MMD 2014/2/4
2877 case 16: // flash 125 module (CDC), DL 2014/6/19
2878 case 26: // F1 TDC module (BCAL), MMD 2014-07-31
2879 ParseJLabModuleData(rocid, iptr, iend, tmp_events);
2880 break;
2881
2882 case 20:
2883 ParseCAEN1190(rocid, iptr, iend, tmp_events);
2884 break;
2885
2886 case 0x55:
2887 ParseModuleConfiguration(rocid, iptr, iend, tmp_events);
2888 break;
2889
2890 case 5:
2891 // Beni's original CDC ROL used for the stand-alone CDC DAQ
2892 // had the following for the TS readout list (used in the TI):
2893 // *dma_dabufp++ = 0xcebaf111;
2894 // *dma_dabufp++ = tsGetIntCount();
2895 // *dma_dabufp++ = 0xdead;
2896 // *dma_dabufp++ = 0xcebaf222;
2897 // We skip this here, but put in the case so that we avoid errors
2898 break;
2899
2900
2901 default:
2902 jerr<<"Unknown module type ("<<det_id<<") encountered for tag="<<bankPtr->tag<<" num="<< (int)bankPtr->num << endl;
2903 bank_parsed = false;
2904 if(VERBOSE>5){
2905 cerr << endl;
2906 cout << "----- First few words to help with debugging -----" << endl;
2907 cout.flush(); cerr.flush();
2908 int i=0;
2909 for(const uint32_t *iiptr = iptr; iiptr<iend; iiptr++, i++){
2910 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<2910<<" "
<< "0x" << hex << *iiptr << dec << endl;
2911 if(i>=8) break;
2912 }
2913
2914 }
2915 }
2916
2917 // Merge this bank's partial events into the full events
2918 if(bank_parsed){
2919 if(VERBOSE>5) evioout << " Merging objects in ParseEVIOEvent" << endl;
2920 MergeObjLists(full_events, tmp_events);
2921 }
2922 }
2923
2924 // The following disabled in preference for keeping the
2925 // run number found by FindRunNumber called from
2926 // GetEvent() 2/15/2016
2927
2928 // // Set the run number for all events
2929 // uint32_t run_number = GetRunNumber(evt);
2930 // list<ObjList*>::iterator evt_iter = full_events.begin();
2931 // for(; evt_iter!=full_events.end(); evt_iter++){
2932 // ObjList *objs = *evt_iter;
2933 // objs->run_number = run_number;
2934 // }
2935
2936 if(VERBOSE>5) evioout << " Leaving ParseEVIOEvent()" << endl;
2937}
2938
2939//----------------
2940// ParseBuiltTriggerBank
2941//----------------
2942void JEventSource_EVIO::ParseBuiltTriggerBank(evioDOMNodeP trigbank, list<ObjList*> &events)
2943{
2944 if(!PARSE_TRIGGER) return;
2945
2946 if(VERBOSE>5) evioout << " Entering ParseBuiltTriggerBank()" << endl;
2947
2948 uint32_t Mevents = 1; // number of events in block (will be overwritten below)
2949 uint32_t Nrocs = (uint32_t)trigbank->num; // number of rocs providing data in this bank
2950 evioDOMNodeP physics_event_bank = trigbank->getParent();
2951 if(physics_event_bank) Mevents = (uint32_t)physics_event_bank->num;
2952
2953 if(VERBOSE>6) evioout << " Mevents=" << Mevents << " Nrocs=" << Nrocs << endl;
2954
2955 // Some values to fill in while parsing the banks that will be used later to create objects
2956 vector<uint64_t> avg_timestamps;
2957 uint32_t run_number = 0;
2958 uint32_t run_type = 0;
2959 uint64_t first_event_num = 1;
2960 vector<uint16_t> event_types;
2961 map<uint32_t, vector<DCODAROCInfo*> > rocinfos; // key=event (from 0 to Mevents-1)
2962 //vector<map<uint32_t, DCODAROCInfo*> > rocinfos; // key=rocid
2963
2964 // Loop over children of built trigger bank
2965 evioDOMNodeListP bankList = trigbank->getChildren();
2966 evioDOMNodeList::iterator iter = bankList->begin();
2967 for(int ibank=1; iter!=bankList->end(); iter++, ibank++){
2968
2969 if(VERBOSE>7) evioout << " Looking for data in child banks ..." << endl;
2970
2971 evioDOMNodeP bankPtr = *iter;
2972
2973 // The "Physics Event's Built Trigger Bank" is a bank of segments that
2974 // may contain banks of 3 data types: uint64_t, uint32_t, and uint16_t
2975 // The uint64_t contains the first event number, average timestamps, and
2976 // run number & types. The uint16_t contains the event type(s). The
2977 // uint32_t contains the optional ROC specific meta data starting with
2978 // the specific timestamp for each event. All of these have some options
2979 // on exactly what info is contained in the bank. The first check here is
2980 // on the data type the bank contains. At most, one of the following pointers
2981 // should be non-zero.
2982 vector<uint64_t> *vec64 = bankPtr->getVector<uint64_t>();
2983 vector<uint32_t> *vec32 = bankPtr->getVector<uint32_t>();
2984 vector<uint16_t> *vec16 = bankPtr->getVector<uint16_t>();
2985
2986 // unit64_t = common data (1st part)
2987 if(vec64){
2988
2989 if(VERBOSE>9) evioout << " found uint64_t data" << endl;
2990
2991 // In addition to the first event number (1st word) there are three
2992 // additional pieces of information that may be present:
2993 // t = average timestamp
2994 // r = run number and type
2995 // d = run specific data
2996 //
2997 // The last one ("d") comes in the form of multiple uint32_t banks
2998 // so is not included in vec64. The other two have their presence
2999 // signaled by bit 0(=t) and bit 1(=r) in the trigbank tag. (We can
3000 // also deduce this from the bank length.)
3001
3002 if(vec64->size() == 0) continue; // need debug message here!
3003
3004 first_event_num = (*vec64)[0];
3005
3006 // Hi and lo 32bit words in 64bit numbers seem to be
3007 // switched for events read from ET, but not read from
3008 // file. Not sure if this is in the swapping routine
3009 if(source_type==kETSource) first_event_num = (first_event_num>>32) | (first_event_num<<32);
3010
3011 uint32_t Ntimestamps = vec64->size()-1;
3012 if(Ntimestamps==0) continue; // no more words of interest
3013 if(trigbank->tag & 0x2) Ntimestamps--; // subtract 1 for run number/type word if present
3014 for(uint32_t i=0; i<Ntimestamps; i++) avg_timestamps.push_back((*vec64)[i+1]);
3015
3016 // run number and run type
3017 if(trigbank->tag & 0x02){
3018 run_number = (*vec64)[vec64->size()-1] >> 32;
3019 run_type = (*vec64)[vec64->size()-1] & 0xFFFFFFFF;
3020 }
3021 }
3022
3023 // uint16_t = common data (2nd part)
3024 if(vec16){
3025
3026 if(VERBOSE>9) evioout << " found uint16_t data" << endl;
3027
3028 for(uint32_t i=0; i<Mevents; i++){
3029 if(i>=vec16->size()) break;
3030 event_types.push_back((*vec16)[i]);
3031 }
3032 }
3033
3034 // uint32_t = inidivdual ROC timestamps and misc. roc-specfic data
3035 if(vec32){
3036
3037 if(VERBOSE>9) evioout << " found uint32_t data" << endl;
3038
3039 // Get pointer to DCODAROCInfo object for this rocid/event, instantiating it if necessary
3040 uint32_t rocid = (uint32_t)bankPtr->tag;
3041 uint32_t Nwords_per_event = vec32->size()/Mevents;
3042 if(vec32->size() != Mevents*Nwords_per_event){
3043 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<3043<<" "
<< "Number of ROC data words in Trigger Bank inconsistent with header" << endl;
3044 exit(-1);
3045 }
3046
3047 uint32_t *iptr = &(*vec32)[0];
3048 for(uint32_t ievent=0; ievent<Mevents; ievent++){
3049
3050 DCODAROCInfo *codarocinfo = new DCODAROCInfo;
3051 codarocinfo->rocid = rocid;
3052
3053 uint64_t ts_low = *iptr++;
3054 uint64_t ts_high = *iptr++;
3055 codarocinfo->timestamp = (ts_high<<32) + ts_low;
3056 for(uint32_t i=2; i<Nwords_per_event; i++) codarocinfo->misc.push_back(*iptr++);
3057
3058 if(VERBOSE>7) evioout << " Adding DCODAROCInfo for rocid="<<rocid<< " with timestamp " << codarocinfo->timestamp << endl;
3059 rocinfos[ievent].push_back(codarocinfo);
3060 }
3061 }
3062 }
3063
3064 // Check that we have agreement on the number of events this data represents
3065 bool Nevent_mismatch = false;
3066 if(!avg_timestamps.empty()) Nevent_mismatch |= (avg_timestamps.size() != Mevents);
3067 if(!event_types.empty() ) Nevent_mismatch |= (event_types.size() != Mevents);
3068 if(!rocinfos.empty() ) Nevent_mismatch |= (rocinfos.size() != Mevents);
3069 if(Nevent_mismatch){
3070 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<3070<<" "
<<"Mismatch in number of events in Trigger Bank!"<<endl;
3071 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<3071<<" "
<<" Mevents="<<Mevents<<endl;
3072 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<3072<<" "
<<" avg_timestamps.size()="<<avg_timestamps.size()<<endl;
3073 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<3073<<" "
<<" event_types.size()="<<event_types.size()<<endl;
3074 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<3074<<" "
<<" rocinfos.size()="<<rocinfos.size()<<endl;
3075 exit(-1);
3076 }
3077
3078 // Copy all objects into events
3079 for(uint32_t i=0; i<Mevents; i++){
3080 while(events.size()<=i){
3081 if(!ENABLE_DISENTANGLING && !events.empty()) break;
3082 events.push_back(new ObjList);
3083 }
3084 ObjList *objs = events.back();
3085
3086 DCODAEventInfo *codaeventinfo = new DCODAEventInfo;
3087 codaeventinfo->run_number = run_number;
3088 codaeventinfo->run_type = run_type;
3089 codaeventinfo->event_number = first_event_num + i;
3090 codaeventinfo->event_type = event_types.empty() ? 0:event_types[i];
3091 codaeventinfo->avg_timestamp = avg_timestamps.empty() ? 0:avg_timestamps[i];
3092 objs->misc_objs.push_back(codaeventinfo);
3093 objs->event_number = codaeventinfo->event_number;
3094
3095 vector<DCODAROCInfo*> &codarocinfos = rocinfos[i];
3096 for(uint32_t i=0; i<codarocinfos.size(); i++) objs->misc_objs.push_back(codarocinfos[i]);
3097 }
3098
3099 if(VERBOSE>6) evioout << " Found "<<events.size()<<" events in Built Trigger Bank"<< endl;
3100 if(VERBOSE>5) evioout << " Leaving ParseBuiltTriggerBank()" << endl;
3101}
3102
3103//----------------
3104// ParseModuleConfiguration
3105//----------------
3106void JEventSource_EVIO::ParseModuleConfiguration(int32_t rocid, const uint32_t* &iptr, const uint32_t *iend, list<ObjList*> &events)
3107{
3108 if(!PARSE_CONFIG){ iptr = iend; return; }
3109
3110 if(VERBOSE>5) evioout << " Entering ParseModuleConfiguration() (events.size()="<<events.size()<<")" << endl;
3111
3112 /// Parse a bank of module configuration data. These are configuration values
3113 /// programmed into the module at the beginning of the run that may be needed
3114 /// in the offline. For example, the number of samples to sum in a FADC pulse
3115 /// integral.
3116 ///
3117 /// The bank has one or more sections, each describing parameters applicable
3118 /// to a number of modules as indicated by a 24bit slot mask.
3119 ///
3120 /// This bank should appear only once per DAQ event which, if in multi-event
3121 /// block mode, may have multiple L1 events. The parameters here will apply
3122 /// to all L1 events in the block. This method will put the config objects
3123 /// in the first event of "events", creating it if needed. The config objects
3124 /// are duplicated for all other events in the block later, after all event
3125 /// parsing is finished and the total number of events is known.
3126 /// (See the end of ParseEvents() .)
3127
3128 while(iptr < iend){
3129 uint32_t slot_mask = (*iptr) & 0xFFFFFF;
3130 uint32_t Nvals = ((*iptr) >> 24) & 0xFF;
3131 iptr++;
3132
3133 Df250Config *f250config = NULL__null;
3134 Df125Config *f125config = NULL__null;
3135 DF1TDCConfig *f1tdcconfig = NULL__null;
3136 DCAEN1290TDCConfig *caen1290tdcconfig = NULL__null;
3137
3138 // Loop over all parameters in this section
3139 for(uint32_t i=0; i< Nvals; i++){
3140 if( iptr >= iend){
3141 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<3141<<" "
<< "DAQ Configuration bank corrupt! slot_mask=0x" << hex << slot_mask << dec << " Nvals="<< Nvals << endl;
3142 exit(-1);
3143 }
3144
3145 daq_param_type ptype = (daq_param_type)((*iptr)>>16);
3146 uint16_t val = (*iptr) & 0xFFFF;
3147
3148 if(VERBOSE>6) evioout << " DAQ parameter of type: 0x" << hex << ptype << dec << " found with value: " << val << endl;
3149
3150 // Create config object of correct type if needed and copy
3151 // parameter value into it.
3152 switch(ptype>>8){
3153
3154 // f250
3155 case 0x05:
3156 if( !f250config ) f250config = new Df250Config(rocid, slot_mask);
3157 switch(ptype){
3158 case kPARAM250_NSA : f250config->NSA = val; break;
3159 case kPARAM250_NSB : f250config->NSB = val; break;
3160 case kPARAM250_NSA_NSB : f250config->NSA_NSB = val; break;
3161 case kPARAM250_NPED : f250config->NPED = val; break;
3162 default: _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<3162<<" "
<< "UNKNOWN DAQ Config Parameter type: 0x" << hex << ptype << dec << endl;
3163 }
3164 break;
3165
3166 // f125
3167 case 0x0F:
3168 if( !f125config ) f125config = new Df125Config(rocid, slot_mask);
3169 switch(ptype){
3170 case kPARAM125_NSA : f125config->NSA = val; break;
3171 case kPARAM125_NSB : f125config->NSB = val; break;
3172 case kPARAM125_NSA_NSB : f125config->NSA_NSB = val; break;
3173 case kPARAM125_NPED : f125config->NPED = val; break;
3174 case kPARAM125_WINWIDTH : f125config->WINWIDTH = val; break;
3175 case kPARAM125_PL : f125config->PL = val; break;
3176 case kPARAM125_NW : f125config->NW = val; break;
3177 case kPARAM125_NPK : f125config->NPK = val; break;
3178 case kPARAM125_P1 : f125config->P1 = val; break;
3179 case kPARAM125_P2 : f125config->P2 = val; break;
3180 case kPARAM125_PG : f125config->PG = val; break;
3181 case kPARAM125_IE : f125config->IE = val; break;
3182 case kPARAM125_H : f125config->H = val; break;
3183 case kPARAM125_TH : f125config->TH = val; break;
3184 case kPARAM125_TL : f125config->TL = val; break;
3185 case kPARAM125_IBIT : f125config->IBIT = val; break;
3186 case kPARAM125_ABIT : f125config->ABIT = val; break;
3187 case kPARAM125_PBIT : f125config->PBIT = val; break;
3188 default: _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<3188<<" "
<< "UNKNOWN DAQ Config Parameter type: 0x" << hex << ptype << dec << endl;
3189 }
3190 break;
3191
3192 // F1TDC
3193 case 0x06:
3194 if( !f1tdcconfig ) f1tdcconfig = new DF1TDCConfig(rocid, slot_mask);
3195 switch(ptype){
3196 case kPARAMF1_REFCNT : f1tdcconfig->REFCNT = val; break;
3197 case kPARAMF1_TRIGWIN : f1tdcconfig->TRIGWIN = val; break;
3198 case kPARAMF1_TRIGLAT : f1tdcconfig->TRIGLAT = val; break;
3199 case kPARAMF1_HSDIV : f1tdcconfig->HSDIV = val; break;
3200 case kPARAMF1_BINSIZE : f1tdcconfig->BINSIZE = val; break;
3201 case kPARAMF1_REFCLKDIV : f1tdcconfig->REFCLKDIV = val; break;
3202 default: _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<3202<<" "
<< "UNKNOWN DAQ Config Parameter type: 0x" << hex << ptype << dec << endl;
3203 }
3204 break;
3205
3206 // caen1290
3207 case 0x10:
3208 if( !caen1290tdcconfig ) caen1290tdcconfig = new DCAEN1290TDCConfig(rocid, slot_mask);
3209 switch(ptype){
3210 case kPARAMCAEN1290_WINWIDTH : caen1290tdcconfig->WINWIDTH = val; break;
3211 case kPARAMCAEN1290_WINOFFSET : caen1290tdcconfig->WINOFFSET = val; break;
3212 default: _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<3212<<" "
<< "UNKNOWN DAQ Config Parameter type: 0x" << hex << ptype << dec << endl;
3213 }
3214 break;
3215
3216 default:
3217 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<3217<<" "
<< "Unknown module type: 0x" << hex << (ptype>>8) << endl;
3218 exit(-1);
3219 }
3220
3221#if 0
3222 // Create config object of correct type if needed. (Only one type
3223 // should be created per section!)
3224 switch(ptype>>8){
3225 case 0x05: if(!f250config ) f250config = new Df250Config(rocid, slot_mask); break;
3226 case 0x0F: if(!f125config ) f125config = new Df125Config(rocid, slot_mask); break;
3227 case 0x06: if(!f1tdcconfig ) f1tdcconfig = new DF1TDCConfig(rocid, slot_mask); break;
3228 case 0x10: if(!caen1290tdcconfig) caen1290tdcconfig = new DCAEN1290TDCConfig(rocid, slot_mask); break;
3229 default:
3230 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<3230<<" "
<< "Unknown module type: 0x" << hex << (ptype>>8) << endl;
3231 exit(-1);
3232 }
3233
3234 // Copy parameter into config. object
3235 switch(ptype){
3236 case kPARAM250_NSA : f250config->NSA = val; break;
3237 case kPARAM250_NSB : f250config->NSB = val; break;
3238 case kPARAM250_NSA_NSB : f250config->NSA_NSB = val; break;
3239 case kPARAM250_NPED : f250config->NPED = val; break;
3240
3241 case kPARAM125_NSA : f125config->NSA = val; break;
3242 case kPARAM125_NSB : f125config->NSB = val; break;
3243 case kPARAM125_NSA_NSB : f125config->NSA_NSB = val; break;
3244 case kPARAM125_NPED : f125config->NPED = val; break;
3245 case kPARAM125_WINWIDTH : f125config->WINWIDTH = val; break;
3246 case kPARAM125_PL : f125config->PL = val; break;
3247 case kPARAM125_NW : f125config->NW = val; break;
3248 case kPARAM125_NPK : f125config->NPK = val; break;
3249 case kPARAM125_P1 : f125config->P1 = val; break;
3250 case kPARAM125_P2 : f125config->P2 = val; break;
3251 case kPARAM125_PG : f125config->PG = val; break;
3252 case kPARAM125_IE : f125config->IE = val; break;
3253 case kPARAM125_H : f125config->H = val; break;
3254 case kPARAM125_TH : f125config->TH = val; break;
3255 case kPARAM125_TL : f125config->TL = val; break;
3256 case kPARAM125_IBIT : f125config->IBIT = val; break;
3257 case kPARAM125_ABIT : f125config->ABIT = val; break;
3258 case kPARAM125_PBIT : f125config->PBIT = val; break;
3259
3260 case kPARAMF1_REFCNT : f1tdcconfig->REFCNT = val; break;
3261 case kPARAMF1_TRIGWIN : f1tdcconfig->TRIGWIN = val; break;
3262 case kPARAMF1_TRIGLAT : f1tdcconfig->TRIGLAT = val; break;
3263 case kPARAMF1_HSDIV : f1tdcconfig->HSDIV = val; break;
3264 case kPARAMF1_BINSIZE : f1tdcconfig->BINSIZE = val; break;
3265 case kPARAMF1_REFCLKDIV : f1tdcconfig->REFCLKDIV = val; break;
3266
3267 case kPARAMCAEN1290_WINWIDTH : caen1290tdcconfig->WINWIDTH = val; break;
3268 case kPARAMCAEN1290_WINOFFSET : caen1290tdcconfig->WINOFFSET = val; break;
3269
3270 default:
3271 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<3271<<" "
<< "UNKNOWN DAQ Config Parameter type: 0x" << hex << ptype << dec << endl;
3272 }
3273#endif
3274
3275 iptr++;
3276 }
3277
3278 // If we get here it means we didn't exit in the switch(ptype>>16) statement above
3279 // so there is at least one DDAQConfig object we need to store. Get pointer to
3280 // first event's ObjList, creating it if needed.
3281 if(events.empty()) events.push_back(new ObjList());
3282 ObjList *objs = *(events.begin());
3283
3284 if(f250config ) objs->config_objs.push_back(f250config );
3285 if(f125config ) objs->config_objs.push_back(f125config );
3286 if(f1tdcconfig ) objs->config_objs.push_back(f1tdcconfig );
3287 if(caen1290tdcconfig) objs->config_objs.push_back(caen1290tdcconfig);
3288 }
3289
3290 if(VERBOSE>5) evioout << " Leaving ParseModuleConfiguration()" << endl;
3291}
3292
3293//----------------
3294// ParseEventTag
3295//----------------
3296void JEventSource_EVIO::ParseEventTag(const uint32_t* &iptr, const uint32_t *iend, list<ObjList*> &events)
3297{
3298 if(!PARSE_EVENTTAG){ iptr = iend; return; }
3299
3300 if(VERBOSE>5) evioout << " Entering ParseEventTag() (events.size()="<<events.size()<<")" << endl;
3301
3302 // Make sure there is one event in the event container
3303 // and get pointer to it.
3304 if(events.empty()) events.push_back(new ObjList());
3305 ObjList *objs = *(events.begin());
3306
3307
3308 DEventTag *etag = new DEventTag;
3309
3310 // event_status
3311 uint64_t lo = *iptr++;
3312 uint64_t hi = *iptr++;
3313 etag->event_status = (hi<<32) + lo;
3314
3315 // L3_status
3316 lo = *iptr++;
3317 hi = *iptr++;
3318 etag->L3_status = (hi<<32) + lo;
3319
3320 // L3_decision
3321 etag->L3_decision = (DL3Trigger::L3_decision_t)*iptr++;
3322
3323 // L3_algorithm
3324 etag->L3_algorithm = *iptr++;
3325
3326 objs->misc_objs.push_back(etag);
3327
3328
3329 if(VERBOSE>5) evioout << " Leaving ParseEventTag()" << endl;
3330}
3331
3332//----------------
3333// ParseJLabModuleData
3334//----------------
3335void JEventSource_EVIO::ParseJLabModuleData(int32_t rocid, const uint32_t* &iptr, const uint32_t *iend, list<ObjList*> &events)
3336{
3337 if(VERBOSE>5) evioout << " Entering ParseJLabModuleData()" << endl;
3338
3339 /// Parse a bank of data coming from one or more JLab modules.
3340 /// The data are assumed to follow the standard JLab format for
3341 /// block headers. If multiple modules are read out in a single
3342 /// chain block transfer, then the data will all be placed in
3343 /// a single EVIO bank and this will loop over the modules.
3344 while(iptr < iend){
3345
3346 if(VERBOSE>9) evioout << "Parsing word: " << hex << *iptr << dec << endl;
3347
3348 // This was observed in some CDC data. Not sure where it came from ...
3349 if(*iptr == 0xF800FAFA){
3350 if(VERBOSE>9) evioout << " 0xf800fafa is a known extra word. Skipping it ..." << endl;
3351 iptr++;
3352 continue;
3353 }
3354
3355 // Get module type from next word (bits 18-21)
3356 uint32_t mod_id = ((*iptr) >> 18) & 0x000F;
3357
3358 // The enum defined in DModuleType.h MUST be kept in alignment
3359 // with the DAQ group's definitions for modules types!
3360 MODULE_TYPE type = (MODULE_TYPE)mod_id;
3361 if(VERBOSE>5) evioout << " Encountered module type: " << type << " (=" << DModuleType::GetModule(type).GetName() << ")" << endl;
3362
3363 if(modtype_translate.find(type) != modtype_translate.end()){
3364 type = modtype_translate[type];
3365 if(VERBOSE>5) evioout << " switched module type to: " << type << " (=" << DModuleType::GetModule(type).GetName() << ")" << endl;
3366 }
3367
3368 // Parse buffer depending on module type
3369 // (Note that each of the ParseXXX routines called below will
3370 // update the "iptr" variable to point to the next word
3371 // after the block it parsed.)
3372 list<ObjList*> tmp_events;
3373 const uint32_t *istart=iptr; // just for UNKNOWN case below
3374 bool module_parsed = true;
3375 switch(type){
3376 case DModuleType::FADC250:
3377 Parsef250Bank(rocid, iptr, iend, tmp_events);
3378 break;
3379
3380 case DModuleType::FADC125:
3381 Parsef125Bank(rocid, iptr, iend, tmp_events);
3382 break;
3383
3384 case DModuleType::F1TDC32:
3385 ParseF1TDCBank(rocid, iptr, iend, tmp_events);
3386 break;
3387
3388 case DModuleType::F1TDC48:
3389 ParseF1TDCBank(rocid, iptr, iend, tmp_events);
3390 break;
3391
3392 case DModuleType::JLAB_TS:
3393 //ParseTSBank(rocid, iptr, iend, tmp_events); // This is not used
3394 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<3394<<" "
<< "What the ? ! This data type isn't supposed to be here!!" << endl;
3395 break;
3396
3397 case DModuleType::TID:
3398 ParseTIBank(rocid, iptr, iend, tmp_events);
3399 break;
3400
3401 case DModuleType::UNKNOWN:
3402 default:
3403 jerr<<"Unknown module type ("<<mod_id<<") iptr=0x" << hex << iptr << dec << endl;
3404
3405 while(iptr<iend && ((*iptr) & 0xF8000000) != 0x88000000) iptr++; // Skip to JLab block trailer
3406 iptr++; // advance past JLab block trailer
3407 while(iptr<iend && *iptr == 0xF8000000) iptr++; // skip filler words after block trailer
3408 module_parsed = false;
3409 jerr<<"...skipping to 0x" << hex << iptr << dec << " (discarding " << (((uint64_t)iptr-(uint64_t)istart)/4) << " words)" << endl;
3410 break;
3411 }
3412
3413 if(VERBOSE>9) evioout << "Finished parsing (last word: " << hex << iptr[-1] << dec << ")" << endl;
3414
3415 if(module_parsed){
3416 if(VERBOSE>5) evioout << " Merging objects in ParseJLabModuleData" << endl;
3417 MergeObjLists(events, tmp_events);
3418 }
3419 }
3420
3421 if(VERBOSE>5) evioout << " Leaving ParseJLabModuleData()" << endl;
3422}
3423
3424//----------------
3425// Parsef250Bank
3426//----------------
3427void JEventSource_EVIO::Parsef250Bank(int32_t rocid, const uint32_t* &iptr, const uint32_t *iend, list<ObjList*> &events)
3428{
3429 /// Parse data from a single FADC250 module.
3430
3431 if(!PARSE_F250){ iptr = iend; return; }
3432
3433 // This will get updated to point to a newly allocated object when an
3434 // event header is encountered. The existing value (if non-NULL) is
3435 // added to the events queue first though so all events are kept.
3436 ObjList *objs = NULL__null;
3437
3438 // From the Block Header
3439 uint32_t slot=0;
3440 //uint32_t Nblock_events;
3441 //uint32_t iblock;
3442
3443 // From the Block Trailer
3444 //uint32_t slot_trailer;
3445 //uint32_t Nwords_in_block;
3446
3447 // From Event header
3448 //uint32_t slot_event_header;
3449 uint32_t itrigger = -1;
3450 uint32_t last_itrigger = -2;
3451
3452 // Loop over data words
3453 for(; iptr<iend; iptr++){
3454
3455 // Skip all non-data-type-defining words at this
3456 // level. When we do encounter one, the appropriate
3457 // case block below should handle parsing all of
3458 // the data continuation words and advance the iptr.
3459 if(((*iptr>>31) & 0x1) == 0)continue;
3460
3461 // Variables used inside of switch, but cannot be declared inside
3462 uint64_t t = 0L;
3463 uint32_t channel = 0;
3464 uint32_t sum = 0;
3465 uint32_t pulse_number = 0;
3466 uint32_t quality_factor = 0;
3467 uint32_t pulse_time = 0;
3468 uint32_t pedestal = 0;
3469 uint32_t pulse_peak = 0;
3470 uint32_t nsamples_integral = 0;
3471 uint32_t nsamples_pedestal = 0;
3472 bool overflow = false;
3473
3474 bool found_block_trailer = false;
3475 uint32_t data_type = (*iptr>>27) & 0x0F;
3476 switch(data_type){
3477 case 0: // Block Header
3478 slot = (*iptr>>22) & 0x1F;
3479 if(VERBOSE>7) evioout << " FADC250 Block Header: slot="<<slot<<" ("<<hex<<*iptr<<dec<<")"<<endl;
3480 //iblock= (*iptr>>8) & 0x03FF;
3481 //Nblock_events= (*iptr>>0) & 0xFF;
3482 break;
3483 case 1: // Block Trailer
3484 //slot_trailer = (*iptr>>22) & 0x1F;
3485 //Nwords_in_block = (*iptr>>0) & 0x3FFFFF;
3486 if(VERBOSE>7) evioout << " FADC250 Block Trailer"<<" ("<<hex<<*iptr<<dec<<")"<<endl;
3487 found_block_trailer = true;
3488 break;
3489 case 2: // Event Header
3490 //slot_event_header = (*iptr>>22) & 0x1F;
3491 itrigger = (*iptr>>0) & 0x3FFFFF;
3492 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;
3493 if( (itrigger!=last_itrigger) || (objs==NULL__null) ){
3494 if(ENABLE_DISENTANGLING){
3495 if(objs){
3496 events.push_back(objs);
3497 objs = NULL__null;
3498 }
3499 }
3500 if(!objs) objs = new ObjList;
3501 last_itrigger = itrigger;
3502 }
3503 break;
3504 case 3: // Trigger Time
3505 t = ((*iptr)&0xFFFFFF)<<0;
3506 if(VERBOSE>7) evioout << " FADC250 Trigger Time: t="<<t<<" ("<<hex<<*iptr<<dec<<")"<<endl;
3507 iptr++;
3508 if(((*iptr>>31) & 0x1) == 0){
3509 t += ((*iptr)&0xFFFFFF)<<24; // from word on the street: second trigger time word is optional!!??
3510 if(VERBOSE>7) evioout << " Trigger time high word="<<(((*iptr)&0xFFFFFF))<<" ("<<hex<<*iptr<<dec<<")"<<endl;
3511 }else{
3512 iptr--;
3513 }
3514 if(objs) objs->hit_objs.push_back(new Df250TriggerTime(rocid, slot, itrigger, t));
3515 break;
3516 case 4: // Window Raw Data
3517 // iptr passed by reference and so will be updated automatically
3518 if(VERBOSE>7) evioout << " FADC250 Window Raw Data"<<" ("<<hex<<*iptr<<dec<<")"<<endl;
3519 MakeDf250WindowRawData(objs, rocid, slot, itrigger, iptr);
3520 break;
3521 case 5: // Window Sum
3522 channel = (*iptr>>23) & 0x0F;
3523 sum = (*iptr>>0) & 0x3FFFFF;
3524 overflow = (*iptr>>22) & 0x1;
3525 if(VERBOSE>7) evioout << " FADC250 Window Sum"<<" ("<<hex<<*iptr<<dec<<")"<<endl;
3526 if(objs) objs->hit_objs.push_back(new Df250WindowSum(rocid, slot, channel, itrigger, sum, overflow));
3527 break;
3528 case 6: // Pulse Raw Data
3529 // iptr passed by reference and so will be updated automatically
3530 if(VERBOSE>7) evioout << " FADC250 Pulse Raw Data"<<" ("<<hex<<*iptr<<dec<<")"<<endl;
3531 MakeDf250PulseRawData(objs, rocid, slot, itrigger, iptr);
3532 break;
3533 case 7: // Pulse Integral
3534 channel = (*iptr>>23) & 0x0F;
3535 pulse_number = (*iptr>>21) & 0x03;
3536 quality_factor = (*iptr>>19) & 0x03;
3537 sum = (*iptr>>0) & 0x7FFFF;
3538 nsamples_integral = 0; // must be overwritten later in GetObjects with value from Df125Config value
3539 nsamples_pedestal = 1; // The firmware returns an already divided pedestal
3540 pedestal = 0; // This will be replaced by the one from Df250PulsePedestal in GetObjects
3541 if(VERBOSE>7) evioout << " FADC250 Pulse Integral: chan="<<channel<<" pulse_number="<<pulse_number<<" sum="<<sum<<" ("<<hex<<*iptr<<dec<<")"<<endl;
3542 if( (objs!=NULL__null) && (pulse_number<F250PULSE_NUMBER_FILTER) ) {
3543 objs->hit_objs.push_back(new Df250PulseIntegral(rocid, slot, channel, itrigger, pulse_number,
3544 quality_factor, sum, pedestal, nsamples_integral, nsamples_pedestal));
3545 }
3546 break;
3547 case 8: // Pulse Time
3548 channel = (*iptr>>23) & 0x0F;
3549 pulse_number = (*iptr>>21) & 0x03;
3550 quality_factor = (*iptr>>19) & 0x03;
3551 pulse_time = (*iptr>>0) & 0x7FFFF;
3552 if(VERBOSE>7) evioout << " FADC250 Pulse Time: chan="<<channel<<" pulse_number="<<pulse_number<<" pulse_time="<<pulse_time<<" ("<<hex<<*iptr<<dec<<")"<<endl;
3553 if( (objs!=NULL__null) && (pulse_number<F250PULSE_NUMBER_FILTER) ) {
3554 objs->hit_objs.push_back(new Df250PulseTime(rocid, slot, channel, itrigger, pulse_number, quality_factor, pulse_time));
3555 }
3556 break;
3557 case 9: // Streaming Raw Data
3558 // This is marked "reserved for future implementation" in the current manual (v2).
3559 // As such, we don't try handling it here just yet.
3560 if(VERBOSE>7) evioout << " FADC250 Streaming Raw Data (unsupported)"<<" ("<<hex<<*iptr<<dec<<")"<<endl;
3561 break;
3562 case 10: // Pulse Pedestal
3563 channel = (*iptr>>23) & 0x0F;
3564 pulse_number = (*iptr>>21) & 0x03;
3565 pedestal = (*iptr>>12) & 0x1FF;
3566 pulse_peak = (*iptr>>0) & 0xFFF;
3567 if(VERBOSE>7) evioout << " FADC250 Pulse Pedestal chan="<<channel<<" pulse_number="<<pulse_number<<" pedestal="<<pedestal<<" pulse_peak="<<pulse_peak<<" ("<<hex<<*iptr<<dec<<")"<<endl;
3568 if( (objs!=NULL__null) && (pulse_number<F250PULSE_NUMBER_FILTER) ) {
3569 objs->hit_objs.push_back(new Df250PulsePedestal(rocid, slot, channel, itrigger, pulse_number, pedestal, pulse_peak));
3570 }
3571 break;
3572 case 13: // Event Trailer
3573 // This is marked "suppressed for normal readout – debug mode only" in the
3574 // current manual (v2). It does not contain any data so the most we could do here
3575 // is return early. I'm hesitant to do that though since it would mean
3576 // different behavior for debug mode data as regular data.
3577 case 14: // Data not valid (empty module)
3578 case 15: // Filler (non-data) word
3579 if(VERBOSE>7) evioout << " FADC250 Event Trailer, Data not Valid, or Filler word ("<<data_type<<")"<<" ("<<hex<<*iptr<<dec<<")"<<endl;
3580 break;
3581 }
3582
3583 // Once we find a block trailer, assume that is it for this module.
3584 if(found_block_trailer){
3585 iptr++; // iptr is still pointing to block trailer. Jump to next word.
3586 break;
3587 }
3588 }
3589
3590 // Chop off filler words
3591 for(; iptr<iend; iptr++){
3592 if(((*iptr)&0xf8000000) != 0xf8000000) break;
3593 }
3594
3595 // Add last event in block to list
3596 if(objs)events.push_back(objs);
3597
3598 // Here, we make object associations to link PulseIntegral, PulseTime, PulseRawData, etc
3599 // objects to each other so it is easier to get to these downstream without having to
3600 // make nested loops. This is the most efficient place to do it since the ObjList objects
3601 // in "event" contain only the objects from this EVIO block (i.e. at most one crate's
3602 // worth.)
3603 list<ObjList*>::iterator iter = events.begin();
3604 for(; iter!=events.end(); iter++){
3605
3606 // Sort list of objects into type-specific lists
3607 vector<DDAQAddress*> &hit_objs = (*iter)->hit_objs;
3608 vector<Df250TriggerTime*> vtrigt;
3609 vector<Df250WindowRawData*> vwrd;
3610 vector<Df250WindowSum*> vws;
3611 vector<Df250PulseRawData*> vprd;
3612 vector<Df250PulseIntegral*> vpi;
3613 vector<Df250PulseTime*> vpt;
3614 vector<Df250PulsePedestal*> vpp;
3615 for(unsigned int i=0; i<hit_objs.size(); i++){
3616 AddIfAppropriate(hit_objs[i], vtrigt);
3617 AddIfAppropriate(hit_objs[i], vwrd);
3618 AddIfAppropriate(hit_objs[i], vws);
3619 AddIfAppropriate(hit_objs[i], vprd);
3620 AddIfAppropriate(hit_objs[i], vpi);
3621 AddIfAppropriate(hit_objs[i], vpt);
3622 AddIfAppropriate(hit_objs[i], vpp);
3623 }
3624
3625 // Connect Df250PulseIntegral, Df250PulseTime, and
3626 // Df250PulsePedestal with Df250PulseRawData
3627 // (n.b. the associations between pi, pt, and pp are
3628 // done in GetObjects where emulated objects are
3629 // also available.)
3630 LinkAssociationsWithPulseNumber(vprd, vpi);
3631 LinkAssociationsWithPulseNumber(vprd, vpt);
3632 LinkAssociationsWithPulseNumber(vprd, vpp);
3633
3634 // Connect Df250WindowSum and Df250WindowRawData
3635 LinkAssociations(vwrd, vws);
3636
3637 // Connect Df250TriggerTime to everything
3638 LinkAssociationsModuleOnly(vtrigt, vwrd);
3639 LinkAssociationsModuleOnly(vtrigt, vws);
3640 LinkAssociationsModuleOnly(vtrigt, vprd);
3641 LinkAssociationsModuleOnly(vtrigt, vpi);
3642 LinkAssociationsModuleOnly(vtrigt, vpt);
3643 LinkAssociationsModuleOnly(vtrigt, vpp);
3644 }
3645}
3646
3647//----------------
3648// MakeDf250WindowRawData
3649//----------------
3650void JEventSource_EVIO::MakeDf250WindowRawData(ObjList *objs, uint32_t rocid, uint32_t slot, uint32_t itrigger, const uint32_t* &iptr)
3651{
3652 uint32_t channel = (*iptr>>23) & 0x0F;
3653 uint32_t window_width = (*iptr>>0) & 0x0FFF;
3654
3655 Df250WindowRawData *wrd = new Df250WindowRawData(rocid, slot, channel, itrigger);
3656
3657 for(uint32_t isample=0; isample<window_width; isample +=2){
3658
3659 // Advance to next word
3660 iptr++;
3661
3662 // Make sure this is a data continuation word, if not, stop here
3663 if(((*iptr>>31) & 0x1) != 0x0){
3664 iptr--; // calling method expects us to point to last word in block
3665 break;
3666 }
3667
3668 bool invalid_1 = (*iptr>>29) & 0x1;
3669 bool invalid_2 = (*iptr>>13) & 0x1;
3670 uint16_t sample_1 = 0;
3671 uint16_t sample_2 = 0;
3672 if(!invalid_1)sample_1 = (*iptr>>16) & 0x1FFF;
3673 if(!invalid_2)sample_2 = (*iptr>>0) & 0x1FFF;
3674
3675 // Sample 1
3676 wrd->samples.push_back(sample_1);
3677 wrd->invalid_samples |= invalid_1;
3678 wrd->overflow |= (sample_1>>12) & 0x1;
3679
3680 if((isample+2) == window_width && invalid_2)break; // skip last sample if flagged as invalid
3681
3682 // Sample 2
3683 wrd->samples.push_back(sample_2);
3684 wrd->invalid_samples |= invalid_2;
3685 wrd->overflow |= (sample_2>>12) & 0x1;
3686 }
3687
3688 // Due to how the calling function works, the value of "objs" passed to us may be NULL.
3689 // This will happen if a Window Raw Data block is encountered before an event header.
3690 // For these cases, we still want to try parsing the data so that the iptr is updated
3691 // but don't have an event to assign it to. If "objs" is non-NULL, add this object to
3692 // the list. Otherwise, delete it now.
3693 if(objs){
3694 objs->hit_objs.push_back(wrd);
3695 }else{
3696 delete wrd;
3697 }
3698}
3699
3700//----------------
3701// MakeDf250PulseRawData
3702//----------------
3703void JEventSource_EVIO::MakeDf250PulseRawData(ObjList *objs, uint32_t rocid, uint32_t slot, uint32_t itrigger, const uint32_t* &iptr)
3704{
3705 const uint32_t *istart = iptr;
3706 uint32_t channel = (*iptr>>23) & 0x0F;
3707 uint32_t pulse_number = (*iptr>>21) & 0x0003;
3708 uint32_t first_sample_number = (*iptr>>0) & 0x03FF;
3709
3710 if(VERBOSE>9) evioout << " DF250PulseRawData: iptr=0x" << hex << iptr << dec << " channel=" << channel << " pulse_number=" << pulse_number << " first_sample=" << first_sample_number << endl;
3711
3712 Df250PulseRawData *prd = new Df250PulseRawData(rocid, slot, channel, itrigger, pulse_number, first_sample_number);
3713
3714 // This loop needs to break when it hits a non-continuation word
3715 for(uint32_t isample=0; isample<1000; isample +=2){
3716
3717 // Advance to next word
3718 iptr++;
3719
3720 // Make sure this is a data continuation word, if not, stop here
3721 if(((*iptr>>31) & 0x1) != 0x0)break;
3722
3723 bool invalid_1 = (*iptr>>29) & 0x1;
3724 bool invalid_2 = (*iptr>>13) & 0x1;
3725 uint16_t sample_1 = 0;
3726 uint16_t sample_2 = 0;
3727 if(!invalid_1)sample_1 = (*iptr>>16) & 0x1FFF;
3728 if(!invalid_2)sample_2 = (*iptr>>0) & 0x1FFF;
3729
3730 // Sample 1
3731 prd->samples.push_back(sample_1);
3732 prd->invalid_samples |= invalid_1;
3733 prd->overflow |= (sample_1>>12) & 0x1;
3734
3735 bool last_word = (iptr[1]>>31) & 0x1;
3736 if(last_word && invalid_2)break; // skip last sample if flagged as invalid
3737
3738 // Sample 2
3739 prd->samples.push_back(sample_2);
3740 prd->invalid_samples |= invalid_2;
3741 prd->overflow |= (sample_2>>12) & 0x1;
3742 }
3743
3744 if(VERBOSE>9) evioout << " number of samples: " << prd->samples.size() << " words processed: " << iptr-istart << endl;
3745
3746 // When should get here because the loop above stopped when it found
3747 // a data defining word (bit 31=1). The method calling this one will
3748 // assume iptr is pointing to the last word of this block and it will
3749 // advance to the first word of the next block. We need to back up one
3750 // word so that it is pointing to the last word of this block.
3751 iptr--;
3752
3753 // Due to how the calling function works, the value of "objs" passed to us may be NULL.
3754 // This will happen if a Window Raw Data block is encountered before an event header.
3755 // For these cases, we still want to try parsing the data so that the iptr is updated
3756 // but don't have an event to assign it to. If "objs" is non-NULL, add this object to
3757 // the list. Otherwise, delete it now.
3758 if(objs){
3759 objs->hit_objs.push_back(prd);
3760 }else{
3761 delete prd;
3762 }
3763}
3764
3765//----------------
3766// Parsef125Bank
3767//----------------
3768void JEventSource_EVIO::Parsef125Bank(int32_t rocid, const uint32_t* &iptr, const uint32_t* iend, list<ObjList*> &events)
3769{
3770 /// Parse data from a single FADC125 module.
3771 /// This is currently written assuming that the Pulse Integral, Pulse Time, and Pulse Pedestal
3772 /// data formats follow what is in the file:
3773 /// https://halldweb1.jlab.org/wiki/index.php/File:FADC125_dataformat_250_modes.docx
3774
3775 if(!PARSE_F125){ iptr = iend; return; }
3776
3777 if(VERBOSE>6) evioout << " Entering Parsef125Bank for rocid=" << rocid << "..."<<endl;
3778
3779 // This will get updated to point to a newly allocated object when an
3780 // event header is encountered. The existing value (if non-NULL) is
3781 // added to the events queue first though so all events are kept.
3782 ObjList *objs = NULL__null;
3783
3784 // From the Block Header
3785 uint32_t slot=0;
3786 //uint32_t Nblock_events;
3787 //uint32_t iblock;
3788
3789 // From the Block Trailer
3790 //uint32_t slot_trailer;
3791 //uint32_t Nwords_in_block;
3792
3793 // From Event header
3794 //uint32_t slot_event_header;
3795 uint32_t itrigger = -1;
3796 uint32_t last_itrigger = -2;
3797 uint32_t last_pulse_time_channel=0;
3798 uint32_t last_slot = -1;
3799 uint32_t last_channel = -1;
3800
3801 // Loop over data words
3802 for(; iptr<iend; iptr++){
3803
3804 // Skip all non-data-type-defining words at this
3805 // level. When we do encounter one, the appropriate
3806 // case block below should handle parsing all of
3807 // the data continuation words and advance the iptr.
3808 if(((*iptr>>31) & 0x1) == 0)continue;
3809
3810 // Variables used inside of switch, but cannot be declared inside
3811 uint64_t t = 0L;
3812 uint32_t channel = 0;
3813 uint32_t sum = 0;
3814 uint32_t pulse_number = 0;
3815 uint32_t pulse_time = 0;
3816 uint32_t quality_factor = 0;
3817 uint32_t overflow_count = 0;
3818 uint32_t pedestal = 0;
3819 uint32_t pulse_peak = 0;
3820 uint32_t peak_time = 0;
3821 uint32_t nsamples_integral = 0;
3822 uint32_t nsamples_pedestal = 0;
3823 uint32_t word1=0;
3824 uint32_t word2=0;
3825
3826 bool found_block_trailer = false;
3827 uint32_t data_type = (*iptr>>27) & 0x0F;
3828 switch(data_type){
3829 case 0: // Block Header
3830 slot = (*iptr>>22) & 0x1F;
3831 if(VERBOSE>7) evioout << " FADC125 Block Header: slot="<<slot<<endl;
3832 //iblock= (*iptr>>8) & 0x03FF;
3833 //Nblock_events= (*iptr>>0) & 0xFF;
3834 break;
3835 case 1: // Block Trailer
3836 //slot_trailer = (*iptr>>22) & 0x1F;
3837 //Nwords_in_block = (*iptr>>0) & 0x3FFFFF;
3838 found_block_trailer = true;
3839 break;
3840 case 2: // Event Header
3841 //slot_event_header = (*iptr>>22) & 0x1F;
3842 itrigger = (*iptr>>0) & 0x3FFFFFF;
3843 if(VERBOSE>7) evioout << " FADC125 Event Header: itrigger="<<itrigger<<" (objs=0x"<<hex<<objs<<dec<<", last_itrigger="<<last_itrigger<<", rocid="<<rocid<<", slot="<<slot<<")" <<endl;
3844 if( (itrigger!=last_itrigger) || (objs==NULL__null) ){
3845 if(ENABLE_DISENTANGLING){
3846 if(objs){
3847 events.push_back(objs);
3848 objs = NULL__null;
3849 }
3850 }
3851 if(!objs) objs = new ObjList;
3852 last_itrigger = itrigger;
3853 }
3854 break;
3855 case 3: // Trigger Time
3856 t = ((*iptr)&0xFFFFFF)<<24; // n.b. Documentation is incorrect! This is opposite of f250 (see e-mail from Naomi/Cody on 4/28/2016)
3857 iptr++;
3858 if(((*iptr>>31) & 0x1) == 0){
3859 t += ((*iptr)&0xFFFFFF)<<0; // (see above)
3860 }else{
3861 iptr--;
3862 }
3863 if(VERBOSE>7) evioout << " FADC125 Trigger Time (t="<<t<<")"<<endl;
3864 if(objs) objs->hit_objs.push_back(new Df125TriggerTime(rocid, slot, itrigger, t));
3865 break;
3866 case 4: // Window Raw Data
3867 // iptr passed by reference and so will be updated automatically
3868 if(VERBOSE>7) evioout << " FADC125 Window Raw Data"<<endl;
3869 MakeDf125WindowRawData(objs, rocid, slot, itrigger, iptr);
3870 break;
3871
3872 case 5: // CDC pulse data (new) (GlueX-doc-2274-v8)
3873
3874 // Word 1:
3875 word1 = *iptr;
3876 channel = (*iptr>>20) & 0x7F;
3877 pulse_number = (*iptr>>15) & 0x1F;
3878 pulse_time = (*iptr>>4 ) & 0x7FF;
3879 quality_factor = (*iptr>>3 ) & 0x1; //time QF bit
3880 overflow_count = (*iptr>>0 ) & 0x7;
3881 if(VERBOSE>8) evioout << " FADC125 CDC Pulse Data word1: " << hex << (*iptr) << dec << endl;
3882 if(VERBOSE>7) evioout << " FADC125 CDC Pulse Data (chan="<<channel<<" pulse="<<pulse_number<<" time="<<pulse_time<<" QF="<<quality_factor<<" OC="<<overflow_count<<")"<<endl;
3883
3884 // Word 2:
3885 ++iptr;
3886 if(iptr>=iend){
3887 jerr << " Truncated f125 CDC hit (block ends before continuation word!)" << endl;
3888 continue;
3889 }
3890 if( ((*iptr>>31) & 0x1) != 0 ){
3891 jerr << " Truncated f125 CDC hit (missing continuation word!)" << endl;
3892 continue;
3893 }
3894 word2 = *iptr;
3895 pedestal = (*iptr>>23) & 0xFF;
3896 sum = (*iptr>>9 ) & 0x3FFF;
3897 pulse_peak = (*iptr>>0 ) & 0x1FF;
3898 if(VERBOSE>8) evioout << " FADC125 CDC Pulse Data word2: " << hex << (*iptr) << dec << endl;
3899 if(VERBOSE>7) evioout << " FADC125 CDC Pulse Data (pedestal="<<pedestal<<" sum="<<sum<<" peak="<<pulse_peak<<")"<<endl;
3900
3901 // Create hit objects
3902 nsamples_integral = 0; // must be overwritten later in GetObjects with value from Df125Config value
3903 nsamples_pedestal = 1; // The firmware pedestal divided by 2^PBIT where PBIT is a config. parameter
3904
3905 if( (objs!=NULL__null) && (pulse_number<F125PULSE_NUMBER_FILTER) ) {
3906 // n.b. This is were we might apply a check on whether we are
3907 // only producing emulated objects. If so, then we shouldn't
3908 // create the Df125CDCPulse. At this point in time though,
3909 // there are 3 config. parameters that control this because
3910 // the original firmware produced 3 separate data types as
3911 // opposed to the new firmware that puts the same infomation
3912 // into a single data type. The emulation framework is also
3913 // being revamped.
3914 objs->hit_objs.push_back( new Df125CDCPulse(rocid, slot, channel, itrigger
3915 , pulse_number // NPK
3916 , pulse_time // le_time
3917 , quality_factor // time_quality_bit
3918 , overflow_count // overflow_count
3919 , pedestal // pedestal
3920 , sum // integral
3921 , pulse_peak // first_max_amp
3922 , word1 // word1
3923 , word2 // word2
3924 , nsamples_pedestal // nsamples_pedestal
3925 , nsamples_integral // nsamples_integral
3926 , false) // emulated
3927 );
3928 }
3929
3930 // n.b. We don't record last_slot, last_channel, etc... here since those
3931 // are only used by data types corresponding to older firmware that did
3932 // not write out data type 5.
3933 break;
3934
3935 case 6: // FDC pulse data-integral (new) (GlueX-doc-2274-v8)
3936
3937 // Word 1:
3938 word1 = *iptr;
3939 channel = (*iptr>>20) & 0x7F;
3940 pulse_number = (*iptr>>15) & 0x1F;
3941 pulse_time = (*iptr>>4 ) & 0x7FF;
3942 quality_factor = (*iptr>>3 ) & 0x1; //time QF bit
3943 overflow_count = (*iptr>>0 ) & 0x7;
3944 if(VERBOSE>8) evioout << " FADC125 FDC Pulse Data(integral) word1: " << hex << (*iptr) << dec << endl;
3945 if(VERBOSE>7) evioout << " FADC125 FDC Pulse Data (chan="<<channel<<" pulse="<<pulse_number<<" time="<<pulse_time<<" QF="<<quality_factor<<" OC="<<overflow_count<<")"<<endl;
3946
3947 // Word 2:
3948 ++iptr;
3949 if(iptr>=iend){
3950 jerr << " Truncated f125 FDC hit (block ends before continuation word!)" << endl;
3951 continue;
3952 }
3953 if( ((*iptr>>31) & 0x1) != 0 ){
3954 jerr << " Truncated f125 FDC hit (missing continuation word!)" << endl;
3955 continue;
3956 }
3957 word2 = *iptr;
3958 pulse_peak = 0;
3959 sum = (*iptr>>19) & 0xFFF;
3960 peak_time = (*iptr>>11) & 0xFF;
3961 pedestal = (*iptr>>0 ) & 0x7FF;
3962 if(VERBOSE>8) evioout << " FADC125 FDC Pulse Data(integral) word2: " << hex << (*iptr) << dec << endl;
3963 if(VERBOSE>7) evioout << " FADC125 FDC Pulse Data (integral="<<sum<<" time="<<peak_time<<" pedestal="<<pedestal<<")"<<endl;
3964
3965 // Create hit objects
3966 nsamples_integral = 0; // must be overwritten later in GetObjects with value from Df125Config value
3967 nsamples_pedestal = 1; // The firmware pedestal divided by 2^PBIT where PBIT is a config. parameter
3968
3969 if( (objs!=NULL__null) && (pulse_number<F125PULSE_NUMBER_FILTER) ) {
3970 // n.b. This is were we might apply a check on whether we are
3971 // only producing emulated objects. If so, then we shouldn't
3972 // create the Df125FDCPulse. At this point in time though,
3973 // there are 3 config. parameters that control this because
3974 // the original firmware produced 3 separate data types as
3975 // opposed to the new firmware that puts the same infomation
3976 // into a single data type. The emulation framework is also
3977 // being revamped.
3978 objs->hit_objs.push_back( new Df125FDCPulse(rocid, slot, channel, itrigger
3979 , pulse_number // NPK
3980 , pulse_time // le_time
3981 , quality_factor // time_quality_bit
3982 , overflow_count // overflow_count
3983 , pedestal // pedestal
3984 , sum // integral
3985 , pulse_peak // peak_amp
3986 , peak_time // peak_time
3987 , word1 // word1
3988 , word2 // word2
3989 , nsamples_pedestal // nsamples_pedestal
3990 , nsamples_integral // nsamples_integral
3991 , false) // emulated
3992 );
3993 }
3994
3995 // n.b. We don't record last_slot, last_channel, etc... here since those
3996 // are only used by data types corresponding to older firmware that did
3997 // not write out data type 6.
3998 break;
3999
4000 case 7: // Pulse Integral
4001 if(VERBOSE>7) evioout << " FADC125 Pulse Integral"<<endl;
4002 channel = (*iptr>>20) & 0x7F;
4003 sum = (*iptr>>0) & 0xFFFFF;
4004 nsamples_integral = 0; // must be overwritten later in GetObjects with value from Df125Config value
4005 nsamples_pedestal = 1; // The firmware returns an already divided pedestal
4006 pedestal = 0; // This will be replaced by the one from Df250PulsePedestal in GetObjects
4007 if (last_slot == slot && last_channel == channel) pulse_number = 1;
4008 last_slot = slot;
4009 last_channel = channel;
4010 if( (objs!=NULL__null) && (pulse_number<F125PULSE_NUMBER_FILTER) ) {
4011 objs->hit_objs.push_back(new Df125PulseIntegral(rocid, slot, channel, itrigger, pulse_number,
4012 quality_factor, sum, pedestal, nsamples_integral, nsamples_pedestal));
4013 }
4014 break;
4015 case 8: // Pulse Time
4016 if(VERBOSE>7) evioout << " FADC125 Pulse Time"<<endl;
4017 channel = (*iptr>>20) & 0x7F;
4018 pulse_number = (*iptr>>18) & 0x03;
4019 pulse_time = (*iptr>>0) & 0xFFFF;
4020 if( (objs!=NULL__null) && (pulse_number<F125PULSE_NUMBER_FILTER) ) {
4021 objs->hit_objs.push_back(new Df125PulseTime(rocid, slot, channel, itrigger, pulse_number, quality_factor, pulse_time));
4022 }
4023 last_pulse_time_channel = channel;
4024 break;
4025
4026 case 9: // FDC pulse data-peak (new) (GlueX-doc-2274-v8)
4027
4028 // Word 1:
4029 word1 = *iptr;
4030 channel = (*iptr>>20) & 0x7F;
4031 pulse_number = (*iptr>>15) & 0x1F;
4032 pulse_time = (*iptr>>4 ) & 0x7FF;
4033 quality_factor = (*iptr>>3 ) & 0x1; //time QF bit
4034 overflow_count = (*iptr>>0 ) & 0x7;
4035 if(VERBOSE>8) evioout << " FADC125 FDC Pulse Data(peak) word1: " << hex << (*iptr) << dec << endl;
4036 if(VERBOSE>7) evioout << " FADC125 FDC Pulse Data (chan="<<channel<<" pulse="<<pulse_number<<" time="<<pulse_time<<" QF="<<quality_factor<<" OC="<<overflow_count<<")"<<endl;
4037
4038 // Word 2:
4039 ++iptr;
4040 if(iptr>=iend){
4041 jerr << " Truncated f125 FDC hit (block ends before continuation word!)" << endl;
4042 continue;
4043 }
4044 if( ((*iptr>>31) & 0x1) != 0 ){
4045 jerr << " Truncated f125 FDC hit (missing continuation word!)" << endl;
4046 continue;
4047 }
4048 word2 = *iptr;
4049 pulse_peak = (*iptr>>19) & 0xFFF;
4050 sum = 0;
4051 peak_time = (*iptr>>11) & 0xFF;
4052 pedestal = (*iptr>>0 ) & 0x7FF;
4053 if(VERBOSE>8) evioout << " FADC125 FDC Pulse Data(peak) word2: " << hex << (*iptr) << dec << endl;
4054 if(VERBOSE>7) evioout << " FADC125 FDC Pulse Data (integral="<<sum<<" time="<<peak_time<<" pedestal="<<pedestal<<")"<<endl;
4055
4056 // Create hit objects
4057 nsamples_integral = 0; // must be overwritten later in GetObjects with value from Df125Config value
4058 nsamples_pedestal = 1; // The firmware pedestal divided by 2^PBIT where PBIT is a config. parameter
4059
4060 if( (objs!=NULL__null) && (pulse_number<F125PULSE_NUMBER_FILTER) ) {
4061 // n.b. This is were we might apply a check on whether we are
4062 // only producing emulated objects. If so, then we shouldn't
4063 // create the Df125FDCPulse. At this point in time though,
4064 // there are 3 config. parameters that control this because
4065 // the original firmware produced 3 separate data types as
4066 // opposed to the new firmware that puts the same infomation
4067 // into a single data type. The emulation framework is also
4068 // being revamped.
4069 objs->hit_objs.push_back( new Df125FDCPulse(rocid, slot, channel, itrigger
4070 , pulse_number // NPK
4071 , pulse_time // le_time
4072 , quality_factor // time_quality_bit
4073 , overflow_count // overflow_count
4074 , pedestal // pedestal
4075 , sum // integral
4076 , pulse_peak // peak_amp
4077 , peak_time // peak_time
4078 , word1 // word1
4079 , word2 // word2
4080 , nsamples_pedestal // nsamples_pedestal
4081 , nsamples_integral // nsamples_integral
4082 , false) // emulated
4083 );
4084 }
4085
4086 // n.b. We don't record last_slot, last_channel, etc... here since those
4087 // are only used by data types corresponding to older firmware that did
4088 // not write out data type 6.
4089 break;
4090
4091 case 10: // Pulse Pedestal (consistent with Beni's hand-edited version of Cody's document)
4092 if(VERBOSE>7) evioout << " FADC125 Pulse Pedestal"<<endl;
4093 //channel = (*iptr>>20) & 0x7F;
4094 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")
4095 pulse_number = (*iptr>>21) & 0x03;
4096 pedestal = (*iptr>>12) & 0x1FF;
4097 pulse_peak = (*iptr>>0) & 0xFFF;
4098 nsamples_pedestal = 1; // The firmware returns an already divided pedestal
4099 if( (objs!=NULL__null) && (pulse_number<F125PULSE_NUMBER_FILTER) ) {
4100 objs->hit_objs.push_back(new Df125PulsePedestal(rocid, slot, channel, itrigger, pulse_number, pedestal, pulse_peak, nsamples_pedestal));
4101 }
4102 break;
4103
4104 case 13: // Event Trailer
4105 case 14: // Data not valid (empty module)
4106 case 15: // Filler (non-data) word
4107 if(VERBOSE>7) evioout << " FADC125 ignored data type: " << data_type <<endl;
4108 break;
4109 }
4110
4111 // Once we find a block trailer, assume that is it for this module.
4112 if(found_block_trailer){
4113 iptr++; // iptr is still pointing to block trailer. Jump to next word.
4114 break;
4115 }
4116 }
4117
4118 // Chop off filler words
4119 for(; iptr<iend; iptr++){
4120 if(((*iptr)&0xf8000000) != 0xf8000000) break;
4121 }
4122
4123 // Add last event in block to list
4124 if(objs)events.push_back(objs);
4125
4126 // Here, we make object associations to link PulseIntegral, PulseTime, PulseRawData, etc
4127 // objects to each other so it is easier to get to these downstream without having to
4128 // make nested loops. This is the most efficient place to do it since the ObjList objects
4129 // in "event" contain only the objects from this EVIO block (i.e. at most one crate's
4130 // worth.)
4131 list<ObjList*>::iterator iter = events.begin();
4132 for(; iter!=events.end(); iter++){
4133
4134 // Sort list of objects into type-specific lists
4135 vector<DDAQAddress*> &hit_objs = (*iter)->hit_objs;
4136 vector<Df125TriggerTime*> vtrigt;
4137 vector<Df125WindowRawData*> vwrd;
4138 vector<Df125PulseRawData*> vprd;
4139 vector<Df125PulseIntegral*> vpi;
4140 vector<Df125PulseTime*> vpt;
4141 vector<Df125PulsePedestal*> vpp;
4142 for(unsigned int i=0; i<hit_objs.size(); i++){
4143 AddIfAppropriate(hit_objs[i], vtrigt);
4144 AddIfAppropriate(hit_objs[i], vwrd);
4145 AddIfAppropriate(hit_objs[i], vprd);
4146 AddIfAppropriate(hit_objs[i], vpi);
4147 AddIfAppropriate(hit_objs[i], vpt);
4148 AddIfAppropriate(hit_objs[i], vpp);
4149 }
4150
4151 // Connect Df125PulseIntegral with Df125PulseTime
4152 LinkAssociationsWithPulseNumber(vprd, vpi);
4153 LinkAssociationsWithPulseNumber(vprd, vpt);
4154 LinkAssociationsWithPulseNumber(vprd, vpp);
4155 LinkAssociationsWithPulseNumber(vpi, vpt);
4156 LinkAssociationsWithPulseNumber(vpi, vpp);
4157 LinkAssociationsWithPulseNumber(vpt, vpp);
4158
4159 // Connect Df125TriggerTime to everything
4160 LinkAssociationsModuleOnly(vtrigt, vwrd);
4161 LinkAssociationsModuleOnly(vtrigt, vprd);
4162 LinkAssociationsModuleOnly(vtrigt, vpi);
4163 LinkAssociationsModuleOnly(vtrigt, vpt);
4164 LinkAssociationsModuleOnly(vtrigt, vpp);
4165 }
4166
4167 if(VERBOSE>6) evioout << " Leaving Parsef125Bank"<<endl;
4168}
4169
4170//----------------
4171// MakeDf125WindowRawData
4172//----------------
4173void JEventSource_EVIO::MakeDf125WindowRawData(ObjList *objs, uint32_t rocid, uint32_t slot, uint32_t itrigger, const uint32_t* &iptr)
4174{
4175 uint32_t channel = (*iptr>>20) & 0x7F;
4176 uint32_t window_width = (*iptr>>0) & 0x0FFF;
4177
4178 Df125WindowRawData *wrd = new Df125WindowRawData(rocid, slot, channel, itrigger);
4179
4180 for(uint32_t isample=0; isample<window_width; isample +=2){
4181
4182 // Advance to next word
4183 iptr++;
4184
4185 // Make sure this is a data continuation word, if not, stop here
4186 if(((*iptr>>31) & 0x1) != 0x0)break;
4187
4188 bool invalid_1 = (*iptr>>29) & 0x1;
4189 bool invalid_2 = (*iptr>>13) & 0x1;
4190 uint16_t sample_1 = 0;
4191 uint16_t sample_2 = 0;
4192 if(!invalid_1)sample_1 = (*iptr>>16) & 0x1FFF;
4193 if(!invalid_2)sample_2 = (*iptr>>0) & 0x1FFF;
4194
4195 // Sample 1
4196 wrd->samples.push_back(sample_1);
4197 wrd->invalid_samples |= invalid_1;
4198 wrd->overflow |= (sample_1>>12) & 0x1;
4199
4200 if((isample+2) == window_width && invalid_2)break; // skip last sample if flagged as invalid
4201
4202 // Sample 2
4203 wrd->samples.push_back(sample_2);
4204 wrd->invalid_samples |= invalid_2;
4205 wrd->overflow |= (sample_2>>12) & 0x1;
4206 }
4207
4208 if(VERBOSE>7) evioout << " FADC125 - " << wrd->samples.size() << " samples" << endl;
4209
4210 // Due to how the calling function works, the value of "objs" passed to us may be NULL.
4211 // This will happen if a Window Raw Data block is encountered before an event header.
4212 // For these cases, we still want to try parsing the data so that the iptr is updated
4213 // but don't have an event to assign it to. If "objs" is non-NULL, add this object to
4214 // the list. Otherwise, delete it now.
4215 if(objs){
4216 objs->hit_objs.push_back(wrd);
4217 }else{
4218 delete wrd;
4219 }
4220}
4221
4222//----------------
4223// MakeDf125PulseRawData
4224//----------------
4225void JEventSource_EVIO::MakeDf125PulseRawData(ObjList *objs, uint32_t rocid, uint32_t slot, uint32_t itrigger, const uint32_t* &iptr)
4226{
4227 uint32_t channel = (*iptr>>23) & 0x0F;
4228 uint32_t pulse_number = (*iptr>>21) & 0x000F;
4229 uint32_t first_sample_number = (*iptr>>0) & 0x03FF;
4230
4231 Df125PulseRawData *prd = new Df125PulseRawData(rocid, slot, channel, itrigger, pulse_number, first_sample_number);
4232
4233 // This loop needs to break when it hits a non-continuation word
4234 for(uint32_t isample=0; isample<1000; isample +=2){
4235
4236 // Advance to next word
4237 iptr++;
4238
4239 // Make sure this is a data continuation word, if not, stop here
4240 if(((*iptr>>31) & 0x1) != 0x0)break;
4241
4242 bool invalid_1 = (*iptr>>29) & 0x1;
4243 bool invalid_2 = (*iptr>>13) & 0x1;
4244 uint16_t sample_1 = 0;
4245 uint16_t sample_2 = 0;
4246 if(!invalid_1)sample_1 = (*iptr>>16) & 0x1FFF;
4247 if(!invalid_2)sample_2 = (*iptr>>0) & 0x1FFF;
4248
4249 // Sample 1
4250 prd->samples.push_back(sample_1);
4251 prd->invalid_samples |= invalid_1;
4252 prd->overflow |= (sample_1>>12) & 0x1;
4253
4254 bool last_word = (iptr[1]>>31) & 0x1;
4255 if(last_word && invalid_2)break; // skip last sample if flagged as invalid
4256
4257 // Sample 2
4258 prd->samples.push_back(sample_2);
4259 prd->invalid_samples |= invalid_2;
4260 prd->overflow |= (sample_2>>12) & 0x1;
4261 }
4262
4263
4264 // Due to how the calling function works, the value of "objs" passed to us may be NULL.
4265 // This will happen if a Window Raw Data block is encountered before an event header.
4266 // For these cases, we still want to try parsing the data so that the iptr is updated
4267 // but don't have an event to assign it to. If "objs" is non-NULL, add this object to
4268 // the list. Otherwise, delete it now.
4269 if(objs){
4270 objs->hit_objs.push_back(prd);
4271 }else{
4272 delete prd;
4273 }
4274}
4275
4276//----------------
4277// ParseF1TDCBank
4278//----------------
4279void JEventSource_EVIO::ParseF1TDCBank(int32_t rocid, const uint32_t* &iptr, const uint32_t* iend, list<ObjList*> &events)
4280{
4281 /// Parse data from a single F1TDCv2 (32 ch) or F1TDCv3 (48 ch) module.
4282 /// This code is based on the document F1TDC_V2_V3_4_29_14.pdf obtained from:
4283 /// https://coda.jlab.org/wiki/index.php/JLab_Module_Manuals
4284
4285 if(!PARSE_F1TDC){ iptr = iend; return; }
4286
4287 if(VERBOSE>6) evioout << " Entering ParseF1TDCBank (rocid=" << rocid << ")" << endl;
4288
4289 const uint32_t *istart = iptr;
4290
4291 // Some early data had a marker word at just before the actual F1 data
4292 if(*iptr == 0xf1daffff) iptr++;
4293
4294 // Block header word
4295 // Double check that block header is set
4296 if( ((*iptr) & 0xF8000000) != 0x80000000 ){
4297 throw JException("F1TDC Block header corrupt! (high 5 bits not set to 0x80000000!)");
4298 }
4299
4300 uint32_t slot_block_header = (*iptr)>>22 & 0x001F;
4301 uint32_t block_num = (*iptr)>> 8 & 0x03FF;
4302 uint32_t Nevents_block_header = (*iptr)>> 0 & 0x00FF;
4303 int modtype = (*iptr)>>18 & 0x000F; // should match a DModuleType::type_id_t
4304 if(VERBOSE>5) evioout << " F1 Block Header: slot=" << slot_block_header << " block_num=" << block_num << " Nevents=" << Nevents_block_header << endl;
4305
4306 // Advance to next word
4307 iptr++;
4308
4309 // Loop over events
4310 ObjList *objs = NULL__null;
4311 while(iptr<iend){
4312
4313 // Event header
4314 // Double check that event header is set
4315 if( ((*iptr) & 0xF8000000) != 0x90000000 ){
4316 if(VERBOSE>10){
4317 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<4317<<" "
<<"Corrupt F1TDC Event header! Data dump follows (\"*\" indicates bad header word):" <<endl;
4318 DumpBinary(istart, iend, 0, iptr);
4319 }
4320 throw JException("F1TDC Event header corrupt! (high 5 bits not set to 0x90000000!)");
4321 }
4322
4323 uint32_t slot_event_header = (*iptr)>>22 & 0x00000001F;
4324 uint32_t itrigger = (*iptr)>>0 & 0x0003FFFFF;
4325 if(VERBOSE>5) evioout << " F1 Event Header: slot=" << slot_block_header << " itrigger=" << itrigger << endl;
4326
4327 // Make sure slot number from event header matches block header
4328 if(slot_event_header != slot_block_header){
4329 char str[256];
4330 sprintf(str, "F1TDC slot from event header(%d) doesn't match block header(%d)", slot_event_header, slot_block_header);
4331 throw JException(str);
4332 }
4333
4334 // Advance to timestamp word
4335 iptr++;
4336 if(iptr>=iend) throw JException("F1TDC data corrupt! Block truncated before timestamp word!");
4337
4338 // The most recent documentation says that the first time stamp
4339 // word holds the low 24 bits and the second the high 16 bits. According to Dave A.,
4340 // the second word is optional.
4341 uint32_t trig_time = ((*iptr)&0xFFFFFF);
4342 if(VERBOSE>6) evioout << " F1 Trigger time: low 24 bits=" << trig_time << endl;
4343 iptr++;
4344 if(iptr>=iend) throw JException("F1TDC data corrupt! Block truncated before trailer word!");
4345 if(((*iptr>>31) & 0x1) == 0){
4346 trig_time += ((*iptr)&0xFFFF)<<24; // from word on the street: second trigger time word is optional!!??
4347 if(VERBOSE>6) evioout << " F1 Trigger time: high 16 bits=" << ((*iptr)&0xFFFF) << " total trig_time=" << trig_time << endl;
4348 }else{
4349 iptr--; // second time word not present, back up pointer
4350 }
4351
4352 // Create a new object list (i.e. new event)
4353 if(objs!=NULL__null && ENABLE_DISENTANGLING){
4354 events.push_back(objs);
4355 objs = NULL__null;
4356 }
4357 if(!objs) objs = new ObjList;
4358
4359 if(objs) objs->hit_objs.push_back(new DF1TDCTriggerTime(rocid, slot_block_header, itrigger, trig_time));
4360
4361 // Advance past last timestamp word to first data word (or rather, F1 chip header)
4362 iptr++;
4363
4364 // Loop over F1 data words
4365 uint32_t chip_f1header=0, chan_on_chip_f1header=0, itrigger_f1header=0, trig_time_f1header=0;
4366 while( iptr<iend && ((*iptr)>>31)==0x1 ){
4367
4368 bool done = false;
4369
4370 uint32_t chip, chan_on_chip, time;
4371 uint32_t channel;
4372 DF1TDCHit *hit=NULL__null;
4373 switch( (*iptr) & 0xF8000000 ){
4374 case 0xC0000000: // F1 Header
4375 chip_f1header = ((*iptr)>> 3) & 0x07;
4376 chan_on_chip_f1header = ((*iptr)>> 0) & 0x07; // this is always 7 in real data!
4377 itrigger_f1header = ((*iptr)>>16) & 0x3F;
4378 trig_time_f1header = ((*iptr)>> 7) & 0x1FF;
4379 if(VERBOSE>5) evioout << " Found F1 header: chip=" << chip_f1header << " chan=" << chan_on_chip_f1header << " itrig=" << itrigger_f1header << " trig_time=" << trig_time_f1header << endl;
4380 //if( itrigger_f1header != (itrigger & 0x3F)) throw JException("Trigger number in F1 header word does not match Event header word!");
4381 break;
4382 case 0xB8000000: // F1 Data
4383 chip = (*iptr>>19) & 0x07;
4384 chan_on_chip = (*iptr>>16) & 0x07;
4385 time = (*iptr>> 0) & 0xFFFF;
4386 if(VERBOSE>5) evioout << " Found F1 data : chip=" << chip << " chan=" << chan_on_chip << " time=" << time << " (header: chip=" << chip_f1header << ")" << endl;
4387 //if(chip!=chip_f1header) throw JException("F1 chip number in data does not match header!");
4388 channel = F1TDC_channel(chip, chan_on_chip, modtype);
4389 hit = new DF1TDCHit(rocid, slot_block_header, channel, itrigger, trig_time_f1header, time, *iptr, MODULE_TYPE(modtype));
4390 if(objs)objs->hit_objs.push_back(hit);
4391 break;
4392 case 0xF8000000: // Filler word
4393 if(VERBOSE>7) evioout << " Found F1 filler word" << endl;
4394 break;
4395 case 0x80000000: // JLab block header (handled in outer loop)
4396 case 0x88000000: // JLab block trailer (handled in outer loop)
4397 case 0x90000000: // JLab event header (handled in outer loop)
4398 case 0x98000000: // Trigger time (handled in outer loop)
4399 case 0xF0000000: // module has no valid data available for read out (how to handle this?)
4400 if(VERBOSE>5) evioout << " Found F1 break word: 0x" << hex << *iptr << dec << endl;
4401 done = true;
4402 break;
4403 default:
4404 cerr<<endl;
4405 cout.flush(); cerr.flush();
4406 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<4406<<" "
<<"Unknown data word in F1TDC block. Dumping for debugging:" << endl;
4407 for(const uint32_t *iiptr = istart; iiptr<iend; iiptr++){
4408 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<4408<<" "
<<"0x"<<hex<<*iiptr<<dec;
4409 if(iiptr == iptr)cerr<<" <----";
4410 switch( (*iiptr) & 0xF8000000 ){
4411 case 0x80000000: cerr << " F1 Block Header"; break;
4412 case 0x90000000: cerr << " F1 Event Header"; break;
4413 case 0x98000000: cerr << " F1 Trigger time"; break;
4414 case 0xC0000000: cerr << " F1 Header"; break;
4415 case 0xB8000000: cerr << " F1 Data"; break;
4416 case 0x88000000: cerr << " F1 Block Trailer"; break;
4417 case 0xF8000000: cerr << " Filler word"; break;
4418 case 0xF0000000: cerr << " <module has no valid data>"; break;
4419 default: break;
4420 }
4421 cerr<<endl;
4422 if(iiptr > (iptr+4)) break;
4423 }
4424
4425 throw JException("Unexpected word type in F1TDC block!");
4426 }
4427
4428 if(done)break;
4429
4430 // Advance to next data word
4431 iptr++;
4432
4433 } // end loop over data words in this event
4434
4435 // If the current word is a JLab block trailer, then we are done
4436 if( ((*iptr) & 0xF8000000) == 0x88000000) break;
4437
4438 } // end loop over events
4439
4440 // Add hits for last event to list of events.
4441 if(objs)events.push_back(objs);
4442
4443 if( ((*iptr) & 0xF8000000) != 0x88000000 ){
4444 throw JException("F1TDC Block Trailer corrupt! (high 5 bits not set to 0x88000000!)");
4445 }
4446
4447 // Advance past JLab block trailer
4448 iptr++;
4449
4450 // Skip filler words
4451 while(iptr<iend && (*iptr&0xF8000000)==0xF8000000)iptr++;
4452
4453 // Double check that we found all of the events we were supposed to
4454 if(!ENABLE_DISENTANGLING) Nevents_block_header=1;
4455 if(events.size() != Nevents_block_header){
4456 stringstream ss;
4457 ss << "F1TDC missing events in block! (found "<< events.size() <<" but should have found "<<Nevents_block_header<<")";
4458 DumpBinary(istart, iend, 128);
4459 throw JException(ss.str());
4460 }
4461
4462 if(VERBOSE>6) evioout << " Leaving ParseF1TDCBank (rocid=" << rocid << ")" << endl;
4463
4464}
4465
4466//----------------
4467// F1TDC_channel
4468//----------------
4469uint32_t JEventSource_EVIO::F1TDC_channel(uint32_t chip, uint32_t chan_on_chip, int modtype)
4470{
4471 /// Convert a F1TDC chip number and channel on the chip to the
4472 /// front panel channel number. This is based on "Input Channel Mapping"
4473 /// section at the very bottom of the document F1TDC_V2_V3_4_29_14.pdf
4474
4475 uint32_t channel_map[8] = {0, 0, 1, 1, 2, 2, 3, 3};
4476 switch(modtype){
4477 case DModuleType::F1TDC32:
4478 return (4 * chip) + channel_map[ chan_on_chip&0x7 ];
4479 case DModuleType::F1TDC48:
4480 return (chip <<3) | chan_on_chip;
4481 default:
4482 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<4482<<" "
<< "Calling F1TDC_channel for module type: " << DModuleType::GetName((DModuleType::type_id_t)modtype) << endl;
4483 throw JException("F1TDC_channel called for non-F1TDC module type");
4484 }
4485 return 1000000; // (should never get here)
4486}
4487
4488//----------------
4489// ParseTSBank
4490//----------------
4491void JEventSource_EVIO::ParseTSBank(int32_t rocid, const uint32_t* &iptr, const uint32_t* iend, list<ObjList*> &events)
4492{
4493 /// Parse data written to the TS roc data during sync events.
4494 /// This is written by the ts_scalers routine in the conf_utils.c
4495 /// file and called from ts_list.c
4496
4497 uint32_t Nwords = ((uint64_t)iend - (uint64_t)iptr)/sizeof(uint32_t);
4498 uint32_t Nwords_expected = (6+32+16+32+16);
4499 if(Nwords != Nwords_expected){
4500 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<4500<<" "
<< "TS bank size does not match expected!!" << endl;
4501 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<4501<<" "
<< "Found " << Nwords << " words. Expected " << Nwords_expected << endl;
4502
4503 }else{
4504 DTSscalers *s = new DTSscalers;
4505 s->nsync_event = *iptr++;
4506 s->int_count = *iptr++;
4507 s->live_time = *iptr++;
4508 s->busy_time = *iptr++;
4509 s->inst_livetime = *iptr++;
4510 s->time = *iptr++;
4511 for(uint32_t i=0; i<32; i++) s->gtp_scalers[i] = *iptr++;
4512 for(uint32_t i=0; i<16; i++) s->fp_scalers[i] = *iptr++;
4513 for(uint32_t i=0; i<32; i++) s->gtp_rate[i] = *iptr++;
4514 for(uint32_t i=0; i<16; i++) s->fp_rate[i] = *iptr++;
4515
4516 if(events.empty()) events.push_back(new ObjList);
4517 ObjList *objs = *(events.begin());
4518 objs->misc_objs.push_back(s);
4519 }
4520
4521 iptr = iend;
4522}
4523
4524//----------------
4525// ParseTIBank
4526//----------------
4527void JEventSource_EVIO::ParseTIBank(int32_t rocid, const uint32_t* &iptr, const uint32_t* iend, list<ObjList*> &events)
4528{
4529 while(iptr<iend && ((*iptr) & 0xF8000000) != 0x88000000) iptr++; // Skip to JLab block trailer
4530 iptr++; // advance past JLab block trailer
4531 while(iptr<iend && *iptr == 0xF8000000) iptr++; // skip filler words after block trailer
4532 //iptr = iend;
4533}
4534
4535//----------------
4536// ParseCAEN1190
4537//----------------
4538void JEventSource_EVIO::ParseCAEN1190(int32_t rocid, const uint32_t* &iptr, const uint32_t *iend, list<ObjList*> &events)
4539{
4540 /// Parse data from a CAEN 1190 or 1290 module
4541 /// (See ppg. 72-74 of V1290_REV15.pdf manual)
4542
4543 if(!PARSE_CAEN1290TDC){ iptr = iend; return; }
4544
4545 uint32_t slot = 0;
4546 uint32_t event_count = 0;
4547 uint32_t word_count = 0;
4548 uint32_t trigger_time_tag = 0;
4549 uint32_t tdc_num = 0;
4550 uint32_t event_id = 0;
4551 uint32_t bunch_id = 0;
4552
4553 // We need to accomodate multi-event blocks where
4554 // events are entangled (i.e. hits from event 1
4555 // are mixed inbetween those of event 2,3,4,
4556 // etc... With CAEN modules, we only know which
4557 // event a hit came from by looking at the event_id
4558 // in the TDC header. This value is only 12 bits
4559 // and could roll over within an event block. This
4560 // means we need to keep track of the order we
4561 // encounter them in so it is maintained in the
4562 // "events" container. The event_id order is kept
4563 // in the "event_id_order" vector.
4564 map<uint32_t, vector<DCAEN1290TDCHit*> > hits_by_event_id;
4565 vector<uint32_t> event_id_order;
4566
4567 while(iptr<iend){
4568
4569 // This word appears to be appended to the data.
4570 // Probably in the ROL. Ignore it if found.
4571 if(*iptr == 0xd00dd00d) {
4572 if(VERBOSE>7) evioout << " CAEN skipping 0xd00dd00d word" << endl;
4573 iptr++;
4574 continue;
4575 }
4576
4577 uint32_t type = (*iptr) >> 27;
4578 uint32_t edge = 0; // 1=trailing, 0=leading
4579 uint32_t channel = 0;
4580 uint32_t tdc = 0;
4581 uint32_t error_flags = 0;
4582 DCAEN1290TDCHit *caen1290tdchit = NULL__null;
4583 map<uint32_t, ObjList*>::iterator iter;
4584 switch(type){
4585 case 0b01000: // Global Header
4586 slot = (*iptr) & 0x1f;
4587 event_count = ((*iptr)>>5) & 0xffffff;
4588 if(VERBOSE>7) evioout << " CAEN TDC Global Header (slot=" << slot << " , event count=" << event_count << ")" << endl;
4589 break;
4590 case 0b10000: // Global Trailer
4591 slot = (*iptr) & 0x1f;
4592 word_count = ((*iptr)>>5) & 0x7ffff;
4593 if(VERBOSE>7) evioout << " CAEN TDC Global Trailer (slot=" << slot << " , word count=" << word_count << ")" << endl;
4594 slot = event_count = word_count = trigger_time_tag = tdc_num = event_id = bunch_id = 0;
4595 break;
4596 case 0b10001: // Global Trigger Time Tag
4597 trigger_time_tag = ((*iptr)>>5) & 0x7ffffff;
4598 if(VERBOSE>7) evioout << " CAEN TDC Global Trigger Time Tag (tag=" << trigger_time_tag << ")" << endl;
4599 break;
4600 case 0b00001: // TDC Header
4601 tdc_num = ((*iptr)>>24) & 0x03;
4602 event_id = ((*iptr)>>12) & 0x0fff;
4603 bunch_id = (*iptr) & 0x0fff;
4604 if( find(event_id_order.begin(), event_id_order.end(), event_id) == event_id_order.end()){
4605 event_id_order.push_back(event_id);
4606 }
4607 if(VERBOSE>7) evioout << " CAEN TDC TDC Header (tdc=" << tdc_num <<" , event id=" << event_id <<" , bunch id=" << bunch_id << ")" << endl;
4608 break;
4609 case 0b00000: // TDC Measurement
4610 edge = ((*iptr)>>26) & 0x01;
4611 channel = ((*iptr)>>21) & 0x1f;
4612 tdc = ((*iptr)>>0) & 0x1fffff;
4613 if(VERBOSE>7) evioout << " CAEN TDC TDC Measurement (" << (edge ? "trailing":"leading") << " , channel=" << channel << " , tdc=" << tdc << ")" << endl;
4614
4615 // Create DCAEN1290TDCHit object
4616 caen1290tdchit = new DCAEN1290TDCHit(rocid, slot, channel, 0, edge, tdc_num, event_id, bunch_id, tdc);
4617 hits_by_event_id[event_id].push_back(caen1290tdchit);
4618 break;
4619 case 0b00100: // TDC Error
4620 error_flags = (*iptr) & 0x7fff;
4621 if(VERBOSE>7) evioout << " CAEN TDC TDC Error (err flags=0x" << hex << error_flags << dec << ")" << endl;
4622 break;
4623 case 0b00011: // TDC Trailer
4624 tdc_num = ((*iptr)>>24) & 0x03;
4625 event_id = ((*iptr)>>12) & 0x0fff;
4626 word_count = ((*iptr)>>0) & 0x0fff;
4627 if(VERBOSE>7) evioout << " CAEN TDC TDC Trailer (tdc=" << tdc_num <<" , event id=" << event_id <<" , word count=" << word_count << ")" << endl;
4628 tdc_num = event_id = bunch_id = 0;
4629 break;
4630 case 0b11000: // Filler Word
4631 if(VERBOSE>7) evioout << " CAEN TDC Filler Word" << endl;
4632 break;
4633 default:
4634 evioout << "Unknown datatype: 0x" << hex << type << " full word: "<< *iptr << dec << endl;
4635 }
4636
4637 iptr++;
4638 }
4639
4640 // If disentagling is disabled, then lump all hits into single event
4641 if( (!ENABLE_DISENTANGLING) && (event_id_order.size()>1) ){
4642 if(VERBOSE>2) evioout << " Disentangling disabled. Merging all hits into single event" << endl;
4643 vector<DCAEN1290TDCHit*> &hits1 = hits_by_event_id[event_id_order[0]];
4644 for(uint32_t i=1; i<event_id_order.size(); i++){
4645 vector<DCAEN1290TDCHit*> &hits2 = hits_by_event_id[event_id_order[i]];
4646 hits1.insert(hits1.end(), hits2.begin(), hits2.end()); // copy hits into first event
4647 hits_by_event_id.erase(event_id_order[i]); // remove hits list for this event_id
4648 }
4649 }
4650
4651 // Add hits for each event to the events container, creating ObjList's as needed
4652 for(uint32_t i=0; i<event_id_order.size(); i++){
4653
4654 // Make sure there are enough event containers to hold this event
4655 while(events.size() <= i) events.push_back(new ObjList);
4656 list<ObjList*>::iterator it = events.begin();
4657 advance(it, i);
4658 ObjList *objs = *it;
4659
4660 vector<DCAEN1290TDCHit*> &hits = hits_by_event_id[event_id_order[i]];
4661 objs->hit_objs.insert(objs->hit_objs.end(), hits.begin(), hits.end());
4662
4663 if(VERBOSE>7) evioout << " Added " << hits.size() << " hits with event_id=" << event_id_order[i] << " to event " << i << endl;
4664 }
4665
4666}
4667
4668//----------------
4669// ParseBORevent
4670//----------------
4671void JEventSource_EVIO::ParseBORevent(evioDOMNodeP bankPtr)
4672{
4673 if(!PARSE_BOR) return;
4674
4675 // This really shouldn't be needed
4676 pthread_rwlock_wrlock(&BOR_lock);
4677
4678 // Delete any existing BOR config objects. BOR events should
4679 // be flagged as sequential (or barrier) events so all threads
4680 // that were using these should be done with them now.
4681 for(uint32_t i=0; i<BORobjs.size(); i++) delete BORobjs[i];
4682 BORobjs.clear();
4683
4684 evioDOMNodeListP bankList = bankPtr->getChildren();
4685 evioDOMNodeList::iterator iter = bankList->begin();
4686 if(VERBOSE>7) evioout << " Looping over " << bankList->size() << " banks in BOR event" << endl;
4687 for(int ibank=1; iter!=bankList->end(); iter++, ibank++){ // ibank only used for debugging messages
4688 evioDOMNodeP childBank = *iter;
4689
4690 if(childBank->tag==0x71){
4691 // uint32_t rocid = childBank->num;
4692 evioDOMNodeListP bankList = childBank->getChildren();
4693 evioDOMNodeList::iterator iter = bankList->begin();
4694 for(; iter!=bankList->end(); iter++){
4695 evioDOMNodeP dataBank = *iter;
4696 // uint32_t slot = dataBank->tag>>5;
4697 uint32_t modType = dataBank->tag&0x1f;
4698
4699 const vector<uint32_t> *vec = dataBank->getVector<uint32_t>();
4700
4701 const uint32_t *src = &(*vec)[0];
4702 uint32_t *dest = NULL__null;
4703 uint32_t sizeof_dest = 0;
4704
4705 Df250BORConfig *f250conf = NULL__null;
4706 Df125BORConfig *f125conf = NULL__null;
4707 DF1TDCBORConfig *F1TDCconf = NULL__null;
4708 DCAEN1290TDCBORConfig *caen1190conf = NULL__null;
4709
4710 switch(modType){
4711 case DModuleType::FADC250: // f250
4712 f250conf = new Df250BORConfig;
4713 dest = (uint32_t*)&f250conf->rocid;
4714 sizeof_dest = sizeof(f250config);
4715 break;
4716 case DModuleType::FADC125: // f125
4717 f125conf = new Df125BORConfig;
4718 dest = (uint32_t*)&f125conf->rocid;
4719 sizeof_dest = sizeof(f125config);
4720 break;
4721
4722 case DModuleType::F1TDC32: // F1TDCv2
4723 case DModuleType::F1TDC48: // F1TDCv3
4724 F1TDCconf = new DF1TDCBORConfig;
4725 dest = (uint32_t*)&F1TDCconf->rocid;
4726 sizeof_dest = sizeof(F1TDCconfig);
4727 break;
4728
4729 case DModuleType::CAEN1190: // CAEN 1190 TDC
4730 case DModuleType::CAEN1290: // CAEN 1290 TDC
4731 caen1190conf = new DCAEN1290TDCBORConfig;
4732 dest = (uint32_t*)&caen1190conf->rocid;
4733 sizeof_dest = sizeof(caen1190config);
4734 break;
4735 }
4736
4737 // Check that the bank size and data structure size match.
4738 // If they do, then copy the data and add the object to
4739 // the event. If not, then delete the object and print
4740 // a warning message.
4741 if( vec->size() == (sizeof_dest/sizeof(uint32_t)) ){
4742
4743 // Copy bank data, assuming format is the same
4744 for(uint32_t i=0; i<vec->size(); i++) *dest++ = *src++;
4745
4746 // Store object for use in this and subsequent events
4747 if(f250conf) BORobjs.push_back(f250conf);
4748 if(f125conf) BORobjs.push_back(f125conf);
4749 if(F1TDCconf) BORobjs.push_back(F1TDCconf);
4750 if(caen1190conf) BORobjs.push_back(caen1190conf);
4751
4752 }else if(sizeof_dest>0){
4753 if(f250conf) delete f250conf;
4754 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<4754<<" "
<< "BOR bank size does not match structure! " << vec->size() <<" != " << (sizeof_dest/sizeof(uint32_t)) << endl;
4755 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<4755<<" "
<< "sizeof(f250config)="<<sizeof(f250config)<<endl;
4756 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<4756<<" "
<< "sizeof(f125config)="<<sizeof(f125config)<<endl;
4757 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<4757<<" "
<< "sizeof(F1TDCconfig)="<<sizeof(F1TDCconfig)<<endl;
4758 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<4758<<" "
<< "sizeof(caen1190config)="<<sizeof(caen1190config)<<endl;
4759 }
4760 }
4761 }
4762 }
4763
4764 pthread_rwlock_unlock(&BOR_lock);
4765
4766}
4767
4768
4769
4770//------------------
4771// ParseFA250Scalers
4772//------------------
4773// Read out fadc250 scalers at sync events
4774// for all boards in the crate.
4775// The data format: slot + 16 scalers
4776void JEventSource_EVIO::ParseFA250Scalers(evioDOMNodeP bankPtr, list<ObjList*> &events, uint32_t rocid){
4777
4778 const vector<uint32_t> *vec = bankPtr->getVector<uint32_t>();
4779
4780 if(vec->size() > 0){
4781 Df250Scaler *sc = new Df250Scaler;
4782
4783 sc->nsync = (*vec)[0];
4784 sc->trig_number = (*vec)[1];
4785 sc->version = (*vec)[2];
4786
4787 sc->crate = rocid;
4788
4789 for(uint32_t ii = 3; ii < vec->size(); ii++){
4790 sc->fa250_sc.push_back((*vec)[ii]);
4791 }
4792
4793 if(events.empty()){
4794 events.push_back(new ObjList());
4795 }
4796
4797 ObjList *objs = *(events.begin());
4798
4799 objs->misc_objs.push_back(sc);
4800 } else {
4801 evioout << " SYNC event: inconsistent format for FA250Scalers. Don't parse " << endl;
4802 }
4803
4804}
4805
4806//-------------------------
4807// ParseFA250AsyncPedestals
4808//-------------------------
4809// Read out fadc250 asynchronous pedestals at sync events
4810// for all boards in the crate.
4811// The data format: slot + 8 32-bit words (ped1, ped2)
4812void JEventSource_EVIO::ParseFA250AsyncPedestals(evioDOMNodeP bankPtr, list<ObjList*> &events, uint32_t rocid){
4813
4814
4815 const vector<uint32_t> *vec = bankPtr->getVector<uint32_t>();
4816
4817 if(vec->size() > 0){
4818
4819 Df250AsyncPedestal *ped = new Df250AsyncPedestal;
4820
4821 ped->nsync = (*vec)[0];
4822 ped->trig_number = (*vec)[1];
4823
4824 ped->crate = rocid;
4825
4826 for(uint32_t ii = 2; ii < vec->size(); ii++){
4827 ped->fa250_ped.push_back((*vec)[ii]);
4828 }
4829
4830 if(events.empty()){
4831 events.push_back(new ObjList());
4832 }
4833
4834 ObjList *objs = *(events.begin());
4835
4836 objs->misc_objs.push_back(ped);
4837 } else {
4838 evioout << " SYNC event: inconsistent format for FA250AsyncPedestals. Don't parse " << endl;
4839 }
4840
4841}
4842
4843
4844//----------------
4845// ParseTSSync event
4846//----------------
4847void JEventSource_EVIO::ParseTSSync(evioDOMNodeP bankPtr, list<ObjList*> &events)
4848{
4849
4850 DL1Info *trig_info = new DL1Info;
4851
4852 // cout << " INSIDE ParseTSSync " << endl;
4853
4854 if((bankPtr->tag & 0xFFFF) == 0xEE02){
4855 const vector<uint32_t> *vec = bankPtr->getVector<uint32_t>();
4856
4857
4858
4859 trig_info->nsync = (*vec)[0];
4860 trig_info->trig_number = (*vec)[1];
4861 trig_info->live_time = (*vec)[2];
4862 trig_info->busy_time = (*vec)[3];
4863 trig_info->live_inst = (*vec)[4];
4864 trig_info->unix_time = (*vec)[5];
4865
4866
4867
4868 // GTP scalers
4869 for(uint32_t ii = 6; ii < 38; ii++){
4870 trig_info->gtp_sc.push_back((*vec)[ii]);
4871 }
4872
4873 // FP scalers
4874 for(uint32_t ii = 38; ii < 54; ii++){
4875 trig_info->fp_sc.push_back((*vec)[ii]);
4876 }
4877
4878 // GTP rate
4879 for(uint32_t ii = 54; ii < 86; ii++){
4880 trig_info->gtp_rate.push_back((*vec)[ii]);
4881 }
4882
4883 // FP rate
4884 for(uint32_t ii = 86; ii < 102; ii++){
4885 trig_info->fp_rate.push_back((*vec)[ii]);
4886 }
4887 }
4888
4889
4890 if(events.empty()){
4891 events.push_back(new ObjList());
4892 // cout << " TSSync: Empty event " << endl;
4893 }
4894
4895 ObjList *objs = *(events.begin());
4896
4897 objs->misc_objs.push_back(trig_info);
4898
4899
4900}
4901
4902//----------------
4903// ParseDVertexBank
4904//----------------
4905void JEventSource_EVIO::ParseDVertexBank(evioDOMNodeP bankPtr, list<ObjList*> &events)
4906{
4907 const vector<uint32_t> *vec = bankPtr->getVector<uint32_t>();
4908
4909 if(vec->size() != 11) {
4910
4911 DVertex* the_vertex = new DVertex();
4912
4913 uint64_t lo_word = (*vec)[0];
4914 uint64_t hi_word = (*vec)[1];
4915 double vertex_x_pos = static_cast<double>( lo_word | (hi_word<<32) );
4916 lo_word = (*vec)[2];
4917 hi_word = (*vec)[3];
4918 double vertex_y_pos = static_cast<double>( lo_word | (hi_word<<32) );
4919 lo_word = (*vec)[4];
4920 hi_word = (*vec)[5];
4921 double vertex_z_pos = static_cast<double>( lo_word | (hi_word<<32) );
4922 lo_word = (*vec)[6];
4923 hi_word = (*vec)[7];
4924 double vertex_t = static_cast<double>( lo_word | (hi_word<<32) );
4925
4926 DVector3 vertex_position(vertex_x_pos, vertex_y_pos, vertex_z_pos);
4927 the_vertex->dSpacetimeVertex = DLorentzVector(vertex_position, vertex_t);
4928 the_vertex->dKinFitNDF = (*vec)[8];
4929
4930 lo_word = (*vec)[9];
4931 hi_word = (*vec)[10];
4932 the_vertex->dKinFitChiSq = static_cast<double>( lo_word | (hi_word<<32) );
4933
4934 if(events.empty()) {
4935 events.push_back(new ObjList());
4936 }
4937
4938 ObjList *objs = *(events.begin());
4939
4940 objs->misc_objs.push_back(the_vertex);
4941
4942 } else {
4943 evioout << " DVertex bank: inconsistent bank format. Don't parse " << endl;
4944 }
4945
4946}
4947
4948
4949
4950//----------------
4951// ParseEPICSevent
4952//----------------
4953void JEventSource_EVIO::ParseEPICSevent(evioDOMNodeP bankPtr, list<ObjList*> &events)
4954{
4955 if(!PARSE_EPICS) return;
4956
4957 time_t timestamp=0;
4958
4959 ObjList *objs = NULL__null;
4960
4961 evioDOMNodeListP bankList = bankPtr->getChildren();
4962 evioDOMNodeList::iterator iter = bankList->begin();
4963 if(VERBOSE>7) evioout << " Looping over " << bankList->size() << " banks in EPICS event" << endl;
4964 for(int ibank=1; iter!=bankList->end(); iter++, ibank++){ // ibank only used for debugging messages
4965 evioDOMNodeP childBank = *iter;
4966
4967 if(childBank->tag == 97){
4968 // timestamp bank
4969 const vector<uint32_t> *vec = childBank->getVector<uint32_t>();
4970 if(vec) {
4971 timestamp = (time_t)(*vec)[0];
4972 if(VERBOSE>7) evioout << " timestamp: " << ctime(&timestamp);
4973 }
4974 }else if(childBank->tag==98){
4975 const vector<uint8_t> *vec = childBank->getVector<uint8_t>();
4976 if(vec){
4977 string nameval = (const char*)&((*vec)[0]);
4978 DEPICSvalue *epicsval = new DEPICSvalue(timestamp, nameval);
4979 if(VERBOSE>7) evioout << " " << nameval << endl;
4980
4981 if(!objs){
4982 if(events.empty()) events.push_back(new ObjList);
4983 objs = *(events.begin());
4984 }
4985 objs->misc_objs.push_back(epicsval);
4986 }
4987 }
4988 }
4989}
4990
4991//----------------
4992// DumpBinary
4993//----------------
4994void JEventSource_EVIO::DumpBinary(const uint32_t *iptr, const uint32_t *iend, uint32_t MaxWords, const uint32_t *imark)
4995{
4996 /// This is used for debugging. It will print to the screen the words
4997 /// starting at the address given by iptr and ending just before iend
4998 /// or for MaxWords words, whichever comes first. If iend is NULL,
4999 /// then MaxWords will be printed. If MaxWords is zero then it is ignored
5000 /// and only iend is checked. If both iend==NULL and MaxWords==0, then
5001 /// only the word at iptr is printed.
5002
5003 cout << "Dumping binary: istart=" << hex << iptr << " iend=" << iend << " MaxWords=" << dec << MaxWords << endl;
5004
5005 if(iend==NULL__null && MaxWords==0) MaxWords=1;
5006 if(MaxWords==0) MaxWords = (uint32_t)0xffffffff;
5007
5008 uint32_t Nwords=0;
5009 while(iptr!=iend && Nwords<MaxWords){
5010
5011 // line1 is hex and line2 is decimal
5012 stringstream line1, line2;
5013
5014 // print words in columns 8 words wide. First part is
5015 // reserved for word number
5016 uint32_t Ncols = 8;
5017 line1 << setw(5) << Nwords;
5018 line2 << string(5, ' ');
5019
5020 // Loop over columns
5021 for(uint32_t i=0; i<Ncols; i++, iptr++, Nwords++){
5022
5023 if(iptr == iend) break;
5024 if(Nwords>=MaxWords) break;
5025
5026 stringstream iptr_hex;
5027 iptr_hex << hex << "0x" << *iptr;
5028
5029 string mark = (iptr==imark ? "*":" ");
5030
5031 line1 << setw(12) << iptr_hex.str() << mark;
5032 line2 << setw(12) << *iptr << mark;
5033 }
5034
5035 cout << line1.str() << endl;
5036 cout << line2.str() << endl;
5037 cout << endl;
5038 }
5039}
5040
5041#endif // HAVE_EVIO
5042
5043#if 0
5044//----------------
5045// GuessModuleType
5046//----------------
5047MODULE_TYPE JEventSource_EVIO::GuessModuleType(const uint32_t* istart, const uint32_t* iend, evioDOMNodeP bankPtr)
5048{
5049 /// Try parsing through the information in the given data buffer
5050 /// to determine which type of module produced the data.
5051
5052 if(IsFADC250(istart, iend)) return DModuleType::FADC250;
5053 if(IsF125ADC(istart, iend)) return DModuleType::F125ADC;
5054 if(IsF1TDC(istart, iend)) return DModuleType::F1TDC;
5055 if(IsTS(istart, iend)) return DModuleType::JLAB_TS;
5056 if(IsTI(istart, iend)) return DModuleType::JLAB_TID;
5057
5058
5059 // Couldn't figure it out...
5060 return DModuleType::UNKNOWN;
5061}
5062
5063//----------------
5064// IsFADC250
5065//----------------
5066bool JEventSource_EVIO::IsFADC250(const uint32_t *istart, const uint32_t *iend)
5067{
5068 //---- Check for f250
5069 // This will check if the first word appears to be a block header.
5070 // If so, it loops over all words looking for a block trailer.
5071 // If the slot number in the block trailer matches that in the
5072 // block header AND the number of words in the block matches that
5073 // specified in the block trailer, then it is assumed to be a f250.
5074 if(((*istart>>31) & 0x1) == 1){
5075 uint32_t data_type = (*istart>>27) & 0x0F;
5076 if(data_type == 0){ // Block Header
5077 uint32_t slot_header = (*istart>>22) & 0x1F;
5078 uint32_t Nwords = 1;
5079 for(const uint32_t *iptr=istart; iptr<iend; iptr++, Nwords++){
5080 if(((*iptr>>31) & 0x1) == 1){
5081 uint32_t data_type = (*iptr>>27) & 0x0F;
5082 if(data_type == 1){ // Block Trailer
5083 uint32_t slot_trailer = (*iptr>>22) & 0x1F;
5084 uint32_t Nwords_trailer = (*iptr>>0) & 0x3FFFFF;
5085
5086 if( slot_header == slot_trailer && Nwords == Nwords_trailer ){
5087 return true;
5088 }else{
5089 return false;
5090 }
5091 }
5092 }
5093 }
5094 }
5095 }
5096
5097 // either first word was not a block header or no block trailer was found
5098 return false;
5099}
5100
5101//----------------
5102// IsF1TDC
5103//----------------
5104bool JEventSource_EVIO::IsF1TDC(const uint32_t *istart, const uint32_t *iend)
5105{
5106 //---- Check for F1TDC
5107 // This will check for consistency in the slot numbers for all words
5108 // in the buffer. The slot number of data words are checked against
5109 // the slot number of the most recently encountered header word.
5110 uint32_t slot_header = 1000;
5111 uint32_t slot_trailer = 1000;
5112
5113 const uint32_t *iptr=istart;
5114
5115 // skip first word which appears to be ROL marker for F1TDC data
5116 if(*istart == 0xf1daffff)iptr++
5117
5118 // There is no distinction between header and trailer
5119 // words other than the order that they appear. We keep
5120 // track by flipping this value
5121 bool looking_for_header = true;
5122
5123 // Keep track of the number of valid blocks of F1TDC data we find
5124 // (i.e. ones where the header and trailer words were found
5125 int Nvalid = 0;
5126
5127 for(; iptr<iend; iptr++){
5128
5129 // ROL end of data marker (only in test setup data)
5130 if(*iptr == 0xda0000ff)break;
5131
5132 uint32_t slot = (*iptr>>27) & 0x1F;
5133
5134 // if slot is 0 or 30, we are supposed to ignore the data.
5135 if(slot == 30 || slot ==0)continue;
5136
5137 if(((*iptr>>23) & 0x1) == 0){
5138 // header/trailer word
5139 if(looking_for_header){
5140 slot_header = slot;
5141 looking_for_header = false;
5142 }else{
5143 slot_trailer = slot;
5144 if(slot_trailer != slot_header)return false;
5145 looking_for_header = true;
5146 Nvalid++;
5147 }
5148 }else{
5149 // data word
5150
5151 // if we encounter a data word when we are expecting
5152 // a header word, then the current word is not from
5153 // an F1TDC. However, if we did find at least one valid
5154 // block at the begining, of the buffer, claim the buffer
5155 // points to F1TDC data. We check for as many valid F1TDC
5156 // blocks as possible to help ensure that is what the data
5157 // is.
5158 if(looking_for_header)return Nvalid>0;
5159
5160 // If the slot number does not match, then this is
5161 // not valid F1TDC data
5162 if(slot != slot_header)return false;
5163 }
5164 }
5165
5166 return Nvalid>0;
5167}
5168
5169//----------------
5170// DumpModuleMap
5171//----------------
5172void JEventSource_EVIO::DumpModuleMap(void)
5173{
5174 // Open output file
5175 string fname = "module_map.txt";
5176 ofstream ofs(fname.c_str());
5177 if(!ofs.is_open()){
5178 jerr<<"Unable to open file \""<<fname<<"\" for writing!"<<endl;
5179 return;
5180 }
5181
5182 jout<<"Writing module map to file \""<<fname<<"\""<<endl;
5183
5184 // Write header
5185 time_t now = time(NULL__null);
5186 ofs<<"# Autogenerated module map"<<endl;
5187 ofs<<"# Created: "<<ctime(&now);
5188 ofs<<"#"<<endl;
5189
5190 // Write known module types in header
5191 vector<DModuleType> modules;
5192 DModuleType::GetModuleList(modules);
5193 ofs<<"# Known module types:"<<endl;
5194 ofs<<"# ----------------------"<<endl;
5195 for(unsigned int i=0; i<modules.size(); i++){
5196 string name = modules[i].GetName();
5197 string space(12-name.size(), ' ');
5198 ofs << "# " << name << space << " - " << modules[i].GetDescription() <<endl;
5199 }
5200 ofs<<"#"<<endl;
5201 ofs<<"#"<<endl;
5202
5203 // Write module map
5204 ofs<<"# Format is:"<<endl;
5205 ofs<<"# tag num type"<<endl;
5206 ofs<<"#"<<endl;
5207
5208 map<tagNum, MODULE_TYPE>::iterator iter = module_type.begin();
5209 for(; iter!=module_type.end(); iter++){
5210
5211 tagNum tag_num = iter->first;
5212 MODULE_TYPE type = iter->second;
5213 ofs<<tag_num.first<<" "<<(int)tag_num.second<<" "<<DModuleType::GetName(type)<<endl;
5214 }
5215 ofs<<endl;
5216
5217 // Close output file
5218 ofs.close();
5219}
5220#endif