Bug Summary

File:libraries/DAQ/JEventSource_EVIO.cc
Location:line 980, column 4
Description:Potential leak of memory pointed to by 'c'

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