From a77694d09bd10a6d0d843780ba664c22e6c5aab6 Mon Sep 17 00:00:00 2001
From: Thomas Owen James <tjames@cmd-scouting-ctrlhub.dyndns.cern.ch>
Date: Mon, 23 May 2022 18:19:18 +0200
Subject: [PATCH] new processor for BX trailer & other new headers/trailers

---
 src/format.h     |  15 +++-
 src/processor.cc | 184 ++++++++++++++++++++++++++++-------------------
 src/processor.h  |   7 +-
 3 files changed, 130 insertions(+), 76 deletions(-)

diff --git a/src/format.h b/src/format.h
index 854b9173..87e06064 100644
--- a/src/format.h
+++ b/src/format.h
@@ -13,6 +13,18 @@ struct block1{
   uint32_t mu2s[8];
 };
 
+struct bx_map_frame{
+uint32_t bx_map_l[8];
+};
+
+struct orbit_trailer{
+uint32_t beefdead[8];
+uint32_t bx_map[14*8];
+uint32_t trailer1[8];
+uint32_t trailer2[8];
+};
+
+
 struct muon{
   uint32_t f; //first word
   uint32_t s; //second word
@@ -126,8 +138,9 @@ struct gmt_scales{
 
 struct constants{
   static constexpr uint32_t deadbeef           = 0xdeadbeef;
+  static constexpr uint32_t beefdead           = 0xbeefdead;
   static constexpr uint32_t intermediate_marker= 0x0000000f;
-  static constexpr uint32_t orbit_trailer_size = 32;
+  static constexpr uint32_t orbit_trailer_size = 544;
   static constexpr uint32_t intermediate       = 0x00000001;
   static constexpr uint32_t final              = 0x00000001;
 };
diff --git a/src/processor.cc b/src/processor.cc
index 26b8b88b..9ebb678b 100644
--- a/src/processor.cc
+++ b/src/processor.cc
@@ -3,6 +3,9 @@
 #include "slice.h"
 #include "log.h"
 #include <iomanip>
+#include <cmath>
+#include <vector>
+#include <algorithm>
 
 StreamProcessor::StreamProcessor(size_t max_size_, bool doZS_, ProcessorType processorType_) :
 	tbb::filter(parallel),
@@ -16,92 +19,99 @@ StreamProcessor::StreamProcessor(size_t max_size_, bool doZS_, ProcessorType pro
 }  
 
 
+std::vector<uint32_t> bit_check(uint32_t word, uint32_t offset)
+{
+	std::vector<uint32_t> vect;
+	for (uint32_t i = 0; i<32; i++)
+	{
+		if (word & 1){
+			vect.push_back(i + offset);
+		}
+		word >>= 1;
+	}
+
+	return vect;
+}
+
 StreamProcessor::~StreamProcessor(){
 	//  fprintf(stderr,"Wrote %d muons \n",totcount);
 	myfile.close();
 }
 
-Slice* StreamProcessor::process(Slice& input, Slice& out)
-{
-	nbPackets++;
-	char* p = input.begin();
-	char* q = out.begin();
-	uint32_t counts = 0;
-	
-	if (processorType == ProcessorType::PASS_THROUGH) {
-		memcpy(q,p,input.size());
-		out.set_end(out.begin() + input.size());
-		out.set_counts(1);
-		return &out;
-	}
-	
+bool StreamProcessor::CheckFrameMultBlock(uint32_t inputSize){
+
 	int bsize = sizeof(block1);
-	if((input.size()-constants::orbit_trailer_size)%bsize!=0){
+	if((inputSize-20*constants::orbit_trailer_size - 32*20 -32)%bsize!=0){
 		LOG(WARNING)
-			<< "Frame size not a multiple of block size. Will be skipped. Size="
-			<< input.size() << " - block size=" << bsize;
-		return &out;
+			<< "Frame size not a multiple of block size. Will be skipped. Frame size = "
+			<< inputSize << ", block size = " << bsize;
+		return false;
 	}
+	return true;
+}
 
+std::vector<unsigned int> StreamProcessor::CountBX(Slice& input){
+
+	char* p = input.begin() + 32; // +32 to account for orbit header
+	std::vector<unsigned int> bx_vect;
+	while( p != input.end()){
+		block1 *bl = (block1*)(p);
+		if(bl->orbit[0]==constants::beefdead){ // found orbit trailer
+			orbit_trailer *ot = (orbit_trailer*)(p);
+			for (unsigned int k = 0; k < (14*8); k++){ // 14*8 = 14 frames, 8 links of orbit trailer containing BX hitmap
+				//bxcount += __builtin_popcount(ot->bx_map[k]);
+				std::vector<unsigned int> bx_vect_t = bit_check(ot->bx_map[k], k*32);
+				bx_vect.insert(bx_vect.end(), bx_vect_t.begin(), bx_vect_t.end());
+			}
+			return bx_vect;
+		}
+
+		p+=sizeof(block1);
+	}
+
+}
 
-	while(p!=input.end()){
-		bool brill_word = false;
-		bool endoforbit = false;
-		block1 *bl = (block1*)p;
+uint32_t StreamProcessor::FillOrbit(Slice& input, Slice& out, std::vector<unsigned int>* bx_vect){
+	char* p = input.begin() + 32; // +32 to account for orbit header
+	char* q = out.begin(); // +32 to account for orbit header
+	uint32_t relbx = 0;
+	uint32_t counts = 0;
+	std::cout << "here1 "<< std::endl;
+	while(relbx < bx_vect->size()){
+		block1 *bl = (block1*)(p);
+		if(bl->orbit[0]==constants::beefdead){break;} 
 		int mAcount = 0;
 		int mBcount = 0;
 		uint32_t bxmatch=0;
 		uint32_t orbitmatch=0;
-		uint32_t brill_marker = 0xFF;
 		bool AblocksOn[8];
 		bool BblocksOn[8];
 		for(unsigned int i = 0; i < 8; i++){
-			if(bl->orbit[i]==constants::deadbeef){
-				p += constants::orbit_trailer_size;
-				endoforbit = true;
-				break;
-			}
-			bool brill_enabled = 0;
-
-			if(( brill_enabled) && ((bl->orbit[i] == 0xFF) ||( bl->bx[i] == 0xFF) ||( bl->mu1f[i] == 0xFF) || 
-					(bl->mu1s[i] == 0xFF) ||( bl->mu2f[i] == 0xFF) ||( bl->mu2s[i] == 0xFF))){
-				brill_word = true;
-			}
-
-			//	std::cout << bl->orbit[i] << std::endl;
-			/*			if (bl->orbit[i] > 258745337){
-						std::cout << bl->orbit[i] << std::endl;
-						brill_word = true;			
-						std::cout << "orbit " << bl->orbit[i] << std::endl;
-						std::cout << "bx " << bl->bx[i] << std::endl;
-						}
-						*/
-			uint32_t bx = (bl->bx[i] >> shifts::bx) & masks::bx;
+			uint32_t bxA = (bl->bx[i] >> shifts::bx) & masks::bx;
+			uint32_t bx = bx_vect->at(relbx);
+			//std::cout << "bxA = " << std::dec << bxA << ", bx = "<< bx << std::endl;
 			uint32_t interm = (bl->bx[i] >> shifts::interm) & masks::interm;
 			uint32_t orbit = bl->orbit[i];
 
-			bxmatch += (bx==((bl->bx[0] >> shifts::bx) & masks::bx))<<i;
+			bxmatch += (bx==bx_vect->at(relbx))<<i;
 			orbitmatch += (orbit==bl->orbit[0])<<i; 
 			uint32_t pt = (bl->mu1f[i] >> shifts::pt) & masks::pt;
 			uint32_t etae = (bl->mu1f[i] >> shifts::etaext) & masks::eta;
-			//			std::cout << bx << "," << orbit << "," << interm << "," << etae << std::endl;
 
-			AblocksOn[i]=((pt>0) || (doZS==0) || (brill_word));
-			if((pt>0) || (doZS==0) || (brill_word)){
+			AblocksOn[i]=((pt>0) || (doZS==0));
+			if((pt>0) || (doZS==0)){
 				mAcount++;
-				//std::cout << "mAcount +" << std::endl;
 			}
 			pt = (bl->mu2f[i] >> shifts::pt) & masks::pt;
-			BblocksOn[i]=((pt>0) || (doZS==0) ||( brill_word));
-			if((pt>0) || (doZS==0) || (brill_word)){
+			BblocksOn[i]=((pt>0) || (doZS==0));
+			if((pt>0) || (doZS==0)){
 				mBcount++;
-				//std::cout << "mBcount +" << std::endl;
 			}
+
 		}
-		if(endoforbit) continue;
 		uint32_t bxcount = std::max(mAcount,mBcount);
 		if(bxcount == 0) {
-			p+=bsize;
+			p+=sizeof(block1);
 			LOG(WARNING) << '#' << nbPackets << ": Detected a bx with zero muons, this should not happen. Packet is skipped."; 
 			continue;
 		}
@@ -111,19 +121,14 @@ Slice* StreamProcessor::process(Slice& input, Slice& out)
 		counts += mAcount;
 		counts += mBcount;
 		memcpy(q,(char*)&header,4); q+=4;
-		memcpy(q,(char*)&bl->bx[0],4); q+=4;
+		memcpy(q,(char*)&bx_vect->at(relbx),4); q+=4;
 		memcpy(q,(char*)&bl->orbit[0],4); q+=4;
 		for(unsigned int i = 0; i < 8; i++){
 			if(AblocksOn[i]){
 				memcpy(q,(char*)&bl->mu1f[i],4); q+=4;
 				memcpy(q,(char*)&bl->mu1s[i],4); q+=4;
-				//memcpy(q,(char*)&(bl->bx[i] &= ~0x1),4); q+=4; //set bit 0 to 0 for first muon
-		// next creating mu.extra which is a copy of bl->bx with a change to the first bit		
-				if(brill_word == true){
-					memcpy(q,&brill_marker,4); q+=4;
-				}	else {
-					memcpy(q,(char*)&(bl->bx[i] &= ~0x1),4); q+=4; //set bit 0 to 0 for first muon
-				}
+				// next creating mu.extra which is a copy of bl->bx with a change to the first bit		
+				memcpy(q,(char*)&(bx_vect->at(relbx) &= ~0x1),4); q+=4; //set bit 0 to 0 for first muon
 			}
 		}
 
@@ -131,27 +136,58 @@ Slice* StreamProcessor::process(Slice& input, Slice& out)
 			if(BblocksOn[i]){
 				memcpy(q,(char*)&bl->mu2f[i],4); q+=4;
 				memcpy(q,(char*)&bl->mu2s[i],4); q+=4;
-				//memcpy(q,(char*)&(bl->bx[i] |= 0x1),4); q+=4; //set bit 0 to 1 for second muon
-		// next creating mu.extra which is a copy of bl->bx with a change to the first bit		
-		if(brill_word == true){
-					memcpy(q,&brill_marker,4); q+=4; 
-				}	else{
-					memcpy(q,(char*)&(bl->bx[i] |= 0x1),4); q+=4; //set bit 0 to 1 for second muon
-				}							
+				// next creating mu.extra which is a copy of bl->bx with a change to the first bit		
+				memcpy(q,(char*)&(bx_vect->at(relbx) |= 0x1),4); q+=4; //set bit 0 to 1 for second muon
 			}
 		}
 
 		p+=sizeof(block1);
 
+		relbx++;
 	}
+	return counts;
+}
 
+Slice* StreamProcessor::process(Slice& input, Slice& out)
+{
+	nbPackets++;
+	char* p = input.begin(); 
+	char* q = out.begin();
+	uint32_t counts = 0;
+	bool endofpacket = false;
 
-	
-	out.set_end(q);
-	out.set_counts(counts);
-	return &out;  
-}
+	if (processorType == ProcessorType::PASS_THROUGH) {
+		memcpy(q,p,input.size());
+		out.set_end(out.begin() + input.size());
+		out.set_counts(1);
+		return &out;
+	}
+
+	if (!CheckFrameMultBlock(input.size())){ return &out; } 
+	while (endofpacket == false){
+
+		std::vector<unsigned int> bx_vect = CountBX(input);
+		std::sort(bx_vect.begin(), bx_vect.end());
+		uint32_t orbitCount = FillOrbit(input, out, &bx_vect);
+		p+= 32 + bx_vect.size()*sizeof(block1) + constants::orbit_trailer_size; // 32 for orbit header, + nBXs + orbit trailer
+		q+= orbitCount*12 + 12*bx_vect.size(); // 12 bytes for each muon/count then 12 bytes for each bx header
+		counts += orbitCount;
+		bx_vect.clear();
 
+
+		if(p < input.end()){
+
+			uint32_t *dma_trailer_word = (uint32_t*)(p);
+			if( *dma_trailer_word == constants::deadbeef){
+				endofpacket = true;
+				out.set_end(q);
+				std::cout << "counts " << counts << std::endl;
+				out.set_counts(counts);
+				return &out;
+			}
+		}
+	}
+}
 void* StreamProcessor::operator()( void* item ){
 	Slice& input = *static_cast<Slice*>(item);
 	Slice& out = *Slice::allocate( 2*max_size);
diff --git a/src/processor.h b/src/processor.h
index 736e9149..4d1d0349 100644
--- a/src/processor.h
+++ b/src/processor.h
@@ -5,6 +5,8 @@
     
 #include <iostream>
 #include <fstream>
+#include <vector>
+
 //reformatter
 
 class Slice;
@@ -20,7 +22,10 @@ public:
 
 private:
   Slice* process(Slice& input, Slice& out);
-  
+  bool CheckFrameMultBlock(uint32_t inputSize);  
+  std::vector<unsigned int> CountBX(Slice& input);
+  uint32_t FillOrbit(Slice& input, Slice& out, std::vector<unsigned int>* bx_vect);
+ 
   std::ofstream myfile;
 private:
   size_t max_size;
-- 
GitLab