Hall A ROOT/C++ Analyzer (podd)
Loading...
Searching...
No Matches
THaCrateMap.cxx
Go to the documentation of this file.
1
2//
3// THaCrateMap
4// Layout, or "map", of DAQ Crates.
5//
6// THaCrateMap contains info on how the DAQ crates
7// are arranged in Hall A, i.e whether slots are
8// fastbus or vme, what the module types are, and
9// what header info to expect. Probably nobody needs
10// to know about this except the author, and at present
11// an object of this class is a private member of the decoder.
12//
13// author Robert Michaels (rom@jlab.org)
14//
16
17
18#include "Decoder.h"
19#include "THaCrateMap.h"
20#include "Helper.h"
21#include "Database.h"
22#include "Textvars.h"
23#include "TError.h"
24#include "TSystem.h"
25#include "TString.h"
26#include <cstdio>
27#include <cerrno> // for errno
28#include <string>
29#include <iostream>
30#include <iomanip>
31#include <sstream>
32#include <unistd.h>
33#include <cstring> // for strerror_r
34#include <memory> // for unique_ptr
35#include <algorithm> // for std::find, std::sort
36#include <array>
37
38// This is a well-known problem with strerror_r
39#if defined(__linux__) && (defined(_GNU_SOURCE) || !(_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE > 600))
40# define GNU_STRERROR_R
41#endif
42
43using namespace std;
44
45//_____________________________________________________________________________
46static string StrError()
47{
48 // Return description of current errno as a std::string
49 const size_t BUFLEN = 128;
50 char buf[BUFLEN];
51
52#ifdef GNU_STRERROR_R
53 const char* s = strerror_r(errno, buf, BUFLEN);
54 string ret = s ? string(s) : string("unknown error ") + to_string(errno);
55#else
56 strerror_r(errno, buf, BUFLEN);
57 string ret = buf;
58#endif
59 return ret;
60}
61
62//_____________________________________________________________________________
63namespace Decoder {
64
65const UInt_t THaCrateMap::MAXCHAN = 8192;
66const UInt_t THaCrateMap::MAXDATA = 65536;
68const Int_t THaCrateMap::CM_ERR = -1;
69
70// default crate number for trigger supervisor
72
73//_____________________________________________________________________________
74THaCrateMap::THaCrateMap( const char* db_filename ) : fTSROC{DEFAULT_TSROC}
75{
76 // Construct uninitialized crate map. The argument is the name of
77 // the database file to use for initialization
78
79 if( !db_filename || !*db_filename ) {
80 ::Warning( "THaCrateMap", "Undefined database file name, "
81 "using default \"db_cratemap.dat\"" );
82 db_filename = "cratemap";
83 }
84 fDBfileName = db_filename;
85}
86
87//_____________________________________________________________________________
89{
90 for( UInt_t crate = 0; crate < crdat.size(); crate++ ) {
91 const auto& cr = crdat[crate];
92 if( !cr.crate_used ) continue;
93 if( isScalerCrate(crate) ) {
94 UInt_t headtry = word & 0xfff00000;
95 UInt_t zero = word & 0x0000ff00;
96 if( (zero == 0) &&
97 (headtry == cr.sltdat[1].header) )
98 return crate;
99 }
100 }
101 return 0;
102}
103
104//_____________________________________________________________________________
106{
107 static const CrateInfo_t empty_crateinfo;
108 if( crate >= crdat.size() )
109 return CM_ERR;
110 crdat[crate] = empty_crateinfo;
111 setUnused(crate);
112 return CM_OK;
113}
114
115//_____________________________________________________________________________
116int THaCrateMap::setCrateType( UInt_t crate, const char* type )
117{
118 assert(crate < crdat.size());
119 string stype(type);
120 CrateInfo_t& cr = crdat[crate];
121 cr.crate_type_name = stype;
122 if( stype == "fastbus" )
123 cr.crate_code = kFastbus;
124 else if( stype == "vme" )
125 cr.crate_code = kVME;
126 else if( stype == "scaler" )
127 cr.crate_code = kScaler;
128 else if( stype == "camac" )
129 cr.crate_code = kCamac;
130 else {
131 cr.crate_used = false;
132 cr.crate_type_name = "unknown";
133 cr.crate_code = kUnknown;
134 return stype == "unused" ? CM_OK : CM_ERR;
135 }
136 cr.crate_used = true;
137 return CM_OK;
138}
139
140//_____________________________________________________________________________
142 UInt_t nchan, UInt_t ndata )
143{
144 setUsed(crate, slot);
145 auto& slt = crdat[crate].sltdat[slot];
146 if( slt.model != 0 && mod == 0 ) {
147 setUnused(crate, slot);
148 }
149 slt.model = mod;
150 if( !SetModelSize( crate, slot, mod )) {
151 slt.nchan = nchan;
152 slt.ndata = ndata;
153 }
154 return CM_OK;
155}
156
157//_____________________________________________________________________________
159{
160 // Set the max number of channels and data words for some known modules
161 assert( crate < crdat.size() && slot < crdat[crate].sltdat.size() );
162 struct ModelPar_t { UInt_t model, nchan, ndata; };
163 static const array<ModelPar_t, 18> modelpar = {{
164 { 1875, 64, 512 }, // Detector TDC
165 { 1877, 96, 672 }, // Wire-chamber TDC
166 { 1881, 64, 64 }, // Detector ADC
167 { 550, 512, 1024 }, // CAEN 550 (RICH)
168 { 560, 16, 16 }, // CAEN 560 scaler
169 { 1182, 8, 128 }, // LeCroy 1182 ADC (?)
170 { 1151, 16, 16 }, // LeCroy 1151 scaler
171 { 3123, 16, 16 }, // VMIC 3123 ADC
172 { 3800, 32, 32 }, // Struck 3800 scaler
173 { 3801, 32, 32 }, // Struck 3801 scaler
174 { 7510, 8, 1024 }, // Struck 7510 ADC (multihit)
175 { 767, 128, 1024 }, // CAEN 767 multihit TDC
176 { 6401, 64, 1024 }, // JLab F1 TDC normal resolution
177 { 3201, 32, 512 }, // JLab F1 TDC high resolution
178 { 775, 32, 32 }, // CAEN V775 TDC
179 { 792, 32, 32 }, // CAEN V792 QDC
180 { 1190, 128, 1024 }, //CAEN 1190A
181 { 250, 16, 20000 }, // FADC 250
182 }};
183 const auto* item =
184 find_if(ALL(modelpar), [model]( const ModelPar_t& modelParam ) {
185 return model == modelParam.model;
186 });
187 if( item != modelpar.end() ) {
188 crdat[crate].sltdat[slot].nchan = item->nchan;
189 crdat[crate].sltdat[slot].ndata = item->ndata;
190 return 1;
191 }
192 return 0;
193}
194
195//_____________________________________________________________________________
197{
198 assert( crate < crdat.size() && slot < crdat[crate].sltdat.size() );
199 auto& cr = crdat[crate];
200 cr.crate_used = true;
201 cr.sltdat[slot].used = true;
202 if( std::find(ALL(used_crates), crate) == used_crates.end() )
203 used_crates.push_back(crate);
204 if( std::find(ALL(cr.used_slots), slot) == cr.used_slots.end() ) {
205 cr.used_slots.push_back(slot);
206 }
207}
208
209//_____________________________________________________________________________
211{
212 auto jt = std::find(ALL(used_crates), crate);
213 if( jt != used_crates.end() )
214 used_crates.erase(jt);
215 crdat[crate].crate_used = false;
216}
217
218//_____________________________________________________________________________
220{
221 assert( crate < crdat.size() && slot < crdat[crate].sltdat.size() );
222 auto& cr = crdat[crate];
223 cr.sltdat[slot].used = false;
224 auto it = std::find(ALL(cr.used_slots), slot);
225 if( it != cr.used_slots.end() ) {
226 cr.used_slots.erase(it);
227 }
228 if( cr.used_slots.empty() )
229 setUnused(crate);
230}
231
232//_____________________________________________________________________________
233Int_t THaCrateMap::readFile( FILE* fi, string& text )
234{
235 // Read contents of opened file 'fi' to 'text'
236 if( !fi )
237 return CM_ERR;
238 Int_t ret = CM_ERR;
239 errno = 0;
240 if( fseek(fi, 0, SEEK_END) == 0 ) {
241 long size = ftell(fi);
242 if( size > 0 ) {
243 rewind(fi);
244 unique_ptr<char[]> fbuf{new char[size]};
245 size_t nread = fread(fbuf.get(), sizeof(char), size, fi);
246 if( nread == static_cast<size_t>(size) ) {
247 text.reserve(nread);
248 text.assign(fbuf.get(), fbuf.get()+nread);
249 ret = CM_OK;
250 }
251 }
252 }
253 return ret;
254}
255
256//_____________________________________________________________________________
257int THaCrateMap::init( FILE* fi, const char* fname )
258{
259 // Get the crate map definition string from the given database file.
260 // The file is read completely into an internal string, which is then
261 // parsed by init(const std::string&).
262
263 const char* const here = "THaCrateMap::init(file)";
264
265 if ( !fi ) {
266 ::Error( here, "Error opening crate map database file %s: %s",
267 fname, StrError().c_str() );
268 return CM_ERR;
269 }
270 // Build the string to parse
271 string db;
272 if( readFile(fi, db) != CM_OK || ferror(fi) ) {
273 ::Error( here, "Error reading crate map database file %s: %s",
274 fname, StrError().c_str() );
275 fclose(fi);
276 return CM_ERR;
277 }
278 fclose(fi);
279
280 // Parse the crate map definition
281 return init(db);
282}
283
284//_____________________________________________________________________________
286{
287 // Initialize the crate map from the database.
288 // 'tloc' is the time-stamp/index into the database's periods of validity.
289
290 const char* const here = "THaCrateMap::init(tloc)";
291 fInitTime = tloc;
292 FILE* fi = Podd::OpenDBFile(fDBfileName.c_str(), fInitTime, here, "r", 1);
293 return init(fi, fDBfileName.c_str());
294}
295
296//_____________________________________________________________________________
297void THaCrateMap::print(ostream& os) const
298{
299 // Pretty-print crate map
300 for( UInt_t roc = 0; roc < crdat.size(); roc++ ) {
301 const auto& cr = crdat[roc];
302 if( !cr.crate_used || cr.used_slots.empty() ) continue;
303 os << "==== Crate " << roc << " type " << cr.crate_type_name;
304 if( !cr.scalerloc.empty() ) os << " \"" << cr.scalerloc << "\"";
305 os << endl;
306 os << "#slot\tmodel\tclear\t header\t mask \tnchan\tndata\n";
307 for( UInt_t slot = 0; slot < cr.sltdat.size(); slot++ ) {
308 const auto& slt = cr.sltdat[slot];
309 if( !slt.used ) continue;
310 os << " " << slot << "\t" << slt.model << "\t" << slt.clear;
311 ios::fmtflags oldf = os.setf(ios::right, ios::adjustfield);
312 os << "\t0x" << hex << setfill('0') << setw(8) << slt.header
313 << "\t0x" << hex << setfill('0') << setw(8) << slt.headmask
314 << dec << setfill(' ') << setw(0)
315 << "\t" << slt.nchan
316 << "\t" << slt.ndata
317 << endl;
318 os.flags(oldf);
319 }
320 }
321}
322
323//_____________________________________________________________________________
324Int_t THaCrateMap::loadConfig( string& line, string& cfgstr )
325{
326 // Check if module configuration option is specified in 'line' and,
327 // if so, extract it and erase the option string from 'line'.
328 const char* const here = "THaCrateMap::loadConfig";
329 auto pos1 = line.find("cfg:");
330 auto pos2 = line.find("dbfile:");
331 bool have_cfg = (pos1 != string::npos);
332 bool have_dbf = (pos2 != string::npos);
333 if( have_cfg or have_dbf ) {
334 if( have_cfg and have_dbf ) {
335 ::Error(here, "Cannot specify both database file and options, "
336 "line = \n%s", line.c_str());
337 return CM_ERR;
338 }
339 if( have_cfg ) {
340 cfgstr = line.substr(pos1 + 4);
341 line.erase(pos1);
342 } else {
343 string fname = line.substr(pos2 + 7);
344 Podd::Trim(fname);
345 errno = 0;
346 FILE* fi = Podd::OpenDBFile(fname.c_str(), fInitTime, here);
347 if ( !fi ) {
348 ::Error(here, "Error opening decoder module database file "
349 "\"db_%s.dat\": %s\n line = %s",
350 fname.c_str(), StrError().c_str(), line.c_str() );
351 return CM_ERR;
352 }
353 if( readFile(fi, cfgstr) != CM_OK ) {
354 ::Error(here, "Error reading decoder module database file "
355 "\"db_%s.dat\": %s", fname.c_str(), StrError().c_str());
356 fclose(fi);
357 return CM_ERR;
358 }
359 fclose(fi);
360 line.erase(pos2);
361 }
362 Podd::Trim(cfgstr);
363 }
364 return CM_OK;
365}
366
367//_____________________________________________________________________________
368Int_t THaCrateMap::ParseCrateInfo( const std::string& line, UInt_t& crate )
369{
370 static const char* const here = "THaCrateMap::ParseCrateInfo";
371
372 char ctype[21];
373 if( sscanf(line.c_str(), "Crate %u type %20s", &crate, ctype) == 2 ) {
374 if( !(resetCrate(crate) == CM_OK && setCrateType(crate, ctype) == CM_OK) ) {
375 cerr << "THaCrateMap:: fatal ERROR 2 setCrateType " << endl;
376 return CM_ERR;
377 }
378 // for a scaler crate, get the 'name' or location as well
379 auto& cr = crdat[crate];
380 if( cr.crate_code == kScaler ) {
381 if( sscanf(line.c_str(), "Crate %*u type %*s %20s", ctype) != 1 ) {
382 cerr << "THaCrateMap:: fatal ERROR 3 " << endl;
383 return CM_ERR;
384 }
385 TString scaler_name(ctype);
386 scaler_name.ReplaceAll("\"", ""); // drop extra quotes
387 cr.scalerloc = scaler_name;
388 }
389 return CM_OK;
390 //in_crate = cr.crate_used; // false for ctype == "unused"
391 //continue; // onto the next line
392 }
393 Error(here, "Invalid/incomplete Crate definition: \"%s\"",
394 line.c_str());
395 return CM_ERR;
396}
397
398//_____________________________________________________________________________
400 string& line )
401{
402 // 'line' is expected to be the definition for a single module (slot).
403 // Parse it and fill corresponding element of the sltdat array.
404
405 // Check for and extract any configuration string given on the line and,
406 // if found, remove it from line and put a copy in cfgstr.
407 // This is primarily intended for bank-decoded VME and scaler modules.
408 string cfgstr;
409 if( crate_code == kVME /*or code == kScaler*/ ) {
410 Int_t st = crmap->loadConfig(line, cfgstr);
411 if( st != CM_OK )
412 return st;
413 }
414
415 // The line is of the format
416 // slot model [clear header mask nchan ndata ]
417 // where clear, header, mask, nchan and ndata are optional.
418 //
419 // Another option is "bank decoding": all data in this CODA bank
420 // belongs to this slot and model. The line has the format
421 // slot model bank
422
423 // Default values
424 Int_t cword = 1, imodel = 0;
425 UInt_t slot = kMaxUInt;
426 UInt_t mask = 0, iheader = 0, ichan = MAXCHAN, idata = MAXDATA;
427
428 Int_t nread = sscanf(line.c_str(), "%u %d %d %x %x %u %u",
429 &slot, &imodel, &cword, &iheader, &mask, &ichan, &idata);
430 // must have at least the slot and model numbers
431 if( nread < 2 ) {
432 cerr << "THaCrateMap:: fatal ERROR 4 " << endl << "Bad line " << endl
433 << line << endl
434 << " Warning: a bad line could cause wrong decoding !" << endl;
435 return CM_ERR;
436 }
437
438 if (nread > 5 )
439 crmap->setModel(crate,slot,imodel,ichan,idata);
440 else
441 crmap->setModel(crate,slot,imodel);
442
443 SlotInfo_t& slt = sltdat[slot];
444 if( nread == 3 )
445 slt.bank = cword;
446 else if( nread > 3 ) {
447 slt.clear = cword;
448 slt.header = iheader;
449 if( nread > 4 )
450 slt.headmask = mask;
451 }
452 slt.cfgstr = std::move(cfgstr);
453
454 return CM_OK;
455}
456
457//_____________________________________________________________________________
459{
460 for( auto& iused: used_crates ) {
461 auto& cr = crdat[iused];
462 assert(!cr.used_slots.empty());
463 sort(ALL(cr.used_slots));
464 auto slot_is_bank = [&]( UInt_t idx ) { return cr.sltdat[idx].bank >= 0; };
465 cr.bank_structure = any_of(ALL(cr.used_slots), slot_is_bank);
466 cr.all_banks = all_of(ALL(cr.used_slots), slot_is_bank);
467 }
468 sort(ALL(used_crates));
469 return 0;
470}
471
472//_____________________________________________________________________________
473int THaCrateMap::init(const string& the_map)
474{
475 // Initialize the crate map according to the lines in the string 'the_map'
476
477 const char* const here = "THaCrateMap::init(string)";
478
479 if ( the_map.empty() ) {
480 // Warn if we didn't get any data
481 ::Warning( here, "Empty crate map definition. Decoder will not be usable. "
482 "Check database." );
483 }
484
485 // For the time being, we use a simple hardcoded array size
486 UInt_t ncrates = MAXROC;
487 crdat.clear(); // support re-init
488 crdat.resize(ncrates);
489 used_crates.clear(); used_crates.reserve(ncrates/2);
490 fTSROC = DEFAULT_TSROC; // default value, if not found in db_cratemap
491
492 UInt_t crate = kMaxUInt; // current CRATE
493 string line; line.reserve(128);
494 istringstream s(the_map);
495 Int_t found_tscrate=0;
496 TDatime keydate(950101, 0), prevdate(950101, 0);
497 bool do_ignore = false, in_crate = false;
498 int lineno = 0;
499
500 while( getline(s, line) ) {
501 ++lineno;
502 // Drop comments
503 auto pos = line.find_first_of("!#");
504 if( pos != string::npos )
505 line.erase(pos);
506 // Skip empty or blank lines
507 if( line.find_first_not_of(" \t") == string::npos )
508 continue;
509
510 // Check for timestamps. Employ the algorithm from Podd::LoadDBvalue, i.e.
511 // read data for timestamps <= init time and newer than prior timestamps.
512 // This may lead to certain crates being defined multiple times as its
513 // parameters are updated for a new validity period.
514 // To remove a previously-defined crate after a certain time stamp, use
515 // crate type "unused".
516 if( Podd::IsDBtimestamp(line, keydate) ) {
517 do_ignore = (keydate > fInitTime || keydate < prevdate);
518 in_crate = false;
519 continue;
520 } else if( do_ignore )
521 continue;
522 prevdate = keydate;
523
524 // Recognize TSROC definition at start of map (or right after a timestamp)
525 if( !in_crate && line.find("TSROC") != string::npos ) {
526 sscanf(line.c_str(), " TSROC %u", &fTSROC);
527 found_tscrate = 1;
528 continue;
529 }
530
531 Int_t ret = CM_OK;
532
533 pos = line.find("Crate");
534 if( pos != string::npos ) {
535 // Make the line "==== Crate" not care about how many "=" chars or other
536 // chars before "Crate", except that lines beginning with '#' or '!' are
537 // still a comment (filtered out above).
538 line.erase(0, pos);
539 // Set the next CRATE number and type
540 if( (ret = ParseCrateInfo(line, crate)) != CM_OK )
541 return ret;
542 in_crate = crdat[crate].crate_used; // false for crate type "unused"
543 continue; // onto the next line
544 }
545 if( crate == kMaxUInt || !in_crate ) {
546 Error(here, "db_%s.dat:%d: Expected Crate definition.\n"
547 "For example: \"==== Crate 5 type vme\". "
548 "Found instead: \"%s\"",
549 fDBfileName.c_str(), lineno, line.c_str());
550 return CM_ERR;
551 }
552
553 if( (ret = crdat[crate].ParseSlotInfo(this, crate, line)) != CM_OK )
554 return ret;
555 }
556
557 SetBankInfo();
558
559 if ( !found_tscrate ) {
560 cout << "THaCrateMap::WARNING: Did not find TSROC. Using default " << fTSROC << endl;
561// cout << "THaCrateMap:: It may be ok for SBS, though."<<endl;
562 }
563
564 return CM_OK;
565}
566
567//_____________________________________________________________________________
569 crate_code(kUnknown), crate_type_name("unknown"),
570 crate_used(false), bank_structure(false), all_banks(false)
571{
572 used_slots.reserve(sltdat.size()/2);
573}
574
575} // namespace Decoder
576
577//_____________________________________________________________________________
int Int_t
unsigned int UInt_t
size_t size(const MatrixT &matrix)
const UInt_t kMaxUInt
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 mask
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
Option_t Option_t TPoint TPoint const char text
static string StrError()
static const char *const here
Definition THaVar.cxx:64
std::array< SlotInfo_t, MAXSLOT > sltdat
std::vector< UInt_t > used_slots
Int_t ParseSlotInfo(THaCrateMap *crmap, UInt_t crate, std::string &line)
void setUsed(UInt_t crate, UInt_t slot)
static const UInt_t MAXDATA
Definition THaCrateMap.h:36
static const UInt_t MAXCHAN
Definition THaCrateMap.h:35
std::string fDBfileName
Definition THaCrateMap.h:86
void print(std::ostream &os=std::cout) const
Int_t loadConfig(std::string &line, std::string &cfgstr)
std::vector< UInt_t > used_crates
UInt_t getScalerCrate(UInt_t word) const
Int_t ParseCrateInfo(const std::string &line, UInt_t &crate)
Int_t resetCrate(UInt_t crate)
Int_t setModel(UInt_t crate, UInt_t slot, Int_t mod, UInt_t nchan=MAXCHAN, UInt_t ndata=MAXDATA)
int init(const std::string &the_map)
static const Int_t CM_ERR
Definition THaCrateMap.h:76
static Int_t readFile(FILE *fi, std::string &text)
static const UInt_t DEFAULT_TSROC
Definition THaCrateMap.h:78
THaCrateMap(const char *db="cratemap")
Int_t SetModelSize(UInt_t crate, UInt_t slot, UInt_t model)
static const Int_t CM_OK
Definition THaCrateMap.h:75
void setUnused(UInt_t crate, UInt_t slot)
std::vector< CrateInfo_t > crdat
bool isScalerCrate(UInt_t crate) const
Int_t setCrateType(UInt_t crate, const char *stype)
TString & ReplaceAll(const char *s1, const char *s2)
unsigned long long ULong64_t
TLine * line
static const UInt_t MAXROC
Definition Decoder.h:33
model
void Error(const char *location, const char *fmt,...)
STL namespace.
ClassImp(TPyArg)