Hall A ROOT/C++ Analyzer (podd)
Loading...
Searching...
No Matches
PipeliningModule.cxx
Go to the documentation of this file.
1
2//
3// PipeliningModule
4// A JLab PipeLining Module. See header file for more comments.
5// R. Michaels, Oct 2016
6//
8
9#include "PipeliningModule.h"
10#include "THaSlotData.h"
11#include "Helper.h"
12#include <iostream>
13#include <cstring> // for memcpy
14#include <algorithm> // for std::transform
15#include <utility> // for std::swap
16
17using namespace std;
18
19//_____________________________________________________________________________
20// Helper function for debugging
21static void PrintBlock( const uint32_t* codabuffer, uint32_t pos, uint32_t len )
22{
23 size_t idx = pos;
24 while( idx < pos+len ) {
25 while( idx < pos+len && !TESTBIT(codabuffer[idx], 31) )
26 ++idx;
27 if( idx == pos+len )
28 break;
29 uint32_t data = codabuffer[idx];
30 uint32_t type = (data >> 27) & 0xF;
31 switch( type ) {
32 case 0:
33 cout << "Block header"
34 << " idx = " << idx
35 << " slot = " << ((data >> 22) & 0x1F)
36 << " blksz = " << ((data >> 0) & 0xFF)
37 << " iblkn = " << ((data >> 8) & 0x3FF);
38 break;
39 case 1:
40 cout << "Block trailer"
41 << " idx = " << idx
42 << " slot = " << ((data >> 22) & 0x1F)
43 << " nwords = " << (data & 0x3FFFFF);
44 break;
45 case 2:
46 cout << " Event header"
47 << " idx = " << idx
48 << " slot = " << ((data >> 22) & 0x1F)
49// << " nevt = " << (data & 0x3FFFFF);
50 << " time = " << ((data >>12) & 0x3FF)
51 << " trignum = " << (data & 0xFFF);
52 break;
53 default:
54 cout << " Type = " << type
55 << " idx = " << idx;
56 break;
57 }
58 cout << endl;
59 ++idx;
60 }
61}
62
63//_____________________________________________________________________________
64namespace Decoder {
65
66//_____________________________________________________________________________
68 : VmeModule(crate, slot),
69 fBlockHeader(0),
70 data_type_def(15), // initialize to FILLER WORD
71 index_buffer(0)
72{
73}
74
75//_____________________________________________________________________________
76void PipeliningModule::Init( const char* configstr )
77{
78 // Set debug level of this module via optional configuration string in
79 // db_cratemap.dat.
80 //
81 // Example:
82 // ==== Crate 30 type vme
83 // # slot model bank configuration string
84 // 10 250 2501 cfg: debug=1
85
86 Init(); // standard Init
87
88 UInt_t debug = 0;
89 vector<ConfigStrReq> req = { { "debug", debug } };
90 ParseConfigStr(configstr, req);
91
92 fDebug = static_cast<Int_t>(debug);
93}
94
95//_____________________________________________________________________________
97{
99 evtblk.clear();
100 index_buffer = 0;
101}
102
103//_____________________________________________________________________________
105 const UInt_t* evbuffer,
106 const UInt_t* pstop )
107{
108 // Load event block. If multi-block data, split the buffer into individual
109 // physics events.
110 // This routine is called for legacy-type buffers without bank structure.
111 // It currently just forwards to the bank-structure version, assuming the
112 // data format within the block is the same in both cases.
113
114 //TODO: is multiblock mode supported for non-bank data?
115 return LoadBank(sldat, evbuffer, 0, pstop+1-evbuffer);
116}
117
118//_____________________________________________________________________________
120 const UInt_t* evbuffer, UInt_t pos, UInt_t len, Long64_t ibeg,
121 Long64_t iend ) const
122{
123 if( iend > 0 ) {
124 // Verify that the word count reported in the block trailer agrees with
125 // the trailer's position in the buffer.
126 UInt_t nwords_inblock = evbuffer[iend] & 0x3FFFFF;
127 if( ibeg + nwords_inblock == iend + 1 )
128 // All good
129 return iend;
130 } else {
131 // Block header without matching block trailer, should not happen
132 goto notfound;
133 }
134 // Apparent misidentification: keep searching until hitting the buffer end
135 if( ++iend < pos+len ) {
136 cerr << "WARNING: Block trailer misidentification, slot " << fSlot
137 << ", roc " << fCrate << ", data 0x" << hex << evbuffer[iend-1] << dec
138 << ". Attempting recovery." << endl;
139 return -iend;
140 } else {
141 notfound:
142 cerr << "ERROR: Block trailer NOT found, slot " << fSlot
143 << ", roc " << fCrate << ". Corrupt data. Giving up." << endl;
144 cout << "Block data:" << endl;
145 PrintBlock(evbuffer, pos, len);
146 return 0;
147 }
148}
149
150//_____________________________________________________________________________
152 const UInt_t* evbuffer,
153 UInt_t pos, UInt_t len )
154{
155 // Load event block. If multi-block data, split the buffer into individual
156 // physics events.
157 // This routine is called for buffers with bank structure.
158
159 if( fDebug > 1 ) // Set fDebug via module config string in db_cratemap.dat
160 PrintBlock(evbuffer,pos,len);
161
162 // Find block for this module's slot
163 auto ibeg = FindIDWord(evbuffer, pos, len, kBlockHeader, fSlot);
164 if( ibeg == -1 )
165 // Slot not present in buffer (OK)
166 return 0;
167 fBlockHeader = evbuffer[ibeg]; // save for convenience
168
169 // Multi-block event?
170 block_size = (evbuffer[ibeg] & 0xFF); // Number of events in block
171 fMultiBlockMode = ( block_size > 1 );
172
173 if( fMultiBlockMode ) {
174 // Multi-block: Find all the event headers (there should be block_size
175 // of them) between here and the block trailer, save their positions,
176 // then proceed with decoding the first block
177 evtblk.reserve(block_size + 1);
178 Long64_t iend = ibeg+1;
179 while( true ) {
180 iend = FindEventsInBlock(evbuffer, iend, len+pos-iend,
182 if( (iend = VerifyBlockTrailer(evbuffer, pos, len, ibeg, iend)) > 0 )
183 break;
184 if( iend == 0 )
185 return 0;
186 iend = -iend;
187 }
188 assert( ibeg >= pos && iend > ibeg && iend < pos+len ); // trivially
189
190 if( evtblk.empty() )
191 //TODO missing event headers, should not happen
192 evtblk.push_back(ibeg+1);
193 // evtblk should have exactly block_size elements now
194 evtblk.push_back(iend + 1); // include block trailer
195
196 // Because our module decoders expect a block header at the start of every
197 // event block, we must unfortunately copy the event block here so that we
198 // have a writable buffer where we can prepend the block header.
199 // This could probably be avoided, but we'd have to rewrite all decoders.
200 size_t blklen = iend + 1 - ibeg;
201 fBuffer.resize(blklen);
202 memcpy(fBuffer.data(), evbuffer+ibeg, blklen * sizeof(fBuffer[0]));
203 // Adjust the saved event header locations such that they reference the
204 // corresponding locations in fBuffer
205 transform(ALL(evtblk), evtblk.begin(),
206 [ibeg]( UInt_t pos ) { return pos-ibeg; });
207
208 index_buffer = 0;
209 return LoadNextEvBuffer(sldat);
210
211 } else {
212 // Single block: Find end of block and let the module decode the event
213 Long64_t iend = ibeg+1;
214 while( true ) {
215 iend = FindIDWord(evbuffer, iend, len+pos-iend,
217 if( (iend = VerifyBlockTrailer(evbuffer, pos, len, ibeg, iend)) > 0 )
218 break;
219 if( iend == 0 )
220 return 0;
221 iend = -iend;
222 }
223 assert( ibeg >= pos && iend > ibeg && iend < pos+len ); // trivially
224
225 return LoadSlot(sldat, evbuffer, ibeg, iend+1-ibeg);
226 }
227 // not reached
228}
229
230//_____________________________________________________________________________
232{
233 // In multi-block mode, load the next event from the current block
234
235 UInt_t ii = index_buffer;
236 assert( ii+1 < evtblk.size() );
237
238 // ibeg = event header, iend = one past last word of this event ( = next
239 // event header if more events pending)
240 auto ibeg = evtblk[ii], iend = evtblk[ii+1];
241 assert(ibeg > 0 && iend > ibeg && static_cast<size_t>(iend) <= fBuffer.size());
242
243 // Let ibeg point to the block header, or one before event header
244 if( ii == 0 )
245 ibeg = 0;
246 else {
247 --ibeg;
248 // Ensure the buffer starts with the block header word
249 std::swap(fBlockHeader, fBuffer[ibeg]);
250 }
251
252 // Load slot starting with block header at ibeg
253 try {
254 ii = LoadSlot(sldat, fBuffer.data(), ibeg, iend-ibeg);
255 }
256
257 catch( ... ) {
258 // In case the calling code wants to continue, put the buffer back in a
259 // consistent state
260 if( ii != 0 ) std::swap(fBlockHeader, fBuffer[ibeg]);
261 throw;
262 }
263 if( ii != 0 ) std::swap(fBlockHeader, fBuffer[ibeg]);
264
265 // Next cached buffer. Set flag if we've exhausted the cache.
266 ++index_buffer;
267 if( index_buffer+1 >= evtblk.size() )
268 fBlockIsDone = true;
269
270 return ii;
271}
272
273//_____________________________________________________________________________
274} //namespace Decoder
275
int Int_t
unsigned int UInt_t
uint32_t nwords_inblock
static void PrintBlock(const uint32_t *codabuffer, uint32_t pos, uint32_t len)
const char Option_t
#define TESTBIT(n, i)
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void data
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
UInt_t fCrate
Definition Module.h:142
virtual void Init()
Definition Module.cxx:51
Bool_t fMultiBlockMode
Definition Module.h:152
UInt_t block_size
Definition Module.h:150
Bool_t fBlockIsDone
Definition Module.h:152
static void ParseConfigStr(const char *configstr, const std::vector< ConfigStrReq > &req)
Definition Module.cxx:100
UInt_t fSlot
Definition Module.h:142
virtual UInt_t LoadNextEvBuffer(THaSlotData *sldat)
static Long64_t FindIDWord(const uint32_t *buf, size_t start, size_t len, uint32_t type)
std::vector< Long64_t > evtblk
virtual UInt_t LoadBank(THaSlotData *sldat, const UInt_t *evbuffer, UInt_t pos, UInt_t len)
virtual void Clear(Option_t *opt="")
virtual UInt_t LoadBlock(THaSlotData *sldat, const UInt_t *evbuffer, const UInt_t *pstop)
static Long64_t FindEventsInBlock(const uint32_t *buf, size_t start, size_t len, uint32_t evthdr, uint32_t blktrl, std::vector< Long64_t > &evtpos, uint32_t slot)
Long64_t VerifyBlockTrailer(const UInt_t *evbuffer, UInt_t pos, UInt_t len, Long64_t ibeg, Long64_t iend) const
VectorUIntNI data
Definition THaSlotData.h:99
virtual UInt_t LoadSlot(THaSlotData *sldat, const UInt_t *evbuffer, const UInt_t *pstop)
Definition VmeModule.cxx:28
void Clear(Option_t *option="") override
long long Long64_t
STL namespace.
ClassImp(TPyArg)