Skip to content
Snippets Groups Projects
Commit c1b9f69e authored by Dinyar Rabady's avatar Dinyar Rabady Committed by Dinyar Rabady
Browse files

Perform BX map decoding on the fly

Belongs to #35.
parent 301049c0
No related branches found
No related tags found
No related merge requests found
...@@ -24,19 +24,6 @@ BrilHistoQueue<std::array<uint32_t, constants::NBXPerOrbit + ...@@ -24,19 +24,6 @@ BrilHistoQueue<std::array<uint32_t, constants::NBXPerOrbit +
constants::NFramesInHistoHeader>> constants::NFramesInHistoHeader>>
StreamProcessor::BrilQueue; StreamProcessor::BrilQueue;
// Loops over each word in the orbit trailer BX map and fills a vector with the
// non-empty BX values
void bit_check(std::vector<unsigned int> *bx_vect, uint32_t word,
uint32_t offset) {
for (uint32_t i = 0; i < 32; i++) {
if (word & 1) {
bx_vect->push_back(i + offset);
}
word >>= 1;
}
return;
}
StreamProcessor::~StreamProcessor() {} StreamProcessor::~StreamProcessor() {}
// checks that the packet size is an integer multiple of the BX block size, // checks that the packet size is an integer multiple of the BX block size,
...@@ -88,32 +75,16 @@ bool StreamProcessor::CheckFrameMultBlock(size_t inputSize) { ...@@ -88,32 +75,16 @@ bool StreamProcessor::CheckFrameMultBlock(size_t inputSize) {
return true; return true;
} }
// Looks for orbit trailer then counts the non-empty bunch crossings and fills a bool StreamProcessor::GetTrailer(Slice &input, char *&rd_ptr) {
// vector with their values The bool (.second) is used to determine valididy of
// the BX count
std::vector<unsigned int> StreamProcessor::CountBX(Slice &input, char *rd_ptr,
bool &trailerError) {
rd_ptr += 32; // +32 to account for orbit header 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); orbit_trailer *ot = reinterpret_cast<orbit_trailer *>(rd_ptr);
if (bl->orbit[0] == constants::beefdead) { // found orbit trailer if (ot->beefdead[0] == constants::beefdead) { // found orbit trailer
orbit_trailer *ot = (orbit_trailer *)(rd_ptr); return true;
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
}
return bx_vect;
} }
rd_ptr += sizeof(blockMuon); rd_ptr += sizeof(blockMuon);
} }
trailerError = true; return false;
return bx_vect;
} }
inline std::pair<uint32_t, bool> inline std::pair<uint32_t, bool>
...@@ -134,32 +105,59 @@ StreamProcessor::ProcessOrbitHeader(char *rd_ptr) { ...@@ -134,32 +105,59 @@ StreamProcessor::ProcessOrbitHeader(char *rd_ptr) {
// Goes through orbit worth of data and fills the output memory with the calo // Goes through orbit worth of data and fills the output memory with the calo
// data corresponding to the non-empty bunchcrossings, as marked in bx_vect // data corresponding to the non-empty bunchcrossings, as marked in bx_vect
StreamProcessor::fillOrbitMetadata StreamProcessor::fillOrbitMetadata
StreamProcessor::FillOrbitCalo(const std::vector<unsigned int> &bx_vect, StreamProcessor::FillOrbitCalo(orbit_trailer *trailer, char *rd_ptr,
char *rd_ptr, char *wr_ptr) { char *wr_ptr) {
std::pair<uint32_t, bool> orbit_header = std::pair<uint32_t, bool>{ std::pair<uint32_t, bool> orbit_header = std::pair<uint32_t, bool>{
ProcessOrbitHeader(rd_ptr)}; //.second is the warning test enable bit ProcessOrbitHeader(rd_ptr)}; //.second is the warning test enable bit
rd_ptr += 32; // +32 to account for orbit header rd_ptr += 32; // +32 to account for orbit header
uint32_t relbx = uint32_t{0}; uint32_t orbit =
uint32_t{orbit_header.first} -
1; // Starting with orbit number one lower than what is in the header
// because the "link orbit" contains a few BXs of the previous orbit
uint32_t counts = uint32_t{0}; uint32_t counts = uint32_t{0};
uint32_t orbit = uint32_t{orbit_header.first}; uint32_t filled_bxs = 0;
while (relbx < bx_vect.size()) { // total number of non-empty BXs in orbit is // We loop over the BX map from the orbit trailer and then match the filled
// given by bx_vect.size() // BXs to the data we got. The logic below is annoyingly convoluted: The first
// BX we get in the data stream is from BX 3555, however the BX map starts at
// BX 1, we therefore need to start reading the BX map from the 3555th bit.
// 3555//32 = 111, so we start at the 111th word; 3555 mod 32 = 3, however we
// start counting at BX1, so the start bit is 2.
uint32_t bx = 3554; // We start at 3554 here, because we increment by 1
// immediately after starting the loops.
size_t word = 111;
size_t bit = 1; // Will be incremented immediately after starting the loop
for (size_t pseudo_bx = 0; pseudo_bx < 3564;
++pseudo_bx) { // Looping over at most an entire orbit here.
if (word == 14 * 8 - 1 &&
bit == 11) { // Bit 11 in word 111 is the last valid BX (3564), so we
// roll over afterwards. (== 11 because that's the one we
// worked on in the previous loop iteration)
word = 0;
bit = 0;
bx = 0; // Will be immediately incremented to 1.
++orbit;
} else if (bit < 31) {
++bit;
} else {
bit = 0;
++word;
}
++bx;
if ((trailer->bx_map[word] & (1 << bit)) == 0) {
continue; // If the bit is zero that BX was empty and we continue.
}
++filled_bxs;
blockCalo *bl = reinterpret_cast<blockCalo *>(rd_ptr); blockCalo *bl = reinterpret_cast<blockCalo *>(rd_ptr);
if (bl->calo0[0] == constants::beefdead) { if (bl->calo0[0] == constants::beefdead) {
break; break;
} // orbit trailer has been reached, end of orbit data } // 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
uint32_t header = uint32_t header =
uint32_t{orbit_header.second}; // header can be added to later uint32_t{orbit_header.second}; // header can be added to later
memcpy(wr_ptr, (char *)&header, 4); memcpy(wr_ptr, (char *)&header, 4);
wr_ptr += 4; wr_ptr += 4;
memcpy(wr_ptr, (char *)&bx, 4); memcpy(wr_ptr, (char *)&bx, 4);
wr_ptr += 4; wr_ptr += 4;
memcpy(wr_ptr, (char *)&orbit_, 4); memcpy(wr_ptr, (char *)&orbit, 4);
wr_ptr += 4; wr_ptr += 4;
for (uint32_t i = 0; i < 8; i++) { for (uint32_t i = 0; i < 8; i++) {
memcpy(wr_ptr, (char *)&i, 4); memcpy(wr_ptr, (char *)&i, 4);
...@@ -179,13 +177,9 @@ StreamProcessor::FillOrbitCalo(const std::vector<unsigned int> &bx_vect, ...@@ -179,13 +177,9 @@ StreamProcessor::FillOrbitCalo(const std::vector<unsigned int> &bx_vect,
} }
counts += 1; counts += 1;
rd_ptr += sizeof(blockCalo); rd_ptr += sizeof(blockCalo);
relbx++;
} }
StreamProcessor::fillOrbitMetadata meta = { StreamProcessor::fillOrbitMetadata meta = {counts, orbit, filled_bxs};
counts,
orbit,
};
return meta; return meta;
} }
...@@ -249,16 +243,48 @@ uint32_t StreamProcessor::FillBril(char *rd_ptr, char *wr_ptr, char *end_ptr) { ...@@ -249,16 +243,48 @@ uint32_t StreamProcessor::FillBril(char *rd_ptr, char *wr_ptr, char *end_ptr) {
// Goes through orbit worth of data and fills the output memory with the muons // Goes through orbit worth of data and fills the output memory with the muons
// corresponding to the non-empty bunchcrossings, as marked in bx_vect // corresponding to the non-empty bunchcrossings, as marked in bx_vect
StreamProcessor::fillOrbitMetadata StreamProcessor::fillOrbitMetadata
StreamProcessor::FillOrbitMuon(const std::vector<unsigned int> &bx_vect, StreamProcessor::FillOrbitMuon(orbit_trailer *trailer, char *rd_ptr,
char *rd_ptr, char *wr_ptr) { char *wr_ptr) {
std::pair<uint32_t, bool> orbit_header = std::pair<uint32_t, bool>{ std::pair<uint32_t, bool> orbit_header = std::pair<uint32_t, bool>{
ProcessOrbitHeader(rd_ptr)}; //.second is the warning test enable bit ProcessOrbitHeader(rd_ptr)}; //.second is the warning test enable bit
rd_ptr += 32; // +32 to account for orbit header rd_ptr += 32; // +32 to account for orbit header
uint32_t orbit = uint32_t{orbit_header.first}; uint32_t orbit =
uint32_t relbx = uint32_t{0}; uint32_t{orbit_header.first} -
1; // Starting with orbit number one lower than what is in the header
// because the "link orbit" contains a few BXs of the previous orbit
uint32_t counts = uint32_t{0}; uint32_t counts = uint32_t{0};
while (relbx < bx_vect.size()) { // total number of non-empty BXs in orbit is uint32_t filled_bxs = 0;
// given by bx_vect.size() // We loop over the BX map from the orbit trailer and then match the filled
// BXs to the data we got. The logic below is annoyingly convoluted: The first
// BX we get in the data stream is from BX 3555, however the BX map starts at
// BX 1, we therefore need to start reading the BX map from the 3555th bit.
// 3555//32 = 111, so we start at the 111th word; 3555 mod 32 = 3, however we
// start counting at BX1, so the start bit is 2.
uint32_t bx = 3554; // We start at 3554 here, because we increment by 1
// immediately after starting the loops.
size_t word = 111;
size_t bit = 1; // Will be incremented immediately after starting the loop
for (size_t pseudo_bx = 0; pseudo_bx < 3564;
++pseudo_bx) { // Looping over at most an entire orbit here.
if (word == 14 * 8 - 1 &&
bit == 11) { // Bit 11 in word 111 is the last valid BX (3564), so we
// roll over afterwards. (== 11 because that's the one we
// worked on in the previous loop iteration)
word = 0;
bit = 0;
bx = 0; // Will be immediately incremented to 1.
++orbit;
} else if (bit < 31) {
++bit;
} else {
bit = 0;
++word;
}
++bx;
if ((trailer->bx_map[word] & (1 << bit)) == 0) {
continue; // If the bit is zero that BX was empty and we continue.
}
++filled_bxs;
blockMuon *bl = reinterpret_cast<blockMuon *>(rd_ptr); blockMuon *bl = reinterpret_cast<blockMuon *>(rd_ptr);
if (bl->orbit[0] == constants::beefdead) { if (bl->orbit[0] == constants::beefdead) {
break; break;
...@@ -267,19 +293,14 @@ StreamProcessor::FillOrbitMuon(const std::vector<unsigned int> &bx_vect, ...@@ -267,19 +293,14 @@ StreamProcessor::FillOrbitMuon(const std::vector<unsigned int> &bx_vect,
int mBcount = 0; int mBcount = 0;
bool AblocksOn[8]; bool AblocksOn[8];
bool BblocksOn[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; uint32_t bxA = (bl->bx[i] >> shifts::bx) & masks::bx;
if ((bxA != bx) && (i == 0) && (bx < 3555) && if ((bxA != bx) && (i == 0) && control.verbosity) {
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 LOG(WARNING) << "BX mismatch, uGMT data word BX = " << std::hex << bxA
<< ", BX extracted from trailer = " << bx << ", orbitN is " << ", BX extracted from trailer = " << bx << ", orbitN is "
<< std::dec << orbit; << std::dec << orbit;
} }
uint32_t orbitA = bl->orbit[i];
uint32_t pt = uint32_t{(bl->mu1f[i] >> shifts::pt) & masks::pt}; uint32_t pt = uint32_t{(bl->mu1f[i] >> shifts::pt) & masks::pt};
...@@ -342,15 +363,9 @@ StreamProcessor::FillOrbitMuon(const std::vector<unsigned int> &bx_vect, ...@@ -342,15 +363,9 @@ StreamProcessor::FillOrbitMuon(const std::vector<unsigned int> &bx_vect,
wr_ptr += 4; // set bit 0 to 1 for second muon wr_ptr += 4; // set bit 0 to 1 for second muon
} }
} }
rd_ptr += sizeof(blockMuon); rd_ptr += sizeof(blockMuon);
relbx++;
} }
StreamProcessor::fillOrbitMetadata meta = { StreamProcessor::fillOrbitMetadata meta = {counts, orbit, filled_bxs};
counts,
orbit,
};
return meta; return meta;
} }
...@@ -372,10 +387,7 @@ void StreamProcessor::process(Slice &input, Slice &out) { ...@@ -372,10 +387,7 @@ void StreamProcessor::process(Slice &input, Slice &out) {
bool endofpacket = false; bool endofpacket = false;
uint32_t orbit_per_packet_count = 0; uint32_t orbit_per_packet_count = 0;
bool firstOrbit = true; bool firstOrbit = true;
StreamProcessor::fillOrbitMetadata meta{ StreamProcessor::fillOrbitMetadata meta{0, 0, 0};
0,
0,
};
if (processorType == ProcessorType::PASS_THROUGH) { if (processorType == ProcessorType::PASS_THROUGH) {
memcpy(wr_ptr, rd_ptr, input.size()); memcpy(wr_ptr, rd_ptr, input.size());
out.set_end(out.begin() + input.size()); out.set_end(out.begin() + input.size());
...@@ -394,9 +406,9 @@ void StreamProcessor::process(Slice &input, Slice &out) { ...@@ -394,9 +406,9 @@ void StreamProcessor::process(Slice &input, Slice &out) {
} }
while (endofpacket == false) { while (endofpacket == false) {
uint32_t orbitCount = 0; uint32_t orbitCount = 0;
bool trailerError = false; char *trailer_ptr = rd_ptr;
std::vector<unsigned int> bx_vect = CountBX(input, rd_ptr, trailerError); bool trailerFound = GetTrailer(input, trailer_ptr);
if (trailerError == true) { if (!trailerFound) {
stats.orbit_trailer_error_count++; stats.orbit_trailer_error_count++;
LOG(WARNING) LOG(WARNING)
<< "Orbit trailer error: orbit trailer not found before end of data " << "Orbit trailer error: orbit trailer not found before end of data "
...@@ -404,36 +416,34 @@ void StreamProcessor::process(Slice &input, Slice &out) { ...@@ -404,36 +416,34 @@ void StreamProcessor::process(Slice &input, Slice &out) {
<< stats.orbit_trailer_error_count; << stats.orbit_trailer_error_count;
return; return;
} }
std::sort(bx_vect.begin(), bx_vect.end()); orbit_trailer *trailer = reinterpret_cast<orbit_trailer *>(trailer_ptr);
if (processorType == ProcessorType::GMT) { if (processorType == ProcessorType::GMT) {
meta = FillOrbitMuon(bx_vect, rd_ptr, wr_ptr); meta = FillOrbitMuon(trailer, rd_ptr, wr_ptr);
orbitCount = meta.counts; orbitCount = meta.counts;
++orbit_per_packet_count; ++orbit_per_packet_count;
wr_ptr += orbitCount * 12 + wr_ptr += meta.counts * 12 +
12 * bx_vect.size(); // 12 bytes for each muon/count then 12 12 * meta.filled_bxs; // 12 bytes for each muon/count then 12
// bytes for each bx header // bytes for each bx header
} else if (processorType == ProcessorType::CALO) { } else if (processorType == ProcessorType::CALO) {
meta = FillOrbitCalo(bx_vect, rd_ptr, wr_ptr); meta = FillOrbitCalo(trailer, rd_ptr, wr_ptr);
orbitCount = meta.counts; orbitCount = meta.counts;
++orbit_per_packet_count; ++orbit_per_packet_count;
// size of calo packet is 4bytes*(8links*7dataWords + 3headerWords)=236 // size of calo packet is 4bytes*(8links*7dataWords + 3headerWords)=236
// bytes Note 7 data words per link because we have the "link number" word // bytes Note 7 data words per link because we have the "link number" word
// + 6 words from calo L2 // + 6 words from calo L2
wr_ptr += 4 * ((8 * 7) + 3) * bx_vect.size(); wr_ptr += 4 * ((8 * 7) + 3) * meta.filled_bxs;
} else { } else {
LOG(ERROR) << "UNKNOWN PROCESSOR_TYPE, EXITING"; LOG(ERROR) << "UNKNOWN PROCESSOR_TYPE, EXITING";
throw std::invalid_argument("ERROR: PROCESSOR_TYPE NOT RECOGNISED"); throw std::invalid_argument("ERROR: PROCESSOR_TYPE NOT RECOGNISED");
} }
rd_ptr += 32 + bx_vect.size() * sizeof(blockMuon) + rd_ptr += 32 + meta.filled_bxs * sizeof(blockMuon) +
constants::orbit_trailer_size; // 32 for orbit header, + nBXs + constants::orbit_trailer_size; // 32 for orbit header, + nBXs +
// orbit trailer // orbit trailer
counts += orbitCount; counts += orbitCount;
if (firstOrbit) { if (firstOrbit) {
out.set_firstOrbitN(meta.orbit); out.set_firstOrbitN(meta.orbit);
firstOrbit = false; firstOrbit = false;
}; }
bx_vect.clear();
if (rd_ptr < input.end()) { if (rd_ptr < input.end()) {
......
...@@ -31,16 +31,16 @@ private: ...@@ -31,16 +31,16 @@ private:
struct fillOrbitMetadata { struct fillOrbitMetadata {
uint32_t counts; uint32_t counts;
uint32_t orbit; uint32_t orbit;
uint32_t filled_bxs;
}; };
void process(Slice &input, Slice &out); void process(Slice &input, Slice &out);
bool CheckFrameMultBlock(size_t inputSize); bool CheckFrameMultBlock(size_t inputSize);
std::vector<unsigned int> CountBX(Slice &input, char *rd_ptr, bool GetTrailer(Slice &input, char *&rd_ptr);
bool &trailerError);
inline std::pair<uint32_t, bool> ProcessOrbitHeader(char *rd_ptr); inline std::pair<uint32_t, bool> ProcessOrbitHeader(char *rd_ptr);
fillOrbitMetadata FillOrbitMuon(std::vector<unsigned int> &bx_vect, fillOrbitMetadata FillOrbitMuon(orbit_trailer *trailer, char *rd_ptr,
char *rd_ptr, char *wr_ptr); char *wr_ptr);
fillOrbitMetadata FillOrbitCalo(std::vector<unsigned int> &bx_vect, fillOrbitMetadata FillOrbitCalo(orbit_trailer *trailer, char *rd_ptr,
char *rd_ptr, char *wr_ptr); char *wr_ptr);
uint32_t FillBril(char *rd_ptr, char *wr_ptr, char *end_ptr); uint32_t FillBril(char *rd_ptr, char *wr_ptr, char *end_ptr);
size_t max_size; size_t max_size;
uint64_t nbPackets; uint64_t nbPackets;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment