Bug Summary

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