Skip to content
Snippets Groups Projects
Commit 28c3fd25 authored by Volker Friese's avatar Volker Friese Committed by Jan de Cuveland
Browse files

Modifications following the suggestions of P.-A. Loizeau and J. de Cuveland...

Modifications following the suggestions of P.-A. Loizeau and J. de Cuveland (see #2268). Refs #2268.
parent 46213614
No related branches found
No related tags found
1 merge request!750Initial version of STS unpacker algo plus integration by task. Refs #2268. Refs #2272.
...@@ -5,62 +5,70 @@ ...@@ -5,62 +5,70 @@
#include "UnpackSts.h" #include "UnpackSts.h"
#include <cassert> #include <cassert>
#include <utility>
#include <vector> #include <vector>
#include <cmath> #include <cmath>
#include "StsXyterMessage.h" #include "StsXyterMessage.h"
using std::unique_ptr;
using std::vector; using std::vector;
namespace cbm::algo namespace cbm::algo
{ {
// ---- Algorithm execution --------------------------------------------- // ---- Algorithm execution ---------------------------------------------
vector<CbmStsDigi> UnpackSts::operator()(const uint8_t* msContent, const fles::MicrosliceDescriptor& msDescr, UnpackSts::resultType UnpackSts::operator()(const uint8_t* msContent, const fles::MicrosliceDescriptor& msDescr,
const uint64_t tTimeslice) const uint64_t tTimeslice)
{ {
// --- Assert that parameters are set // --- Assert that parameters are set
assert(fParams); assert(fParams);
fCurrentTsTime = tTimeslice;
// --- Output vector // --- Output data
vector<CbmStsDigi> digiVec; vector<CbmStsDigi> digiVec = {};
UnpackStsMonitorData moni = {};
// --- Current Timeslice time and TS_MSB epoch cycle
fCurrentTsTime = tTimeslice;
auto msTime = msDescr.idx; // Unix time of MS in ns
fCurrentCycle = std::ldiv(msTime, fkCycleLength).quot;
// --- Current TS_MSB epoch cycle // --- Interpret MS content as sequence of SMX messages
auto msTime = msDescr.idx; // Unix time of MS in ns auto message = reinterpret_cast<const stsxyter::Message*>(msContent);
fCurrentCycle = std::ldiv(msTime, fCycleLength).quot;
// --- Get first TS_MSB (first message in microslice must be of type ts_msb) // --- Get first TS_MSB (first message in microslice must be of type ts_msb)
const stsxyter::Message firstMessage(msContent[0]); if (message[0].GetMessType() != stsxyter::MessType::TsMsb) {
assert(firstMessage.GetMessType() == stsxyter::MessType::TsMsb); moni.fNumErrInvalidFirstMessage++;
ProcessTsmsbMessage(firstMessage); return std::make_pair(digiVec, moni);
}
ProcessTsmsbMessage(message[0]);
// --- Number of messages in microslice // --- Number of messages in microslice
auto msSize = msDescr.size; auto msSize = msDescr.size;
assert(msSize % sizeof(stsxyter::Message) == 0); if (msSize % sizeof(stsxyter::Message) != 0) {
moni.fNumErrInvalidMsSize++;
return std::make_pair(digiVec, moni);
}
const uint32_t numMessages = msSize / sizeof(stsxyter::Message); const uint32_t numMessages = msSize / sizeof(stsxyter::Message);
// --- Message loop // --- Message loop
for (uint32_t messageNr = 1; messageNr < numMessages; messageNr++) { for (uint32_t messageNr = 1; messageNr < numMessages; messageNr++) {
// --- Cast MS content to STSXYTER message
const stsxyter::Message message(msContent[messageNr]);
const stsxyter::MessType type = message.GetMessType();
// --- Action depending on message type // --- Action depending on message type
switch (type) { switch (message[messageNr].GetMessType()) {
case stsxyter::MessType::Hit: { case stsxyter::MessType::Hit: {
ProcessHitMessage(message, digiVec); ProcessHitMessage(message[messageNr], digiVec, moni);
break; break;
} }
case stsxyter::MessType::TsMsb: { case stsxyter::MessType::TsMsb: {
ProcessTsmsbMessage(message); ProcessTsmsbMessage(message[messageNr]);
break; break;
} }
default: { default: {
moni.fNumNonHitOrTsbMessage++;
break; break;
} }
...@@ -68,23 +76,29 @@ namespace cbm::algo ...@@ -68,23 +76,29 @@ namespace cbm::algo
} //# Messages } //# Messages
return digiVec; return std::make_pair(digiVec, moni);
} }
// -------------------------------------------------------------------------- // --------------------------------------------------------------------------
// ----- Process hit message -------------------------------------------- // ----- Process hit message --------------------------------------------
void UnpackSts::ProcessHitMessage(const stsxyter::Message& message, vector<CbmStsDigi>& digiVec) const void UnpackSts::ProcessHitMessage(const stsxyter::Message& message, vector<CbmStsDigi>& digiVec,
UnpackStsMonitorData& moni) const
{ {
uint16_t elink = message.GetLinkIndexHitBinning(); // --- Check eLink and get parameters
const UnpackStsElinkPar& elinkPar = fParams->GetElinkPar(elink); uint16_t elink = message.GetLinkIndexHitBinning();
if (elink >= fParams->fElinkParams.size()) {
moni.fNumErrElinkOutOfRange++;
return;
}
const UnpackStsElinkPar& elinkPar = fParams->fElinkParams.at(elink);
uint32_t asicNr = elinkPar.fAsicNr; uint32_t asicNr = elinkPar.fAsicNr;
uint32_t numChansPerModule = fParams->fNumAsicsPerModule * fParams->fNumChansPerAsic;
// --- Hardware-to-software address // --- Hardware-to-software address
uint32_t address = elinkPar.fAddress; uint32_t numChansPerModule = fParams->fNumAsicsPerModule * fParams->fNumChansPerAsic;
uint32_t channel = 0; uint32_t address = elinkPar.fAddress;
uint32_t channel = 0;
if (asicNr < fParams->fNumAsicsPerModule / 2) { // front side (n side) if (asicNr < fParams->fNumAsicsPerModule / 2) { // front side (n side)
channel = message.GetHitChannel() + fParams->fNumChansPerAsic * asicNr; channel = message.GetHitChannel() + fParams->fNumChansPerAsic * asicNr;
} }
...@@ -94,10 +108,13 @@ namespace cbm::algo ...@@ -94,10 +108,13 @@ namespace cbm::algo
// --- Time stamp // --- Time stamp
// --- Expand to full Unix time in clock cycles // --- Expand to full Unix time in clock cycles
uint64_t timeCC = message.GetHitTimeBinning() + fCurrentEpochTime; uint64_t timeCc = message.GetHitTimeBinning() + fCurrentEpochTime;
if (timeCc >> 59 != 0) { // avoid overflow in 64 bit // TODO: Hard-coded number!
moni.fNumErrTimestampOverflow++;
return;
}
// --- Convert time into ns // --- Convert time into ns
assert(timeCC >> 59 == 0); // avoid overflow in 64 bit uint64_t timeNs = (timeCc * fkClockCycleNom + fkClockCycleDen / 2) / fkClockCycleDen;
uint64_t timeNs = (timeCC * fParams->fClockCycleNom) / fParams->fClockCycleDen;
// --- Correct ASIC-wise offsets // --- Correct ASIC-wise offsets
timeNs -= elinkPar.fTimeOffset; timeNs -= elinkPar.fTimeOffset;
// --- Calculate time relative to timeslice // --- Calculate time relative to timeslice
...@@ -124,7 +141,7 @@ namespace cbm::algo ...@@ -124,7 +141,7 @@ namespace cbm::algo
// --- Update current epoch // --- Update current epoch
fCurrentEpoch = epoch; fCurrentEpoch = epoch;
fCurrentEpochTime = (fCurrentCycle * fParams->fEpochsPerCycle + epoch) * fParams->fEpochLength; fCurrentEpochTime = (fCurrentCycle * fkEpochsPerCycle + epoch) * fkEpochLength;
} }
// -------------------------------------------------------------------------- // --------------------------------------------------------------------------
......
...@@ -23,10 +23,10 @@ namespace cbm::algo ...@@ -23,10 +23,10 @@ namespace cbm::algo
{ {
/** @struct UnpackStsAsicPar /** @struct UnpackStsElinkPar
** @author Volker Friese <v.friese@gsi.de> ** @author Volker Friese <v.friese@gsi.de>
** @since 25 November 2021 ** @since 25 November 2021
** @brief Unpacking parameters for one eLink / ASIC ** @brief STS Unpacking parameters for one eLink / ASIC
**/ **/
struct UnpackStsElinkPar { struct UnpackStsElinkPar {
uint32_t fAddress = 0; ///< CbmStsAddress for the connected module uint32_t fAddress = 0; ///< CbmStsAddress for the connected module
...@@ -43,22 +43,23 @@ namespace cbm::algo ...@@ -43,22 +43,23 @@ namespace cbm::algo
** @brief Parameters required for the STS unpacking (specific to one component) ** @brief Parameters required for the STS unpacking (specific to one component)
**/ **/
struct UnpackStsPar { struct UnpackStsPar {
uint32_t fNumChansPerAsic = 0; ///< Number of channels per ASIC
uint32_t fNumAsicsPerModule = 0; ///< Number of ASICS per module
std::vector<UnpackStsElinkPar> fElinkParams = {}; ///< Parameters for each eLink
};
uint32_t fNumChansPerAsic = 0; ///< Number of channels per ASIC /** @struct UnpackStsMoni
uint32_t fNumAsicsPerModule = 0; ///< Number of ASICS per module ** @author Volker Friese <v.friese@gsi.de>
uint64_t fEpochsPerCycle = 0; ///< TS_MSB epochs per epoch cycle ** @since 2 December 2021
uint64_t fEpochLength = 0; ///< Length of TS_MSB epoch in clock cycles ** @brief Monitoring data for STS unpacking
uint32_t fClockCycleNom = 0; ///< Clock cycle nominator [ns] **/
uint32_t fClockCycleDen = 0.; ///< Clock cycle denominator struct UnpackStsMonitorData {
std::vector<UnpackStsElinkPar> fElinkParams; ///< Parameters for each eLink uint32_t fNumNonHitOrTsbMessage = 0;
uint32_t fNumErrElinkOutOfRange = 0; ///< Elink not contained in parameters
size_t GetNumElinks() const { return fElinkParams.size(); } uint32_t fNumErrInvalidFirstMessage = 0; ///< First message is not TS_MSB
uint32_t fNumErrInvalidMsSize = 0; ///< Microslice size is not multiple of message size
const UnpackStsElinkPar& GetElinkPar(size_t eLink) const uint32_t fNumErrTimestampOverflow = 0; ///< Overflow in 64 bit time stamp
{
assert(eLink < GetNumElinks());
return fElinkParams[eLink];
}
}; };
...@@ -71,6 +72,9 @@ namespace cbm::algo ...@@ -71,6 +72,9 @@ namespace cbm::algo
class UnpackSts { class UnpackSts {
public: public:
typedef std::pair<std::vector<CbmStsDigi>, UnpackStsMonitorData> resultType;
/** @brief Default constructor **/ /** @brief Default constructor **/
UnpackSts() {}; UnpackSts() {};
...@@ -85,39 +89,43 @@ namespace cbm::algo ...@@ -85,39 +89,43 @@ namespace cbm::algo
** @param tTimeslice Unix start time of timeslice [ns] ** @param tTimeslice Unix start time of timeslice [ns]
** @return STS digi data ** @return STS digi data
**/ **/
std::vector<CbmStsDigi> 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);
/** @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<UnpackStsPar> params) void SetParams(std::unique_ptr<UnpackStsPar> params) { fParams = std::move(params); }
{
fParams = std::move(params);
fCycleLength = (fParams->fEpochsPerCycle * fParams->fEpochLength * fParams->fClockCycleNom);
fCycleLength /= fParams->fClockCycleDen;
}
private: private: // methods
/** @brief Process an epoch message (TS_MSB) /** @brief Process a hit message
** @param message SMX message (32-bit word) ** @param message SMX message (32-bit word)
** @param digiVec Vector to append the created digi to ** @param digiVec Vector to append the created digi to
**/ **/
void ProcessTsmsbMessage(const stsxyter::Message& message); void ProcessHitMessage(const stsxyter::Message& message, std::vector<CbmStsDigi>& digiVec,
UnpackStsMonitorData& moni) const;
/** @brief Process a hit message /** @brief Process an epoch message (TS_MSB)
** @param message SMX message (32-bit word) ** @param message SMX message (32-bit word)
** @param digiVec Vector to append the created digi to ** @param digiVec Vector to append the created digi to
**/ **/
void ProcessHitMessage(const stsxyter::Message& message, std::vector<CbmStsDigi>& digiVec) const; void ProcessTsmsbMessage(const stsxyter::Message& message);
private: private: // members
uint64_t fCurrentTsTime = 0; ///< Unix time of timeslice in ns uint64_t fCurrentTsTime = 0; ///< Unix time of timeslice in ns
uint64_t fCurrentCycle = 0; ///< Current epoch cycle uint64_t fCurrentCycle = 0; ///< Current epoch cycle
uint32_t fCurrentEpoch = 0; ///< Current epoch number within epoch cycle uint32_t fCurrentEpoch = 0; ///< Current epoch number within epoch cycle
uint64_t fCurrentEpochTime = 0; ///< Unix time of current epoch in clock cycles uint64_t fCurrentEpochTime = 0; ///< Unix time of current epoch in clock cycles
uint64_t fCycleLength = 0; ///< Epoch cycle length in ns
static constexpr uint64_t fkEpochsPerCycle = stsxyter::kuTsMsbNbTsBinsBinning; ///< TS_MSB epochs per epoch cycle
static constexpr uint64_t fkEpochLength =
stsxyter::kuHitNbTsBinsBinning; ///< Length of TS_MSB epoch in clock cycles
static constexpr uint32_t fkClockCycleNom = stsxyter::kulClockCycleNom; ///< Clock cycle nominator [ns]
static constexpr uint32_t fkClockCycleDen = stsxyter::kulClockCycleDen; ///< Clock cycle denominator
static constexpr uint64_t fkCycleLength =
(fkEpochsPerCycle * fkEpochLength * fkClockCycleNom) / fkClockCycleDen; ///< Epoch cycle length in ns
std::unique_ptr<UnpackStsPar> fParams = nullptr; ///< Parameter container std::unique_ptr<UnpackStsPar> fParams = nullptr; ///< Parameter container
}; };
......
...@@ -155,10 +155,11 @@ namespace stsxyter ...@@ -155,10 +155,11 @@ namespace stsxyter
static const uint32_t kuTsMsbNbTsBins = (0 < kusLenTsMsbVal ? 1 << kusLenTsMsbVal : 0); static const uint32_t kuTsMsbNbTsBins = (0 < kusLenTsMsbVal ? 1 << kusLenTsMsbVal : 0);
static const uint64_t kulTsCycleNbBins = static const uint64_t kulTsCycleNbBins =
static_cast<uint64_t>(kuTsMsbNbTsBins) * static_cast<uint64_t>(kuHitNbTsBins); static_cast<uint64_t>(kuTsMsbNbTsBins) * static_cast<uint64_t>(kuHitNbTsBins);
static const uint16_t kusMaskTsMsbOver = (1 << kusLenHitTsOver) - 1; static const uint16_t kusMaskTsMsbOver = (1 << kusLenHitTsOver) - 1;
static const double kdClockCycleNs = 3.125; // ns, equivalent to 2*160 MHz clock static constexpr uint32_t kulClockCycleNom = 25; ///< Clock cycle nominator [ns], equivalent to 2*160 MHz clock
/// Binning FW adds 1 bit to TS in HIT message static constexpr uint32_t kulClockCycleDen = 8; ///< Clock cycle denominator, equivalent to 2*160 MHz clock
/// => Quick and dirty hack is a factor 2!!! static constexpr double kdClockCycleNs = static_cast<double>(kulClockCycleNom) / kulClockCycleDen; // ns, not rounded
static const uint32_t kuHitNbTsBinsBinning = 1 << 10; static const uint32_t kuHitNbTsBinsBinning = 1 << 10;
static const uint32_t kuTsMsbNbTsBinsBinning = 1 << kusLenTsMsbValBinning; static const uint32_t kuTsMsbNbTsBinsBinning = 1 << kusLenTsMsbValBinning;
static const uint64_t kulTsCycleNbBinsBinning = static const uint64_t kulTsCycleNbBinsBinning =
......
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