ATLAS Offline Software
Loading...
Searching...
No Matches
ITkPixelDecodingAlg.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2024 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) ITkPixelDecoding::ScopedTimer timer_##__LINE__(name, msg)
12#else
13#define SCOPED_TIMER(name, msg)
14#endif
15
16
17using namespace itksw::pix::endec;
18
19ITkPixelDecodingAlg::ITkPixelDecodingAlg(const std::string& name, ISvcLocator* pSvcLocator) :
20 AthReentrantAlgorithm(name, pSvcLocator)
21{
22
23}
24
25
27{
29
30 ATH_CHECK(m_pixelCablingKey.initialize());
31
32 ATH_CHECK(detStore()->retrieve(m_idHelper, "PixelID"));
33
34 ATH_CHECK(m_pixelRDOKey.initialize());
35
36 //this should go into the cabling likely...
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 ITkPixelDecodingAlg::execute(const EventContext& ctx) const
48{
49 //Timing
50 SCOPED_TIMER("ITkPixelDecodingAlg::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 output. RN using the old pixel RDO, nothing fancier than that
57 std::unique_ptr<PixelRDO_Container> rdoCont = std::make_unique<PixelRDO_Container>(m_idHelper->wafer_hash_max());
58
59 //Instantiate the decoder. Doing this once per event is fine and MT-safe
60 //It needs a "callback" that implements methods required by concepts. This is
61 //the drawback of using an external code (by ITk online sw). Each of these methods
62 //is then called at appropriate places in the decoding. The decoder is configured
63 //with data format options. The callback can do whatever with the decoded hits
64 //e. g. print them on the screen or put them in a container as RDOs.
65 DataFormat fmt;
66 fmt.options.en_chip_id = true;
67 fmt.options.en_eos = true;
68 PixelCallbacks::RDOCallback cb(rdoCont.get(), m_idHelper);
69 DecCore<PixelCallbacks::RDOCallback> core(fmt, cb);
70 core.initialize();
71
72 //Invoke ROBDataProviderService, fetch the concerned ROBs.
73 std::vector<const eformat::ROBFragment<const uint32_t*>*> ROBs;
74 m_robDataProviderSvc->getROBData(ctx, m_sourceIDs, ROBs);
75 ATH_MSG_DEBUG("Retrieved " << ROBs.size() << " fragments");
76
77 //We can now loop over the payloads of the ROB fragments retrieved earlier.
78 //There's as of now a little annoyance that the decoder eats 64 bit frames
79 //but the ROBs come in 32 bits. At least they have the same endian polarity.
80 //Nevertheless, we need to rearrange them.
81 std::vector<uint64_t> payload64;
82 std::array<std::vector<uint64_t>, 4> split_streams;
83 for (const auto& ROB : ROBs){
84 const uint32_t* payload = ROB->rod_data();
85 uint32_t length = ROB->rod_ndata();
86
87 //Translate the data into 64 bits. We know the length, so we can reserve
88 //the space to avoid reallocation. Since the frames are always 64 bits split
89 //into 32, they'll always be divisible by 2 without modulo.
90 payload64.clear();
91 payload64.resize(length / 2);
92 for (uint32_t word = 0; word < length; word += 2){
93 payload64[word / 2] = ((uint64_t)(payload[word]) << 32) | payload[word + 1];
94 }
95
96
97 //Need to set the correct offline ID for this ROB
98 ITkPixelCabling::ModuleInfo mi = cabling->offlineModuleInfo(ROB->rob_source_id());
99 cb.setOfflineID(mi.id.get_identifier32().get_compact());
100
101 //Set transform type
103
104 //If this is a merged quad, it has all 4 chips in one ROB
105 //In such case we need to decode them separately. Otherwise
106 //It's a 1:1 correspondence
107
109 cb.setChipID(0);
110 core.decode(payload64);
111 }
112 else {
113 //split according to chip ID, which is always in highest bits 1 and 2
114 for (auto &v : split_streams) v.clear();
115 for (const uint64_t& word64: payload64) split_streams[(word64 >> 61) & 0b11].push_back(word64);
116 for (uint8_t chipID = 0; chipID < 4; chipID++){
117 if (!split_streams[chipID].empty()){
118 cb.setChipID(chipID);
119 core.decode(split_streams[chipID]);
120 }
121 }
122 }
123 }
124
125 //The container is filled by now. We can write it to SG
126 SG::WriteHandle<PixelRDO_Container> pixelRDOContainerHandle(m_pixelRDOKey, ctx);
127 ATH_CHECK(pixelRDOContainerHandle.record(std::move(rdoCont)));
128
129 return StatusCode::SUCCESS;
130}
131
133 return StatusCode::SUCCESS;
134}
#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.
virtual StatusCode initialize() override
ServiceHandle< IROBDataProviderSvc > m_robDataProviderSvc
std::vector< uint32_t > m_sourceIDs
virtual StatusCode finalize() override
virtual StatusCode execute(const EventContext &ctx) const override
SG::WriteHandleKey< PixelRDO_Container > m_pixelRDOKey
const PixelID * m_idHelper
SG::ReadCondHandleKey< ITkPixelCablingData > m_pixelCablingKey
ITkPixelDecodingAlg(const std::string &name, ISvcLocator *pSvcLocator)
void setChipID(const uint8_t &chipID)
void setOfflineID(const uint32_t &offlineID)
void setTransformType(const ITkPixelCabling::TransformType &transform)
StatusCode record(std::unique_ptr< T > data)
Record a const object to the store.