Bug Summary

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

Annotated Source Code

1// $Id$
2// $HeadURL$
3//
4// File: JEventSource_EVIO.cc
5// Created: Tue Aug 7 15:22:29 EDT 2012
6// Creator: davidl (on Darwin harriet.jlab.org 11.4.0 i386)
7//
8
9// See comments in JEventSource_EVIO.h for overview description
10
11#include <unistd.h>
12#include <stdint.h>
13
14#include <string>
15#include <cmath>
16#include <iomanip>
17using namespace std;
18
19
20// This flag allows us to switch back and forth from using HDEVIO and
21// the CODA-supplied EVIO
22#define USE_HDEVIO1 1
23
24//#define ENABLE_UPSAMPLING
25
26#ifdef HAVE_EVIO1
27
28#if USE_HDEVIO1 == 0
29#include <evioFileChannel.hxx>
30#endif
31
32extern "C" uint32_t *swap_int32_t(uint32_t *data, unsigned int length, uint32_t *dest);
33#endif // HAVE_EVIO
34
35#ifdef HAVE_ET
36//#include <evioETChannel.hxx>
37#include <et.h>
38#endif // HAVE_ET
39
40#include "JEventSourceGenerator_EVIO.h"
41//#include "JFactoryGenerator_DAQ.h"
42#include "JEventSource_EVIO.h"
43
44using namespace jana;
45
46#include <DANA/DStatusBits.h>
47#include <TTAB/DTranslationTable.h>
48#include <TTAB/DTranslationTable_factory.h>
49#include <DAQ/Df125EmulatorAlgorithm_factory.h>
50#include <DAQ/Df250EmulatorAlgorithm_factory.h>
51
52#define _DBG_DAQ(A)cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<":"<<
52<<" 0x"<<hex<<A<<" cntrl:0x"<<
(A&0xF0000000)<<dec<<" slot:"<<((A>>
22)&0x1F)<<endl
cerr<<__FILE__"libraries/DAQ/JEventSource_EVIO.cc"<<":"<<__LINE__52<<" 0x"<<hex<<A<<" cntrl:0x"<<(A&0xF0000000)<<dec<<" slot:"<<((A>>22)&0x1F)<<endl
53
54// Make us a plugin
55#include <JANA/JApplication.h>
56//extern "C"{
57// void InitPlugin(JApplication *app){
58// InitJANAPlugin(app);
59// app->AddEventSourceGenerator(new JEventSourceGenerator_EVIO());
60// app->AddFactoryGenerator(new JFactoryGenerator_DAQ());
61// }
62//} // "C"
63
64// if we don't find a run number in the file, then it's nice to let the user know
65static bool WARN_USER_RUN_FILENAME = false;
66
67set<uint32_t> ROCIDS_TO_PARSE;
68
69//:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
70// If EVIO support is not available, define dummy methods
71#ifndef HAVE_EVIO1
72JEventSource_EVIO::JEventSource_EVIO(const char* source_name):JEventSource(source_name){
73 cerr << endl;
74 cerr << "You are trying to use code requiring EVIO when support" << endl;
75 cerr << "for EVIO was not built into this binary. Set your" << endl;
76 cerr << "EVIOROOT *and* your ETROOT environment variables to" << endl;
77 cerr << "point to your EVIO installation and recompile." << endl;
78 cerr << endl;
79 exit(-1);
80}
81 JEventSource_EVIO::~JEventSource_EVIO(){}
82jerror_t JEventSource_EVIO::GetEvent(jana::JEvent &event){return NOERROR;}
83 void JEventSource_EVIO::FreeEvent(jana::JEvent &event){}
84jerror_t JEventSource_EVIO::GetObjects(jana::JEvent &event, jana::JFactory_base *factory){return NOERROR;}
85jerror_t JEventSource_EVIO::ReadEVIOEvent(uint32_t* &buf){return NOERROR;}
86//:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
87
88#else // HAVE_EVIO
89
90//----------------
91// Constructor
92//----------------
93JEventSource_EVIO::JEventSource_EVIO(const char* source_name):JEventSource(source_name)
94{
95 // Initialize connection objects and flags to NULL
96 et_connected = false;
97 //chan = NULL;
98 hdevio = NULL__null;
99 source_type = kNoSource;
100 quit_on_next_ET_timeout = false;
101
102 // Initialize dedicated JStreamLog used for debugging messages
103 evioout.SetTag("--- EVIO ---: ");
104 evioout.SetTimestampFlag();
105 evioout.SetThreadstampFlag();
106
107 // Define base set of status bits
108 if(japp) DStatusBits::SetStatusBitDescriptions(japp);
109
110 // Get configuration parameters
111 AUTODETECT_MODULE_TYPES = true;
112 DUMP_MODULE_MAP = false;
113 MAKE_DOM_TREE = true;
114 PARSE_EVIO_EVENTS = true;
115 PARSE_F250 = true;
116 PARSE_F125 = true;
117 PARSE_F1TDC = true;
118 PARSE_CAEN1290TDC = true;
119 PARSE_CONFIG = true;
120 PARSE_BOR = true;
121 PARSE_EPICS = true;
122 PARSE_EVENTTAG = true;
123 PARSE_TRIGGER = true;
124 BUFFER_SIZE = 20000000; // in bytes
125 ET_STATION_NEVENTS = 10;
126 ET_STATION_CREATE_BLOCKING = false;
127 ET_DEBUG_WORDS_TO_DUMP = 0;
128 LOOP_FOREVER = false;
129 VERBOSE = 0;
130 TIMEOUT = 2.0;
131 MODTYPE_MAP_FILENAME = "modtype.map";
132 ENABLE_DISENTANGLING = true;
133
134 F125_EMULATION_MODE = kEmulationAuto;
135 F250_EMULATION_MODE = kEmulationAuto;
136
137 USER_RUN_NUMBER = 0;
138 F125PULSE_NUMBER_FILTER = 1000;
139 F250PULSE_NUMBER_FILTER = 1000;
140
141 if(gPARMS){
142 // JANA doesn't know about EmulationModeType so we use temporary variables
143 uint32_t f250_emulation_mode = F250_EMULATION_MODE;
144 uint32_t f125_emulation_mode = F125_EMULATION_MODE;
145
146 gPARMS->SetDefaultParameter("EVIO:AUTODETECT_MODULE_TYPES", AUTODETECT_MODULE_TYPES, "Try and guess the module type tag,num values for which there is no module map entry.");
147 gPARMS->SetDefaultParameter("EVIO:DUMP_MODULE_MAP", DUMP_MODULE_MAP, "Write module map used to file when source is destroyed. n.b. If more than one input file is used, the map file will be overwritten!");
148 gPARMS->SetDefaultParameter("EVIO:MAKE_DOM_TREE", MAKE_DOM_TREE, "Set this to 0 to disable generation of EVIO DOM Tree and parsing of event. (for benchmarking/debugging)");
149 gPARMS->SetDefaultParameter("EVIO:PARSE_EVIO_EVENTS", PARSE_EVIO_EVENTS, "Set this to 0 to disable parsing of event but still make the DOM tree, so long as MAKE_DOM_TREE isn't set to 0. (for benchmarking/debugging)");
150 gPARMS->SetDefaultParameter("EVIO:PARSE_F250", PARSE_F250, "Set this to 0 to disable parsing of data from F250 ADC modules (for benchmarking/debugging)");
151 gPARMS->SetDefaultParameter("EVIO:PARSE_F125", PARSE_F125, "Set this to 0 to disable parsing of data from F125 ADC modules (for benchmarking/debugging)");
152 gPARMS->SetDefaultParameter("EVIO:PARSE_F1TDC", PARSE_F1TDC, "Set this to 0 to disable parsing of data from F1TDC modules (for benchmarking/debugging)");
153 gPARMS->SetDefaultParameter("EVIO:PARSE_CAEN1290TDC", PARSE_CAEN1290TDC, "Set this to 0 to disable parsing of data from CAEN 1290 TDC modules (for benchmarking/debugging)");
154 gPARMS->SetDefaultParameter("EVIO:PARSE_CONFIG", PARSE_CONFIG, "Set this to 0 to disable parsing of ROC configuration data in the data stream (for benchmarking/debugging)");
155 gPARMS->SetDefaultParameter("EVIO:PARSE_BOR", PARSE_BOR, "Set this to 0 to disable parsing of BOR events from the data stream (for benchmarking/debugging)");
156 gPARMS->SetDefaultParameter("EVIO:PARSE_EPICS", PARSE_EPICS, "Set this to 0 to disable parsing of EPICS events from the data stream (for benchmarking/debugging)");
157 gPARMS->SetDefaultParameter("EVIO:PARSE_EVENTTAG", PARSE_EVENTTAG, "Set this to 0 to disable parsing of event tag data in the data stream (for benchmarking/debugging)");
158 gPARMS->SetDefaultParameter("EVIO:PARSE_TRIGGER", PARSE_TRIGGER, "Set this to 0 to disable parsing of the built trigger bank from CODA (for benchmarking/debugging)");
159
160 gPARMS->SetDefaultParameter("EVIO:BUFFER_SIZE", BUFFER_SIZE, "Size in bytes to allocate for holding a single EVIO event.");
161 gPARMS->SetDefaultParameter("EVIO:ET_STATION_NEVENTS", ET_STATION_NEVENTS, "Number of events to use if we have to create the ET station. Ignored if station already exists.");
162 gPARMS->SetDefaultParameter("EVIO:ET_STATION_CREATE_BLOCKING", ET_STATION_CREATE_BLOCKING, "Set this to 0 to create station in non-blocking mode (default is to create it in blocking mode). Ignored if station already exists.");
163 gPARMS->SetDefaultParameter("EVIO:ET_DEBUG_WORDS_TO_DUMP", ET_DEBUG_WORDS_TO_DUMP, "Number of words to dump to screen from ET buffer (useful for debugging only).");
164 gPARMS->SetDefaultParameter("EVIO:LOOP_FOREVER", LOOP_FOREVER, "If reading from EVIO file, keep re-opening file and re-reading events forever (only useful for debugging) If reading from ET, this is ignored.");
165 gPARMS->SetDefaultParameter("EVIO:VERBOSE", VERBOSE, "Set verbosity level for processing and debugging statements while parsing. 0=no debugging messages. 10=all messages");
166 gPARMS->SetDefaultParameter("ET:TIMEOUT", TIMEOUT, "Set the timeout in seconds for each attempt at reading from ET system (repeated attempts will still be made indefinitely until program quits or the quit_on_et_timeout flag is set.");
167 gPARMS->SetDefaultParameter("EVIO:MODTYPE_MAP_FILENAME", MODTYPE_MAP_FILENAME, "Optional module type conversion map for use with files generated with the non-standard module types");
168 gPARMS->SetDefaultParameter("EVIO:ENABLE_DISENTANGLING", ENABLE_DISENTANGLING, "Enable/disable disentangling of multi-block events. Enabled by default. Set to 0 to disable.");
169
170 gPARMS->SetDefaultParameter("EVIO:F250_EMULATION_MODE", f250_emulation_mode, "Set f250 emulation mode. 0=no emulation, 1=always, 2=auto. Default is 2 (auto).");
171 gPARMS->SetDefaultParameter("EVIO:F125_EMULATION_MODE", f125_emulation_mode, "Set f125 emulation mode. 0=no emulation, 1=always, 2=auto. Default is 2 (auto).");
172
173 gPARMS->SetDefaultParameter("EVIO:RUN_NUMBER", USER_RUN_NUMBER, "User-supplied run number. Override run number from other sources with this.(will be ignored if set to zero)");
174 gPARMS->SetDefaultParameter("EVIO:F125PULSE_NUMBER_FILTER", F125PULSE_NUMBER_FILTER, "Ignore data for DF125XXX objects with a pulse number equal or greater than this.");
175 gPARMS->SetDefaultParameter("EVIO:F250PULSE_NUMBER_FILTER", F250PULSE_NUMBER_FILTER, "Ignore data for DF250XXX objects with a pulse number equal or greater than this.");
176
177 F250_EMULATION_MODE = (EmulationModeType)f250_emulation_mode;
178 F125_EMULATION_MODE = (EmulationModeType)f125_emulation_mode;
179 }
180
181 // Try to open the file.
182 try {
183
184 if(VERBOSE>0) evioout << "Attempting to open \""<<this->source_name<<"\" as EVIO file..." <<endl;
185
186#if USE_HDEVIO1
187 //---------- HDEVIO ------------
188 hdevio = new HDEVIO(this->source_name);
189 if( ! hdevio->is_open ) throw std::exception(); // throw exception if unable to open
190#else // USE_HDEVIO
191 //-------- CODA EVIO -----------
192 jerr << "You are attempting to use the CODA Channels library for reading" << endl;
193 jerr << "and EVIO file and this mechanism has been disabled from in the" << endl;
194 jerr << "DAQ library. Contact davidl@jlab.org if you need this to be" << endl;
195 jerr << "reinstated." << endl;
196 quit(0);
197 //chan = new evioFileChannel(this->source_name, "r", BUFFER_SIZE);
198 //chan->open(); // open the file. Throws exception if not successful
199
200#endif // USE_HDEVIO
201
202 source_type = kFileSource;
203
204 } catch (std::exception &e) {
205
206#ifdef HAVE_ET
207 // Could not open file. Check if name starts with "ET:"
208 //chan = NULL;
209 if(this->source_name.substr(0,3) == "ET:"){
210 if(VERBOSE>0) evioout << "Attempting to open \""<<this->source_name<<"\" as ET (network) source..." <<endl;
211 ConnectToET(source_name);
212 }
213
214 if(!et_connected) throw JException("Failed to open ET system: " + this->source_name);
215
216 // open the channel. Throws exception if not successful
217 // chan->open(); // evioETchannel no longer used
218 source_type = kETSource;
219
220#else // HAVE_ET
221
222 // No ET and the file didn't work so re-throw the exception
223 if(this->source_name.substr(0,3) == "ET:"){
224 cerr << endl;
225 cerr << "=== ERROR: ET source specified and this was compiled without ===" << endl;
226 cerr << "=== ET support. You need to install ET and set your ===" << endl;
227 cerr << "=== ETROOT environment variable appropriately before ===" << endl;
228 cerr << "=== recompiling. ===" << endl;
229 cerr << endl;
230 }
231 throw e;
232
233#endif // HAVE_ET
234 }
235 if(VERBOSE>0) evioout << "Success opening event source \"" << this->source_name << "\"!" <<endl;
236
237
238 // Create list of data types this event source can provide
239 // (must match what is returned by JObject::className() )
240 // n.b. there is an ugly hack down in GetObjects that will
241 // probably also need a line added for each data type added
242 // here.
243 event_source_data_types.insert("Df250Config");
244 event_source_data_types.insert("Df250PulseIntegral");
245 event_source_data_types.insert("Df250StreamingRawData");
246 event_source_data_types.insert("Df250WindowSum");
247 event_source_data_types.insert("Df250PulseRawData");
248 event_source_data_types.insert("Df250TriggerTime");
249 event_source_data_types.insert("Df250PulseTime");
250 event_source_data_types.insert("Df250PulsePedestal");
251 event_source_data_types.insert("Df250WindowRawData");
252 event_source_data_types.insert("Df125Config");
253 event_source_data_types.insert("Df125PulseIntegral");
254 event_source_data_types.insert("Df125TriggerTime");
255 event_source_data_types.insert("Df125PulseTime");
256 event_source_data_types.insert("Df125PulsePedestal");
257 event_source_data_types.insert("Df125WindowRawData");
258 event_source_data_types.insert("Df125CDCPulse");
259 event_source_data_types.insert("Df125FDCPulse");
260 event_source_data_types.insert("DF1TDCConfig");
261 event_source_data_types.insert("DF1TDCHit");
262 event_source_data_types.insert("DF1TDCTriggerTime");
263 event_source_data_types.insert("DCAEN1290TDCConfig");
264 event_source_data_types.insert("DCAEN1290TDCHit");
265 event_source_data_types.insert("DCODAEventInfo");
266 event_source_data_types.insert("DCODAROCInfo");
267 event_source_data_types.insert("DTSscalers");
268 event_source_data_types.insert("DEPICSvalue");
269 event_source_data_types.insert("DEventTag");
270 event_source_data_types.insert("DL1Info");
271
272 // Read in optional module type translation map if it exists
273 ReadOptionalModuleTypeTranslation();
274
275 last_run_number = 0;
276 filename_run_number = 0;
277 current_event_count = 0;
278
279 // Try extracting the run number from the filename. (This is
280 // only used if the run number is not found in the EVIO data.)
281 size_t pos2 = this->source_name.find_last_of('_');
282 if(pos2 != string::npos){
283 size_t pos1 = this->source_name.find_last_of('_', pos2-1);
284 if(pos1 != string::npos){
285 pos1++;
286 string runstr = this->source_name.substr(pos1, pos2-pos1);
287 if(runstr.length()>0) filename_run_number = atoi(runstr.c_str());
288 }
289 }
290
291 pthread_mutex_init(&evio_buffer_pool_mutex, NULL__null);
292 pthread_mutex_init(&stored_events_mutex, NULL__null);
293 pthread_mutex_init(&current_event_count_mutex, NULL__null);
294 pthread_rwlock_init(&BOR_lock, NULL__null);
295}
296
297//----------------
298// Destructor
299//----------------
300JEventSource_EVIO::~JEventSource_EVIO()
301{
302 // close event source here
303// if(chan){
304// if(VERBOSE>0) evioout << "Closing event source \"" << this->source_name << "\"" <<endl;
305// chan->close();
306// delete chan;
307// }
308
309#ifdef HAVE_ET
310 if(et_connected){
311 if(VERBOSE>0) evioout << "Closing ET connection \"" << this->source_name << "\"" <<endl;
312 et_close(sys_id);
313 et_connected = false;
314 }
315#endif
316
317 if(hdevio){
318 if(VERBOSE>0) evioout << "Closing hdevio event source \"" << this->source_name << "\"" <<endl;
319 hdevio->PrintStats();
320 delete hdevio;
321 }
322
323 // Release memory used for the event buffer pool
324 while(!evio_buffer_pool.empty()){
325 free(evio_buffer_pool.front());
326 evio_buffer_pool.pop_front();
327 }
328
329 // Delete any BOR config objects
330 for(uint32_t i=0; i<BORobjs.size(); i++) delete BORobjs[i];
331 BORobjs.clear();
332
333 // Optionally dump the module map
334 if(DUMP_MODULE_MAP)DumpModuleMap();
335}
336
337//---------------------------------
338// ReadOptionalModuleTypeTranslation
339//---------------------------------
340void JEventSource_EVIO::ReadOptionalModuleTypeTranslation(void)
341{
342 // Some data may be taken with bad ROLs or drivers that
343 // write module type values that are non-standard. This
344 // allows the user to specify a simple text file that
345 // can be read in to translate the types found in the
346 // file to another type so that they can be properly parsed.
347 ifstream ifs(MODTYPE_MAP_FILENAME.c_str());
348 if(!ifs.is_open()) return;
349
350 cout << "Opened JLab module type translation map: " << endl;
351 cout << " " << MODTYPE_MAP_FILENAME << endl;
352 while(ifs.good()){
353 char line[256];
354 ifs.getline(line, 256);
355 if(ifs.gcount() < 1) break;
356 if(line[0] == '#') continue;
357
358 stringstream ss(line);
359 uint32_t from=10000, to=10000;
360 ss >> from >> to; // from=evio to=TT
361 if( to==10000 ){
362 if( from!=10000){
363 cout << "unable to convert line:" << endl;
364 cout << " " << line;
365 }
366 }else{
367 modtype_translate[(MODULE_TYPE)from] = (MODULE_TYPE)to;
368 }
369 }
370 ifs.close();
371
372 cout << " Read " << modtype_translate.size() << " entries" << endl;
373 map<MODULE_TYPE,MODULE_TYPE>::iterator iter;
374 for(iter=modtype_translate.begin(); iter != modtype_translate.end(); iter++){
375 cout << " type " << iter->first << " -> type " << iter->second << endl;
376 }
377}
378
379//----------------
380// ConnectToET
381//----------------
382void JEventSource_EVIO::ConnectToET(const char* source_name)
383{
384#ifdef HAVE_ET
385
386 /// Format for ET source strings is:
387 ///
388 /// ET:session:station:host:port
389 ///
390 /// The session is used to form the filename of the ET
391 /// system. For example, if an session of "eb" is specified,
392 /// then a file named "/tmp/et_sys_eb" is assumed to be
393 /// what should be opened. If no session is specified (or
394 /// an empty session name) then "none" is used as the session.
395 ///
396 /// If the station name specified does not exist, it will
397 /// be created. If it does exist, the existing station will
398 /// be used. If no station is specified, then the station
399 /// name "DANA" will be used. Any station created will be
400 /// set to "blocking" *unless* the configuration paramter
401 /// EVIO:ET_STATION_CREATE_BLOCKING is set to "0"
402 /// in which case it will be set to non-blocking.
403 ///
404 /// If the host is specified, then an attempt will be made
405 /// to open that system. If it is not specified, then
406 /// it will attempt to open an ET system on the local machine.
407 ///
408 /// If port is specified, it is used as the TCP port number
409 /// on the remote host to attach to. If the host is not
410 /// specified (i.e. by having two colons and therefore
411 /// an empty string) then the port is ignored. If the
412 /// port is omitted or specified as "0", then the default
413 /// port is used.
414 ///
415
416 // Split source name into session, station, etc...
417 vector<string> fields;
418 string str = source_name;
419 size_t startpos=0, endpos=0;
420 while((endpos = str.find(":", startpos)) != str.npos){
421 size_t len = endpos-startpos;
422 fields.push_back(len==0 ? "":str.substr(startpos, len));
423 startpos = endpos+1;
424 }
425 if(startpos<str.length()) fields.push_back(str.substr(startpos, str.npos));
426
427 string session = fields.size()>1 ? fields[1]:"";
428 string station = fields.size()>2 ? fields[2]:"";
429 string host = fields.size()>3 ? fields[3]:"localhost";
430 int port = fields.size()>4 ? atoi(fields[4].c_str()):ET_SERVER_PORT;
431
432 if(session == "") session = "none";
433 if(station == "") station = "DANA";
434 if(host == "") host = "localhost";
435 string fname = session.at(0)=='/' ? session:(string("/tmp/et_sys_") + session);
436
437 // Report to user what we're doing
438 jout << " Opening ET system:" << endl;
439 if(session!=fname) jout << " session: " << session << endl;
440 jout << " station: " << station << endl;
441 jout << " system file: " << fname << endl;
442 jout << " host: " << host << endl;
443 if(port !=0) jout << " port: " << port << endl;
444
445 // connect to the ET system
446 et_openconfig openconfig;
447 et_open_config_init(&openconfig);
448 if(host != ""){
449 if(host.find("239.")==0){
450 cout<<__FILE__"libraries/DAQ/JEventSource_EVIO.cc"<<":"<<__LINE__450<<" Configuring input ET for multicast" << endl;
451 et_open_config_setcast(openconfig, ET_MULTICAST);
452 et_open_config_addmulticast(openconfig, host.c_str());
453 et_open_config_sethost(openconfig, ET_HOST_ANYWHERE);
454 et_open_config_setport(openconfig, port);
455 struct timespec tspec={5,5};
456 et_open_config_settimeout(openconfig, tspec);
457 et_open_config_setwait(openconfig, ET_OPEN_WAIT);
458 }else{
459 cout<<__FILE__"libraries/DAQ/JEventSource_EVIO.cc"<<":"<<__LINE__459<<" Configuring input ET for direct connection" << endl;
460 et_open_config_setcast(openconfig, ET_DIRECT);
461 et_open_config_setmode(openconfig, ET_HOST_AS_LOCAL); // ET_HOST_AS_LOCAL or ET_HOST_AS_REMOTE
462 et_open_config_sethost(openconfig, host.c_str());
463 et_open_config_setport(openconfig, ET_BROADCAST_PORT);
464 if(port != 0)et_open_config_setserverport(openconfig, port);
465 }
466 }
467 int err = et_open(&sys_id,fname.c_str(),openconfig);
468 if(err != ET_OK){
469 cerr << __FILE__"libraries/DAQ/JEventSource_EVIO.cc"<<":"<<__LINE__469<<" Problem opening ET system"<<endl;
470 cerr << et_perror(err);
471 return;
472 }
473
474 // create station config in case no station exists
475 et_statconfig et_station_config;
476 et_station_config_init(&et_station_config);
477 et_station_config_setblock(et_station_config, ET_STATION_CREATE_BLOCKING ? ET_STATION_BLOCKING:ET_STATION_NONBLOCKING);
478 et_station_config_setselect(et_station_config,ET_STATION_SELECT_ALL);
479 et_station_config_setuser(et_station_config,ET_STATION_USER_MULTI);
480 et_station_config_setrestore(et_station_config,ET_STATION_RESTORE_OUT);
481 et_station_config_setcue(et_station_config,ET_STATION_NEVENTS);
482 et_station_config_setprescale(et_station_config,1);
483 cout<<"ET station configured\n";
484
485 // create station if not already created
486 int status=et_station_create(sys_id,&sta_id,station.c_str(),et_station_config);
487 if((status!=ET_OK)&&(status!=ET_ERROR_EXISTS)) {
488 et_close(sys_id);
489 cerr << "Unable to create station " << station << endl;
490 cerr << et_perror(status);
491
492 // Check that the number of events in the ET system is not
493 // less than the number of events we specified for the station CUE.
494 int Nevents = 0;
495 et_system_getnumevents(sys_id, &Nevents);
496 if(Nevents <= ET_STATION_NEVENTS){
497 jerr << "NOTE: The number of events specified for the station cue is equal to" << endl;
498 jerr << "or greater than the number of events in the entire ET system:" << endl;
499 jerr << endl;
500 jerr << " " << ET_STATION_NEVENTS << " >= " << Nevents << endl;
501 jerr << endl;
502 jerr << "Try re-running with: " << endl;
503 jerr << endl;
504 jerr << " -PEVIO:ET_STATION_NEVENTS=" << (Nevents+1)/2 << endl;
505 jerr << endl;
506 }
507 return;
508 }
509 if(status==ET_ERROR_EXISTS){
510 jout << " Using existing ET station " << station << endl;
511 }else{
512 jout << " ET station " << station << " created\n";
513 }
514
515 // Attach to the ET station
516 status=et_station_attach(sys_id,sta_id,&att_id);
517 if(status!=ET_OK) {
518 et_close(sys_id);
519 jerr << "Unable to attach to station " << station << endl;
520 return;
521 }
522
523 jout << "...now connected to ET system: " << fname
524 << ", station: " << station << " (station id=" << sta_id << ", attach id=" << att_id <<")" << endl;
525
526 et_connected = true;
527 // chan = new evioETChannel(sys_id, att_id);
528
529 // Make sure the size of event buffers we will allocate are at least as big
530 // as the event size used in the ET system
531 size_t eventsize;
532 et_system_geteventsize(sys_id, &eventsize);
533 if((uint32_t)eventsize > BUFFER_SIZE){
534 jout<<" Events in ET system are larger than currently set buffer size:"<<endl;
535 jout<<" "<<eventsize<<" > "<<BUFFER_SIZE<<endl;
536 jout<<" Setting BUFFER_SIZE to "<<eventsize<<endl;
537 BUFFER_SIZE = (uint32_t)eventsize;
538 }else{
539 jout<<" ET system event size:"<<eventsize<<" JEventSource_EVIO.BUFFER_SIZE:"<<BUFFER_SIZE<<endl;
540 }
541
542#else
543 jerr << endl;
544 jerr << "You are attempting to connect to an ET system using a binary that" <<endl;
545 jerr << "was compiled without ET support. Please reconfigure and recompile" <<endl;
546 jerr << "To get ET support." << endl;
547 jerr << endl;
548 throw exception();
549#endif // HAVE_ET
550}
551
552//----------------
553// Cleanup
554//----------------
555void JEventSource_EVIO::Cleanup(void)
556{
557 /// This is called internally by the JEventSource_EVIO class
558 /// once all events have been read in. Its purpose is to
559 /// free the hidden memory in all of the container class
560 /// members of the JEventSource_EVIO class. This is needed
561 /// for jobs that process a lot of input files and therefore
562 /// create a lot JEventSource_EVIO objects. JANA does not delete
563 /// these objects until the end of the job so this tends to
564 /// act like a memory leak. The data used can be substantial
565 /// (nearly 1GB per JEventSource_EVIO object).
566 if(hdevio) delete hdevio;
567 hdevio = NULL__null;
568 //if(chan) delete chan;
569 //chan = NULL;
570#ifdef HAVE_ET
571 if(et_connected) et_close(sys_id);
572 et_connected = false;
573#endif // HAVE_ET
574
575 module_type.clear();
576 modtype_translate.clear();
577
578 for(uint32_t i=0; i<hit_objs.size(); i++) hit_objs[i].resize(0);
579 hit_objs.resize(0);
580
581 while(!stored_events.empty()){
582 delete stored_events.front();
583 stored_events.pop();
584 }
585 while(!evio_buffer_pool.empty()) {
586 delete evio_buffer_pool.back();
587 evio_buffer_pool.pop_back();
588 }
589 while(!event_source_data_types.empty()){
590 event_source_data_types.erase(event_source_data_types.begin());
591 }
592}
593
594//----------------
595// GetEvent
596//----------------
597jerror_t JEventSource_EVIO::GetEvent(JEvent &event)
598{
599 if(VERBOSE>1) evioout << "GetEvent called for &event = " << hex << &event << dec << endl;
600
601 // If we couldn't even open the source, then there's nothing to do
602 bool no_source = true;
603#if USE_HDEVIO1
604 if(source_type==kFileSource && hdevio->is_open) no_source = false;
605#endif
606 if(source_type==kETSource && et_connected) no_source = false;
607 if(no_source)throw JException(string("Unable to open EVIO channel for \"") + source_name + "\"");
608
609
610 // This may not be a long term solution, but here goes:
611 // We need to write single events out in EVIO format, possibly
612 // with new information attached. The easiest way to do this
613 // is to keep the DOM tree when the event is read in and modify
614 // it if needed before writing it out. The complication comes
615 // in that entangled events will not have a dedicated DOM tree
616 // for every event. This is only an issue if disentangling is
617 // not done upstream. How this is handled now is that the DOM
618 // tree pointer is copied into the ObjList object for the first
619 // physics event found in the DAQ event. The DOM tree is freed
620 // in FreeEvent (if the pointer is non-NULL). Note that for
621 // single event blocks (i.e. already disentangled events) the
622 // stored_events list will always be empty so "evt" is always
623 // set.
624
625 // Check for event stored from parsing a previously read in
626 // DAQ event
627 ObjList *objs_ptr = NULL__null;
628 pthread_mutex_lock(&stored_events_mutex);
629 if(!stored_events.empty()){
630 objs_ptr = stored_events.front();
631 stored_events.pop();
632
633 // If this is a stored event then it almost certainly
634 // came from a multi-event block of physics events.
635 // Set the physics event status bit.
636 event.SetStatusBit(kSTATUS_PHYSICS_EVENT);
637 }
638 pthread_mutex_unlock(&stored_events_mutex);
639
640 // If no events are currently stored in the buffer, then
641 // read in another event block.
642 if(objs_ptr == NULL__null){
643 uint32_t *buff = NULL__null; // ReadEVIOEvent will allocate memory from pool for this
644 double t1 = GetTime();
645 jerror_t err = ReadEVIOEvent(buff);
646 double t2 = GetTime();
647 if(err != NOERROR) return err;
648 if(buff == NULL__null) return MEMORY_ALLOCATION_ERROR;
649 uint32_t buff_size = ((*buff) + 1)*4; // first word in EVIO buffer is total bank size in words
650
651 objs_ptr = new ObjList();
652 objs_ptr->time_evio_read = t2 - t1;
653 objs_ptr->eviobuff = buff;
654 objs_ptr->eviobuff_size = buff_size;
655 objs_ptr->run_number = FindRunNumber(buff);
656 objs_ptr->event_number = FindEventNumber(buff);
657
658 // Increment counter that keeps track of how many events
659 // are currently being processed.
660 pthread_mutex_lock(&current_event_count_mutex);
661 current_event_count++;
662 pthread_mutex_unlock(&current_event_count_mutex);
663 }
664
665 // Store a pointer to the ObjList object for this event in the
666 // JEvent as the Reference value. Parsing will be done later
667 // in GetObjects() -> ParseEvents() using the eviobuff pointer.
668 event.SetJEventSource(this);
669 event.SetEventNumber((uint64_t)objs_ptr->event_number);
670 event.SetRunNumber(objs_ptr->run_number);
671 event.SetRef(objs_ptr);
672 event.SetStatusBit(kSTATUS_EVIO);
673 if( source_type == kFileSource ) event.SetStatusBit(kSTATUS_FROM_FILE);
674 if( source_type == kETSource ) event.SetStatusBit(kSTATUS_FROM_ET);
675 if(objs_ptr)
676 if(objs_ptr->eviobuff) FindEventType(objs_ptr->eviobuff, event);
677
678 // EPICS and BOR events are barrier events
679 if(event.GetStatusBit(kSTATUS_EPICS_EVENT) || event.GetStatusBit(kSTATUS_BOR_EVENT) ){
680 event.SetSequential();
681 }
682
683 Nevents_read++;
684
685 return NOERROR;
686}
687
688//----------------
689// FreeEvent
690//----------------
691void JEventSource_EVIO::FreeEvent(JEvent &event)
692{
693 if(VERBOSE>1) evioout << "FreeEvent called for event: " << event.GetEventNumber() << endl;
694
695 ObjList *objs_ptr = (ObjList*)event.GetRef();
696 if(objs_ptr){
697
698 // If a DAQ event was read in but GetObjects never called
699 // then the buffer will never have been parsed. Since the
700 // DAQ event could hold multiple Physics events, we parse
701 // it now to ensure all physics events are presented by
702 // the event source. The ParseEvents call will copy the
703 // first event's parameters into our objs_ptr object, but
704 // any additional ones will be placed in stored_events.
705 if(!objs_ptr->eviobuff_parsed) ParseEvents(objs_ptr);
706
707 if(objs_ptr->own_objects){
708
709 for(unsigned int i=0; i<objs_ptr->hit_objs.size(); i++){
710 delete objs_ptr->hit_objs[i];
711 }
712
713 for(unsigned int i=0; i<objs_ptr->config_objs.size(); i++){
714 delete objs_ptr->config_objs[i];
715 }
716
717 for(unsigned int i=0; i<objs_ptr->misc_objs.size(); i++){
718 delete objs_ptr->misc_objs[i];
719 }
720 }
721
722 if(objs_ptr->DOMTree != NULL__null) delete objs_ptr->DOMTree;
723 if(objs_ptr->eviobuff){
724
725 // If we have not already stopped reading events from
726 // the source then return this buffer to the pool. Otherwise,
727 // delete the buffer.
728 if(hdevio){
729 // Return EVIO buffer to pool for recycling
730 pthread_mutex_lock(&evio_buffer_pool_mutex);
731 evio_buffer_pool.push_front(objs_ptr->eviobuff);
732 pthread_mutex_unlock(&evio_buffer_pool_mutex);
733 }else{
734 free(objs_ptr->eviobuff);
735 }
736 }
737
738 delete objs_ptr;
739
740 // Decrement counter that keeps track of how many events
741 // are currently being processed.
742 pthread_mutex_lock(&current_event_count_mutex);
743 current_event_count--;
744 bool last_event = (hdevio==NULL__null) && (current_event_count==0);
745 pthread_mutex_unlock(&current_event_count_mutex);
746
747 // If we are the last event, then clean up as much memory as
748 // possible.
749 if(last_event) Cleanup();
750 }
751}
752
753//----------------
754// ParseEvents
755//----------------
756jerror_t JEventSource_EVIO::ParseEvents(ObjList *objs_ptr)
757{
758 /// This is the high-level entry point for parsing the
759 /// DAQ event in order to create one or more Physics
760 /// events. It will be called from either GetObjects
761 /// or FreeEvent, the latter being done only if needed
762 /// to ensure the event does eventually get parsed.
763 /// The grunt work of actually parsing the data starts
764 /// in ParseEVIOEvent().
765 ///
766 /// This method is here so that the DOM Tree creation
767 /// and data parsing can be deferred from the EventBuffer
768 /// thread (of which there is only one) to an event
769 /// processor thread (or which there may be many). Since
770 /// the DOM tree creating and data parsing represent the
771 /// larger time cost of getting the event into memory,
772 /// a siginificant performance increase can be gained
773 /// using this slightly more complicated method.
774
775 if(VERBOSE>2) evioout << " Entering ParseEvents() with objs_ptr=" << hex << objs_ptr << dec << endl;
1
Taking false branch
776
777 // Double check that we're not re-parsing an event
778 if(objs_ptr->eviobuff_parsed){
2
Taking false branch
779 jerr << " DAQ event already parsed!! Bug in code. Contact davidl@jlab.org" << endl;
780 return UNKNOWN_ERROR;
781 }
782
783 // Bomb-proof against getting a NULL buffer
784 uint32_t *buff = objs_ptr->eviobuff;
785 if(buff == NULL__null){
3
Taking false branch
786 jerr << " Bad buffer pointer passed to JEventSource_EVIO::ParseEvent()!!" << endl;
787 return RESOURCE_UNAVAILABLE;
788 }
789
790 // This container will be used to hold all of the individual
791 // Physics (L1 triggered) events for this DAQ event. This includes
792 // both dientangling multi-event blocks and separating multi-event
793 // ET events.
794 list<ObjList*> full_events;
795
796 // Setup up iptr and iend to point to the start of the first event
797 // and the word just after the end of the last event respectively.
798 // Initialize them for the case of reading from a file and not a
799 // CODA-produced ET event
800 uint32_t *iptr = &buff[0];
801 uint32_t *iend = &buff[buff[0]+1]; // EVIO length word is exclusive so +1
802
803 // If the "event" was read from ET, then it may (and likely
804 // will) contain several DAQ events. (Each DAQ event may itself
805 // contain many L1 trigger events.) In addition, the ET event
806 // will have a Network Transport Header (NTH) that must be skipped
807 // but only if read from CODA. Events put into the ET system
808 // by other means will not include the NTH. To decide whether
809 // there is an NTH, we look at the magic word and the header length.
810 // Note that byteswapping should already have occured.
811 if(source_type==kETSource && buff[7]==0xc0da0100 && buff[2]==8){
812 // This buffer read from ET. Redefine iptr and iend
813 iptr = &buff[8];
814 iend = &buff[buff[0]]; // EVIO length word in NTH is inclusive so don't add 1
815 }
816
817 if(VERBOSE>5) evioout << " Looping event stack with " << *iptr << " words" << endl;
4
Taking false branch
818
819 // Loop over events in buffer until entire buffer is parsed.
820 // When reading from a file, this loop should only get executed once.
821 int Nevents_in_stack=0;
822 while(iptr < iend){
5
Assuming 'iptr' is >= 'iend'
6
Loop condition is false. Execution continues on line 880
823
824 double time_dom_tree = 0;
825 double time_evio_parse = 0;
826
827 // Make a evioDOMTree for this DAQ event
828 evioDOMTree *evt = NULL__null;
829 if(MAKE_DOM_TREE){
830 try{
831 double tstart = GetTime();
832 evt = new evioDOMTree(iptr);
833 time_dom_tree = GetTime() - tstart;
834 }catch(evioException &e){
835 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<835<<" "
<< "Problem creating EVIO DOM Tree!!" << endl;
836 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<836<<" "
<< e.what() << endl;
837 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<837<<" "
<< "Binary dump of first 160 words follows:" << endl;
838 DumpBinary(iptr, iend, 160);
839 exit(-1);
840 }
841 }
842
843 if(evt){
844 // Parse event, making other ObjList objects
845 list<ObjList*> my_full_events;
846 //bool skipped_parsing = true;
847 if(PARSE_EVIO_EVENTS){
848 try{
849 double tstart = GetTime();
850 ParseEVIOEvent(evt, my_full_events);
851 time_evio_parse = GetTime() - tstart;
852 }catch(JException &jexception){
853 jerr << "Exception thrown from ParseEVIOEvent!" << endl;
854 jerr << jexception.toString() << endl;
855 }
856 }
857
858 // Append physics events found for this DAQ event to the list of all physics events
859 if(!my_full_events.empty()) {
860 my_full_events.front()->DOMTree = evt; // keep DOMTree pointer with first event from this DAQ event
861 my_full_events.front()->time_dom_tree = time_dom_tree;
862 my_full_events.front()->time_evio_parse = time_evio_parse;
863 full_events.insert( full_events.end(), my_full_events.begin(), my_full_events.end() );
864 }else{
865 delete evt;
866 }
867 }else{
868 // No DOM tree made for this buffer. Insert an empty event into
869 // the list so we can keep track of the number of events seen
870 // even when DOMTree creation is turned off.
871 ObjList *objs = new ObjList;
872 full_events.push_back(objs);
873 }
874
875 // Advance pointer to next event in buffer
876 iptr += iptr[0]+1;
877 Nevents_in_stack++; // number of events processed in this buffer (for debugging)
878 }
879
880 if(VERBOSE>5) evioout << " Loop finished. " << full_events.size() << " events total found (" << Nevents_in_stack << " events in stack)" << endl;
7
Taking false branch
881
882 // At this point, we have parsed the DAQ event and extracted all physics
883 // events into the full_events list. In the case of a prestart or go event
884 // read from an EVIO file, the full_events list may actually be empty at
885 // this point. For these cases, we need to add an empty event for the
886 // current thread to "process".
887 bool empty_event = full_events.empty();
888 if(empty_event) full_events.push_back(new ObjList());
8
Assuming 'empty_event' is 0
9
Taking false branch
889
890 // Whether we actually parsed the events or not, we mark them as being
891 // parsed since it is really just used as a flag to tell whether this
892 // method should be called or not.
893 list<ObjList*>::iterator iter = full_events.begin();
894 for( ; iter != full_events.end(); iter++ ) (*iter)->eviobuff_parsed = true;
10
Loop condition is false. Execution continues on line 897
895
896 // Copy the first event's objects obtained from parsing into this event's ObjList
897 ObjList *objs = full_events.front();
898 full_events.pop_front();
899 //objs_ptr->run_number = empty_event ? objs_ptr->run_number:objs->run_number;
900 objs_ptr->own_objects = objs->own_objects;
901 objs_ptr->hit_objs = objs->hit_objs;
902 objs_ptr->config_objs = objs->config_objs;
903 objs_ptr->misc_objs = objs->misc_objs;
904 objs_ptr->eviobuff_parsed = objs->eviobuff_parsed;
905 objs_ptr->time_dom_tree = objs->time_dom_tree;
906 objs_ptr->time_evio_parse = objs->time_evio_parse;
907 //objs_ptr->eviobuff = objs->eviobuff; // Don't copy this! (it causes memory leak)
908 //objs_ptr->eviobuff_size = objs->eviobuff_size;
909 objs_ptr->DOMTree = objs->DOMTree;
910 delete objs;
911
912 // Config objects come from banks that are created when a block
913 // of events is read out. Thus, a single set of config. objects
914 // will be created when parsing a multi-event block. Here, we duplicate
915 // all config objects for the first event for every other event in the
916 // block. To make this a little more compact and maintainable, we use a
917 // #define. This allows us to write the class type once and guarantee
918 // that it shows up the same in all places. For example, using
919 // CloneConfigObject(Df125Config) will expand to something like:
920 //
921 // if(confobj->className() == string("Df125Config")){
922 // c = new Df125Config(confobj->rocid,confobj->slot_mask);
923 // *((Df125Config*)c) = *((Df125Config*)confobj);
924 // }
925#define CloneConfigObject(T){ if(confobj->className() == string("T")){ c = new T(confobj
->rocid,confobj->slot_mask); *((T*)c) = *((T*)confobj);
} }
{ if(confobj->className() == string(#T)){ c = new T(confobj->rocid,confobj->slot_mask); *((T*)c) = *((T*)confobj);} }
926 list<ObjList*>::iterator feiter = full_events.begin();
927 for(; feiter!=full_events.end(); feiter++){
11
Loop condition is true. Entering loop body
13
Loop condition is true. Entering loop body
15
Loop condition is true. Entering loop body
928 ObjList *objs = *feiter;
929 for(uint32_t j=0; j<objs_ptr->config_objs.size(); j++){
12
Loop condition is false. Execution continues on line 927
14
Loop condition is false. Execution continues on line 927
16
Loop condition is true. Entering loop body
930 DDAQConfig *confobj = objs_ptr->config_objs[j];
931 DDAQConfig *c = NULL__null;
932 CloneConfigObject(Df250Config){ if(confobj->className() == string("Df250Config")){ c = new
Df250Config(confobj->rocid,confobj->slot_mask); *((Df250Config
*)c) = *((Df250Config*)confobj);} }
;
933 CloneConfigObject(Df125Config){ if(confobj->className() == string("Df125Config")){ c = new
Df125Config(confobj->rocid,confobj->slot_mask); *((Df125Config
*)c) = *((Df125Config*)confobj);} }
;
934 CloneConfigObject(DF1TDCConfig){ if(confobj->className() == string("DF1TDCConfig")){ c = new
DF1TDCConfig(confobj->rocid,confobj->slot_mask); *((DF1TDCConfig
*)c) = *((DF1TDCConfig*)confobj);} }
;
17
Within the expansion of the macro 'CloneConfigObject':
a
Memory is allocated
935 CloneConfigObject(DCAEN1290TDCConfig){ if(confobj->className() == string("DCAEN1290TDCConfig"))
{ c = new DCAEN1290TDCConfig(confobj->rocid,confobj->slot_mask
); *((DCAEN1290TDCConfig*)c) = *((DCAEN1290TDCConfig*)confobj
);} }
;
18
Within the expansion of the macro 'CloneConfigObject':
a
Potential leak of memory pointed to by 'c'
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;
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];
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;
4522 for(int ibank=1; iter!=bankList->end(); iter++, ibank++){ // ibank only used for debugging messages
4523 evioDOMNodeP childBank = *iter;
4524
4525 if(childBank->tag==0x71){
4526 // uint32_t rocid = childBank->num;
4527 evioDOMNodeListP bankList = childBank->getChildren();
4528 evioDOMNodeList::iterator iter = bankList->begin();
4529 for(; iter!=bankList->end(); iter++){
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){
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)) ){
4577
4578 // Copy bank data, assuming format is the same
4579 for(uint32_t i=0; i<vec->size(); i++) *dest++ = *src++;
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){
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