Line data Source code
1 : /**
2 : * @file FelixReaderModule.cc FelixReaderModule DAQModule implementation
3 : *
4 : * This is part of the DUNE DAQ Application Framework, copyright 2020.
5 : * Licensing/copyright details are in the COPYING file that you should have
6 : * received with this code.
7 : */
8 : #include "confmodel/Connection.hpp"
9 : #include "confmodel/QueueWithSourceId.hpp"
10 : #include "confmodel/DetDataSender.hpp"
11 : #include "confmodel/DetectorStream.hpp"
12 : #include "confmodel/GeoId.hpp"
13 :
14 : #include "appmodel/DataReaderModule.hpp"
15 : #include "appmodel/FelixDetectorToDaqConnection.hpp"
16 : #include "appmodel/FelixInterface.hpp"
17 : #include "appmodel/FelixDataSender.hpp"
18 :
19 : #include "CreateElink.hpp"
20 : #include "FelixReaderModule.hpp"
21 : #include "FelixIssues.hpp"
22 :
23 : #include "logging/Logging.hpp"
24 :
25 : #include "flxcard/FlxException.h"
26 :
27 : #include <chrono>
28 : #include <memory>
29 : #include <string>
30 : #include <thread>
31 : #include <utility>
32 : #include <vector>
33 :
34 : /**
35 : * @brief Name used by TRACE TLOG calls from this source file
36 : */
37 : #define TRACE_NAME "FelixReaderModule" // NOLINT
38 :
39 : /**
40 : * @brief TRACE debug levels used in this source file
41 : */
42 : enum
43 : {
44 : TLVL_ENTER_EXIT_METHODS = 5,
45 : TLVL_WORK_STEPS = 10,
46 : TLVL_BOOKKEEPING = 15
47 : };
48 :
49 : namespace dunedaq {
50 : namespace flxlibs {
51 :
52 0 : FelixReaderModule::FelixReaderModule(const std::string& name)
53 : : DAQModule(name)
54 0 : , m_configured(false)
55 0 : , m_card_id(0)
56 0 : , m_logical_unit(0)
57 0 : , m_links_enabled()
58 0 : , m_num_links(0)
59 0 : , m_block_size(0)
60 0 : , m_block_router(nullptr)
61 : //, block_ptr_sinks_{ }
62 :
63 : {
64 :
65 0 : register_command("conf", &FelixReaderModule::do_configure);
66 0 : register_command("start", &FelixReaderModule::do_start);
67 0 : register_command("stop_trigger_sources", &FelixReaderModule::do_stop);
68 0 : }
69 :
70 : void
71 0 : FelixReaderModule::init(const std::shared_ptr<appfwk::ConfigurationManager> mcfg)
72 : {
73 : //auto ini = args.get<appfwk::app::ModInit>();
74 :
75 0 : auto modconf = mcfg->get_dal<appmodel::DataReaderModule>(get_name());
76 0 : auto session = mcfg->get_session();
77 :
78 0 : if (modconf->get_connections().size() != 1) {
79 0 : throw InitializationError(ERS_HERE, "FLX Data Reader does not have a unique associated flx_if");
80 : }
81 :
82 0 : const auto det_conn = modconf->get_connections()[0]->cast<appmodel::FelixDetectorToDaqConnection>();
83 :
84 : // Create a source_id to local elink map
85 0 : std::map<uint, uint> src_id_to_elink_map;
86 0 : auto flx_if = det_conn->receiver()->cast<appmodel::FelixInterface>();
87 0 : auto det_senders = det_conn->get_felix_senders();
88 :
89 0 : if (!det_senders.empty()) { // Redundant test as schema forbids 0 senders
90 0 : for (const auto& data_sender : det_senders) {
91 : // Check if sender enabled
92 0 : if (data_sender->is_disabled(*session)) {
93 0 : continue;
94 : }
95 0 : for (const auto& stream : data_sender->get_streams()) {
96 0 : src_id_to_elink_map[stream->get_source_id()] = data_sender->get_link();
97 : }
98 :
99 0 : TLOG(TLVL_BOOKKEEPING) << "Registering link: " << (uint32_t)data_sender->get_link() << " / " << m_links_enabled.size();
100 0 : m_links_enabled.push_back(data_sender->get_link());
101 :
102 : }
103 : }
104 0 : m_num_links = m_links_enabled.size();
105 0 : if (flx_if != nullptr) {
106 0 : m_card_wrapper = std::make_unique<CardWrapper>(flx_if, m_links_enabled);
107 0 : m_card_id = flx_if->get_card();
108 0 : m_logical_unit = flx_if->get_slr();
109 0 : m_block_size = flx_if->get_dma_block_size() * m_1kb_block_size;
110 0 : m_chunk_trailer_size = flx_if->get_chunk_trailer_size();
111 : }
112 :
113 :
114 0 : for (auto qi : modconf->get_outputs()) {
115 0 : auto q_with_id = qi->cast<confmodel::QueueWithSourceId>();
116 0 : if (q_with_id == nullptr) continue;
117 0 : TLOG_DEBUG(TLVL_WORK_STEPS) << ": CardReader output queue is " << q_with_id->UID();
118 0 : TLOG_DEBUG(TLVL_WORK_STEPS) << "Creating ElinkModel for target queue: " << q_with_id->UID() << " DLH number: " << q_with_id->get_source_id();
119 0 : auto elink = src_id_to_elink_map[q_with_id->get_source_id()];
120 0 : auto link_ptr = m_elinks[elink] = createElinkModel(q_with_id->UID());
121 0 : if ( ! link_ptr ) {
122 0 : ers::fatal(InitializationError(ERS_HERE, "CreateElink failed to provide an appropriate model for queue!"));
123 : }
124 0 : register_node( q_with_id->UID(), link_ptr);
125 0 : link_ptr->init(m_block_queue_capacity);
126 : //m_elinks[q_with_id->get_source_id()]->init(args, m_block_queue_capacity);
127 0 : }
128 :
129 : // Router function of block to appropriate ElinkHandlers
130 0 : m_block_router = [&](uint64_t block_addr) { // NOLINT
131 : // block_counter++;
132 0 : const auto* block = const_cast<felix::packetformat::block*>(
133 0 : felix::packetformat::block_from_bytes(reinterpret_cast<const char*>(block_addr)) // NOLINT
134 : );
135 0 : auto elink = block->elink;
136 0 : if (m_elinks.count(elink) != 0) {
137 0 : m_elinks[elink]->queue_in_block_address(block_addr);
138 : } else {
139 : // Really bad -> unexpeced ELINK ID in Block.
140 : // This check is needed in order to avoid dynamically add thousands
141 : // of ELink parser implementations on the fly, in case the data
142 : // corruption is extremely severe.
143 : //
144 : // Possible causes:
145 : // -> enabled links that don't connect to anything
146 : // -> unexpected format (fw/sw version missmatch)
147 : // -> data corruption from FE
148 : // -> data corruption from CR (really rare, last possible cause)
149 :
150 : // NO TLOG_DEBUG, but should count and periodically report corrupted DMA blocks.
151 : }
152 0 : };
153 :
154 : // Set function for the CardWrapper's block processor.
155 0 : m_card_wrapper->set_block_addr_handler(m_block_router);
156 0 : }
157 :
158 : void
159 0 : FelixReaderModule::do_configure(const CommandData_t& /*args*/)
160 : {
161 :
162 0 : bool is_32b_trailer = false;
163 :
164 0 : TLOG(TLVL_BOOKKEEPING) << "Number of felix links specified in configuration: " << m_links_enabled.size();
165 0 : TLOG(TLVL_BOOKKEEPING) << "Number of data link handlers: " << m_elinks.size();
166 :
167 : // Config checks
168 0 : if (m_num_links != m_elinks.size()) {
169 0 : ers::fatal(ElinkConfigurationInconsistency(ERS_HERE, m_links_enabled.size()));
170 : }
171 0 : if (m_block_size % m_1kb_block_size != 0) {
172 0 : ers::fatal(BlockSizeConfigurationInconsistency(ERS_HERE, m_block_size));
173 0 : } else if (m_block_size != m_1kb_block_size && m_chunk_trailer_size != m_32b_trailer_size) {
174 0 : ers::fatal(BlockSizeConfigurationInconsistency(ERS_HERE, m_block_size));
175 0 : } else if (m_chunk_trailer_size == m_32b_trailer_size) {
176 0 : is_32b_trailer = true;
177 : }
178 :
179 : // Configure components
180 0 : TLOG(TLVL_WORK_STEPS) << "Card ID: " << m_card_id;
181 0 : TLOG(TLVL_WORK_STEPS) << "Configuring components with Block size:" << m_block_size
182 0 : << " & trailer size: " << m_chunk_trailer_size;
183 0 : m_card_wrapper->configure();
184 : // get linkids defined by queues
185 0 : std::vector<int> linkids;
186 0 : for(auto& [id, elink] : m_elinks) {
187 0 : linkids.push_back(id);
188 : }
189 : // loop through all elinkmodels, change the linkids to link tags and configure
190 0 : for (unsigned i = 0; i < m_num_links; ++i) {
191 0 : auto elink = m_elinks.extract(linkids[i]);
192 0 : auto tag = m_links_enabled[i] * m_elink_multiplier;
193 0 : elink.key() = tag;
194 0 : m_elinks.insert(std::move(elink));
195 0 : m_elinks[tag]->set_ids(m_card_id, m_logical_unit, m_links_enabled[i], tag);
196 0 : m_elinks[tag]->conf(m_block_size, is_32b_trailer);
197 0 : }
198 0 : }
199 :
200 : void
201 0 : FelixReaderModule::do_start(const CommandData_t& /*args*/)
202 : {
203 0 : m_card_wrapper->start();
204 0 : for (auto& [tag, elink] : m_elinks) {
205 0 : elink->start();
206 : }
207 0 : }
208 :
209 : void
210 0 : FelixReaderModule::do_stop(const CommandData_t& /*args*/)
211 : {
212 0 : m_card_wrapper->stop();
213 0 : for (auto& [tag, elink] : m_elinks) {
214 0 : elink->stop();
215 : }
216 0 : }
217 :
218 :
219 : } // namespace flxlibs
220 : } // namespace dunedaq
221 :
222 0 : DEFINE_DUNE_DAQ_MODULE(dunedaq::flxlibs::FelixReaderModule)
|