ATLAS Offline Software
Loading...
Searching...
No Matches
ITkPixelDecodingPhaseIIRDOAlg.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
4
7#include "eformat/ROBFragment.h"
8
9#define ENABLE_TIMING = true;
10#ifdef ENABLE_TIMING
11#define SCOPED_TIMER(name, msg) ITkPixelDecodingPhaseIIRDO::ScopedTimer timer_##__LINE__(name, msg)
12#else
13#define SCOPED_TIMER(name, msg)
14#endif
15
16using namespace itksw::pix::endec;
17
18ITkPixelDecodingPhaseIIRDOAlg::ITkPixelDecodingPhaseIIRDOAlg(const std::string& name, ISvcLocator* pSvcLocator) :
19 AthReentrantAlgorithm(name, pSvcLocator)
20{
21
22}
23
24
26{
28
29 ATH_CHECK(m_pixelCablingKey.initialize());
30
31 ATH_CHECK(detStore()->retrieve(m_idHelper, "PixelID"));
32
33 ATH_CHECK(m_pixelRDOKey.initialize());
34
35 //this should go into the cabling likely...
36
37 for (size_t hash = 0; hash < m_idHelper->wafer_hash_max(); hash++){
38 m_sourceIDs.push_back(m_idHelper->wafer_id(hash).get_identifier32().get_compact() | 0b00 );
39 m_sourceIDs.push_back(m_idHelper->wafer_id(hash).get_identifier32().get_compact() | 0b10 );
40 m_sourceIDs.push_back(m_idHelper->wafer_id(hash).get_identifier32().get_compact() | 0b01 );
41 m_sourceIDs.push_back(m_idHelper->wafer_id(hash).get_identifier32().get_compact() | 0b11 );
42 }
43
44 return StatusCode::SUCCESS;
45}
46
47StatusCode ITkPixelDecodingPhaseIIRDOAlg::execute(const EventContext& ctx) const
48{
49 //Timing
50 SCOPED_TIMER("ITkPixelDecodingPhaseIIRDOAlg::execute", msg());
51
52 //Retrieve the ROB IDs from cabling - dummy as of now, happens in initialize()
54 const ITkPixelCablingData* cabling = *cablingData;
55
56 //Instantiate the decoder. Doing this once per event is fine and MT-safe
57 //It needs a "callback" that implements methods required by concepts. This is
58 //the drawback of using an external code (by ITk online sw). Each of these methods
59 //is then called at appropriate places in the decoding. The decoder is configured
60 //with data format options. The callback can do whatever with the decoded hits
61 //e. g. print them on the screen or put them in a container as RDOs.
62 DataFormat fmt;
63 fmt.options.en_chip_id = true;
64 fmt.options.en_eos = true;
65 int container_list_size = 2;
66
67 auto cont_coll = std::make_unique< PhaseIIPixelRawDataContainerMT>(m_idHelper->wafer_hash_max(), container_list_size);
68 PhaseIIPixelRawDataContainerMT::ContainerPtr rdoCont = cont_coll->getNewContainerPtr();
69 PixelCallbacksPhaseIIRDO::PhaseIIRDOCallback cb(cont_coll.get(), rdoCont, m_idHelper, msg());
70
71 // Instantiate the output (PhaseII).
72 rdoCont->reserve(m_n_rdos_est);
73
74 DecCore<PixelCallbacksPhaseIIRDO::PhaseIIRDOCallback> core(fmt, cb);
75 core.initialize();
76
77 //Invoke ROBDataProviderService, fetch the concerned ROBs.
78 std::vector<const eformat::ROBFragment<const uint32_t*>*> ROBs;
79 m_robDataProviderSvc->getROBData(ctx, m_sourceIDs, ROBs);
80 ATH_MSG_DEBUG("Retrieved " << ROBs.size() << " fragments");
81
82 //First, sort the ROBs according to the module offline ID
83 //This can work because we have 1 e-link per ROB for now
84 //A new implementation will be required to do that per e-link in the future
85 // (This is pending the DetectorResourceID implementation)
86
87 std::vector<const eformat::ROBFragment<const uint32_t*>*> ROBs_sorted;
88 unsigned int ROBIndex = 0;
89 std::vector<std::pair<uint32_t, uint32_t> > rob_ind_offlineID;
90 for (const auto& ROB : ROBs){
91 ITkPixelCabling::ModuleInfo mi = cabling->offlineModuleInfo(ROB->rob_source_id());
92 rob_ind_offlineID.emplace_back(std::pair<uint32_t, uint32_t> (ROBIndex, mi.id.get_identifier32().get_compact()));
93 ROBIndex++;
94 }
95 //Lambda function to sort the vector of pairs according to the offline ID
96 std::sort(rob_ind_offlineID.begin(), rob_ind_offlineID.end(), [](auto &left, auto &right) {
97 return left.second < right.second;
98 });
99 //fill the sorted vector
100 for (const auto& robID : rob_ind_offlineID){
101 ROBs_sorted.emplace_back(ROBs[robID.first]);
102 }
103 // End of the sorting of ROBs
104
105 //We can now loop over the payloads of the ROB fragments retrieved earlier.
106 //There's as of now a little annoyance that the decoder eats 64 bit frames
107 //but the ROBs come in 32 bits. At least they have the same endian polarity.
108 //Nevertheless, we need to rearrange them.
109 std::vector<uint64_t> payload64;
110 std::array<std::vector<uint64_t>, 4> split_streams;
111
112 for (const auto& ROB : ROBs_sorted){
113 const uint32_t* payload = ROB->rod_data();
114 uint32_t length = ROB->rod_ndata();
115
116 //Translate the data into 64 bits. We know the length, so we can reserve
117 //the space to avoid reallocation. Since the frames are always 64 bits split
118 //into 32, they'll always be divisible by 2 without modulo.
119 payload64.clear();
120 payload64.resize(length / 2);
121 for (uint32_t word = 0; word < length; word += 2){
122 payload64[word / 2] = ((uint64_t)(payload[word]) << 32) | payload[word + 1];
123 }
124
125
126 //Need to set the correct offline ID for this ROB
127 ITkPixelCabling::ModuleInfo mi = cabling->offlineModuleInfo(ROB->rob_source_id());
128 cb.setOfflineID(mi.id.get_identifier32().get_compact());
129
130 //Set transform type
132
133 //If this is a merged quad, it has all 4 chips in one ROB
134 //In such case we need to decode them separately. Otherwise
135 //It's a 1:1 correspondence
136
138 cb.setChipID(0);
139 core.decode(payload64);
140 }
141 else {
142 //split according to chip ID, which is always in highest bits 1 and 2
143 for (auto &v : split_streams) v.clear();
144 for (const uint64_t& word64: payload64) split_streams[(word64 >> 61) & 0b11].push_back(word64);
145 for (uint8_t chipID = 0; chipID < 4; chipID++){
146 if (!split_streams[chipID].empty()){
147 cb.setChipID(chipID);
148 core.decode(split_streams[chipID]);
149 }
150 }
151 }
152 }
154
155
156 //The container is filled by now. We can write it to SG
158 ATH_CHECK(pixelRDOContainerHandle.record(std::move(cont_coll)));
159
160 return StatusCode::SUCCESS;
161}
162
164
165 return StatusCode::SUCCESS;
166}
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_DEBUG(x)
double length(const pvec &v)
#define SCOPED_TIMER(name, msg)
Handle class for reading from StoreGate.
const char *const fmt
static const Attributes_t empty
const ServiceHandle< StoreGateSvc > & detStore() const
An algorithm that can be simultaneously executed in multiple threads.
ServiceHandle< IROBDataProviderSvc > m_robDataProviderSvc
SG::WriteHandleKey< PhaseIIPixelRawDataContainer > m_pixelRDOKey
SG::ReadCondHandleKey< ITkPixelCablingData > m_pixelCablingKey
virtual StatusCode execute(const EventContext &ctx) const override
const Gaudi::Property< uint32_t > m_n_rdos_est
ITkPixelDecodingPhaseIIRDOAlg(const std::string &name, ISvcLocator *pSvcLocator)
typename DynamicContainerListHelper< PhaseII::PixelRawDataContainer >::ContainerPtr ContainerPtr
void setTransformType(const ITkPixelCabling::TransformType &transform)
StatusCode record(std::unique_ptr< T > data)
Record a const object to the store.
void sort(typename DataModel_detail::iterator< DVL > beg, typename DataModel_detail::iterator< DVL > end)
Specialization of sort for DataVector/List.