Bug Summary

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

Annotated Source Code

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