Skip to content
Snippets Groups Projects

algo: Unpack RICH in parallel.

Merged Felix Weiglhofer requested to merge fweig/cbmroot:parallel-rich-unpack into master
All threads resolved!
3 files
+ 110
90
Compare changes
  • Side-by-side
  • Inline
Files
3
@@ -12,30 +12,27 @@ namespace cbm::algo::rich
{
// ---- Algorithm execution ---------------------------------------------
Unpack::resultType Unpack::operator()(const uint8_t* msContent, const fles::MicrosliceDescriptor& msDescr,
const uint64_t tTimeslice)
const uint64_t tTimeslice) const
{
// --- Output data
resultType result = {};
fMonitor = UnpackMonitorData();
fOutputVec.clear();
MSContext ctx;
// Clear CbmTime of MS. Used to get time offset of subtriggers to MS start
fCbmTimeMS = 0;
ctx.cbmTimeMS = 0;
ctx.digis.reserve(msDescr.size / sizeof(u32));
rich::MicrosliceReader reader;
reader.SetData(msContent, msDescr.size);
const auto mstime = msDescr.idx;
fMsRefTime = mstime - tTimeslice;
ctx.refTime = mstime - tTimeslice;
// There are a lot of MS with 8 bytes size
// Does one need these MS?
if (reader.GetSize() <= 8) return result;
if (reader.GetSize() <= 8) return {};
while (true) {
ProcessTrbPacket(reader);
ProcessHubBlock(reader);
ProcessTrbPacket(reader, ctx);
ProcessHubBlock(reader, ctx);
// -4*2 for 2 last words which contain microslice index
if (reader.GetOffset() >= reader.GetSize() - 8) break;
@@ -45,19 +42,17 @@ namespace cbm::algo::rich
uint32_t msIndexWord1 = reader.NextWord();
uint32_t msIndexWord2 = reader.NextWord();
result.first = fOutputVec;
result.second = fMonitor;
return result;
return std::make_pair(std::move(ctx.digis), std::move(ctx.monitor));
}
void Unpack::ProcessTrbPacket(rich::MicrosliceReader& reader)
void Unpack::ProcessTrbPacket(rich::MicrosliceReader& reader, MSContext& ctx) const
{
//process CBM time
const uint32_t word_MSB = reader.NextWord(); // CBM 63:32
const uint32_t word_LSB = reader.NextWord(); // CBM 31: 0
fCbmTimePacket = (uint64_t) word_MSB << 32 | word_LSB;
if (fCbmTimeMS == 0) fCbmTimeMS = fCbmTimePacket;
ctx.cbmTimePacket = (uint64_t) word_MSB << 32 | word_LSB;
if (ctx.cbmTimeMS == 0) ctx.cbmTimeMS = ctx.cbmTimePacket;
//discard unused words
for (auto l = 0; l < 10; ++l) {
@@ -72,9 +67,9 @@ namespace cbm::algo::rich
const TdcTimeData td = ProcessTimeData(wordTime);
const double fullTime = CalculateTime(epoch, td.fCoarse, td.fFine);
if (l == 0) fPrevLastCh0ReTime[12] = fullTime;
if (l == 1) fMbsCorr = fullTime - fPrevLastCh0ReTime[12]; // = MbsPrevTimeCh1 - MbsPrevTimeCh0
if (l > 1) fPrevLastCh0ReTime[l - 2] = fullTime;
if (l == 0) ctx.prevLastCh0ReTime[12] = fullTime;
if (l == 1) ctx.mbsCorr = fullTime - ctx.prevLastCh0ReTime[12]; // = MbsPrevTimeCh1 - MbsPrevTimeCh0
if (l > 1) ctx.prevLastCh0ReTime[l - 2] = fullTime;
}
const uint32_t trbNum = reader.NextWord(); // TRB trigger number
@@ -82,7 +77,7 @@ namespace cbm::algo::rich
}
void Unpack::ProcessHubBlock(rich::MicrosliceReader& reader)
void Unpack::ProcessHubBlock(rich::MicrosliceReader& reader, MSContext& ctx) const
{
uint32_t word = reader.NextWord();
const uint32_t hubId = word & 0xffff; // 16 bits
@@ -90,7 +85,7 @@ namespace cbm::algo::rich
bool isLast = false; // if true then it is CTS sub-sub-event
size_t totalSize = 0;
fCurrentSubSubEvent = 0;
ctx.currentSubSubEvent = 0;
uint32_t subSubEventId, subSubEventSize;
@@ -104,18 +99,18 @@ namespace cbm::algo::rich
if (!isLast) { // all except last are DiRICH events
if (((subSubEventId >> 12) & 0xF) != 0x7) { // catch invalid ids
fMonitor.fNumErrInvalidHubId++;
ctx.monitor.fNumErrInvalidHubId++;
}
if (totalSize == hubSize) { fMonitor.fNumErrInvalidHubSize++; }
ProcessSubSubEvent(reader, subSubEventSize, subSubEventId);
fCurrentSubSubEvent++;
if (totalSize == hubSize) { ctx.monitor.fNumErrInvalidHubSize++; }
ProcessSubSubEvent(reader, subSubEventSize, subSubEventId, ctx);
ctx.currentSubSubEvent++;
}
}
//last event ist expected to be CTS
if (totalSize != hubSize || !isLast) { fMonitor.fNumErrInvalidHubSize++; }
if (totalSize != hubSize || !isLast) { ctx.monitor.fNumErrInvalidHubSize++; }
subSubEventSize = ProcessCtsHeader(reader, subSubEventSize, subSubEventId);
ProcessSubSubEvent(reader, subSubEventSize, subSubEventId);
ProcessSubSubEvent(reader, subSubEventSize, subSubEventId, ctx);
// read last words
int lastWordsCounter = 0;
@@ -126,11 +121,11 @@ namespace cbm::algo::rich
if (reader.IsNextPadding()) word = reader.NextWord();
break;
}
if (lastWordsCounter >= 7) { fMonitor.fNumErrExcessLastWords++; }
if (lastWordsCounter >= 7) { ctx.monitor.fNumErrExcessLastWords++; }
}
}
int Unpack::ProcessCtsHeader(rich::MicrosliceReader& reader, uint32_t subSubEventSize, uint32_t subSubEventId)
int Unpack::ProcessCtsHeader(rich::MicrosliceReader& reader, uint32_t subSubEventSize, uint32_t subSubEventId) const
{
const uint32_t word = reader.NextWord();
const uint32_t ctsState = word & 0xffff; // 16 bits
@@ -154,7 +149,8 @@ namespace cbm::algo::rich
return nofTimeWords;
}
void Unpack::ProcessSubSubEvent(rich::MicrosliceReader& reader, int nofTimeWords, uint32_t subSubEventId)
void Unpack::ProcessSubSubEvent(rich::MicrosliceReader& reader, int nofTimeWords, uint32_t subSubEventId,
MSContext& ctx) const
{
uint32_t epoch = 0; // store last epoch obtained in sub-sub-event
@@ -171,11 +167,11 @@ namespace cbm::algo::rich
}
// First word is expected to be of type "header"
if (GetTdcWordType(reader.NextWord()) != TdcWordType::Header) { fMonitor.fNumErrInvalidFirstMessage++; }
if (GetTdcWordType(reader.NextWord()) != TdcWordType::Header) { ctx.monitor.fNumErrInvalidFirstMessage++; }
// Second word is expected to be of type "epoch"
uint32_t word = reader.NextWord();
if (GetTdcWordType(word) != TdcWordType::Epoch) { fMonitor.fNumErrInvalidSecondMessage++; }
if (GetTdcWordType(word) != TdcWordType::Epoch) { ctx.monitor.fNumErrInvalidSecondMessage++; }
else {
epoch = ProcessEpoch(word);
}
@@ -185,7 +181,7 @@ namespace cbm::algo::rich
word = reader.NextWord();
switch (GetTdcWordType(word)) {
case TdcWordType::TimeData: {
ProcessTimeDataWord(epoch, word, subSubEventId, raisingTime);
ProcessTimeDataWord(epoch, word, subSubEventId, raisingTime, ctx);
break;
}
case TdcWordType::Epoch: {
@@ -193,43 +189,44 @@ namespace cbm::algo::rich
break;
}
case TdcWordType::Header: {
fMonitor.fNumErrWildHeaderMessage++;
ctx.monitor.fNumErrWildHeaderMessage++;
break;
}
case TdcWordType::Trailer: {
fMonitor.fNumErrWildTrailerMessage++;
ctx.monitor.fNumErrWildTrailerMessage++;
break;
}
case TdcWordType::Debug: {
break;
// for the moment do nothing
fMonitor.fNumDebugMessage++;
ctx.monitor.fNumDebugMessage++;
break;
}
case TdcWordType::Error: {
fMonitor.fNumErrTdcErrorWord++;
ctx.monitor.fNumErrTdcErrorWord++;
break;
}
}
}
// Last word is expected to be of type "trailer"
if (GetTdcWordType(reader.NextWord()) != TdcWordType::Trailer) { fMonitor.fNumErrInvalidLastMessage++; }
if (GetTdcWordType(reader.NextWord()) != TdcWordType::Trailer) { ctx.monitor.fNumErrInvalidLastMessage++; }
}
// ---- ProcessTimeDataWord ----
void Unpack::ProcessTimeDataWord(uint32_t epoch, uint32_t tdcWord, uint32_t subSubEventId,
std::vector<double>& raisingTime)
std::vector<double>& raisingTime, MSContext& ctx) const
{
const TdcTimeData td = ProcessTimeData(tdcWord);
const double fullTime = CalculateTime(epoch, td.fCoarse, td.fFine);
if (td.fChannel != 0) {
const double dT = fullTime - fPrevLastCh0ReTime[fCurrentSubSubEvent];
const double subtrigOffset = (fCbmTimePacket - fCbmTimeMS) * 25.0; // offset of SubTrigger to MS start in ns
const double fullTimeCorr = dT - fMbsCorr + subtrigOffset;
const double dT = fullTime - ctx.prevLastCh0ReTime[ctx.currentSubSubEvent];
const double subtrigOffset =
(ctx.cbmTimePacket - ctx.cbmTimeMS) * 25.0; // offset of SubTrigger to MS start in ns
const double fullTimeCorr = dT - ctx.mbsCorr + subtrigOffset;
if (td.fChannel < 1 || td.fChannel >= raisingTime.size()) { fMonitor.fNumErrChannelOutOfBounds++; }
if (td.fChannel < 1 || td.fChannel >= raisingTime.size()) { ctx.monitor.fNumErrChannelOutOfBounds++; }
if (td.fIsRisingEdge) {
// always store the latest raising edge. It means that in case RRFF situation only middle RF will be matched.
raisingTime[td.fChannel] = fullTimeCorr;
@@ -239,7 +236,9 @@ namespace cbm::algo::rich
// Matching was found, calculate ToT, if tot is in a good range -> create digi
const double ToT = fullTimeCorr - raisingTime[td.fChannel];
if (ToT >= fToTMin && ToT <= fToTMax) {
if (fullTimeCorr >= 0.0) { WriteOutputDigi(subSubEventId, td.fChannel, raisingTime[td.fChannel], ToT); }
if (fullTimeCorr >= 0.0) {
WriteOutputDigi(subSubEventId, td.fChannel, raisingTime[td.fChannel], ToT, ctx);
}
}
// pair was created, set raising edge to -1.
raisingTime[td.fChannel] = -1.;
@@ -248,25 +247,25 @@ namespace cbm::algo::rich
}
}
double Unpack::CalculateTime(uint32_t epoch, uint32_t coarse, uint32_t fine)
double Unpack::CalculateTime(uint32_t epoch, uint32_t coarse, uint32_t fine) const
{
return ((double) epoch) * 2048. * 5. + ((double) coarse) * 5. - ((double) fine) * 0.005;
}
void Unpack::WriteOutputDigi(int32_t fpgaID, int32_t channel, double time, double tot)
void Unpack::WriteOutputDigi(int32_t fpgaID, int32_t channel, double time, double tot, MSContext& ctx) const
{
double ToTcorr = fbDoToTCorr ? fParams.fElinkParams[fpgaID].fToTshift[channel] : 0.;
double ToTcorr = fbDoToTCorr ? fParams.fElinkParams.at(fpgaID).fToTshift[channel] : 0.;
int32_t pixelUID = GetPixelUID(fpgaID, channel);
//check ordering
double finalTime = time + (double) fMsRefTime - fParams.fElinkParams[fpgaID].fTimeOffset;
double finalTime = time + (double) ctx.refTime - fParams.fElinkParams.at(fpgaID).fTimeOffset;
// Do not accept digis, where the MS und TS differs by more than 6 sec (mainly TS0)
if (6e9 < finalTime) return;
fOutputVec.emplace_back(pixelUID, finalTime, tot - ToTcorr);
ctx.digis.emplace_back(pixelUID, finalTime, tot - ToTcorr);
}
bool Unpack::CheckMaskedDiRICH(int32_t subSubEventId)
bool Unpack::CheckMaskedDiRICH(int32_t subSubEventId) const
{
for (unsigned int i = 0; i < fMaskedDiRICHes.size(); ++i) {
if (fMaskedDiRICHes.at(i) == subSubEventId) return true;
@@ -274,7 +273,7 @@ namespace cbm::algo::rich
return false;
}
TdcWordType Unpack::GetTdcWordType(uint32_t tdcWord)
TdcWordType Unpack::GetTdcWordType(uint32_t tdcWord) const
{
uint32_t tdcTimeDataMarker = (tdcWord >> 31) & 0x1; // 1 bit
uint32_t tdcMarker = (tdcWord >> 29) & 0x7; // 3 bits
@@ -293,14 +292,14 @@ namespace cbm::algo::rich
return TdcWordType::Error;
}
int32_t Unpack::GetPixelUID(int32_t fpgaID, int32_t ch)
int32_t Unpack::GetPixelUID(int32_t fpgaID, int32_t ch) const
{
// First 16 bits are used for the FPGA ID, then
// 8 bits unused and then 8 bits are used for the channel
return ((fpgaID << 16) | (ch & 0x00FF));
}
TdcTimeData Unpack::ProcessTimeData(uint32_t tdcWord)
TdcTimeData Unpack::ProcessTimeData(uint32_t tdcWord) const
{
TdcTimeData out;
out.fCoarse = static_cast<uint32_t>(tdcWord & 0x7ff); // 11 bits
@@ -310,13 +309,13 @@ namespace cbm::algo::rich
return out;
}
uint32_t Unpack::ProcessEpoch(uint32_t tdcWord) { return static_cast<uint32_t>(tdcWord & 0xfffffff); }
uint32_t Unpack::ProcessEpoch(uint32_t tdcWord) const { return static_cast<uint32_t>(tdcWord & 0xfffffff); }
uint16_t Unpack::ProcessHeader(uint32_t tdcWord)
uint16_t Unpack::ProcessHeader(uint32_t tdcWord) const
{
return static_cast<uint16_t>(tdcWord & 0xff); //8 bits
}
uint16_t Unpack::ProcessTrailer(uint32_t tdcWord) { return static_cast<uint16_t>(tdcWord & 0xffff); }
uint16_t Unpack::ProcessTrailer(uint32_t tdcWord) const { return static_cast<uint16_t>(tdcWord & 0xffff); }
} // namespace cbm::algo::rich
Loading