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
126 //
127 // Payload information
128 //
129 std::vector<uint32_t> vDataWords;
130 vDataWords.reserve(ndata);
131 if (msgLvl(MSG::VERBOSE)) {
132 ATH_MSG_VERBOSE(" Dumping xAOD::CTPResult Words:");
133 for (const uint32_t word : CxxUtils::span{it_data, ndata}) {
134 ATH_MSG_VERBOSE(" 0x" << MSG::hex << std::setfill('0') << std::setw(8) << word << MSG::dec);
135 }
136 }
137 vDataWords.assign(CxxUtils::span{it_data, ndata}.begin(), CxxUtils::span{it_data, ndata}.end());
138
139 uint32_t nExtraWords=0;
140 nExtraWords=CTPfragment::numberExtraPayloadWords(rob);
141 unsigned int ctpVersionNumber = CTPfragment::ctpFormatVersion(rob);
142
143 //
144 // Create xAOD
145 //
146 auto result = std::make_unique<xAOD::CTPResult>();
147 auto resultAux = std::make_unique<xAOD::CTPResultAuxInfo>();
148 result->setStore(resultAux.get());
149
150 // Initialize takes care of the most payload info
151 CTPResultUtils::initialize(*result, ctpVersionNumber, vDataWords, nExtraWords);
152
153 // Initialize the remaining words
154 result->setHeader(headerMarker, formatVersion, sourceID, L1ID, runNum, bcid, trigType, evtType); // Header words
155 result->setTrailer(ndata, errStatus, statInfo); // Trailer words
156 result->setL1AcceptBunchPosition(CTPfragment::lvl1AcceptBunch(rob)); // L1A bunch position
157 result->setTurnCounter(CTPfragment::turnCounter(rob)); // Turn counter
158
159 // Record result
161 SG::WriteHandle<xAOD::CTPResult> ctpResultWriteHandle = SG::makeHandle( m_outKeyCTPResult, eventContext );
162 ATH_CHECK( ctpResultWriteHandle.record( std::move(result), std::move(resultAux) ));
163 ATH_MSG_DEBUG("Created xAOD::CTPResult from bytestream");
164
165 return StatusCode::SUCCESS;
166}
167
168
169// -----------------------------------------------------------------------------
170// xAOD->BS conversion
171// -----------------------------------------------------------------------------
172StatusCode CTPResultByteStreamTool::convertToBS(std::vector<WROBF*>& vrobf, const EventContext& eventContext) {
173
174 // Retrieve the xAOD::CTPResult object
176 ATH_CHECK(result.isValid());
177
178 // Get CTP version
179 unsigned int ctpVersionNumber = result->ctpVersionNumber();
180 CTPdataformatVersion ctpDataFormat(ctpVersionNumber);
181
182 // Compute rodSize from object content
183 size_t totalPerBunchWords = 0;
184 for (uint32_t bunch = 0; bunch < result->numberOfBunches(); ++bunch) {
185 totalPerBunchWords += result->getTIPWords(bunch).size();
186 totalPerBunchWords += result->getTBPWords(bunch).size();
187 totalPerBunchWords += result->getTAPWords(bunch).size();
188 totalPerBunchWords += result->getTAVWords(bunch).size();
189 }
190
191 size_t rodSize = ctpDataFormat.getNumberTimeWords() // time words
192 + totalPerBunchWords // TIP/TBP/TAP/TAV words
193 + result->additionalWords().size(); // extra words
194
195 // Allocate memory
196 clearCache(eventContext);
197 uint32_t* data = newRodData(eventContext, rodSize);
198 std::vector<uint32_t> vDataWords(rodSize, 0);
199
200 size_t idx = 0;
201
202 // Time words
203 if (ctpDataFormat.getNumberTimeWords() >= 2) {
204 vDataWords[idx++] = result->timeNanoSec();
205 vDataWords[idx++] = result->timeSec();
206 } else {
207 ATH_MSG_WARNING("Unexpected number of time words: " << ctpDataFormat.getNumberTimeWords());
208 }
209
210 // TIP/TBP/TAP/TAV words per bunch
211 for (uint32_t bunch = 0; bunch < result->numberOfBunches(); ++bunch) {
212
213 // Helper lambda function
214 auto copyWords = [&](const std::vector<uint32_t>& words, const char* tag) -> StatusCode {
215 for (size_t i = 0; i < words.size(); ++i) {
216 if (idx >= vDataWords.size()) {
217 ATH_MSG_ERROR(tag << " write out-of-bounds: idx = " << idx << " >= ROD size = " << vDataWords.size());
218 return StatusCode::FAILURE;
219 }
220 vDataWords[idx++] = words[i];
221 }
222 return StatusCode::SUCCESS;
223 };
224
225 ATH_CHECK(copyWords(result->getTIPWords(bunch), "TIP"));
226 ATH_CHECK(copyWords(result->getTBPWords(bunch), "TBP"));
227 ATH_CHECK(copyWords(result->getTAPWords(bunch), "TAP"));
228 ATH_CHECK(copyWords(result->getTAVWords(bunch), "TAV"));
229 }
230
231 // Additional words
232 for (size_t i = 0; i < result->additionalWords().size(); ++i) {
233 if (idx >= vDataWords.size()) {
234 ATH_MSG_ERROR("Additional word write out-of-bounds at idx = " << idx);
235 return StatusCode::FAILURE;
236 }
237 vDataWords[idx++] = result->additionalWords()[i];
238 }
239
240 // Sanity check that all words accounted for given xAOD::CTPResult object
241 ATH_CHECK(idx == rodSize);
242
243 // Fill ROD
244 for (size_t i = 0; i < rodSize; ++i) {
245 data[i] = vDataWords[i];
246 }
247
248 // Create ROB fragment
249 vrobf.push_back(newRobFragment(eventContext, result->sourceID(), rodSize, data, m_detEvType));
251 rob->rod_minor_version(result->headerFormatVersion() & 0xffffu);
252 rob->rod_bc_id(result->BCID());
253 rob->rod_lvl1_type(result->triggerType());
254 rob->rod_run_no(result->runNumber());
255 rob->rod_lvl1_id(result->L1ID());
256
257 ATH_MSG_DEBUG("Encoded xAOD::CTPResult to bytestream");
258
259 return StatusCode::SUCCESS;
260}
#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
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.
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())
Simplified version of the C++20 std::span.
MsgStream & msg
Definition testRead.cxx:32