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 for (size_t hash = 0; hash < m_idHelper->wafer_hash_max(); hash++){
37 m_sourceIDs.push_back(m_idHelper->wafer_id(hash).get_identifier32().get_compact() | 0b00 );
38 m_sourceIDs.push_back(m_idHelper->wafer_id(hash).get_identifier32().get_compact() | 0b10 );
39 m_sourceIDs.push_back(m_idHelper->wafer_id(hash).get_identifier32().get_compact() | 0b01 );
40 m_sourceIDs.push_back(m_idHelper->wafer_id(hash).get_identifier32().get_compact() | 0b11 );
41 }
42
43 return StatusCode::SUCCESS;
44}
45
46StatusCode ITkPixelDecodingPhaseIIRDOAlg::execute(const EventContext& ctx) const
47{
48 //Timing
49 SCOPED_TIMER("ITkPixelDecodingPhaseIIRDOAlg::execute", msg());
50
51 //Retrieve the ROB IDs from cabling - dummy as of now, happens in initialize()
53 const ITkPixelCablingData* cabling = *cablingData;
54
55 //Instantiate the decoder. Doing this once per event is fine and MT-safe
56 //It needs a "callback" that implements methods required by concepts. This is
57 //the drawback of using an external code (by ITk online sw). Each of these methods
58 //is then called at appropriate places in the decoding. The decoder is configured
59 //with data format options. The callback can do whatever with the decoded hits
60 //e. g. print them on the screen or put them in a container as RDOs.
61 DataFormat fmt;
62 fmt.options.en_chip_id = true;
63 fmt.options.en_eos = true;
64 int container_list_size = 2;
65 auto cont_coll = std::make_unique< PhaseIIPixelRawDataContainerMT>(m_idHelper->wafer_hash_max(), container_list_size);
66 PhaseIIPixelRawDataContainerMT::ContainerPtr rdoCont = cont_coll->getNewContainerPtr();
67 PixelCallbacksPhaseIIRDO::PhaseIIRDOCallback cb(cont_coll.get(), rdoCont, m_idHelper);
68
69 // Instantiate the output (PhaseII).
70 rdoCont->reserve(m_n_rdos_est);
71
72 DecCore<PixelCallbacksPhaseIIRDO::PhaseIIRDOCallback> core(fmt, cb);
73 core.initialize();
74
75 //Invoke ROBDataProviderService, fetch the concerned ROBs.
76 std::vector<const eformat::ROBFragment<const uint32_t*>*> ROBs;
77 m_robDataProviderSvc->getROBData(ctx, m_sourceIDs, ROBs);
78 ATH_MSG_DEBUG("Retrieved " << ROBs.size() << " fragments");
79
80 //First, sort the ROBs according to the module offline ID
81 //This can work because we have 1 e-link per ROB for now
82 //A new implementation will be required to do that per e-link in the future
83 // (This is pending the DetectorResourceID implementation)
84
85 std::vector<const eformat::ROBFragment<const uint32_t*>*> ROBs_sorted;
86 unsigned int ROBIndex = 0;
87 std::vector<std::pair<uint32_t, uint32_t> > rob_ind_offlineID;
88 for (const auto& ROB : ROBs){
89 ITkPixelCabling::ModuleInfo mi = cabling->offlineModuleInfo(ROB->rob_source_id());
90 rob_ind_offlineID.emplace_back(std::pair<uint32_t, uint32_t> (ROBIndex, mi.id.get_identifier32().get_compact()));
91 ROBIndex++;
92 }
93 //Lambda function to sort the vector of pairs according to the offline ID
94 std::sort(rob_ind_offlineID.begin(), rob_ind_offlineID.end(), [](auto &left, auto &right) {
95 return left.second < right.second;
96 });
97 //fill the sorted vector
98 for (const auto& robID : rob_ind_offlineID){
99 ROBs_sorted.emplace_back(ROBs[robID.first]);
100 }
101 // End of the sorting of ROBs
102
103 //We can now loop over the payloads of the ROB fragments retrieved earlier.
104 //There's as of now a little annoyance that the decoder eats 64 bit frames
105 //but the ROBs come in 32 bits. At least they have the same endian polarity.
106 //Nevertheless, we need to rearrange them.
107 std::vector<uint64_t> payload64;
108 std::array<std::vector<uint64_t>, 4> split_streams;
109
110 for (const auto& ROB : ROBs_sorted){
111 const uint32_t* payload = ROB->rod_data();
112 uint32_t length = ROB->rod_ndata();
113
114
115 //Translate the data into 64 bits. We know the length, so we can reserve
116 //the space to avoid reallocation. Since the frames are always 64 bits split
117 //into 32, they'll always be divisible by 2 without modulo.
118 payload64.clear();
119 payload64.resize(length / 2);
120 for (uint32_t word = 0; word < length; word += 2){
121 payload64[word / 2] = ((uint64_t)(payload[word]) << 32) | payload[word + 1];
122 }
123
124
125 //Need to set the correct offline ID for this ROB
126 ITkPixelCabling::ModuleInfo mi = cabling->offlineModuleInfo(ROB->rob_source_id());
127 cb.setOfflineID(mi.id.get_identifier32().get_compact());
128
129 //Set transform type
131
132 //If this is a merged quad, it has all 4 chips in one ROB
133 //In such case we need to decode them separately. Otherwise
134 //It's a 1:1 correspondence
135
137 cb.setChipID(0);
138 core.decode(payload64);
139 }
140 else {
141 //split according to chip ID, which is always in highest bits 1 and 2
142 for (auto &v : split_streams) v.clear();
143 for (const uint64_t& word64: payload64) split_streams[(word64 >> 61) & 0b11].push_back(word64);
144 for (uint8_t chipID = 0; chipID < 4; chipID++){
145 if (!split_streams[chipID].empty()){
146 cb.setChipID(chipID);
147 core.decode(split_streams[chipID]);
148 }
149 }
150 }
152 }
153
154
155 //The container is filled by now. We can write it to SG
157 ATH_CHECK(pixelRDOContainerHandle.record(std::move(cont_coll)));
158
159 return StatusCode::SUCCESS;
160}
161
163
164 return StatusCode::SUCCESS;
165}
#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.