Hall C ROOT/C++ Analyzer (hcana)
Loading...
Searching...
No Matches
TIBlobModule.cxx
Go to the documentation of this file.
1
10#include "TIBlobModule.h"
11#include "THaSlotData.h"
12#include <cassert>
13#include <iostream>
14#include <sstream>
15
16using namespace std;
17
18namespace Decoder {
19
20Module::TypeIter_t TIBlobModule::fgThisType =
21 DoRegister( ModuleType( "Decoder::TIBlobModule" , 4 ));
22
23//_____________________________________________________________________________
26
27//_____________________________________________________________________________
29 : PipeliningModule(crate, slot)
30 , fEvBuf{nullptr}
31 , fNfill{0}
32 , fDataAvail{0}
33 , fWord4Type{0}
34 , fHasTimestamp{true}
35{
37}
38
39//_____________________________________________________________________________
41
42//_____________________________________________________________________________
44{
46#if defined DEBUG && defined WITH_DEBUG
47 // This will make a HUGE output
48 delete fDebugFile; fDebugFile = 0;
49 fDebugFile = new ofstream;
50 fDebugFile->open(string("TIBlob_debug.txt"));
51#endif
52 //fDebugFile=0;
53 Clear();
54 IsInit = kTRUE;
55
56 fName = "TIBlob";
57}
58
59//_____________________________________________________________________________
60void TIBlobModule::Init( const char* configstr )
61{
62 // Set parameters of this module via optional configuration string in
63 // db_cratemap.dat. Supported parameters:
64 // debug: debug level
65 // word4: type of word4 (0 = auto, 3 = counter bits, 4 = trigger bits)
66 //
67 // Example:
68 // ==== Crate 30 type vme
69 // # slot model bank configuration string
70 // 21 4 4 cfg: debug=1
71
72 Init(); // standard Init
73
74 UInt_t debug = 0, word4 = 0;
75 vector<ConfigStrReq> req = { { "debug", debug },
76 { "word4", word4} };
77 ParseConfigStr(configstr, req);
78
79 fDebug = static_cast<Int_t>(debug);
80 SetWord4Type(word4);
81}
82
83//_____________________________________________________________________________
85 const UInt_t* pstop )
86{
87 // Load from evbuffer between [evbuffer,pstop]
88
89 return LoadSlot(sldat, evbuffer, 0, pstop + 1 - evbuffer);
90}
91
92//_____________________________________________________________________________
93string TIBlobModule::Here( const char* function )
94{
95 ostringstream os;
96 os << "TIBlobModule::" << function << ": slot/crate "
97 << fSlot << "/" << fCrate << ": ";
98 return os.str();
99}
100
101//_____________________________________________________________________________
102static inline bool IsTrigBits( UInt_t word )
103{
104 return (word & 0xFFFF0000) == 0xDA560000;
105}
106
107//_____________________________________________________________________________
108void TIBlobModule::CheckWarnTrigBits( UInt_t word, UInt_t nopt, const char* here )
109{
110 if( !IsTrigBits(word) ) {
111 cerr << Here(here)
112 << "Unexpected data in event with " << nopt << " optional "
113 << "words. Expected trigger bits 0xDA5600XX, but found."
114 << hex << "0x" << word << dec << endl;
115 }
116}
117
118//_____________________________________________________________________________
120 UInt_t pos, UInt_t len ) {
121 // Load from bank data in evbuffer between [pos,pos+len)
122
123 // evbuffer+pos points to the event header, evbuffer+pos+len is one past
124 // the last word of the event, which is either the block trailer in single
125 // block mode or for the last event in multi-block mode, or the next event
126 // header in multi-block mode.
127
128 const char* const here = "LoadSlot";
129
130 // Clear event data and ensure there is enough space including optional data.
131 // Don't call Clear() here; it would wipe out the bank-level info.
132 fDataAvail = 0;
133 fData.assign(kNTICHAN,0);
134
135 if( len < 2 )
136 return 0;
137
138 // Event data:
139 // event[0]: header: trigger type, event length
140 // event[1]: trigger number lower 32 bits
141 // event[2]: trigger time lower 32 bits (optional)
142 // event[3]: trigger number/time upper 16 bits (optional, firmware-dependent)
143 // event[4]: front-panel trigger bit pattern (bits 0-5) | 0xDA560000 (optional)
144 // If any optional values are missing, the indices of any following words
145 // are correspondingly smaller, i.e. the event size depends on how many
146 // optional data are configured.
147 const auto* p = evbuffer + pos;
148 UInt_t nwords = (*p & 0xFFFF) + 1; // Number of words in this event
149 if( nwords > len || nwords > kNTICHAN ) {
150 cerr << Here(here) << "Reported event length too long: hdr = "
151 << nwords << ", buf = " << len << ", need <= " << kNTICHAN
152 << " and <= " << len << endl;
153 return 0;
154 }
155 if( nwords < 2 ) {
156 cerr << Here(here) << "Reported event length too short. Got "
157 << nwords << ", need >= 2" << endl;
158 return 0;
159 }
160 if( nwords == 2 && fHasTimestamp ) {
161 cerr << Here(here) << "Inconsistent event length = " << nwords
162 << " but timestamp present requires >= 3" << endl;
163 return 0;
164 }
165 if( nwords < len ) {
166 cerr << Here(here) << "Warning: TI event data unexpectedly "
167 <<" followed by " << len-nwords << " extra words" << endl;
168 }
169 // Trigger type:
170 // 0x00: filler events
171 // 0x01-0x40: Physics trigger; if the trigger is from TS, 0x01-0x20 indicates
172 // one bit from the GTP, 0x21-0x40 indicates one bit from TS front panel
173 // 0xfc: multiple trigger inputs to TS
174 // 0xfd: VME trigger
175 // 0xfe: Random trigger
176 // For TImaster, bit(31:26) represents the TS#6-1 inputs
178 fData[kTriggerType] = (*p++ >> 24) & 0xFF;
179 // Trigger number starting at 1
181 fData[kTriggerNum] = *p++;
182 // Trigger timing in units of 4 ns
183 if( fHasTimestamp ) {
184 assert(nwords >= 3); // nwords >= 3 assured above
186 fData[kTimestamp] = *p++;
187 }
188 // From here on, the data format leaves something to be desired
189 const auto* q = evbuffer + pos + nwords; // end of data + 1
190 assert(p <= q);
191 auto noptional = q-p;
192 if( noptional == 2 ) {
193 // This case is unambiguous
194
195 // Upper 16 bits of trigger number (bits 31:16) and trigger time (bits 15:0)
197 fData[kCounterBits] = *p++;
198
199 // TI front panel TSinput(6:1), before prescale
200 CheckWarnTrigBits(*p, noptional, here);
202 fData[kTriggerBits] = (*p++ & 0x3F);
203 }
204 else if( noptional == 1 ) {
205 // One optional word is ambiguous without extra information
206 if( (fWord4Type == 0 // If data format hint not set
207 // then guess the type. This may be wrong in the very rare case that
208 // the upper 16 bits of event data "word4" (counter bits) happen to
209 // match the magic number 0xDA56
210 && IsTrigBits(*p))
211 // User provided data format hint
213 {
214 if( fWord4Type == kTriggerBits )
215 CheckWarnTrigBits(*p, noptional, here);
217 fData[kTriggerBits] = (*p++ & 0x3F);
218 } else {
220 fData[kCounterBits] = *p++;
221 }
222 }
223 if( p != q ) {
224 cerr << Here(here) << "Unexpected decoding error, read "
225 << p - evbuffer - pos
226 << " words out of " << nwords << ". Call expert." << endl;
227 }
228 for( UInt_t i = 0; i < kNTICHAN; i++ ) {
229 if( TESTBIT(fDataAvail, i) )
230 sldat->loadData(i, fData[i], fData[i]);
231 }
232
233 return nwords;
234}
235
236//_____________________________________________________________________________
237static inline
239 UInt_t slot ) {
240 // Search 'buf' for data type identifier word encoding 'type', 'slot',
241 // and 'id'. The format is (T=type, S=slot, D=ID)
242 // 1TTT TSSS SSDD DDXX XXXX XXXX XXXX XXXX
243 // bit 28 24 20 16 12 8 4 0
244 //
245 // The buffer is searched between [start,start+len)
246 // Returns the offset into 'buf' containing the word, or -1 if not found.
247
248 const uint32_t ID = BIT(31) | (slot & 0x1F) << 22;
249 const auto* p = buf + start;
250 const auto* q = p + len;
251 while( p != q && (*p & 0xFFFC0000) != ID )
252 ++p;
253 return (p != q) ? p - buf : -1;
254}
255
256//_____________________________________________________________________________
258 const UInt_t* evbuffer,
259 UInt_t pos, UInt_t len )
260{
261 // Load event block. If multi-block data, split the buffer into individual
262 // events. This routine is called for buffers with bank structure.
263
264 const char* const here = "LoadBank";
265
266 // Note: Clear() has been called at this point
267
268 if( len < 5 ) {
269 cerr << here << "Bank too short. Expected >= 5, got " << len << " words."
270 << endl;
271 // Caller has no provision for error codes and doesn't handle exceptions.
272 // Hopeless.
273 return 0;
274 }
275 // Find block header for this module's slot
276 // There should never be more than one TI module per bank per ROC, so this
277 // really ought to match the very first word.
278 auto ibeg = FindBlockHeaderForSlot(evbuffer, pos, len, fSlot);
279 if( ibeg == -1 ) {
280 // Block header not present. Should not happen.
281 cerr << Here(here)
282 << "No block header found in bank. Call expert." << endl;
283 return 0;
284 }
285 if( ibeg != pos ) {
286 cerr << Here(here)
287 << "Warning: " << ibeg-pos << " words of leading garbage" << endl;
288 }
289 const UInt_t* p = evbuffer+ibeg;
290 // Block header lower 18 bits
291 fBlockHeader = *p;
292 block_size = (*p & 0x000000FF); // Number of events in block
293 //fBlockNum = (*p & 0x0003FF00) >> 8; // Block number
294
295 // Block header #2
296 UInt_t hdr2id = (*++p & 0xFFFEFF00);
297 if( hdr2id != 0xFF102000 ) {
298 cerr << Here(here) << "Invalid block header #2 signature = " << hex
299 << "0x" << *p << dec << ", expected 0xFF1020xx or 0xFF1120xx" << endl;
300 return 0;
301 }
302 fHasTimestamp = TESTBIT(*p, 16);
303 UInt_t block_size2 = (*p & 0x000000FF);
304 if( block_size != block_size2 ) {
305 cerr << Here(here) << "Warning: block sizes in block headers #1 and #2 "
306 << "disagree: " << block_size << ", " << block_size2 << endl;
307 }
308
309 // Find all the event headers (there should be block_size of them)
310 // between here and the block trailer, save their positions,
311 // then proceed with decoding the first block
312 evtblk.reserve(block_size + 1);
313
314 UInt_t blksz = block_size;
315 ++p;
316 while( blksz > 0 && p-evbuffer < pos+len) {
317 UInt_t sig = (*p & 0x00FF0000) >> 16;
318 if( sig != 0x01 ) {
319 cerr << Here(here) << "Invalid event header signature for iblock "
320 << block_size-blksz << ". Expected xx01xxxx, got "
321 << hex << "0x" << *p << dec << endl;
322 return 0;
323 }
324 UInt_t nwords = (*p & 0xFFFF) + 1; // Number of 32-bit words in event
325 if( nwords < 2 ) {
326 cerr << Here(here) << "Event data too short, expected >= 2, got "
327 << nwords << endl;
328 return 0;
329 }
330 evtblk.push_back(p - evbuffer);
331 p += nwords;
332 --blksz;
333 }
334
335 if( evtblk.size() != block_size ) {
336 cerr << Here(here) << "Incorrect number of events found, expected "
337 << block_size << ", found " << evtblk.size() << endl;
338 return 0;
339 }
340 // evtblk must have exactly block_size elements now
341 evtblk.push_back(p-evbuffer); // include block trailer
342
343 // Verify block trailer
344 if( (*p & 0xFFC00000) != (BIT(31) | (kBlockTrailer << 27) | (fSlot & 0x1F) << 22) ) {
345 cerr << Here(here) << "Warning: Missing block trailer" << endl;
346 }
347 UInt_t nwords_inblock = *p & 0x3FFFFF;
348 Long64_t iend = p-evbuffer; // Position of block trailer
349 size_t blklen = iend + 1 - ibeg;
350 if( nwords_inblock != blklen ) {
351 cerr << Here(here) << "Warning: block trailer word count mismatch, "
352 << "got " << nwords_inblock << ", expected " << blklen << endl;
353 }
354 assert( ibeg >= pos && iend > ibeg && iend < pos+len ); // trivially
355
356 // Consume filler words
357 while( ++p-evbuffer < pos+len
358 && (*p & 0xF7C00000) == (0xF0000000 | (fSlot & 0x1F) << 22) ) {
359 ++fNfill;
360 }
361 if( p-evbuffer != pos+len ) {
362 cerr << Here(here) << evbuffer+pos+len-p
363 << " trailing garbage words" << endl;
364 }
365
366 // Multi-block event?
367 fMultiBlockMode = ( block_size > 1 );
368
369 if( fMultiBlockMode ) {
370 // Save pointer to event buffer for use in LoadNextEvBuffer
371 fEvBuf = evbuffer;
372 // Multi-block: decode first event, using event positions from evtblk[]
373 index_buffer = 0;
374 return LoadNextEvBuffer(sldat)
375 + 2; // 2 block header words
376
377 } else {
378 // Single block: decode, starting at event header
379 ibeg += 2;
380 return LoadSlot(sldat, evbuffer, ibeg, iend-ibeg)
381 + 3 // 2 block header words + 1 block trailer word
382 + fNfill;
383 }
384 // not reached
385}
386
387//_____________________________________________________________________________
389{
390 // In multi-block mode, load the next event from the current block
391
392 UInt_t ii = index_buffer;
393 assert( ii+1 < evtblk.size() );
394
395 // ibeg = event header, iend = one past last word of this event ( = next
396 // event header if more events pending)
397 auto ibeg = evtblk[ii], iend = evtblk[ii+1];
398 assert(ibeg > 0 && iend > ibeg); // else bug in LoadBank
399
400 assert(fEvBuf); // We should never get here without a prior call to LoadBank
401 // or after fBlockIsDone is set
402
403 // Load slot starting with event header at ibeg
404 ii = LoadSlot(sldat, fEvBuf, ibeg, iend-ibeg);
405
406 // Next cached buffer. Set flag if we've exhausted the cache.
407 ++index_buffer;
408 if( index_buffer+1 >= evtblk.size() ) {
409 fBlockIsDone = true;
410 fEvBuf = nullptr;
411 }
412
413 if( fBlockIsDone )
414 ii += 1 + fNfill; // block trailer + filler words
415 return ii;
416}
417
418//_____________________________________________________________________________
419 /* Does anything use this method */
421{
422 if (chan >= fNumChan) return 0;
423 return fData[chan];
424}
425
426//_____________________________________________________________________________
427// Clear module's data in preparation for new event/new bank
429{
431 fData.assign(kNTICHAN, 0);
432 fNfill = 0;
433 fDataAvail = 0;
434 fHasTimestamp = true;
435}
436
437//_____________________________________________________________________________
439{
440 if( type != 0 && type != kCounterBits && type != kTriggerBits ) {
441 Warning( "TIBlobModule::SetWord4Type",
442 "Unsupported type for 3rd/4th data word: %u. "
443 "Check configuration string in crate map.", type);
444 return;
445 }
447}
448
449} // namespace Decoder
450
int Int_t
unsigned int UInt_t
uint32_t nwords_inblock
uint32_t chan
const Bool_t kTRUE
const char Option_t
#define BIT(n)
#define SETBIT(n, i)
#define TESTBIT(n, i)
winID h TVirtualViewer3D TVirtualGLPainter p
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t unsigned char prop_list Atom_t Atom_t Atom_t Time_t UChar_t len
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t unsigned char prop_list Atom_t Atom_t Atom_t Time_t type
ClassImp(VDC::AnalyticTTDConv) using namespace std
float * q
string::size_type pos
virtual void Init()
Bool_t fMultiBlockMode
std::ofstream * fDebugFile
static void ParseConfigStr(const char *configstr, const std::vector< ConfigStrReq > &req)
std::vector< UInt_t > fData
std::vector< Long64_t > evtblk
virtual void Clear(Option_t *opt="")
Int_t loadData(const char *type, UInt_t chan, UInt_t dat, UInt_t raw)
virtual UInt_t LoadNextEvBuffer(THaSlotData *sldat)
virtual UInt_t LoadSlot(THaSlotData *sldat, const UInt_t *evbuffer, const UInt_t *pstop)
const UInt_t * fEvBuf
std::string Here(const char *function)
virtual void Clear(const Option_t *opt="")
virtual UInt_t GetData(UInt_t chan) const
void SetWord4Type(UInt_t type)
void CheckWarnTrigBits(UInt_t word, UInt_t nopt, const char *here)
static TypeIter_t fgThisType
virtual UInt_t LoadBank(THaSlotData *sldat, const UInt_t *evbuffer, UInt_t pos, UInt_t len)
TString fName
virtual void Warning(const char *method, const char *msgfmt,...) const
long long Long64_t
static bool IsTrigBits(UInt_t word)
static Long64_t FindBlockHeaderForSlot(const UInt_t *buf, UInt_t start, UInt_t len, UInt_t slot)
void function(const Char_t *name_, T fun, const Char_t *docstring=0)
start
STL namespace.