Skip to content
Snippets Groups Projects
Commit a79885a6 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 a27c3a90
No related branches found
No related tags found
No related merge requests found
......@@ -31,19 +31,6 @@ BrilHistoQueue<std::array<uint32_t, constants::NBXPerOrbit +
constants::NFramesInHistoHeader>>
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() {}
// checks that the packet size is an integer multiple of the BX block size,
......@@ -92,31 +79,16 @@ bool StreamProcessor::CheckFrameMultBlock(size_t inputSize) {
return true;
}
// Looks for orbit trailer then counts the non-empty bunch crossings and fills a
// 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) {
bool StreamProcessor::GetTrailer(Slice &input, char *&rd_ptr) {
rd_ptr += 32; // +32 to account for orbit header
std::vector<unsigned int> bx_vect;
trailerError = false;
while (rd_ptr != input.end()) {
blockMuon *bl = reinterpret_cast<blockMuon *>(rd_ptr);
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
}
return bx_vect;
orbit_trailer *ot = reinterpret_cast<orbit_trailer *>(rd_ptr);
if (ot->beefdead[0] == constants::beefdead) { // found orbit trailer
return true;
}
rd_ptr += sizeof(blockMuon);
}
trailerError = true;
return bx_vect;
return false;
}
inline std::pair<uint32_t, bool> StreamProcessor::ProcessOrbitHeader(
......@@ -137,31 +109,58 @@ inline std::pair<uint32_t, bool> StreamProcessor::ProcessOrbitHeader(
// 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
StreamProcessor::fillOrbitMetadata StreamProcessor::FillOrbitCalo(
const std::vector<unsigned int> &bx_vect, char *rd_ptr, char *wr_ptr) {
orbit_trailer *trailer, char *rd_ptr, char *wr_ptr) {
std::pair<uint32_t, bool> orbit_header = std::pair<uint32_t, bool>{
ProcessOrbitHeader(rd_ptr)}; //.second is the warning test enable bit
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 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()
uint32_t filled_bxs = 0;
// 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;
blockCalo *bl = reinterpret_cast<blockCalo *>(rd_ptr);
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
uint32_t header =
uint32_t{orbit_header.second}; // header can be added to later
memcpy(wr_ptr, (char *)&header, 4);
wr_ptr += 4;
memcpy(wr_ptr, (char *)&bx, 4);
wr_ptr += 4;
memcpy(wr_ptr, (char *)&orbit_, 4);
memcpy(wr_ptr, (char *)&orbit, 4);
wr_ptr += 4;
for (uint32_t i = 0; i < 8; i++) {
memcpy(wr_ptr, (char *)&i, 4);
......@@ -181,13 +180,9 @@ StreamProcessor::fillOrbitMetadata StreamProcessor::FillOrbitCalo(
}
counts += 1;
rd_ptr += sizeof(blockCalo);
relbx++;
}
StreamProcessor::fillOrbitMetadata meta = {
counts,
orbit,
};
StreamProcessor::fillOrbitMetadata meta = {counts, orbit, filled_bxs};
return meta;
}
......@@ -250,15 +245,47 @@ 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
// corresponding to the non-empty bunchcrossings, as marked in bx_vect
StreamProcessor::fillOrbitMetadata StreamProcessor::FillOrbitMuon(
const std::vector<unsigned int> &bx_vect, char *rd_ptr, char *wr_ptr) {
orbit_trailer *trailer, char *rd_ptr, char *wr_ptr) {
std::pair<uint32_t, bool> orbit_header = std::pair<uint32_t, bool>{
ProcessOrbitHeader(rd_ptr)}; //.second is the warning test enable bit
rd_ptr += 32; // +32 to account for orbit header
uint32_t orbit = uint32_t{orbit_header.first};
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};
while (relbx < bx_vect.size()) { // total number of non-empty BXs in orbit is
// given by bx_vect.size()
uint32_t filled_bxs = 0;
// 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);
if (bl->orbit[0] == constants::beefdead) {
break;
......@@ -267,19 +294,14 @@ StreamProcessor::fillOrbitMetadata StreamProcessor::FillOrbitMuon(
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++) {
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) && control.verbosity) {
LOG(WARNING) << "BX mismatch, uGMT data word BX = " << std::hex << bxA
<< ", BX extracted from trailer = " << bx << ", orbitN is "
<< std::dec << orbit;
}
uint32_t orbitA = bl->orbit[i];
uint32_t pt = uint32_t{(bl->mu1f[i] >> shifts::pt) & masks::pt};
......@@ -342,15 +364,9 @@ StreamProcessor::fillOrbitMetadata StreamProcessor::FillOrbitMuon(
wr_ptr += 4; // set bit 0 to 1 for second muon
}
}
rd_ptr += sizeof(blockMuon);
relbx++;
}
StreamProcessor::fillOrbitMetadata meta = {
counts,
orbit,
};
StreamProcessor::fillOrbitMetadata meta = {counts, orbit, filled_bxs};
return meta;
}
......@@ -372,10 +388,7 @@ void StreamProcessor::process(Slice &input, Slice &out) {
bool endofpacket = false;
uint32_t orbit_per_packet_count = 0;
bool firstOrbit = true;
StreamProcessor::fillOrbitMetadata meta{
0,
0,
};
StreamProcessor::fillOrbitMetadata meta{0, 0, 0};
if (processorType == ProcessorType::PASS_THROUGH) {
memcpy(wr_ptr, rd_ptr, input.size());
out.set_end(out.begin() + input.size());
......@@ -394,9 +407,9 @@ void StreamProcessor::process(Slice &input, Slice &out) {
}
while (endofpacket == false) {
uint32_t orbitCount = 0;
bool trailerError = false;
std::vector<unsigned int> bx_vect = CountBX(input, rd_ptr, trailerError);
if (trailerError == true) {
char *trailer_ptr = rd_ptr;
bool trailerFound = GetTrailer(input, trailer_ptr);
if (!trailerFound) {
stats.orbit_trailer_error_count++;
LOG(WARNING)
<< "Orbit trailer error: orbit trailer not found before end of data "
......@@ -404,36 +417,34 @@ void StreamProcessor::process(Slice &input, Slice &out) {
<< stats.orbit_trailer_error_count;
return;
}
std::sort(bx_vect.begin(), bx_vect.end());
orbit_trailer *trailer = reinterpret_cast<orbit_trailer *>(trailer_ptr);
if (processorType == ProcessorType::GMT) {
meta = FillOrbitMuon(bx_vect, rd_ptr, wr_ptr);
meta = FillOrbitMuon(trailer, rd_ptr, wr_ptr);
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
wr_ptr += meta.counts * 12 +
12 * meta.filled_bxs; // 12 bytes for each muon/count then 12
// bytes for each bx header
} else if (processorType == ProcessorType::CALO) {
meta = FillOrbitCalo(bx_vect, rd_ptr, wr_ptr);
meta = FillOrbitCalo(trailer, rd_ptr, wr_ptr);
orbitCount = meta.counts;
++orbit_per_packet_count;
// size of calo packet is 4bytes*(8links*7dataWords + 3headerWords)=236
// bytes 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();
wr_ptr += 4 * ((8 * 7) + 3) * meta.filled_bxs;
} else {
LOG(ERROR) << "UNKNOWN PROCESSOR_TYPE, EXITING";
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 +
// orbit trailer
counts += orbitCount;
if (firstOrbit) {
out.set_firstOrbitN(meta.orbit);
firstOrbit = false;
};
bx_vect.clear();
}
if (rd_ptr < input.end()) {
uint32_t *dma_trailer_word = (uint32_t *)(rd_ptr);
......
......@@ -32,16 +32,16 @@ class StreamProcessor : public tbb::filter {
struct fillOrbitMetadata {
uint32_t counts;
uint32_t orbit;
uint32_t filled_bxs;
};
void process(Slice &input, Slice &out);
bool CheckFrameMultBlock(size_t inputSize);
std::vector<unsigned int> CountBX(Slice &input, char *rd_ptr,
bool &trailerError);
bool GetTrailer(Slice &input, char *&rd_ptr);
inline std::pair<uint32_t, bool> ProcessOrbitHeader(char *rd_ptr);
fillOrbitMetadata FillOrbitMuon(std::vector<unsigned int> &bx_vect,
char *rd_ptr, char *wr_ptr);
fillOrbitMetadata FillOrbitCalo(std::vector<unsigned int> &bx_vect,
char *rd_ptr, char *wr_ptr);
fillOrbitMetadata FillOrbitMuon(orbit_trailer *trailer, char *rd_ptr,
char *wr_ptr);
fillOrbitMetadata FillOrbitCalo(orbit_trailer *trailer, char *rd_ptr,
char *wr_ptr);
uint32_t FillBril(char *rd_ptr, char *wr_ptr, char *end_ptr);
size_t max_size;
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