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