Bug Summary

File:plugins/monitoring/DAQ_online/JEventProcessor_DAQ_online.cc
Location:line 428, column 3
Description:Value stored to 'evio_buffsize' is never read

Annotated Source Code

1// $Id$
2//
3// File: JEventProcessor_DAQ_online.cc
4// Created: Thu Aug 7 09:37:03 EDT 2014
5// Creator: dalton (on Linux gluon05.jlab.org 2.6.32-358.18.1.el6.x86_64 x86_64)
6//
7
8#include <stdint.h>
9#include <vector>
10
11#include "JEventProcessor_DAQ_online.h"
12#include <JANA/JApplication.h>
13#include <JANA/JFactory.h>
14
15using namespace std;
16using namespace jana;
17
18#include <DAQ/DF1TDCHit.h>
19#include <DAQ/Df250PulseIntegral.h>
20#include <DAQ/JEventSource_EVIO.h>
21#include <TTAB/DTranslationTable.h>
22
23#include <TDirectory.h>
24#include <TH2.h>
25#include <TH1.h>
26#include <TProfile.h>
27#include <TProfile2D.h>
28#include <TROOT.h>
29
30
31static const int highcratenum=100;
32// root hist pointers
33static TH2I *daq_occ_crates[highcratenum];
34static TProfile2D *daq_ped_crates[highcratenum];
35static TProfile2D *daq_TDClocked_crates[highcratenum];
36static TProfile2D *daq_TDCovr_crates[highcratenum];
37static TProfile *daq_hits_per_event;
38static TProfile *daq_words_per_event;
39static TH1D *daq_event_size;
40static TH1D *daq_event_tdiff;
41static TH1D *daq_words_by_type;
42static bool ttab_labels_set = false;
43
44// Routine used to create our JEventProcessor
45extern "C"{
46 void InitPlugin(JApplication *app){
47 InitJANAPlugin(app);
48 app->AddProcessor(new JEventProcessor_DAQ_online());
49 }
50} // "C"
51
52
53//------------------
54// JEventProcessor_DAQ_online (Constructor)
55//------------------
56JEventProcessor_DAQ_online::JEventProcessor_DAQ_online()
57{
58
59}
60
61//------------------
62// ~JEventProcessor_DAQ_online (Destructor)
63//------------------
64JEventProcessor_DAQ_online::~JEventProcessor_DAQ_online()
65{
66
67}
68
69//------------------
70// init
71//------------------
72jerror_t JEventProcessor_DAQ_online::init(void)
73{
74 printf("JEventProcessor_DAQ_online::init()\n");
75
76 // lock all root operations
77 japp->RootWriteLock();
78
79 // create root folder for DAQ and cd to it, store main dir
80 maindir = gDirectory(TDirectory::CurrentDirectory());
81 daqdir = maindir->mkdir("DAQ");
82 daqdir->cd();
83
84 // Initialise histograms and variables
85 for (int i=0; i<highcratenum; i++) {
86 daq_occ_crates[i] = NULL__null;
87 daq_ped_crates[i] = NULL__null;
88 daq_TDClocked_crates[i] = NULL__null;
89 daq_TDCovr_crates[i] = NULL__null;
90 }
91
92 daq_hits_per_event = new TProfile("daq_hits_per_event", "Hits/event vs. rocid", 100, 0.5, 100.5);
93 daq_words_per_event = new TProfile("daq_words_per_event", "words/event vs. rocid", 100, 0.5, 100.5);
94 daq_event_size = new TH1D("daq_event_size", "Event size in kB", 1000, 0.0, 1.0E3);
95 daq_event_tdiff = new TH1D("daq_event_tdiff", "Time between events", 10000, 0.0, 1.0E2);
96 daq_words_by_type = new TH1D("daq_words_by_type", "Number of words in EVIO file by type", kNEVIOWordTypes, 0, (double)kNEVIOWordTypes);
97
98 daq_words_per_event->GetXaxis()->SetBinLabel(1 ,"Trigger Bank");
99 daq_words_per_event->GetXaxis()->SetBinLabel(99 ,"Residual");
100
101 daq_event_size->SetXTitle("Total event size (kB)");
102 daq_event_tdiff->SetXTitle("#deltat between events (ms)");
103
104 daq_words_by_type->GetXaxis()->SetBinLabel(1 + kUnknown, "unknown");
105 daq_words_by_type->GetXaxis()->SetBinLabel(1 + kEVIOEventNumber, "Event Number Word");
106 daq_words_by_type->GetXaxis()->SetBinLabel(1 + kEVIOTimestamp, "Timestamp");
107
108 daq_words_by_type->GetXaxis()->SetBinLabel(1 + kf250BlockHeader, "f250 Block Header");
109 daq_words_by_type->GetXaxis()->SetBinLabel(1 + kf250BlockTrailer, "f250 Block Trailer");
110 daq_words_by_type->GetXaxis()->SetBinLabel(1 + kf250EventHeader, "f250 Event Header");
111 daq_words_by_type->GetXaxis()->SetBinLabel(1 + kf250TriggerTime, "f250 Trigger Time");
112 daq_words_by_type->GetXaxis()->SetBinLabel(1 + kf250WindowRawData, "f250 Window Raw Data");
113 daq_words_by_type->GetXaxis()->SetBinLabel(1 + kf250WindowSum, "f250 Window Sum");
114 daq_words_by_type->GetXaxis()->SetBinLabel(1 + kf250PulseRawData, "f250 Pulse Raw Data");
115 daq_words_by_type->GetXaxis()->SetBinLabel(1 + kf250PulseIntegral, "f250 Pulse Integral");
116 daq_words_by_type->GetXaxis()->SetBinLabel(1 + kf250PulseTime, "f250 Pulse Time");
117 daq_words_by_type->GetXaxis()->SetBinLabel(1 + kf250PulsePedestal, "f250 Pulse Pedestal");
118 daq_words_by_type->GetXaxis()->SetBinLabel(1 + kf250EventTrailer, "f250 Event Trailer");
119 daq_words_by_type->GetXaxis()->SetBinLabel(1 + kf250DataNotValid, "f250 Data Not Valid");
120 daq_words_by_type->GetXaxis()->SetBinLabel(1 + kf250Filler, "f250 Filler Word");
121
122 daq_words_by_type->GetXaxis()->SetBinLabel(1 + kf125BlockHeader, "f125 Block Header");
123 daq_words_by_type->GetXaxis()->SetBinLabel(1 + kf125BlockTrailer, "f125 Block Trailer");
124 daq_words_by_type->GetXaxis()->SetBinLabel(1 + kf125EventHeader, "f125 Event Header");
125 daq_words_by_type->GetXaxis()->SetBinLabel(1 + kf125TriggerTime, "f125 Trigger Time");
126 daq_words_by_type->GetXaxis()->SetBinLabel(1 + kf125WindowRawData, "f125 Window Raw Data");
127 daq_words_by_type->GetXaxis()->SetBinLabel(1 + kf125WindowSum, "f125 Window Sum");
128 daq_words_by_type->GetXaxis()->SetBinLabel(1 + kf125PulseRawData, "f125 Pulse Raw Data");
129 daq_words_by_type->GetXaxis()->SetBinLabel(1 + kf125PulseIntegral, "f125 Pulse Integral");
130 daq_words_by_type->GetXaxis()->SetBinLabel(1 + kf125PulseTime, "f125 Pulse Time");
131 daq_words_by_type->GetXaxis()->SetBinLabel(1 + kf125PulsePedestal, "f125 Pulse Pedestal");
132 daq_words_by_type->GetXaxis()->SetBinLabel(1 + kf125EventTrailer, "f125 Event Trailer");
133 daq_words_by_type->GetXaxis()->SetBinLabel(1 + kf125DataNotValid, "f125 Data Not Valid");
134 daq_words_by_type->GetXaxis()->SetBinLabel(1 + kf125Filler, "f125 Filler Word");
135
136 daq_words_by_type->GetXaxis()->SetBinLabel(1 + kF1v2BlockHeader, "F1v2 Block Header");
137 daq_words_by_type->GetXaxis()->SetBinLabel(1 + kF1v2BLockTrailer, "F1v2 Block Trailer");
138 daq_words_by_type->GetXaxis()->SetBinLabel(1 + kF1v2EventHeader, "F1v2 Event Header");
139 daq_words_by_type->GetXaxis()->SetBinLabel(1 + kF1v2TriggerTime, "F1v2 Trigger Time");
140 daq_words_by_type->GetXaxis()->SetBinLabel(1 + kF1v2ChipHeader, "F1v2 Chip Header");
141 daq_words_by_type->GetXaxis()->SetBinLabel(1 + kF1v2Data, "F1v2 Data");
142 daq_words_by_type->GetXaxis()->SetBinLabel(1 + kF1v2Filler, "F1v2 Filler");
143 daq_words_by_type->GetXaxis()->SetBinLabel(1 + kF1v2BreakWord, "F1v2 Break Word");
144
145 daq_words_by_type->GetXaxis()->SetBinLabel(1 + kF1v3BlockHeader, "F1v3 Block Header");
146 daq_words_by_type->GetXaxis()->SetBinLabel(1 + kF1v3BLockTrailer, "F1v3 Block Trailer");
147 daq_words_by_type->GetXaxis()->SetBinLabel(1 + kF1v3EventHeader, "F1v3 Event Header");
148 daq_words_by_type->GetXaxis()->SetBinLabel(1 + kF1v3TriggerTime, "F1v3 Trigger Time");
149 daq_words_by_type->GetXaxis()->SetBinLabel(1 + kF1v3ChipHeader, "F1v3 Chip Header");
150 daq_words_by_type->GetXaxis()->SetBinLabel(1 + kF1v3Data, "F1v3 Data");
151 daq_words_by_type->GetXaxis()->SetBinLabel(1 + kF1v3Filler, "F1v3 Filler");
152 daq_words_by_type->GetXaxis()->SetBinLabel(1 + kF1v3BreakWord, "F1v3 Break Word");
153
154 daq_words_by_type->GetXaxis()->SetBinLabel(1 + kCAEN1190GlobalHeader, "CAEN1190 GLobal Header");
155 daq_words_by_type->GetXaxis()->SetBinLabel(1 + kCAEN1190GlobalTrailer, "CAEN1190 Global Trailer");
156 daq_words_by_type->GetXaxis()->SetBinLabel(1 + kCAEN1190GlobalTriggerTime, "CAEN1190 Trigger Time");
157 daq_words_by_type->GetXaxis()->SetBinLabel(1 + kCAEN1190TDCHeader, "CAEN1190 TDC Header");
158 daq_words_by_type->GetXaxis()->SetBinLabel(1 + kCAEN1190TDCData, "CAEN1190 TDC Data");
159 daq_words_by_type->GetXaxis()->SetBinLabel(1 + kCAEN1190TDCError, "CAEN1190 TDC Error");
160 daq_words_by_type->GetXaxis()->SetBinLabel(1 + kCAEN1190TDCTrailer, "CAEN1190 TDC Trailer");
161 daq_words_by_type->GetXaxis()->SetBinLabel(1 + kCAEN1190Filler, "CAEN1190 Filler");
162
163 daq_words_by_type->GetXaxis()->SetBinLabel(1 + kConfig, "DAQ Config");
164 daq_words_by_type->GetXaxis()->SetBinLabel(1 + kConfigf250, "DAQ Config f250");
165 daq_words_by_type->GetXaxis()->SetBinLabel(1 + kConfigf125, "DAQ Config f125");
166 daq_words_by_type->GetXaxis()->SetBinLabel(1 + kConfigF1, "DAQ Config F1");
167 daq_words_by_type->GetXaxis()->SetBinLabel(1 + kConfigCAEN1190, "DAQ Config CAEN1190");
168
169 daq_words_by_type->GetXaxis()->SetBinLabel(1 + kEPICSheader, "EPICS header");
170 daq_words_by_type->GetXaxis()->SetBinLabel(1 + kEPICSdata, "EPICS data");
171
172 daq_words_by_type->GetXaxis()->SetBinLabel(1 + kF800FAFA, "0xf800fafa");
173 daq_words_by_type->GetXaxis()->SetBinLabel(1 + kD00DD00D, "0xd00dd00d");
174
175 daq_words_by_type->GetXaxis()->SetBinLabel(1 + kTotWords, "Total words in all events");
176 daq_words_by_type->GetXaxis()->SetBinLabel(1 + kNevents, "Number of events");
177
178 // back to main dir
179 maindir->cd();
180
181 // unlock
182 japp->RootUnLock();
183
184 return NOERROR;
185}
186
187//------------------
188// AddROCIDLabels
189//------------------
190void JEventProcessor_DAQ_online::AddROCIDLabels(JEventLoop *loop)
191{
192 /// This is called just once to set the x-axis labels
193 /// of histograms whose x-axis is the rocid so that we
194 /// can label them by detector.
195
196 const DTranslationTable *ttab = NULL__null;
197 loop->GetSingle(ttab);
198
199 japp->RootWriteLock();
200
201 // Loop over all rocid values
202 for(uint32_t rocid=2; rocid<99; rocid++){
203 // We don't actually know what slot/channel combos are defined
204 // for this so we loop until we find one.
205 bool found_chan = false;
206 daq_hits_per_event->GetXaxis()->SetBinLabel(rocid, "");
207 daq_words_per_event->GetXaxis()->SetBinLabel(rocid, "");
208 for(uint32_t slot=2; slot<24; slot++){
209 for(uint32_t channel=0; channel<3; channel++){
210 try{
211 DTranslationTable::csc_t csc = {rocid, slot, channel};
212 const DTranslationTable::DChannelInfo &chinfo = ttab->GetDetectorIndex(csc);
213 daq_hits_per_event->GetXaxis()->SetBinLabel(rocid, ttab->DetectorName(chinfo.det_sys).c_str());
214 daq_words_per_event->GetXaxis()->SetBinLabel(rocid, ttab->DetectorName(chinfo.det_sys).c_str());
215 found_chan = true;
216 break;
217 }catch(JException &e){
218 // Do nothing
219 }
220 }
221 if(found_chan) break;
222 }
223 }
224
225 japp->RootUnLock();
226}
227
228//------------------
229// brun
230//------------------
231jerror_t JEventProcessor_DAQ_online::brun(JEventLoop *eventLoop, int32_t runnumber)
232{
233 // This is called whenever the run number changes
234 return NOERROR;
235}
236
237//------------------
238// evnt
239//------------------
240jerror_t JEventProcessor_DAQ_online::evnt(JEventLoop *loop, uint64_t eventnumber)
241{
242 // This is called for every event. Use of common resources like writing
243 // to a file or filling a histogram should be mutex protected. Using
244 // loop->Get(...) to get reconstructed objects (and thereby activating the
245 // reconstruction algorithm) should be done outside of any mutex lock
246 // since multiple threads may call this method at the same time.
247 // Here's an example:
248 vector<const DF1TDCHit*> f1tdchits;
249 vector<const Df250PulseIntegral*> f250PIs;
250 vector<const Df125PulseIntegral*> f125PIs;
251 vector<const DCAEN1290TDCHit*> caen1290hits;
252
253 loop->Get(f1tdchits);
254 loop->Get(f250PIs);
255 loop->Get(f125PIs);
256 loop->Get(caen1290hits);
257
258 ParseEventSize(loop->GetJEvent());
259
260 // Set rocid histogram labels based on detector if needed
261 if(!ttab_labels_set){
262 ttab_labels_set = true;
263 AddROCIDLabels(loop);
264 }
265
266 // Initialize counters looking at num. hits per crate
267 uint32_t Nhits_rocid[101];
268 for(uint32_t rocid=0; rocid<101; rocid++) Nhits_rocid[rocid] = 0;
269
270 // Lock ROOT
271 japp->RootWriteLock();
272
273 if (daqdir!=NULL__null) daqdir->cd();
274
275
276 // Access TDC from DF1TDCHit object
277 for(unsigned int i=0; i<f1tdchits.size(); i++) {
278 const DF1TDCHit *hit = f1tdchits[i];
279 int rocid = hit->rocid;
280 int slot = hit->slot;
281 int channel = hit->channel;
282 int data_word = hit->data_word;
283
284 if(rocid>=0 && rocid<=100) Nhits_rocid[rocid]++;
285
286 if (daq_occ_crates[rocid]==NULL__null) {
287 printf("JEventProcessor_DAQ_online::evnt creating occupancy histogram for crate %i\n",rocid);
288 char cratename[255],title[255];
289 sprintf(cratename,"daq_occ_crate%i",rocid);
290 sprintf(title,"Crate %i occupancy (TDC);Slot;Channel",rocid);
291 daq_occ_crates[rocid] = new TH2I(cratename,title,21,0.5,21.5,32,-0.5,31.5);
292 daq_occ_crates[rocid]->SetStats(0);
293 sprintf(cratename,"daq_TDClocked_crate%i",rocid);
294 sprintf(title,"Crate %i TDC lock status (TDC);Slot;Channel",rocid);
295 daq_TDClocked_crates[rocid] = new TProfile2D(cratename,title,21,0.5,21.5,32,-0.5,31.5);
296 daq_TDClocked_crates[rocid]->SetStats(0);
297 sprintf(cratename,"daq_TDCovr_crate%i",rocid);
298 sprintf(title,"Crate %i TDC overflow status (TDC);Slot;Channel",rocid);
299 daq_TDCovr_crates[rocid] = new TProfile2D(cratename,title,21,0.5,21.5,32,-0.5,31.5);
300 daq_TDCovr_crates[rocid]->SetStats(0);
301
302 }
303 daq_occ_crates[rocid]->Fill(slot,channel);
304 daq_TDClocked_crates[rocid]->Fill(slot,channel,(data_word>>26)&(1));
305 daq_TDCovr_crates[rocid]->Fill(slot,channel,(data_word>>25)&(1));
306 daq_TDCovr_crates[rocid]->Fill(slot,channel,(data_word>>24)&(1));
307 }
308
309 // Access F250 from Df250PulseIntegral object
310 for(unsigned int i=0; i<f250PIs.size(); i++) {
311 const Df250PulseIntegral *hit = f250PIs[i];
312 int rocid = hit->rocid;
313 int slot = hit->slot;
314 int channel = hit->channel;
315
316 if(rocid>=0 && rocid<=100) {
317 Nhits_rocid[rocid]++;
318
319 if (daq_occ_crates[rocid]==NULL__null) {
320 printf("JEventProcessor_DAQ_online::evnt creating occupancy histogram for crate %i\n",rocid);
321 char cratename[255],title[255];
322 sprintf(cratename,"daq_occ_crate%i",rocid);
323 sprintf(title,"Crate %i occupancy (F250);Slot;Channel",rocid);
324 daq_occ_crates[rocid] = new TH2I(cratename,title,21,0.5,21.5,16,-0.5,15.5);
325 daq_occ_crates[rocid]->SetStats(0);
326 }
327 daq_occ_crates[rocid]->Fill(slot,channel);
328
329 if (daq_ped_crates[rocid]==NULL__null) {
330 printf("JEventProcessor_DAQ_online::evnt creating pedestal histogram for crate %i\n",rocid);
331 char cratename[255],title[255];
332 sprintf(cratename,"daq_ped_crate%i",rocid);
333 sprintf(title,"Crate %i Average Pedestal (F250);Slot;Channel",rocid);
334 daq_ped_crates[rocid] = new TProfile2D(cratename,title,21,0.5,21.5,16,-0.5,15.5);
335 daq_ped_crates[rocid]->SetStats(0);
336 }
337 if (hit->pedestal > 0) {
338 daq_ped_crates[rocid]->Fill(slot,channel,hit->pedestal);
339 }
340 }
341 }
342
343 // Access F125 from Df125PulseIntegral object
344 for(unsigned int i=0; i<f125PIs.size(); i++) {
345 const Df125PulseIntegral *hit = f125PIs[i];
346 int rocid = hit->rocid;
347 int slot = hit->slot;
348 int channel = hit->channel;
349
350 if(rocid>=0 && rocid<=100) {
351 Nhits_rocid[rocid]++;
352
353 if (daq_occ_crates[rocid]==NULL__null) {
354 printf("JEventProcessor_DAQ_online::evnt creating occupancy histogram for crate %i\n",rocid);
355 char cratename[255],title[255];
356 sprintf(cratename,"daq_occ_crate%i",rocid);
357 sprintf(title,"Crate %i occupancy (F250);Slot;Channel",rocid);
358 daq_occ_crates[rocid] = new TH2I(cratename,title,21,0.5,21.5,16,-0.5,15.5);
359 daq_occ_crates[rocid]->SetStats(0);
360 }
361 daq_occ_crates[rocid]->Fill(slot,channel);
362
363 if (daq_ped_crates[rocid]==NULL__null) {
364 printf("JEventProcessor_DAQ_online::evnt creating pedestal histogram for crate %i\n",rocid);
365 char cratename[255],title[255];
366 sprintf(cratename,"daq_ped_crate%i",rocid);
367 sprintf(title,"Crate %i Average Pedestal (F250);Slot;Channel",rocid);
368 daq_ped_crates[rocid] = new TProfile2D(cratename,title,21,0.5,21.5,16,-0.5,15.5);
369 daq_ped_crates[rocid]->SetStats(0);
370 }
371 if (hit->pedestal > 0) {
372 daq_ped_crates[rocid]->Fill(slot,channel,hit->pedestal);
373 }
374 }
375
376 }
377
378 // Access CAEN1290 TDC hits
379 for(unsigned int i=0; i<caen1290hits.size(); i++) {
380 const DCAEN1290TDCHit *hit = caen1290hits[i];
381 int rocid = hit->rocid;
382 //int slot = hit->slot;
383 //int channel = hit->channel;
384
385 if(rocid>=0 && rocid<=100) Nhits_rocid[rocid]++;
386 }
387
388 // Fill in hits by crate
389 for(uint32_t rocid=0; rocid<101; rocid++) daq_hits_per_event->Fill(rocid, Nhits_rocid[rocid]);
390
391
392 maindir->cd();
393 // Unlock ROOT
394 japp->RootUnLock();
395
396 return NOERROR;
397}
398
399//------------------
400// ParseEventSize
401//------------------
402void JEventProcessor_DAQ_online::ParseEventSize(JEvent &event)
403{
404 /// This ugliness is needed to get at the true banks for each event by rocid.
405
406 // Bombproof
407 if(event.GetJEventSource()->className() != string("JEventSource_EVIO")){
408 static bool warned = false;
409 if(!warned){
410 cout << "WARNING: This is not an event source of type JEventSource_EVIO!" << endl;
411 cout << " Event size statistics filling unavailable!" << endl;
412 warned = true;
413 }
414 return;
415 }
416
417 void *ref = event.GetRef();
418 if(!ref) return;
419 uint32_t *istart = JEventSource_EVIO::GetEVIOBufferFromRef(ref);
420 uint32_t evio_buffsize = JEventSource_EVIO::GetEVIOBufferSizeFromRef(ref);
421 uint32_t evio_buffwords = evio_buffsize/sizeof(uint32_t);
422 uint32_t *iend = &istart[evio_buffwords];
423
424 if( istart==NULL__null ) return;
425 if( (evio_buffwords>=10) && (istart[7]==0xc0da0100) ){
426 // NTH is first 8 words so skip them
427 istart= &istart[8];
428 evio_buffsize -= 8*sizeof(uint32_t);
Value stored to 'evio_buffsize' is never read
429 evio_buffwords -= 8;
430 }
431
432 // Check if this is EPICS data
433 if( evio_buffwords >= 4 ){
434 if( istart[1] == (0x60<<16) + (0xD<<8) + (0x1<<0) ){
435 if( istart[2] == (0x61<<24) + (0x1<<16) + (0x1<<0) ){
436
437 japp->RootWriteLock();
438 daq_words_by_type->Fill(kEPICSheader, 3.0); // EVIO outer and segment headers + timestamp
439 daq_words_by_type->Fill(kEPICSdata, istart[0]/sizeof(uint32_t) - 3);
440 japp->RootUnLock();
441 return; // no further parsing needed
442 }
443 }
444 }
445
446 // Physics event length
447 uint32_t physics_event_len = istart[0];
448 if( (istart[1] & 0xFF001000) != 0xFF001000 ) return; // not a physics event
449
450 // Trigger bank event length
451 uint32_t trigger_bank_len = istart[2];
452 if( (istart[3] & 0xFF202000) != 0xFF202000 ) return; // not a trigger bank
453 uint64_t tlo = istart[2+5];
454 uint64_t thi = istart[2+6];
455 uint64_t timestamp = (thi<<32) + (tlo<<0);
456
457 // Allocate memory to hold stats data
458 uint32_t Nwords[100]; // total data words for each ROC (includes event length words)
459 uint32_t word_stats[kNEVIOWordTypes]; // obtained from parsing event
460 for(uint32_t rocid=0; rocid<100; rocid++) Nwords[rocid] = 0;
461 for(uint32_t i=0; i<kNEVIOWordTypes; i++) word_stats[i] = 0;
462
463 word_stats[kNevents]++;
464 word_stats[kTotWords] += evio_buffwords;
465
466 // Loop over data banks
467 uint32_t *iptr = &istart[3+trigger_bank_len];
468 while(iptr < iend){
469
470 uint32_t len = *iptr;
471 uint32_t rocid = (iptr[1]>>16) & 0XFF;
472
473 if(rocid<100) Nwords[rocid] += len+1;
474
475 uint32_t *imyend = &iptr[len+1];
476 if(imyend > iend) imyend = iend;
477
478 DataWordStats(iptr, imyend, word_stats);
479
480 iptr = &iptr[len +1];
481 }
482
483 // Fill histograms
484 japp->RootWriteLock();
485
486 // Calculating time between events is tricky when using multiple-threads.
487 // We need the timestamp of two sequential events, but the order in which
488 // they are processed here will likely not be in event order. Thus, we keep
489 // a running list of the last 128 timestamps and event numbers seen by this
490 // routine. We can then search this for the event prior to this one and if
491 // found, use it.
492 uint32_t event_num = event.GetEventNumber();
493 static uint32_t recent_event_nums[128];
494 static uint64_t recent_timestamps[128];
495 static uint32_t ievent = 0;
496 for(uint32_t i=0; i<ievent; i++){
497 if(i>=128) break;
498 if(recent_event_nums[i] == (event_num-1)){
499 double tdiff = (double)(timestamp - recent_timestamps[i])/250.0E6; // convert to seconds
500 daq_event_tdiff->Fill(tdiff*1000.0); // ms
501 break;
502 }
503 }
504
505 // Record this timestamp/event number in the ring buffer
506 uint32_t idx = ievent%128;
507 recent_event_nums[idx] = event_num;
508 recent_timestamps[idx] = timestamp;
509 ievent++;
510
511 // Fill event size histos
512 double physics_event_len_kB = (double)((physics_event_len+1)*sizeof(uint32_t))/1024.0;
513 daq_event_size->Fill(physics_event_len_kB);
514 uint32_t TotalWords = 0;
515 for(uint32_t rocid=0; rocid<100; rocid++){
516 daq_words_per_event->Fill(rocid, Nwords[rocid]);
517 TotalWords += Nwords[rocid];
518 }
519
520 daq_words_per_event->Fill(1, trigger_bank_len+1);
521 daq_words_per_event->Fill(99, physics_event_len - trigger_bank_len - TotalWords);
522
523 for(uint32_t i=0; i<kNEVIOWordTypes; i++){
524 daq_words_by_type->Fill(i, (double)word_stats[i]);
525 }
526
527 japp->RootUnLock();
528
529}
530
531//------------------
532// DataWordStats
533//------------------
534void JEventProcessor_DAQ_online::DataWordStats(uint32_t *iptr, uint32_t *iend, uint32_t *word_stats)
535{
536 // Upon entry, the iptr will point to the start of the "Physics Event's Data Bank".
537 // It will loop over all sub-banks, tallying the word count as it goes up to
538 // but not including iend.
539
540 iptr++; // advance past length word
541 uint32_t rocid = (*iptr++)>>16 & 0x0FFF;
542 while(iptr < iend){
543 uint32_t data_block_bank_len = *iptr++;
544 uint32_t *iendbank = &iptr[data_block_bank_len];
545 uint32_t det_id = ((*iptr) >> 16) & 0x0FFF;
546 iptr++; // advance to first raw data word
547
548 uint32_t Ntoprocess = data_block_bank_len - 1; // 1 for bank header
549
550#if 0 // I don't know if these words are actually implmented ??
551 word_stats[kEVIOEventNumber]++; // starting event number
552 word_stats[kEVIOTimestamp] += 2; // 48-bit timestamp
553 iptr++; // starting event number
554 iptr++; // 48-bit timestamp
555 iptr++; // 48-bit timestamp
556 Ntoprocess -= 3;
557#endif
558 uint32_t *irawdata = iptr;
559
560 switch(det_id){
561 case 0:
562 case 1:
563 case 3:
564 case 6: // flash 250 module, MMD 2014/2/4
565 case 16: // flash 125 module (CDC), DL 2014/6/19
566 case 26: // F1 TDC module (BCAL), MMD 2014-07-31
567 ParseJLabModuleData(rocid, iptr, iendbank, word_stats);
568 break;
569
570 case 20:
571 ParseCAEN1190(rocid, iptr, iendbank, word_stats);
572 break;
573
574 case 0x55:
575 ParseModuleConfiguration(rocid, iptr, iendbank, word_stats);
576 break;
577 default:
578 break;
579 }
580
581 uint32_t Nprocessed = (uint32_t)((uint64_t)iptr - (uint64_t)irawdata)/sizeof(uint32_t);
582 if(Nprocessed < Ntoprocess) word_stats[kUnknown] += Ntoprocess - Nprocessed;
583 iptr = iendbank;
584 }
585
586
587}
588
589//------------------
590// ParseJLabModuleData
591//------------------
592void JEventProcessor_DAQ_online::ParseJLabModuleData(uint32_t rocid, uint32_t *&iptr, uint32_t *iend, uint32_t *word_stats)
593{
594 while(iptr < iend){
595 if(*iptr != 0xf800fafa) break;
596 word_stats[kF800FAFA]++;
597 iptr++;
598 }
599
600 uint32_t mod_id = ((*iptr) >> 18) & 0x000F;
601 switch(mod_id){
602 case DModuleType::FADC250: Parsef250Bank(rocid, iptr, iend, word_stats); break;
603 case DModuleType::FADC125: Parsef125Bank(rocid, iptr, iend, word_stats); break;
604 case DModuleType::F1TDC32: ParseF1v2TDCBank(rocid, iptr, iend, word_stats); break;
605 case DModuleType::F1TDC48: ParseF1v3TDCBank(rocid, iptr, iend, word_stats); break;
606 //case DModuleType::JLAB_TS: ParseTSBank(rocid, iptr, iend, word_stats); break;
607 //case DModuleType::TID: ParseTIBank(rocid, iptr, iend, word_stats); break;
608 }
609}
610
611//------------------
612// Parsef250Bank
613//------------------
614void JEventProcessor_DAQ_online::Parsef250Bank(uint32_t rocid, uint32_t *&iptr, uint32_t *iend, uint32_t *word_stats)
615{
616 while(iptr<iend){
617
618 if(((*iptr>>31) & 0x1) == 0) { word_stats[kUnknown]++ ; iptr++; continue;}
619
620 uint32_t window_width;
621 uint32_t window_words;
622 uint32_t data_type = (*iptr>>27) & 0x0F;
623 switch(data_type){
624 case 0: word_stats[kf250BlockHeader]++; iptr++; break;
625 case 1: word_stats[kf250BlockTrailer]++; iptr++; break;
626 case 2: word_stats[kf250EventHeader]++; iptr++; break;
627 case 3: // Trigger time
628 word_stats[kf250TriggerTime]++;
629 iptr++;
630 if(((*iptr>>31) & 0x1) == 0){ word_stats[kf250TriggerTime]++; iptr++; }
631 break;
632 case 4: // Window Raw Data
633 window_width = (*iptr>>0) & 0x0FFF;
634 window_words = 1 + ((window_width+1)/2); // 1 is for header word + 2 sample per word
635 word_stats[kf250WindowRawData] += window_words;
636 iptr = &iptr[window_words];
637 break;
638 case 7: word_stats[kf250PulseIntegral]++; iptr++; break;
639 case 8: word_stats[kf250PulseTime]++; iptr++; break;
640 case 10: word_stats[kf250PulsePedestal]++; iptr++; break;
641 case 13: word_stats[kf250EventTrailer]++; iptr++; break;
642 case 14: word_stats[kf250DataNotValid]++; iptr++; break;
643 case 15: word_stats[kf250Filler]++; iptr++; break;
644
645 default: word_stats[kUnknown]++; iptr++; break;
646 }
647 }
648}
649
650//------------------
651// Parsef125Bank
652//------------------
653void JEventProcessor_DAQ_online::Parsef125Bank(uint32_t rocid, uint32_t *&iptr, uint32_t *iend, uint32_t *word_stats)
654{
655 while(iptr<iend){
656
657 if(((*iptr>>31) & 0x1) == 0) { word_stats[kUnknown]++ ; iptr++; continue;}
658
659 uint32_t window_width;
660 uint32_t window_words;
661 uint32_t data_type = (*iptr>>27) & 0x0F;
662 switch(data_type){
663 case 0: word_stats[kf125BlockHeader]++; iptr++; break;
664 case 1: word_stats[kf125BlockTrailer]++; iptr++; break;
665 case 2: word_stats[kf125EventHeader]++; iptr++; break;
666 case 3: // Trigger time
667 word_stats[kf125TriggerTime]++;
668 iptr++;
669 if(((*iptr>>31) & 0x1) == 0){ word_stats[kf125TriggerTime]++; iptr++; }
670 break;
671 case 4: // Window Raw Data
672 window_width = (*iptr>>0) & 0x0FFF;
673 window_words = 1 + ((window_width+1)/2); // 1 is for header word + 2 sample per word
674 word_stats[kf125WindowRawData] += window_words;
675 iptr = &iptr[window_words];
676 break;
677 case 7: word_stats[kf125PulseIntegral]++; iptr++; break;
678 case 8: word_stats[kf125PulseTime]++; iptr++; break;
679 case 10: word_stats[kf125PulsePedestal]++; iptr++; break;
680 case 13: word_stats[kf125EventTrailer]++; iptr++; break;
681 case 14: word_stats[kf125DataNotValid]++; iptr++; break;
682 case 15: word_stats[kf125Filler]++; iptr++; break;
683
684 default: word_stats[kUnknown]++; iptr++; break;
685 }
686 }
687}
688
689//------------------
690// ParseF1v2TDCBank
691//------------------
692void JEventProcessor_DAQ_online::ParseF1v2TDCBank(uint32_t rocid, uint32_t *&iptr, uint32_t *iend, uint32_t *word_stats)
693{
694 while(iptr<iend){
695 switch( (*iptr++) & 0xF8000000 ){
696 case 0xC0000000: word_stats[kF1v2ChipHeader]++; break;
697 case 0xB8000000: word_stats[kF1v2Data]++; break;
698 case 0xF8000000: word_stats[kF1v2Filler]++; break;
699 case 0x80000000: word_stats[kF1v2BlockHeader]++; break;
700 case 0x88000000: word_stats[kF1v2BLockTrailer]++; break;
701 case 0x90000000: word_stats[kF1v2EventHeader]++; break;
702 case 0x98000000: word_stats[kF1v2TriggerTime]++; break;
703 case 0xF0000000: word_stats[kF1v2BreakWord]++; break;
704 default: word_stats[kUnknown]++; break;
705 }
706 }
707}
708
709//------------------
710// ParseF1v3TDCBank
711//------------------
712void JEventProcessor_DAQ_online::ParseF1v3TDCBank(uint32_t rocid, uint32_t *&iptr, uint32_t *iend, uint32_t *word_stats)
713{
714 while(iptr<iend){
715 switch( (*iptr++) & 0xF8000000 ){
716 case 0xC0000000: word_stats[kF1v3ChipHeader]++; break;
717 case 0xB8000000: word_stats[kF1v3Data]++; break;
718 case 0xF8000000: word_stats[kF1v3Filler]++; break;
719 case 0x80000000: word_stats[kF1v3BlockHeader]++; break;
720 case 0x88000000: word_stats[kF1v3BLockTrailer]++; break;
721 case 0x90000000: word_stats[kF1v3EventHeader]++; break;
722 case 0x98000000: word_stats[kF1v3TriggerTime]++; break;
723 case 0xF0000000: word_stats[kF1v3BreakWord]++; break;
724 default: word_stats[kUnknown]++; break;
725 }
726 }
727}
728
729//------------------
730// ParseCAEN1190
731//------------------
732void JEventProcessor_DAQ_online::ParseCAEN1190(uint32_t rocid, uint32_t *&iptr, uint32_t *iend, uint32_t *word_stats)
733{
734 while(iptr<iend){
735
736 // This word appears to be appended to the data.
737 // Probably in the ROL. Ignore it if found.
738 if(*iptr == 0xd00dd00d) {
739 word_stats[kD00DD00D]++;
740 iptr++;
741 continue;
742 }
743
744 uint32_t type = (*iptr++) >> 27;
745 switch(type){
746 case 0b01000: word_stats[kCAEN1190GlobalHeader]++; break;
747 case 0b10000: word_stats[kCAEN1190GlobalTrailer]++; break;
748 case 0b10001: word_stats[kCAEN1190GlobalTriggerTime]++; break;
749 case 0b00001: word_stats[kCAEN1190TDCHeader]++; break;
750 case 0b00000: word_stats[kCAEN1190TDCData]++; break;
751 case 0b00100: word_stats[kCAEN1190TDCError]++; break;
752 case 0b00011: word_stats[kCAEN1190TDCTrailer]++; break;
753 case 0b11000: word_stats[kCAEN1190Filler]++; break;
754 default: word_stats[kUnknown]++; break;
755 }
756 }
757}
758
759//------------------
760// ParseModuleConfiguration
761//------------------
762void JEventProcessor_DAQ_online::ParseModuleConfiguration(uint32_t rocid, uint32_t *&iptr, uint32_t *iend, uint32_t *word_stats)
763{
764 while(iptr < iend){
765
766 word_stats[kConfig]++; // Count headers as generic
767 uint32_t Nvals = ((*iptr++) >> 24) & 0xFF;
768
769 // Loop over all parameters in this section
770 for(uint32_t i=0; i< Nvals; i++){
771
772 switch((*iptr++)>>24){
773 case 0x05: word_stats[kConfigf250]++; break;
774 case 0x0F: word_stats[kConfigf125]++; break;
775 case 0x06: word_stats[kConfigF1]++; break;
776 case 0x10: word_stats[kConfigCAEN1190]++; break;
777 default: word_stats[kConfig]++; break;
778 }
779 }
780 }
781}
782
783//------------------
784// erun
785//------------------
786jerror_t JEventProcessor_DAQ_online::erun(void)
787{
788 // This is called whenever the run number changes, before it is
789 // changed to give you a chance to clean up before processing
790 // events from the next run number.
791 return NOERROR;
792}
793
794//------------------
795// fini
796//------------------
797jerror_t JEventProcessor_DAQ_online::fini(void)
798{
799 // Called before program exit after event processing is finished.
800 return NOERROR;
801}
802