Skip to content
Snippets Groups Projects
Commit a8f7d7ad authored by Felix Weiglhofer's avatar Felix Weiglhofer
Browse files

algo: Make MUCH Unpacker thread-safe.

parent 050ff780
No related branches found
No related tags found
1 merge request!1242algo::Unpack: Unpack BMON and MUCH in parallel.
...@@ -20,22 +20,25 @@ namespace cbm::algo ...@@ -20,22 +20,25 @@ namespace cbm::algo
// ---- Algorithm execution --------------------------------------------- // ---- Algorithm execution ---------------------------------------------
UnpackMuch::resultType UnpackMuch::operator()(const uint8_t* msContent, const fles::MicrosliceDescriptor& msDescr, UnpackMuch::resultType UnpackMuch::operator()(const uint8_t* msContent, const fles::MicrosliceDescriptor& msDescr,
const uint64_t tTimeslice) const uint64_t tTimeslice) const
{ {
// --- Output data // --- Output data
resultType result = {}; resultType result = {};
TimeSpec time;
// --- Current Timeslice start time in epoch units. Note that it is always a multiple of epochs // --- Current Timeslice start time in epoch units. Note that it is always a multiple of epochs
// --- and the epoch is a multiple of ns. // --- and the epoch is a multiple of ns.
const uint64_t epochLengthInNs = fkEpochLength * fkClockCycleNom / fkClockCycleDen; const uint64_t epochLengthInNs = fkEpochLength * fkClockCycleNom / fkClockCycleDen;
fCurrentTsTime = tTimeslice / epochLengthInNs; time.currentTsTime = tTimeslice / epochLengthInNs;
// --- Current TS_MSB epoch cycle // --- Current TS_MSB epoch cycle
auto const msTime = msDescr.idx; // Unix time of MS in ns auto const msTime = msDescr.idx; // Unix time of MS in ns
fCurrentCycle = std::ldiv(msTime, fkCycleLength).quot; time.currentCycle = std::ldiv(msTime, fkCycleLength).quot;
fCurrentEpoch = 0; // Needed to make each MS independent of the previous! Will be updated in message 1 if MS OK time.currentEpoch = 0; // Needed to make each MS independent of the previous! Will be updated in message 1 if MS OK
fCurrentEpochTime = 0; // Needed to make each MS independent of the previous! Will be updated in message 1 if MS OK time.currentEpochTime =
0; // Needed to make each MS independent of the previous! Will be updated in message 1 if MS OK
// --- Number of messages in microslice // --- Number of messages in microslice
auto msSize = msDescr.size; auto msSize = msDescr.size;
...@@ -66,7 +69,7 @@ namespace cbm::algo ...@@ -66,7 +69,7 @@ namespace cbm::algo
result.second.fNumErrInvalidFirstMessage++; result.second.fNumErrInvalidFirstMessage++;
return result; return result;
} }
ProcessTsmsbMessage(message[1]); ProcessTsmsbMessage(message[1], time);
// --- Message loop // --- Message loop
for (uint32_t messageNr = 2; messageNr < numMessages; messageNr++) { for (uint32_t messageNr = 2; messageNr < numMessages; messageNr++) {
...@@ -75,11 +78,11 @@ namespace cbm::algo ...@@ -75,11 +78,11 @@ namespace cbm::algo
switch (message[messageNr].GetMessType()) { switch (message[messageNr].GetMessType()) {
case stsxyter::MessType::Hit: { case stsxyter::MessType::Hit: {
ProcessHitMessage(message[messageNr], result.first, result.second); ProcessHitMessage(message[messageNr], time, result.first, result.second);
break; break;
} }
case stsxyter::MessType::TsMsb: { case stsxyter::MessType::TsMsb: {
ProcessTsmsbMessage(message[messageNr]); ProcessTsmsbMessage(message[messageNr], time);
break; break;
} }
default: { default: {
...@@ -97,8 +100,8 @@ namespace cbm::algo ...@@ -97,8 +100,8 @@ namespace cbm::algo
// ----- Process hit message -------------------------------------------- // ----- Process hit message --------------------------------------------
inline void UnpackMuch::ProcessHitMessage(const stsxyter::Message& message, vector<CbmMuchDigi>& digiVec, inline void UnpackMuch::ProcessHitMessage(const stsxyter::Message& message, const TimeSpec& time,
UnpackMuchMonitorData& monitor) const vector<CbmMuchDigi>& digiVec, UnpackMuchMonitorData& monitor) const
{ {
// --- Check eLink and get parameters // --- Check eLink and get parameters
uint16_t elink = message.GetLinkIndexHitBinning(); uint16_t elink = message.GetLinkIndexHitBinning();
...@@ -115,7 +118,7 @@ namespace cbm::algo ...@@ -115,7 +118,7 @@ namespace cbm::algo
uint32_t address = (elinkPar.fAddress)[channel]; uint32_t address = (elinkPar.fAddress)[channel];
// --- Expand time stamp to time within timeslice (in clock cycle) // --- Expand time stamp to time within timeslice (in clock cycle)
uint64_t messageTime = message.GetHitTimeBinning() + fCurrentEpochTime; uint64_t messageTime = message.GetHitTimeBinning() + time.currentEpochTime;
// --- Convert time stamp from clock cycles to ns. Round to nearest full ns. // --- Convert time stamp from clock cycles to ns. Round to nearest full ns.
messageTime = (messageTime * fkClockCycleNom + fkClockCycleDen / 2) / fkClockCycleDen; messageTime = (messageTime * fkClockCycleNom + fkClockCycleDen / 2) / fkClockCycleDen;
...@@ -133,7 +136,7 @@ namespace cbm::algo ...@@ -133,7 +136,7 @@ namespace cbm::algo
// ----- Process an epoch (TS_MSB) message ------------------------------ // ----- Process an epoch (TS_MSB) message ------------------------------
inline void UnpackMuch::ProcessTsmsbMessage(const stsxyter::Message& message) inline void UnpackMuch::ProcessTsmsbMessage(const stsxyter::Message& message, TimeSpec& time) const
{ {
// The compression of time is based on the hierarchy epoch cycle - epoch - message time. // The compression of time is based on the hierarchy epoch cycle - epoch - message time.
// Cycles are counted from the start of Unix time and are multiples of an epoch (ts_msb). // Cycles are counted from the start of Unix time and are multiples of an epoch (ts_msb).
...@@ -146,13 +149,13 @@ namespace cbm::algo ...@@ -146,13 +149,13 @@ namespace cbm::algo
auto epoch = message.GetTsMsbValBinning(); auto epoch = message.GetTsMsbValBinning();
// --- Cycle wrap // --- Cycle wrap
if (epoch < fCurrentEpoch) fCurrentCycle++; if (epoch < time.currentEpoch) time.currentCycle++;
// --- Update current epoch counter // --- Update current epoch counter
fCurrentEpoch = epoch; time.currentEpoch = epoch;
// --- Calculate epoch time in clocks cycles relative to timeslice start time // --- Calculate epoch time in clocks cycles relative to timeslice start time
fCurrentEpochTime = (fCurrentCycle * fkEpochsPerCycle + epoch - fCurrentTsTime) * fkEpochLength; time.currentEpochTime = (time.currentCycle * fkEpochsPerCycle + epoch - time.currentTsTime) * fkEpochLength;
} }
// -------------------------------------------------------------------------- // --------------------------------------------------------------------------
......
...@@ -100,13 +100,21 @@ namespace cbm::algo ...@@ -100,13 +100,21 @@ namespace cbm::algo
** @return STS digi data ** @return STS digi data
**/ **/
resultType operator()(const uint8_t* msContent, const fles::MicrosliceDescriptor& msDescr, resultType operator()(const uint8_t* msContent, const fles::MicrosliceDescriptor& msDescr,
const uint64_t tTimeslice); const uint64_t tTimeslice) const;
/** @brief Set the parameter container /** @brief Set the parameter container
** @param params Pointer to parameter container ** @param params Pointer to parameter container
**/ **/
void SetParams(std::unique_ptr<UnpackMuchPar> params) { fParams = *(std::move(params)); } void SetParams(std::unique_ptr<UnpackMuchPar> params) { fParams = *(std::move(params)); }
private: // datatypes
struct TimeSpec {
uint64_t currentTsTime = 0; ///< Unix time of timeslice in units of epoch length
uint64_t currentCycle = 0; ///< Current epoch cycle
uint32_t currentEpoch = 0; ///< Current epoch number within epoch cycle
uint64_t currentEpochTime = 0; ///< Current epoch time relative to timeslice in clock cycles
};
private: // methods private: // methods
/** @brief Process a hit message /** @brief Process a hit message
...@@ -114,20 +122,16 @@ namespace cbm::algo ...@@ -114,20 +122,16 @@ namespace cbm::algo
** @param digiVec Vector to append the created digi to ** @param digiVec Vector to append the created digi to
** @param monitor Reference to monitor object ** @param monitor Reference to monitor object
**/ **/
void ProcessHitMessage(const stsxyter::Message& message, std::vector<CbmMuchDigi>& digiVec, void ProcessHitMessage(const stsxyter::Message& message, const TimeSpec& time, std::vector<CbmMuchDigi>& digiVec,
UnpackMuchMonitorData& monitor) const; UnpackMuchMonitorData& monitor) const;
/** @brief Process an epoch message (TS_MSB) /** @brief Process an epoch message (TS_MSB)
** @param message SMX message (32-bit word) ** @param message SMX message (32-bit word)
**/ **/
void ProcessTsmsbMessage(const stsxyter::Message& message); void ProcessTsmsbMessage(const stsxyter::Message& message, TimeSpec& time) const;
private: // members private: // members
uint64_t fCurrentTsTime = 0; ///< Unix time of timeslice in units of epoch length
uint64_t fCurrentCycle = 0; ///< Current epoch cycle
uint32_t fCurrentEpoch = 0; ///< Current epoch number within epoch cycle
uint64_t fCurrentEpochTime = 0; ///< Current epoch time relative to timeslice in clock cycles
UnpackMuchPar fParams = {}; ///< Parameter container UnpackMuchPar fParams = {}; ///< Parameter container
/** Number of TS_MSB epochs per cycle **/ /** Number of TS_MSB epochs per cycle **/
......
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