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 uint32_t bcid = rob->rod_bc_id();
76 uint32_t trigType = rob->rod_lvl1_trigger_type();
77 uint32_t runNum = rob->rod_run_no();
78 uint32_t evtType = rob->rod_detev_type();
79
80 //
81 // Trailer information
82 //
83 DataStatus dataStatus;
84 dataStatus.rob_error = false;
85 dataStatus.rod_error = false;
86 dataStatus.status_word = 0;
87 dataStatus.status_info = 0;
88
89 try {
90 if (rob->check_rob()) ATH_MSG_VERBOSE("ROB fragment checked ok");
91 }
92 catch (std::exception const & ex) {
93 ATH_MSG_WARNING("ROB fragment not valid: " << ex.what());
94 dataStatus.rob_error = true;
95 }
96
97 try {
98 if (rob->check_rod()) ATH_MSG_VERBOSE("ROD fragment checked ok");
99 }
100 catch (std::exception const & ex) {
101 ATH_MSG_WARNING("ROD fragment not valid: " << ex.what());
102 dataStatus.rod_error = true;
103 }
104
105 // Process the status words
106 DataType status;
107 rob->rod_status(status);
108 uint32_t nstatus = rob->rod_nstatus();
109 if (msgLvl(MSG::VERBOSE)) {
110 ATH_MSG_VERBOSE("Number of status words: " << nstatus);
111 for (uint32_t i=0; i<nstatus; ++i, ++status) {
112 ATH_MSG_VERBOSE(" Status word: 0x" << MSG::hex << std::setw(8) << std::setfill('0') << *status);
113 }
114 }
115 rob->rod_status(status);
116
117 if(nstatus > 0) dataStatus.status_word = static_cast<uint32_t>(*status);
118 if(nstatus > 1) {
119 ++status;
120 dataStatus.status_info = static_cast<uint32_t>(*status);
121 }
122
123 uint32_t errStatus = dataStatus.status_word; // error status
124 uint32_t statInfo = dataStatus.status_info; // status info
125 uint32_t statPos = rob->rod_status_position(); // status info position
126
127 //
128 // Payload information
129 //
130 std::vector<uint32_t> vDataWords;
131 vDataWords.reserve(ndata);
132 if (msgLvl(MSG::VERBOSE)) {
133 ATH_MSG_VERBOSE(" Dumping xAOD::CTPResult Words:");
134 for (const uint32_t word : CxxUtils::span{it_data, ndata}) {
135 ATH_MSG_VERBOSE(" 0x" << MSG::hex << std::setfill('0') << std::setw(8) << word << MSG::dec);
136 }
137 }
138 vDataWords.assign(CxxUtils::span{it_data, ndata}.begin(), CxxUtils::span{it_data, ndata}.end());
139
140 uint32_t nExtraWords=0;
141 nExtraWords=CTPfragment::numberExtraPayloadWords(rob);
142 unsigned int ctpVersionNumber = CTPfragment::ctpFormatVersion(rob);
143
144 //
145 // Create xAOD
146 //
147 auto result = std::make_unique<xAOD::CTPResult>();
148 auto resultAux = std::make_unique<xAOD::CTPResultAuxInfo>();
149 result->setStore(resultAux.get());
150
151 // Initialize takes care of the most payload info
152 CTPResultUtils::initialize(*result, ctpVersionNumber, vDataWords, nExtraWords);
153
154 // Initialize the remaining words
155 result->setHeader(headerMarker, formatVersion, sourceID, L1ID, runNum, bcid, trigType, evtType); // Header words
156 result->setTrailer(ndata, errStatus, statInfo, nstatus, statPos); // Trailer words
157 result->setL1AcceptBunchPosition(CTPfragment::lvl1AcceptBunch(rob)); // L1A bunch position
158 result->setTurnCounter(CTPfragment::turnCounter(rob)); // Turn counter
159
160 // Check status and print warning message if issue is seen
161 std::vector<std::string> ctpResultIssues = result->checkForIssues();
162 if (!ctpResultIssues.empty()) {
163 ATH_MSG_WARNING("Found " << ctpResultIssues.size() << " CTPResult issues");
164 for (const auto& issue : ctpResultIssues) {
165 ATH_MSG_WARNING(issue);
166 }
167 }
168
169 // Record result
171 SG::WriteHandle<xAOD::CTPResult> ctpResultWriteHandle = SG::makeHandle( m_outKeyCTPResult, eventContext );
172 ATH_CHECK( ctpResultWriteHandle.record( std::move(result), std::move(resultAux) ));
173 ATH_MSG_DEBUG("Created xAOD::CTPResult from bytestream");
174
175 return StatusCode::SUCCESS;
176}
177
178
179// -----------------------------------------------------------------------------
180// xAOD->BS conversion
181// -----------------------------------------------------------------------------
182StatusCode CTPResultByteStreamTool::convertToBS(std::vector<WROBF*>& vrobf,
183 const xAOD::TrigCompositeContainer* /*tc*/,
184 const EventContext& eventContext) {
185
186 // Retrieve the xAOD::CTPResult object
188 ATH_CHECK(result.isValid());
189
190 // Get CTP version
191 unsigned int ctpVersionNumber = result->ctpVersionNumber();
192 CTPdataformatVersion ctpDataFormat(ctpVersionNumber);
193
194 // Compute rodSize from object content
195 size_t totalPerBunchWords = 0;
196 for (uint32_t bunch = 0; bunch < result->numberOfBunches(); ++bunch) {
197 totalPerBunchWords += result->getTIPWords(bunch).size();
198 totalPerBunchWords += result->getTBPWords(bunch).size();
199 totalPerBunchWords += result->getTAPWords(bunch).size();
200 totalPerBunchWords += result->getTAVWords(bunch).size();
201 }
202
203 size_t rodSize = ctpDataFormat.getNumberTimeWords() // time words
204 + totalPerBunchWords // TIP/TBP/TAP/TAV words
205 + result->additionalWords().size(); // extra words
206
207 // Allocate memory
208 clearCache(eventContext);
209 uint32_t* data = newRodData(eventContext, rodSize);
210 std::vector<uint32_t> vDataWords(rodSize, 0);
211
212 size_t idx = 0;
213
214 // Time words
215 if (ctpDataFormat.getNumberTimeWords() >= 2) {
216 vDataWords[idx++] = result->timeNanoSec();
217 vDataWords[idx++] = result->timeSec();
218 } else {
219 ATH_MSG_WARNING("Unexpected number of time words: " << ctpDataFormat.getNumberTimeWords());
220 }
221
222 // TIP/TBP/TAP/TAV words per bunch
223 for (uint32_t bunch = 0; bunch < result->numberOfBunches(); ++bunch) {
224
225 // Helper lambda function
226 auto copyWords = [&](const std::vector<uint32_t>& words, const char* tag) -> StatusCode {
227 for (size_t i = 0; i < words.size(); ++i) {
228 if (idx >= vDataWords.size()) {
229 ATH_MSG_ERROR(tag << " write out-of-bounds: idx = " << idx << " >= ROD size = " << vDataWords.size());
230 return StatusCode::FAILURE;
231 }
232 vDataWords[idx++] = words[i];
233 }
234 return StatusCode::SUCCESS;
235 };
236
237 ATH_CHECK(copyWords(result->getTIPWords(bunch), "TIP"));
238 ATH_CHECK(copyWords(result->getTBPWords(bunch), "TBP"));
239 ATH_CHECK(copyWords(result->getTAPWords(bunch), "TAP"));
240 ATH_CHECK(copyWords(result->getTAVWords(bunch), "TAV"));
241 }
242
243 // Additional words
244 for (size_t i = 0; i < result->additionalWords().size(); ++i) {
245 if (idx >= vDataWords.size()) {
246 ATH_MSG_ERROR("Additional word write out-of-bounds at idx = " << idx);
247 return StatusCode::FAILURE;
248 }
249 vDataWords[idx++] = result->additionalWords()[i];
250 }
251
252 // Sanity check that all words accounted for given xAOD::CTPResult object
253 ATH_CHECK(idx == rodSize);
254
255 // Fill ROD
256 for (size_t i = 0; i < rodSize; ++i) {
257 data[i] = vDataWords[i];
258 }
259
260 // Create ROB fragment
261 vrobf.push_back(newRobFragment(eventContext, result->sourceID(), rodSize, data, m_detEvType));
263 rob->rod_minor_version(result->headerFormatVersion() & 0xffffu);
264 rob->rod_bc_id(result->BCID());
265 rob->rod_lvl1_type(result->triggerType());
266 rob->rod_run_no(result->runNumber());
267 rob->rod_lvl1_id(result->L1ID());
268
269 ATH_MSG_DEBUG("Encoded xAOD::CTPResult to bytestream");
270
271 return StatusCode::SUCCESS;
272}
#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
OFFLINE_FRAGMENTS_NAMESPACE_WRITE::ROBFragment WROBF
size_t size() const
Number of registered mappings.
virtual StatusCode initialize() override
Gaudi::Property< uint16_t > m_detEvType
Gaudi::Property< std::vector< uint32_t > > m_robIds
SG::ReadHandleKey< xAOD::CTPResult > m_inKeyCTPResult
virtual StatusCode convertToBS(std::vector< OFFLINE_FRAGMENTS_NAMESPACE_WRITE::ROBFragment * > &vrobf, const xAOD::TrigCompositeContainer *tc, const EventContext &eventContext) override
SG::WriteHandleKey< xAOD::CTPResult > m_outKeyCTPResult
virtual StatusCode convertFromBS(const std::vector< const OFFLINE_FRAGMENTS_NAMESPACE::ROBFragment * > &vrobf, const EventContext &eventContext) const 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.
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.
const std::string print(const xAOD::CTPResult &ctpRes)
Print object content in human readable format in a string.
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())
TrigCompositeContainer_v1 TrigCompositeContainer
Declare the latest version of the container.
Simplified version of the C++20 std::span.
MsgStream & msg
Definition testRead.cxx:32