// $Id$ /******************************************************************** * The Data Acquisition Backbone Core (DABC) ******************************************************************** * Copyright (C) 2009- * GSI Helmholtzzentrum fuer Schwerionenforschung GmbH * Planckstr. 1 * 64291 Darmstadt * Germany * Contact: http://dabc.gsi.de ******************************************************************** * This software can be used under the GPL license agreements as stated * in LICENSE.txt file which is part of the distribution. ********************************************************************/ #include #include #include #include "hadaq/api.h" #include "dabc/string.h" #include "dabc/Url.h" #include "dabc/api.h" int usage(const char* errstr = 0) { if (errstr!=0) { printf("Error: %s\n\n", errstr); } printf("utility for printing HLD events\n"); printf("hldprint source [args]\n\n"); printf("Following source kinds are supported:\n"); printf(" hld://path/file.hld - HLD file reading\n"); printf(" file.hld - HLD file reading (file extension MUST be '.hld')\n"); printf(" mbs://dabcnode - DABC stream server\n"); printf(" mbs://dabcnode:port - DABC stream server with custom port\n"); printf(" mbs://dabcnode/Transport - DABC transport server\n"); printf(" lmd://path/file.lmd - LMD file reading\n"); printf("Additional arguments:\n"); printf(" -tmout value - maximal time in seconds for waiting next event (default 5)\n"); printf(" -maxage value - maximal age time for events, if expired queue are cleaned (default off)\n"); printf(" -num number - number of events to print, 0 - all events (default 10)\n"); printf(" -skip number - number of events to skip before start printing\n"); printf(" -sub - try to scan for subsub events (default false)\n"); printf(" -stat - accumulate different kinds of statistics (default false)\n"); printf(" -raw - printout of raw data (default false)\n"); printf(" -onlyraw subsubid - printout of raw data only for specified subsubevent\n"); printf(" -tdc mask - printout raw data of tdc subsubevents (default none) \n"); printf(" -onlytdc tdcid - printout raw data only of specified tdc subsubevent (default none) \n"); printf(" -fullid value - printout only events with specified fullid (default all) \n"); printf(" -hub value - identify hub inside subevent to printout raw data inside (default none) \n"); printf(" -rate - display only events rate\n"); return errstr ? 1 : 0; } enum TdcMessageKind { tdckind_Reserved = 0x00000000, tdckind_Header = 0x20000000, tdckind_Debug = 0x40000000, tdckind_Epoch = 0x60000000, tdckind_Mask = 0xe0000000, tdckind_Hit = 0x80000000, tdckind_Hit1 = 0xa0000000, tdckind_Hit2 = 0xc0000000, tdckind_Hit3 = 0xe0000000 }; enum { NumTdcErr = 4 }; enum TdcErrorsKind { tdcerr_MissHeader = 0x0001, tdcerr_MissCh0 = 0x0002, tdcerr_MissEpoch = 0x0004, tdcerr_NoData = 0x0008 }; const char* TdcErrName(int cnt) { switch(cnt) { case 0: return "header"; case 1: return "ch0"; case 2: return "epoch"; case 3: return "nodata"; } return "uncknown"; } struct SubevStat { long unsigned num; // number of subevent seen long unsigned sizesum; // sum of all subevents sizes bool istdc; // indicate if it is TDC subevent long unsigned tdcerr[NumTdcErr]; // tdc errors double aver_size() { return num>0 ? sizesum / (1.*num) : 0.; } double tdcerr_rel(unsigned n) { return (n < NumTdcErr) && (num>0) ? tdcerr[n] / (1.*num) : 0.; } SubevStat() : num(0), sizesum(0), istdc(false) { for (int n=0;nGetSize() - sizeof(hadaq::RawSubevent)) / sub->Alignment()); if (ix>=sz) return; if ((len==0) || (ix + len > sz)) len = sz - ix; unsigned wlen = 2; if (len>99) wlen = 3; else if (len>999) wlen = 4; unsigned epoch(0); double tm; errmask = 0; bool haschannel0 = false; unsigned channel(0); int epoch_channel(-11); // -11 no epoch, -1 - new epoch, 0..127 - epoch assigned with specified channel for (unsigned cnt=0;cntData(ix); if (prefix>0) printf("%*s[%*u] %08x ", prefix, "", wlen, ix, msg); if ((cnt==0) && ((msg & tdckind_Mask) != tdckind_Header)) errmask |= tdcerr_MissHeader; switch (msg & tdckind_Mask) { case tdckind_Reserved: if (prefix>0) printf("reserved\n"); break; case tdckind_Header: if (prefix>0) printf("tdc header\n"); break; case tdckind_Debug: if (prefix>0) printf("tdc debug\n"); break; case tdckind_Epoch: epoch = msg & 0xFFFFFFF; tm = (epoch << 11) *5.; epoch_channel = -1; // indicate that we have new epoch if (prefix>0) printf("epoch %u tm %6.3f ns\n", msg & 0xFFFFFFF, tm); break; case tdckind_Hit: channel = (msg >> 22) & 0x7F; if (channel == 0) haschannel0 = true; if (epoch_channel==-1) epoch_channel = channel; if ((epoch_channel == -11) || (epoch_channel != (int) channel)) errmask |= tdcerr_MissEpoch; tm = ((epoch << 11) + (msg & 0x7FF)) *5.; // coarse time tm += (((msg >> 12) & 0x3FF) - 20)/470.*5.; // approx fine time 20-490 if (prefix>0) printf("hit ch:%2u isrising:%u tc:0x%03x tf:0x%03x tm:%6.3f ns\n", (msg >> 22) & 0x7F, (msg >> 11) & 0x1, (msg & 0x7FF), (msg >> 12) & 0x3FF, tm); break; default: if (prefix>0) printf("undefined\n"); break; } } if (len<2) errmask |= tdcerr_NoData; else if (!haschannel0) errmask |= tdcerr_MissCh0; } int main(int argc, char* argv[]) { if (argc<2) return usage(); long number(10), skip(0); double tmout(-1.), maxage(-1.), debug_delay(-1); bool printraw(false), printsub(false), showrate(false), reconnect(false), dostat(false); unsigned tdcmask(0), onlytdc(0), onlyraw(0), hubmask(0), fullid(0); int n = 1; while (++n stat; long cnt(0), lastcnt(0), printcnt(0); dabc::TimeStamp last = dabc::Now(); dabc::TimeStamp first = last; dabc::TimeStamp lastevtm = last; dabc::InstallCtrlCHandler(); while (!dabc::CtrlCPressed()) { evnt = ref.NextEvent(maxage > 0 ? maxage/2. : 1., maxage); if (debug_delay>0) dabc::Sleep(debug_delay); dabc::TimeStamp curr = dabc::Now(); if (evnt!=0) { // ignore events which are nor match with specified id if ((fullid!=0) && (evnt->GetId()!=fullid)) continue; cnt++; lastevtm = curr; } else if (curr - lastevtm > tmout) break; if (showrate) { double tm = curr - last; if (tm>=0.3) { printf("\rTm:%6.1fs Ev:%8ld Rate:%8.2f Ev/s", first.SpentTillNow(), cnt, (cnt-lastcnt)/tm); fflush(stdout); last = curr; lastcnt = cnt; } // when showing rate, only with statistic one need to analyze event if (!dostat) continue; } if (evnt==0) continue; if (skip>0) { skip--; continue; } printcnt++; if (!showrate && !dostat) evnt->Dump(); hadaq::RawSubevent* sub = 0; while ((sub=evnt->NextSubevent(sub))!=0) { bool print_sub_header(false); if ((onlytdc==0) && (onlyraw==0) && !showrate && !dostat) { sub->Dump(printraw && !printsub); print_sub_header = true; } unsigned trbSubEvSize = sub->GetSize() / 4 - 4; unsigned ix = 0; while ((ix < trbSubEvSize) && (printsub || dostat)) { unsigned data = sub->Data(ix++); unsigned datalen = (data >> 16) & 0xFFFF; unsigned datakind = data & 0xFFFF; bool as_raw(false), as_tdc(false); if ((onlytdc!=0) && (datakind==onlytdc)) { as_tdc = true; } else if ((tdcmask!=0) && ((datakind & 0xff) <= (tdcmask & 0xff)) && ((datakind & 0xff00) == (tdcmask & 0xff00))) { as_tdc = true; } else if ((hubmask!=0) && (datakind==hubmask)) { // this is hack - skip hub header, inside is normal subsub events structure if (dostat) { stat[datakind].num++; stat[datakind].sizesum+=datalen; } continue; } else if ((onlyraw!=0) && (datakind==onlyraw)) { as_raw = true; } else if (printraw) { as_raw = (onlytdc==0) && (onlyraw==0); } if (!dostat && !showrate) { // do raw printout when necessary if (as_raw || as_tdc) { if (!print_sub_header) { sub->Dump(false); print_sub_header = true; } printf(" *** Subsubevent size %3u id 0x%04x full %08x\n", datalen, datakind, data); } unsigned errmask(0); if (as_tdc) PrintTdcData(sub, ix, datalen, 9, errmask); else if (as_raw) sub->PrintRawData(ix,datalen,9); if (errmask!=0) { printf(" !!!! TDC errors detected:"); unsigned mask = 1; for (int n=0;n0) && (printcnt >= number)) break; } if (showrate) { printf("\n"); fflush(stdout); } ref.Disconnect(); if (dostat) { printf("Statistic: %ld events analyzed\n", printcnt); int width = 3; if (printcnt > 1000) width = 6; for (std::map::iterator iter = stat.begin(); iter!=stat.end(); iter++) { printf(" Subevent 0x%04x : cnt %*lu averlen %5.1f", iter->first, width, iter->second.num, iter->second.aver_size()); if (iter->second.istdc) { printf(" TDC"); for (int n=0;nsecond.tdcerr[n]>0) { printf(" %s=%lu (%3.1f%s)", TdcErrName(n), iter->second.tdcerr[n], iter->second.tdcerr_rel(n) * 100., "\%"); } } printf("\n"); } } return 0; }