Bug Summary

File:libraries/DAQ/JEventSource_EVIO.cc
Location:line 4579, column 67
Description:Dereference of null pointer

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