ATLAS Offline Software
Loading...
Searching...
No Matches
CTPResultByteStreamTool.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3*/
4
5// Local include(s):
7
8// TDAQ include(s):
9#include "eformat/SourceIdentifier.h"
10#include "CTPfragment/CTPfragment.h"
11#include "CTPfragment/CTPdataformat.h"
12#include "CTPfragment/CTPdataformatVersion.h"
13
14// Trigger include(s):
18
19// Athena includes
20#include "CxxUtils/span.h"
21
25
26// -----------------------------------------------------------------------------
27// Initialisation
28// -----------------------------------------------------------------------------
30 ConversionMode mode = getConversionMode(m_inKeyCTPResult, m_outKeyCTPResult, msg());
31 ATH_CHECK(mode!=ConversionMode::Undefined);
32 ATH_CHECK(m_outKeyCTPResult.initialize(mode==ConversionMode::Decoding));
33 ATH_CHECK(m_inKeyCTPResult.initialize(mode==ConversionMode::Encoding));
34 ATH_MSG_DEBUG((mode==ConversionMode::Encoding ? "Encoding" : "Decoding") << " ROB IDs: "
35 << MSG::hex << m_robIds.value() << MSG::dec);
36 if (m_robIds.value().size() != 1) {
37 ATH_MSG_ERROR("This tool implementation assumes there is exactly one CTP ROB, but "
38 << m_robIds.size() << " were configured");
39 return StatusCode::SUCCESS;
40 }
41 return StatusCode::SUCCESS;
42}
43
44// -----------------------------------------------------------------------------
45// BS->xAOD conversion
46// -----------------------------------------------------------------------------
47StatusCode CTPResultByteStreamTool::convertFromBS(const std::vector<const ROBF*>& vrobf, const EventContext& eventContext) const {
48
49 //
50 // Find the ROB fragment to decode
51 //
52 const eformat::helper::SourceIdentifier sid(m_robIds.value().at(0));
53 auto it = std::find_if(vrobf.begin(), vrobf.end(), [&sid](const ROBF* rob){return rob->rob_source_id() == sid.code();});
54 if (it == vrobf.end()) {
55 ATH_MSG_ERROR("No CTP ROB fragment with ID 0x" << std::hex << sid.code() << std::dec << " was found!");
56 return StatusCode::FAILURE;
57 }
58 ATH_MSG_VERBOSE("Found CTP ROD with source ID 0x" << MSG::hex << sid.code() << MSG::dec);
59
60 //
61 // Retrieve the ROD data
62 //
63 const ROBF* rob = *it;
64 DataType it_data;
65 rob->rod_data( it_data );
66 const uint32_t ndata = rob->rod_ndata();
67
68 //
69 // Header information
70 //
71 uint32_t headerMarker = eformat::ROD;
72 uint32_t formatVersion = rob->rod_version();
73 uint32_t L1ID = rob->rod_lvl1_id();
74 uint32_t sourceID = rob->rod_source_id();
75
76 //
77 // Trailer information
78 //
79 DataStatus dataStatus;
80 dataStatus.rob_error = false;
81 dataStatus.rod_error = false;
82 dataStatus.status_word = 0;
83 dataStatus.status_info = 0;
84
85 try {
86 if (rob->check_rob()) ATH_MSG_VERBOSE("ROB fragment checked ok");
87 }
88 catch (std::exception const & ex) {
89 ATH_MSG_WARNING("ROB fragment not valid: " << ex.what());
90 dataStatus.rob_error = true;
91 }
92
93 try {
94 if (rob->check_rod()) ATH_MSG_VERBOSE("ROD fragment checked ok");
95 }
96 catch (std::exception const & ex) {
97 ATH_MSG_WARNING("ROD fragment not valid: " << ex.what());
98 dataStatus.rod_error = true;
99 }
100
101 // Process the status words
102 DataType status;
103 rob->rod_status(status);
104 uint32_t nstatus = rob->rod_nstatus();
105 if (msgLvl(MSG::VERBOSE)) {
106 ATH_MSG_VERBOSE("Number of status words: " << nstatus);
107 for (uint32_t i=0; i<nstatus; ++i, ++status) {
108 ATH_MSG_VERBOSE(" Status word: 0x" << MSG::hex << std::setw(8) << std::setfill('0') << *status);
109 }
110 }
111 rob->rod_status(status);
112
113 if(nstatus > 0) dataStatus.status_word = static_cast<uint32_t>(*status);
114 if(nstatus > 1) {
115 ++status;
116 dataStatus.status_info = static_cast<uint32_t>(*status);
117 }
118
119 uint32_t errStatus = dataStatus.status_word; // error status
120 uint32_t statInfo = dataStatus.status_info; // status info
121
122 //
123 // Payload information
124 //
125 std::vector<uint32_t> vDataWords;
126 vDataWords.reserve(ndata);
127 if (msgLvl(MSG::VERBOSE)) {
128 ATH_MSG_VERBOSE(" Dumping xAOD::CTPResult Words:");
129 for (const uint32_t word : CxxUtils::span{it_data, ndata}) {
130 ATH_MSG_VERBOSE(" 0x" << MSG::hex << std::setfill('0') << std::setw(8) << word << MSG::dec);
131 }
132 }
133 vDataWords.assign(CxxUtils::span{it_data, ndata}.begin(), CxxUtils::span{it_data, ndata}.end());
134
135 uint32_t nExtraWords=0;
136 nExtraWords=CTPfragment::numberExtraPayloadWords(rob);
137 unsigned int ctpVersionNumber = CTPfragment::ctpFormatVersion(rob);
138
139 //
140 // Create xAOD
141 //
142 auto result = std::make_unique<xAOD::CTPResult>();
143 auto resultAux = std::make_unique<xAOD::CTPResultAuxInfo>();
144 result->setStore(resultAux.get());
145
146 // Initialize takes care of the most payload info
147 CTPResultUtils::initialize(*result, ctpVersionNumber, vDataWords, nExtraWords);
148
149 // Initialize the remaining words
150 result->setHeader(headerMarker, formatVersion, sourceID, L1ID); // Header words
151 result->setTrailer(ndata, errStatus, statInfo); // Trailer words
152 result->setL1AcceptBunchPosition(CTPfragment::lvl1AcceptBunch(rob)); // L1A bunch position
153 result->setTurnCounter(CTPfragment::turnCounter(rob)); // Turn counter
154
155 // Record result
156 SG::WriteHandle<xAOD::CTPResult> ctpResultWriteHandle = SG::makeHandle( m_outKeyCTPResult, eventContext );
157 ATH_CHECK( ctpResultWriteHandle.record( std::move(result), std::move(resultAux) ));
158 ATH_MSG_DEBUG("Created xAOD::CTPResult from bytestream");
159
160 return StatusCode::SUCCESS;
161}
162
163
164// -----------------------------------------------------------------------------
165// xAOD->BS conversion
166// -----------------------------------------------------------------------------
167StatusCode CTPResultByteStreamTool::convertToBS(std::vector<WROBF*>& vrobf, const EventContext& eventContext) {
168
169 // Retrieve the xAOD::CTPResult object
171 ATH_CHECK(result.isValid());
172
173 // Get CTP version
174 unsigned int ctpVersionNumber = result->ctpVersionNumber();
175 CTPdataformatVersion ctpDataFormat(ctpVersionNumber);
176
177 // Compute rodSize from object content
178 size_t totalPerBunchWords = 0;
179 for (uint32_t bunch = 0; bunch < result->numberOfBunches(); ++bunch) {
180 totalPerBunchWords += result->getTIPWords(bunch).size();
181 totalPerBunchWords += result->getTBPWords(bunch).size();
182 totalPerBunchWords += result->getTAPWords(bunch).size();
183 totalPerBunchWords += result->getTAVWords(bunch).size();
184 }
185
186 size_t rodSize = ctpDataFormat.getNumberTimeWords() // time words
187 + totalPerBunchWords // TIP/TBP/TAP/TAV words
188 + result->additionalWords().size(); // extra words
189
190 // Allocate memory
191 clearCache(eventContext);
192 uint32_t* data = newRodData(eventContext, rodSize);
193 std::vector<uint32_t> vDataWords(rodSize, 0);
194
195 size_t idx = 0;
196
197 // Time words
198 if (ctpDataFormat.getNumberTimeWords() >= 2) {
199 vDataWords[idx++] = result->timeNanoSec();
200 vDataWords[idx++] = result->timeSec();
201 } else {
202 ATH_MSG_WARNING("Unexpected number of time words: " << ctpDataFormat.getNumberTimeWords());
203 }
204
205 // TIP/TBP/TAP/TAV words per bunch
206 for (uint32_t bunch = 0; bunch < result->numberOfBunches(); ++bunch) {
207
208 // Helper lambda function
209 auto copyWords = [&](const std::vector<uint32_t>& words, const char* tag) -> StatusCode {
210 for (size_t i = 0; i < words.size(); ++i) {
211 if (idx >= vDataWords.size()) {
212 ATH_MSG_ERROR(tag << " write out-of-bounds: idx = " << idx << " >= ROD size = " << vDataWords.size());
213 return StatusCode::FAILURE;
214 }
215 vDataWords[idx++] = words[i];
216 }
217 return StatusCode::SUCCESS;
218 };
219
220 ATH_CHECK(copyWords(result->getTIPWords(bunch), "TIP"));
221 ATH_CHECK(copyWords(result->getTBPWords(bunch), "TBP"));
222 ATH_CHECK(copyWords(result->getTAPWords(bunch), "TAP"));
223 ATH_CHECK(copyWords(result->getTAVWords(bunch), "TAV"));
224 }
225
226 // Additional words
227 for (size_t i = 0; i < result->additionalWords().size(); ++i) {
228 if (idx >= vDataWords.size()) {
229 ATH_MSG_ERROR("Additional word write out-of-bounds at idx = " << idx);
230 return StatusCode::FAILURE;
231 }
232 vDataWords[idx++] = result->additionalWords()[i];
233 }
234
235 // Sanity check that all words accounted for given xAOD::CTPResult object
236 ATH_CHECK(idx == rodSize);
237
238 // Fill ROD
239 for (size_t i = 0; i < rodSize; ++i) {
240 data[i] = vDataWords[i];
241 }
242
243 // Create ROB fragment
244 vrobf.push_back(newRobFragment(eventContext, result->sourceID(), rodSize, data, m_detEvType));
246 rob->rod_minor_version(result->headerFormatVersion() & 0xffffu);
247
248 ATH_MSG_DEBUG("Encoded xAOD::CTPResult to bytestream");
249
250 return StatusCode::SUCCESS;
251}
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(x)
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
OFFLINE_FRAGMENTS_NAMESPACE_WRITE::ROBFragment ROBF
OFFLINE_FRAGMENTS_NAMESPACE::PointerType DataType
char data[hepevt_bytes_allocation_ATLAS]
Definition HepEvt.cxx:11
virtual StatusCode initialize() override
Gaudi::Property< uint16_t > m_detEvType
Gaudi::Property< std::vector< uint32_t > > m_robIds
SG::ReadHandleKey< xAOD::CTPResult > m_inKeyCTPResult
SG::WriteHandleKey< xAOD::CTPResult > m_outKeyCTPResult
virtual StatusCode convertFromBS(const std::vector< const OFFLINE_FRAGMENTS_NAMESPACE::ROBFragment * > &vrobf, const EventContext &eventContext) const override
virtual StatusCode convertToBS(std::vector< OFFLINE_FRAGMENTS_NAMESPACE_WRITE::ROBFragment * > &vrobf, const EventContext &eventContext) override
Simplified version of the C++20 std::span.
Definition span.h:61
constexpr iterator begin() noexcept
Return a begin iterator.
constexpr iterator end() noexcept
Return an end iterator.
StatusCode record(std::unique_ptr< T > data)
Record a const object to the store.
OFFLINE_FRAGMENTS_NAMESPACE_WRITE::ROBFragment WROBF
void initialize(xAOD::CTPResult &ctpRes, const uint32_t ctpVersionNumber, std::vector< uint32_t > &data, const uint32_t nExtraWords)
Initialize the object using xAOD::Header, xAOD::Trailer, and the payload data.
eformat::write::ROBFragment ROBFragment
Definition RawEvent.h:33
const DataType * PointerType
Definition RawEvent.h:25
eformat::ROBFragment< PointerType > ROBFragment
Definition RawEvent.h:27
SG::ReadCondHandle< T > makeHandle(const SG::ReadCondHandleKey< T > &key, const EventContext &ctx=Gaudi::Hive::currentContext())
Simplified version of the C++20 std::span.
MsgStream & msg
Definition testRead.cxx:32