diff --git a/src/controls.h b/src/controls.h index 3025226c14e5f8168647b0d2576b35e220878375..fd7a947964c5110d240cd1fc2e93609d47f74c68 100644 --- a/src/controls.h +++ b/src/controls.h @@ -13,8 +13,5 @@ struct ctrl { uint64_t max_file_size; int packets_per_report; int n_orbits_per_dma_packet; - std::atomic<uint32_t> orbit_trailer_error_count; - std::atomic<uint64_t> packet_count; - std::atomic<uint64_t> excessOrbitsPerPacketCount; }; #endif diff --git a/src/processor.cc b/src/processor.cc index 9d5b37f955254e96408dd00e1c74dffdcb0ad823..f2acecd074d727984444e9e4903d8603cafdac36 100644 --- a/src/processor.cc +++ b/src/processor.cc @@ -7,6 +7,9 @@ #include <vector> #include <algorithm> +// Definition of the static member stats +StreamProcessor::Statistics StreamProcessor::stats; + StreamProcessor::StreamProcessor(size_t max_size_, bool doZS_, ProcessorType processorType_, uint32_t nOrbitsPerDMAPacket_, uint32_t prescaleFactor_, ctrl& control_) : tbb::filter(parallel), max_size(max_size_), @@ -15,8 +18,8 @@ StreamProcessor::StreamProcessor(size_t max_size_, bool doZS_, ProcessorType pro processorType(processorType_), nOrbitsPerDMAPacket(nOrbitsPerDMAPacket_), prescaleFactor(prescaleFactor_), - control(control_) -{ + control(control_) +{ LOG(TRACE) << "Created transform filter at " << static_cast<void*>(this); myfile.open ("example.txt"); } @@ -44,10 +47,31 @@ StreamProcessor::~StreamProcessor(){ bool StreamProcessor::CheckFrameMultBlock(size_t inputSize){ int bsize = sizeof(blockMuon); - if((inputSize-nOrbitsPerDMAPacket*constants::orbit_trailer_size - 32*nOrbitsPerDMAPacket -32)%bsize!=0){ + if ((inputSize-nOrbitsPerDMAPacket*constants::orbit_trailer_size - 32*nOrbitsPerDMAPacket -32)%bsize!=0){ + + stats.n_consistent_sized_packets = 0; + stats.packet_skipped_inconsistent_size++; + + if (( stats.packet_skipped_inconsistent_size++ == 1) || + ((stats.packet_skipped_inconsistent_size < 100) && (stats.packet_skipped_inconsistent_size%10 == 0)) || + ((stats.packet_skipped_inconsistent_size < 1000) && (stats.packet_skipped_inconsistent_size%100 == 0)) || + ((stats.packet_skipped_inconsistent_size < 10000) && (stats.packet_skipped_inconsistent_size%1000 == 0)) || + (stats.packet_skipped_inconsistent_size%10000 == 0)) { + LOG(WARNING) << "Frame size not a multiple of block size after headers and trailers have been subtracted. Counted " << stats.packet_skipped_inconsistent_size << " packets skipped."; + } + + if (control.verbosity != 0){ + LOG(WARNING) << "Frame size not a multiple of block size after orbit headers (32B*nOrbitsPerPacket), orbit trailers (544B*nOrbitsPerPacket), and packet trailer (32B) have been subtracted. \n Frame size = " << inputSize << ", block size = " << bsize << ", packet will be skipped"; + } return false; + } else { + stats.n_consistent_sized_packets++; + if (stats.n_consistent_sized_packets == 6000000){ // every ~10 mins + LOG(WARNING) << "Resetting packet_skipped_inconsistent_size counter to 0 after 6000000M consistnent packets. Count was at "<< stats.packet_skipped_inconsistent_size; + stats.packet_skipped_inconsistent_size = 0; + } } return true; } @@ -59,9 +83,9 @@ std::vector<unsigned int> StreamProcessor::CountBX(Slice& input, char* rd_ptr, b rd_ptr += 32; // +32 to account for orbit header std::vector<unsigned int> bx_vect; trailerError = false; - while( rd_ptr != input.end()){ + while ( rd_ptr != input.end()){ blockMuon *bl = reinterpret_cast<blockMuon*>(rd_ptr); - if(bl->orbit[0]==constants::beefdead){ // found orbit trailer + if (bl->orbit[0]==constants::beefdead){ // found orbit trailer orbit_trailer *ot = (orbit_trailer*)(rd_ptr); for (unsigned int k = 0; k < (14*8); k++){ // 14*8 = 14 frames, 8 links of orbit trailer containing BX hitmap bit_check(&bx_vect, ot->bx_map[k], (k*32 + 1));// +1 added to account for BX counting starting at 1 @@ -95,7 +119,7 @@ StreamProcessor::fillOrbitMetadata StreamProcessor::FillOrbitCalo(std::vector<un uint32_t orbit = uint32_t{orbit_header.first}; while(relbx < bx_vect.size()){ //total number of non-empty BXs in orbit is given by bx_vect.size() blockCalo *bl = reinterpret_cast<blockCalo*>(rd_ptr); - if(bl->calo0[0]==constants::beefdead){break;} // orbit trailer has been reached, end of orbit data + if (bl->calo0[0]==constants::beefdead){break;} // orbit trailer has been reached, end of orbit data uint32_t bx = uint32_t{bx_vect[relbx]}; uint32_t orbit_ = uint32_t{orbit_header.first}; if (bx > 3554){orbit_--;} //fix for the fact that bx 3555 - 3564 are from the previous orbit @@ -131,21 +155,21 @@ uint32_t StreamProcessor::FillBril(char* rd_ptr, char* wr_ptr, char* end_ptr){ //BrilHistoQueue<std::array<uint32_t, constants::NBXPerOrbit + constants::NFramesInHistoHeader>> BrilQueue; - while( (rd_ptr != end_ptr) && (histo_i < NHistosPerPacket)){ + while ( (rd_ptr != end_ptr) && (histo_i < NHistosPerPacket)){ brilFrame *fr = reinterpret_cast<brilFrame*>(rd_ptr); - if(fr->word == constants::bril_header){ + if (fr->word == constants::bril_header){ rd_ptr += 32; histo_i++; histo_word_i = 0; continue; } - if(histo_i == 0){continue;} // Currently appears to be a bug where first histogram of packet is truncated, need to understand and fix, for now skip + if (histo_i == 0){continue;} // Currently appears to be a bug where first histogram of packet is truncated, need to understand and fix, for now skip - if(histo_word_i < constants::NFramesInHistoHeader){ + if (histo_word_i < constants::NFramesInHistoHeader){ histo_arr[histo_i][histo_word_i] = (fr->word >> 0) & 0xffffffff; - }else{ + } else { histo_arr[histo_i][(histo_word_i*2) - constants::NFramesInHistoHeader ] = (fr->word >> 0) & 0xffff; histo_arr[histo_i][(histo_word_i*2) + 1 - constants::NFramesInHistoHeader] = (fr->word >> 16) & 0xffff; } @@ -156,7 +180,7 @@ uint32_t StreamProcessor::FillBril(char* rd_ptr, char* wr_ptr, char* end_ptr){ uint32_t packed_size = sizeof(uint32_t)*NHistosPerPacket*(constants::NBXPerOrbit + constants::NFramesInHistoHeader); memcpy(wr_ptr,(char*)&histo_arr,packed_size); wr_ptr+=packed_size; - for(std::array<uint32_t, constants::NBXPerOrbit + constants::NFramesInHistoHeader> & hist : histo_arr){ + for (std::array<uint32_t, constants::NBXPerOrbit + constants::NFramesInHistoHeader> & hist : histo_arr){ BrilQueue.push(hist); } @@ -170,18 +194,18 @@ StreamProcessor::fillOrbitMetadata StreamProcessor::FillOrbitMuon(std::vector<un uint32_t orbit = uint32_t{orbit_header.first}; uint32_t relbx = uint32_t{0}; uint32_t counts = uint32_t{0}; - while(relbx < bx_vect.size()){ //total number of non-empty BXs in orbit is given by bx_vect.size() + while (relbx < bx_vect.size()){ //total number of non-empty BXs in orbit is given by bx_vect.size() blockMuon *bl = reinterpret_cast<blockMuon*>(rd_ptr); - if(bl->orbit[0]==constants::beefdead){break;} // orbit trailer has been reached, end of orbit data + if (bl->orbit[0]==constants::beefdead){ break; } // orbit trailer has been reached, end of orbit data int mAcount = 0; int mBcount = 0; bool AblocksOn[8]; bool BblocksOn[8]; uint32_t bx = uint32_t {bx_vect[relbx]}; if (bx > 3554){orbit--;} //fix for the fact that bx 3555 - 3564 are from the previous orbit - for(unsigned int i = 0; i < 8; i++){ + for (unsigned int i = 0; i < 8; i++){ uint32_t bxA = (bl->bx[i] >> shifts::bx) & masks::bx; - if((bxA != bx) && (i == 0) && (bx<3555) && control.verbosity){ //only prints warning when BX < 3555 i.e from the same orbit + if ((bxA != bx) && (i == 0) && (bx<3555) && control.verbosity){ //only prints warning when BX < 3555 i.e from the same orbit LOG(WARNING) << "BX mismatch, uGMT data word BX = " << std::hex << bxA << ", BX extracted from trailer = "<< bx << ", orbitN is " << std::dec << orbit; } @@ -189,18 +213,18 @@ StreamProcessor::fillOrbitMetadata StreamProcessor::FillOrbitMuon(std::vector<un uint32_t pt = uint32_t{(bl->mu1f[i] >> shifts::pt) & masks::pt}; AblocksOn[i]=((pt>0) || (doZS==0)); - if((pt>0) || (doZS==0)){ + if ((pt>0) || (doZS==0)){ mAcount++; } pt = (bl->mu2f[i] >> shifts::pt) & masks::pt; BblocksOn[i]=((pt>0) || (doZS==0)); - if((pt>0) || (doZS==0)){ + if ((pt>0) || (doZS==0)){ mBcount++; } } uint32_t bxcount = std::max(mAcount,mBcount); - if(bxcount == 0) { + if (bxcount == 0) { rd_ptr+=sizeof(blockMuon); LOG(WARNING) << '#' << nbPackets << ": Detected a bx with zero muons, this should not happen. Packet is skipped."; continue; @@ -214,8 +238,8 @@ StreamProcessor::fillOrbitMetadata StreamProcessor::FillOrbitMuon(std::vector<un memcpy(wr_ptr,(char*)&header,4); wr_ptr+=4; memcpy(wr_ptr,(char*)&bx,4); wr_ptr+=4; memcpy(wr_ptr,(char*)&orbit,4); wr_ptr+=4; - for(unsigned int i = 0; i < 8; i++){ - if(AblocksOn[i]){ + for (unsigned int i = 0; i < 8; i++){ + if (AblocksOn[i]){ memcpy(wr_ptr,(char*)&bl->mu1f[i],4); wr_ptr+=4; memcpy(wr_ptr,(char*)&bl->mu1s[i],4); wr_ptr+=4; // next creating mu.extra which is a copy of bl->bx with a change to the first bit @@ -223,8 +247,8 @@ StreamProcessor::fillOrbitMetadata StreamProcessor::FillOrbitMuon(std::vector<un } } - for(unsigned int i = 0; i < 8; i++){ - if(BblocksOn[i]){ + for (unsigned int i = 0; i < 8; i++){ + if (BblocksOn[i]){ memcpy(wr_ptr,(char*)&bl->mu2f[i],4); wr_ptr+=4; memcpy(wr_ptr,(char*)&bl->mu2s[i],4); wr_ptr+=4; // next creating mu.extra which is a copy of bl->bx with a change to the first bit @@ -243,11 +267,11 @@ StreamProcessor::fillOrbitMetadata StreamProcessor::FillOrbitMuon(std::vector<un void StreamProcessor::process(Slice& input, Slice& out) { nbPackets++; - control.packet_count++; + stats.packet_count++; //Implement prescale - only for CALO if ((processorType == ProcessorType::CALO) && (prescaleFactor!=0)) { - if(control.packet_count%prescaleFactor != 0){return;} + if (stats.packet_count%prescaleFactor != 0){return;} } char* rd_ptr = input.begin(); @@ -264,7 +288,7 @@ void StreamProcessor::process(Slice& input, Slice& out) out.set_counts(1); return; } - if(processorType == ProcessorType::BRIL){ + if (processorType == ProcessorType::BRIL){ counts = FillBril(rd_ptr, wr_ptr, end_ptr); out.set_end(out.begin() + counts); out.set_counts(counts); @@ -278,8 +302,8 @@ void StreamProcessor::process(Slice& input, Slice& out) bool trailerError = false; bx_vect = CountBX(input, rd_ptr, trailerError); if(trailerError == true){ - control.orbit_trailer_error_count++; - LOG(WARNING) << "Orbit trailer error: orbit trailer not found before end of data packet. Packet will be skipped. Orbit trailer error count = " << control.orbit_trailer_error_count; + stats.orbit_trailer_error_count++; + LOG(WARNING) << "Orbit trailer error: orbit trailer not found before end of data packet. Packet will be skipped. Orbit trailer error count = " << stats.orbit_trailer_error_count; return; } std::sort(bx_vect.begin(), bx_vect.end()); @@ -288,7 +312,7 @@ void StreamProcessor::process(Slice& input, Slice& out) orbitCount = meta.counts; ++orbit_per_packet_count; wr_ptr+= orbitCount*12 + 12*bx_vect.size(); // 12 bytes for each muon/count then 12 bytes for each bx header - }else if (processorType == ProcessorType::CALO){ + } else if (processorType == ProcessorType::CALO){ meta = FillOrbitCalo(bx_vect, rd_ptr, wr_ptr); orbitCount = meta.counts; ++orbit_per_packet_count; @@ -296,37 +320,37 @@ void StreamProcessor::process(Slice& input, Slice& out) // Note 7 data words per link because we have the "link number" word + 6 words from calo L2 wr_ptr+= 4*((8*7) + 3)*bx_vect.size(); - }else{ + } else { LOG(ERROR) << "UNKNOWN PROCESSOR_TYPE, EXITING"; throw std::invalid_argument("ERROR: PROCESSOR_TYPE NOT RECOGNISED"); } rd_ptr+= 32 + bx_vect.size()*sizeof(blockMuon) + constants::orbit_trailer_size; // 32 for orbit header, + nBXs + orbit trailer counts += orbitCount; - if(firstOrbit){ + if (firstOrbit){ out.set_firstOrbitN(meta.orbit); firstOrbit = false; }; bx_vect.clear(); - if(rd_ptr < input.end()){ + if (rd_ptr < input.end()){ uint32_t *dma_trailer_word = (uint32_t*)(rd_ptr); - if( *dma_trailer_word == constants::deadbeef){ + if ( *dma_trailer_word == constants::deadbeef){ endofpacket = true; out.set_end(wr_ptr); out.set_counts(counts); return; } - if(orbit_per_packet_count > nOrbitsPerDMAPacket){ - if(control.verbosity){ + if (orbit_per_packet_count > nOrbitsPerDMAPacket){ + if (control.verbosity){ LOG(WARNING) << "expected DMA trailer word deadbeef, found " << std::hex << *dma_trailer_word << ". Orbits per packet count " << orbit_per_packet_count << ", > expected, (" << nOrbitsPerDMAPacket <<") skipping packet."; } - control.excessOrbitsPerPacketCount++; - if(control.excessOrbitsPerPacketCount%10000 == 0){ - LOG(WARNING) << "count of packets with excess # orbits " << control.excessOrbitsPerPacketCount; + stats.excess_orbits_per_packet_count++; + if (stats.excess_orbits_per_packet_count%10000 == 0){ + LOG(WARNING) << "count of packets with excess # orbits " << stats.excess_orbits_per_packet_count; } return; } diff --git a/src/processor.h b/src/processor.h index 5b9bf0623cee28dd60ee402855d6ecb209e1b218..8fef3c73dc7b7b99abcb212eb407308a1d942ffe 100644 --- a/src/processor.h +++ b/src/processor.h @@ -14,7 +14,6 @@ class Slice; class StreamProcessor: public tbb::filter { - public: static BrilHistoQueue<std::array<uint32_t, constants::NBXPerOrbit + constants::NFramesInHistoHeader>> BrilQueue; @@ -44,6 +43,23 @@ private: uint32_t nOrbitsPerDMAPacket; uint32_t prescaleFactor; ctrl& control; + + public: + static class Statistics { + public: + Statistics() + : orbit_trailer_error_count(0), + packet_count(0), + excess_orbits_per_packet_count(0), + packet_skipped_inconsistent_size(0), + n_consistent_sized_packets(0) {} + + std::atomic<uint32_t> orbit_trailer_error_count; + std::atomic<uint64_t> packet_count; + std::atomic<uint64_t> excess_orbits_per_packet_count; + std::atomic<uint64_t> packet_skipped_inconsistent_size; + std::atomic<uint64_t> n_consistent_sized_packets; + } stats; }; #endif diff --git a/src/scdaq.cc b/src/scdaq.cc index 59d6a95d4c164c0603656e3ed088adc112effcbd..6bba17daf37a86ea5a7c782231c78e98164d6169 100644 --- a/src/scdaq.cc +++ b/src/scdaq.cc @@ -156,15 +156,12 @@ if(argc < 2){ control.running = false; control.run_number = 0; - control.orbit_trailer_error_count = 0; - control.packet_count = 0; control.max_file_size = conf.getOutputMaxFileSize();//in Bytes control.packets_per_report = conf.getPacketsPerReport(); control.output_force_write = conf.getOutputForceWrite(); - control.n_orbits_per_dma_packet = conf.getNOrbitsPerDMAPacket(); control.verbosity = conf.getVerbosity(); - control.excessOrbitsPerPacketCount = 0; - + control.n_orbits_per_dma_packet = conf.getNOrbitsPerDMAPacket(); + // Firmware needs at least 1MB buffer for DMA if (conf.getDmaPacketBufferSize() < 1024*1024) { LOG(ERROR) << "dma_packet_buffer_size must be at least 1048576 bytes (1MB), but " << conf.getDmaPacketBufferSize() << " bytes was given. Check the configuration file."; diff --git a/test/config/scdaq-calo.conf b/test/config/scdaq-calo.conf index e31dfa2072bc7bf862f70052b8475676fd22ff31..534020238e1716bead82ce9eb0151b6b7f42e318 100644 --- a/test/config/scdaq-calo.conf +++ b/test/config/scdaq-calo.conf @@ -10,7 +10,7 @@ # "filedma" for reading from file and simulating DMA # "micronDMA" for PICO driver # -input:fit/config/scdaq-calo.confedma +input:filedma # Settings for Micron board only loadBitFile:yes diff --git a/test/config/scdaq-gmt.conf b/test/config/scdaq-gmt.conf index 8e0b525fa66d2621680352a177916095cc53e807..e520b3ee25b36cea1526f1d7d8fdc3f62159e0b1 100644 --- a/test/config/scdaq-gmt.conf +++ b/test/config/scdaq-gmt.conf @@ -104,7 +104,7 @@ quality_cut:12 threads:8 # verbosity level, currently supports 0 and 1 -verbosity:1 +verbosity:0 # N orbits to store to each file # Configured to store fixed number of orbits per file when nOrbitsPerFile > 1