Bug Summary

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

Annotated Source Code

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