REDAC HybridController
Firmware for LUCIDAC/REDAC Teensy
Loading...
Searching...
No Matches
carrier.cpp
Go to the documentation of this file.
1// Copyright (c) 2024 anabrid GmbH
2// Contact: https://www.anabrid.com/licensing/
3// SPDX-License-Identifier: MIT OR GPL-2.0-or-later
4
5#include "pb_decode.h"
6#include "redac/calibration.h"
7#include "run/run_manager.h"
8
9#include <entity/visitor.h>
10#include <lucidac/lucidac.h>
11#include <mode/mode.h>
12#include <span>
13#include <net/settings.h>
14#include <redac/redac.h>
15#include <utils/is_number.h>
16
17carrier::Carrier::Carrier(std::vector<platform::Cluster> clusters, carrier::Carrier_HAL *hardware)
18 : Entity("", hardware), hardware(hardware), clusters(std::move(clusters)) {
19 classifier.class_enum = CLASS_;
20}
21
22carrier::Carrier *carrier::Carrier::from_entity_classifier(entities::EntityClassifier classifier,
23 __attribute__((__unused__))
24 const bus::addr_t block_address) {
25 if (!classifier or classifier.class_enum != entities::EntityClass::CARRIER)
26 return nullptr;
27
28 auto type = classifier.type_as<TYPES>();
29 switch (type) {
30 case TYPES::UNKNOWN:
31 // This is already checked by !classifier above
32 return nullptr;
33 case TYPES::LUCIDAC:
34 return platform::LUCIDAC::from_entity_classifier(classifier, block_address);
35 case TYPES::mREDAC:
36 return platform::REDAC::from_entity_classifier(classifier, block_address);
37 }
38 // Any unknown value results in a nullptr here.
39 // Adding default case to switch suppresses warnings about missing cases.
40 return nullptr;
41}
42
43carrier::Carrier *carrier::Carrier::detect() {
44 return entities::detect<carrier::Carrier>(bus::address_from_tuple(bus::CARRIER_BADDR, 0));
45}
46
47UnitResult carrier::Carrier::better_init() {
48 LOG(ANABRID_DEBUG_INIT, __PRETTY_FUNCTION__);
49
50 entity_id = net::StartupConfig::get().mac;
51
52 if (entity_id.empty())
53 return UnitResult::err("Cannot determine Carrier MAC");
54
55 // Detect CTRL-block
56 ctrl_block = entities::detect<blocks::CTRLBlock>(bus::address_from_tuple(bus::CTRL_BLOCK_BADDR, 0));
57 if (!ctrl_block) {
58 return UnitResult::err("Missing CTRL Block");
59 }
60
61 for (auto &cluster : clusters) {
62 TRY_TRUE(cluster.init());
63 }
64
65 reset(entities::ResetAction::EVERYTHING);
66
67 return UnitResult::ok();
68}
69
70uint8_t carrier::Carrier::get_active_adc_channel_range() const{
71 uint8_t num_adc_channels = 0;
72 for(size_t idx = 0; idx < m_adc_channels.size(); idx++){
73 if(m_adc_channels[idx].src != ADCChannel::DISABLED)
74 num_adc_channels = idx + 1;
75 }
76 return num_adc_channels;
77}
78
79std::vector<entities::Entity *> carrier::Carrier::get_child_entities() {
80 std::vector<entities::Entity *> children;
81 for (auto &cluster : clusters) {
82 children.push_back(&cluster);
83 }
84 if (ctrl_block)
85 children.push_back(ctrl_block);
86 return children;
87}
88
89entities::Entity *carrier::Carrier::get_child_entity(std::string_view child_id) {
90 auto opt_int = utils::view_to_number(child_id);
91 if (opt_int.has_value()) {
92 auto cluster_idx = opt_int.value();
93 if (cluster_idx < 0 or clusters.size() < cluster_idx)
94 return nullptr;
95 return &clusters[cluster_idx];
96 }
97 if (child_id == "CTRL")
98 return ctrl_block;
99 if (child_id.size() == 17)
100 return this;
101 return nullptr;
102}
103
104ConfigResult carrier::Carrier::config(const pb_Item &item) {
105 if (TRY(Entity::config(item)))
106 return ConfigResult::ok(true);
107
108 if (!hardware)
109 return ConfigResult::err("Carrier cannot be configured without hardware");
110
111 if (item.which_kind == pb_Item_adc_config_tag) {
112 auto& carrier_config = item.kind.adc_config;
113
114 if (carrier_config.channels_count > m_adc_channels.size())
115 return ConfigResult::err("Channel count too large");
116
117 m_adc_channels.fill(ADCChannel());
118 for (size_t idx = 0; idx < carrier_config.channels_count; ++idx) {
119 auto& channel = m_adc_channels[idx];
120
121 auto& config_channel = carrier_config.channels[idx];
122 channel.src = config_channel.idx;
123 channel.gain = config_channel.gain;
124 channel.offset = config_channel.offset;
125 channel.probe = config_channel.probe;
126 }
127
128 if (!hardware->write_adc_bus_mux(m_adc_channels))
129 return ConfigResult::err("Could not configure ACLs from configuration");
130
131 return ConfigResult::ok(true);
132 }
133
134 return ConfigResult::ok(false);
135}
136
137void carrier::Carrier::extract(entities::ExtractVisitor &collector) {
138 Entity::extract(collector);
139
140 if (collector.include_specification()) {
141 auto& entity_spec = collector.create(pb_Item_entity_specification_tag).kind.entity_specification;
142 entity_spec.has_entity = true;
143 encode_classifier(entity_spec.entity);
144 }
145
146 if (collector.include_configuration()) {
147 auto& item = collector.create(pb_Item_adc_config_tag);
148 auto& carrier_config = item.kind.adc_config = pb_AdcConfig_init_zero;
149 for (auto & channel : m_adc_channels) {
150 if (channel.src == ADCChannel::DISABLED) continue;
151 auto& pb_channel = carrier_config.channels[carrier_config.channels_count++];
152 pb_channel.idx = static_cast<uint32_t>(channel.src);
153 pb_channel.gain = channel.gain;
154 pb_channel.offset = channel.offset;
155 pb_channel.probe = channel.probe;
156 }
157 }
158}
159
160bool carrier::Carrier::write_to_hardware() {
161 int cluster_index = 1;
162 for (auto &cluster : clusters) {
163 auto result = cluster.write_to_hardware();
164 if (!result) {
165 return UnitResult::err("Cluster " + std::to_string(cluster_index) + " write failed.");
166 }
167 cluster_index++;
168 }
169
170 return write_adcs_to_hardware();
171}
172
173UnitResult carrier::Carrier::calibrate_offsets() {
174 LOG(ANABRID_DEBUG_CALIBRATION, __PRETTY_FUNCTION__);
175
176 for (auto &cluster : clusters)
177 TRY(cluster.calibrate_offsets());
178
179 LOG(ANABRID_DEBUG_CALIBRATION, __PRETTY_FUNCTION__);
180 return UnitResult::ok();
181}
182
183UnitResult carrier::Carrier::calibrate_routes() {
184 //entities::Setup setup;
185 //entities::ExtractSettings settings{
186 // .include_configuration = true
187 //};
188 //setup.extract(this, settings);
189 auto result = calibrate_routes_raw();
190 //setup.apply(this, true);
191 return result;
192}
193
194// This calibration function is working for a generic array of clusters that don't have any shared connections.
195// LUCIDAC relies on this function, an mREDAC overwrites this function, as it can have cross cluster
196// connections.
197UnitResult carrier::Carrier::calibrate_routes_raw() {
198 LOG(ANABRID_DEBUG_CALIBRATION, __PRETTY_FUNCTION__);
199
200 bool gain_correction_exceeding = false;
201 for (auto &cluster : clusters) {
202 LOG_ANABRID_DEBUG_CALIBRATION(
203 ("Calibrating routes in cluster " + std::to_string(cluster.get_cluster_idx())).c_str());
204 // Save and change ADC bus selection
205 auto old_adcbus = ctrl_block->get_adc_bus();
206 auto old_adc_channels = get_adc_channels();
207
208 reset_adc_channels();
209
210 ctrl_block->set_adc_bus(blocks::CTRLBlock::ADCBus::ADC);
211 TRY_TRUE(ctrl_block->write_to_hardware());
212
213 // Save current U-block transmission modes and set them to zero
214 LOG_ANABRID_DEBUG_CALIBRATION("Starting calibration");
215 auto old_transmission_modes = cluster.ublock->get_all_transmission_modes();
216 auto old_reference_magnitude = cluster.ublock->get_reference_magnitude();
217
218 // Enable reference signal for calibration
219 LOG_ANABRID_DEBUG_CALIBRATION("Enable u-block reference");
220 cluster.ublock->change_all_transmission_modes(blocks::UBlock::Transmission_Mode::POS_REF);
221 TRY_TRUE(cluster.ublock->write_to_hardware());
222
223 // Save C-Block factors
224 LOG_ANABRID_DEBUG_CALIBRATION("Reset c-block");
225 auto old_c_block_factors = cluster.cblock->get_factors();
226 cluster.cblock->set_factors({});
227 TRY_TRUE (cluster.cblock->write_to_hardware());
228
229 // Find an M block usable for its identity lanes
230 blocks::MBlock *id_block = nullptr;
231 if (cluster.m0block && cluster.m0block->has_id_lanes())
232 id_block = cluster.m0block;
233
234 if (!id_block && cluster.m1block && cluster.m1block->has_id_lanes())
235 id_block = cluster.m1block;
236
237 if (!id_block) {
238 return UnitResult::err("No M Block with ID Lanes found, calibration impossible!");
239 }
240
241 uint8_t id_in_lane = 0, id_out_lane = 4;
242 for (auto i = 0; i < id_block->ID_OUTPUT_CONNECTIONS().size(); i++) {
243 if (id_block->ID_OUTPUT_CONNECTIONS()[i] != -1) {
244 id_out_lane = id_block->slot_to_global_io_index(i);
245 id_in_lane = id_block->slot_to_global_io_index(id_block->ID_OUTPUT_CONNECTIONS()[i]);
246 break;
247 }
248 }
249
250 std::array<std::vector<uint8_t>, blocks::IBlock::NUM_OUTPUTS> old_i_block_connections;
251 for (auto i_out_idx : blocks::IBlock::OUTPUT_IDX_RANGE()) {
252 for (auto i_in_idx : blocks::IBlock::INPUT_IDX_RANGE()) {
253
254 // Only do something is this lane is used in the original I-block configuration
255 if (!cluster.iblock->is_connected(i_in_idx, i_out_idx))
256 continue;
257
258 // If we don't have a complete connection through the u block, we don't need / we can't calibrate this
259 // route from here
260 if (!cluster.ublock->is_output_connected(i_in_idx))
261 continue;
262
263 // Store this i block input to output connection
264 old_i_block_connections[i_out_idx].emplace_back(i_in_idx);
265 }
266 }
267
268 LOG_ANABRID_DEBUG_CALIBRATION("Reset i-block");
269 cluster.iblock->reset_outputs();
270 TRY_TRUE(cluster.iblock->write_to_hardware());
271
272 // Now we restore each summation isolated from the rest and route each summation output / i block output to
273 // an M-Mul block
274 for (auto i_out_idx : blocks::IBlock::OUTPUT_IDX_RANGE()) {
275 for (auto i_in_idx : old_i_block_connections[i_out_idx])
276 TRY(cluster.iblock->connect(i_in_idx, id_in_lane));
277
278 TRY_TRUE(cluster.iblock->write_to_hardware());
279
280 // Now switch through all relevant input signals and put one of them to 1.0
281 for (auto i_in_idx : old_i_block_connections[i_out_idx]) {
282 // Setup measure path
283 TRY(set_adc_channel(0, id_out_lane));
284 if (!hardware->write_adc_bus_mux(m_adc_channels))
285 return UnitResult::err("Writing adcs failed!");
286
287 // Depending on whether upscaling is enabled for this lane, we apply +1 or +0.1 reference
288 // This is done on all lanes (but no other I-block connection exists, so no other current flows)
289 bool upscaled_channel = cluster.iblock->get_upscaling(i_in_idx);
290 cluster.ublock->change_reference_magnitude(upscaled_channel
291 ? blocks::UBlock::Reference_Magnitude::ONE_TENTH
292 : blocks::UBlock::Reference_Magnitude::ONE);
293 TRY_TRUE(cluster.ublock->write_to_hardware());
294
295 // First measure the offset of each measuring lane. The SH Block can not calibrate offsets that occur
296 // after himself so we need to take care of that.
297 TRY(cluster.cblock->set_factor(i_in_idx, 0.0f));
298 TRY(cluster.cblock->set_gain_correction(i_in_idx, 1.0f));
299 TRY_TRUE(cluster.cblock->write_to_hardware());
300
301 // Calibrate offsets for this specific route
302 TRY(calibrate_offsets());
303
304 auto measured_offset = -daq::average(daq::sample, 4, 10)[0];
305
306 // Allow this connection to go up to full scale. Those values are allways legal so we can ignore the
307 // return value
308 (void)cluster.cblock->set_factor(i_in_idx, 1.0f);
309 TRY_TRUE(cluster.cblock->write_to_hardware());
310
311 delay(10);
312
313 // Measure gain output
314 auto measured_gain = -daq::average(daq::sample, 4, 10)[0];
315 LOG_ANABRID_DEBUG_CALIBRATION(measured_gain);
316 // Calculate necessary gain correction
317 auto gain_correction = (upscaled_channel ? 0.8 : 1.0) / (measured_gain - measured_offset);
318 LOG_ANABRID_DEBUG_CALIBRATION(gain_correction);
319 if (gain_correction > 1.1f) {
320 gain_correction_exceeding = true;
321 gain_correction = 1.1f;
322 }
323 // Set gain correction on C-block, which will automatically get applied when writing to hardware
324 TRY(cluster.cblock->set_gain_correction(i_in_idx, gain_correction));
325 // Deactivate this lane again
326 TRY(cluster.cblock->set_factor(i_in_idx, 0.0f));
327 LOG_ANABRID_DEBUG_CALIBRATION(" ");
328 }
329
330 cluster.iblock->reset_outputs();
331 reset_adc_channels();
332 }
333
334 // Restore original U-block transmission modes and reference
335 cluster.ublock->change_all_transmission_modes(old_transmission_modes);
336 cluster.ublock->change_reference_magnitude(old_reference_magnitude);
337 // Write them to hardware
338 LOG_ANABRID_DEBUG_CALIBRATION("Restoring u-block");
339 TRY_TRUE(cluster.ublock->write_to_hardware());
340
341 // Restore C-block factors
342 cluster.cblock->set_factors(old_c_block_factors);
343 LOG_ANABRID_DEBUG_CALIBRATION("Restoring c-block");
344 TRY_TRUE(cluster.cblock->write_to_hardware());
345
346 // Restore I-block connections
347 LOG_ANABRID_DEBUG_CALIBRATION("Restoring i-block");
348 for (auto i_out_idx : blocks::IBlock::OUTPUT_IDX_RANGE())
349 for (auto i_in_idx : old_i_block_connections[i_out_idx])
350 TRY(cluster.iblock->connect(i_in_idx, i_out_idx));
351
352 TRY_TRUE(cluster.iblock->write_to_hardware());
353
354 // Restore ADC bus selection
355 ctrl_block->set_adc_bus(old_adcbus);
356 TRY_TRUE(ctrl_block->write_to_hardware());
357
358 TRY(set_adc_channels(old_adc_channels));
359 if (!hardware->write_adc_bus_mux(m_adc_channels))
360 return UnitResult::err("Writing adcs failed");
361 }
362
363 if (gain_correction_exceeding)
364 return UnitResult::err("Gain correction is too high, this is probably a problem with the hardware");
365
366 // Calibrate offsets for complete system
367 auto result = Carrier::calibrate_offsets();
368 LOG(ANABRID_DEBUG_CALIBRATION, __PRETTY_FUNCTION__);
369 return result;
370}
371
372UnitResult carrier::Carrier::calibrate_mblock(platform::Cluster &cluster, blocks::MBlock &mblock) {
373 // CARE: This function does not preserve the currently configured routes
374 LOG(ANABRID_DEBUG_CALIBRATION, __PRETTY_FUNCTION__);
375
376 // The calibration for each M-Block is prepared by connecting all outputs
377 // to the ADCs. This limits the calibration to one M-Block (and one cluster) at a time,
378 // which is not a problem though.
379 // Each M-Block must connect required reference signals by itself.
380
381 LOG(ANABRID_DEBUG_CALIBRATION, "Connecting outputs to ADC...");
382 for (auto output_idx : blocks::MBlock::SLOT_OUTPUT_IDX_RANGE()) {
383 auto lane_idx = mblock.slot_to_global_io_index(output_idx);
384 TRY(set_adc_channel(output_idx, lane_idx, cluster.get_cluster_idx()));
385 }
386 // Write to hardware
387 TRY_TRUE(write_to_hardware());
388
389 // Pass to calibration function
390 LOG(ANABRID_DEBUG_CALIBRATION, "Passing control to M-block...");
391 TRY(mblock.calibrate(&cluster, this));
392
393 LOG(ANABRID_DEBUG_CALIBRATION, "Cleaning up calibration signals...");
394 reset(entities::ResetAction::CIRCUIT_RESET);
395
396 // Write final clean-up to hardware
397 TRY_TRUE(write_to_hardware());
398
399 LOG(ANABRID_DEBUG_CALIBRATION, "Calibration done.");
400 LOG(ANABRID_DEBUG_CALIBRATION, __PRETTY_FUNCTION__);
401
402 return UnitResult::ok();
403}
404
405UnitResult carrier::Carrier::calibrate_m_blocks() {
406 for (auto &cluster : clusters) {
407 for (auto mblock : {cluster.m0block, cluster.m1block}) {
408 if (!mblock) continue;
409 TRY(calibrate_mblock(cluster, *mblock));
410 }
411 }
412
413 return UnitResult::ok();
414}
415
416void carrier::Carrier::reset(entities::ResetAction action) {
417 for (auto &cluster : clusters) {
418 cluster.reset(action);
419 }
420 if (ctrl_block)
421 ctrl_block->reset(action);
422 reset_adc_channels();
423}
424
425const std::array<carrier::ADCChannel, 8> &carrier::Carrier::get_adc_channels() const { return m_adc_channels; }
426
427UnitResult carrier::Carrier::set_adc_channels(const std::array<carrier::ADCChannel, 8> &channels) {
428 // Check that all inputs are in a valid range
429 uint8_t channel_idx = 0;
430 for (auto channel : channels) {
431 TRY(set_adc_channel(channel_idx, channel));
432 ++channel_idx;
433 }
434 return UnitResult::ok();
435}
436
437UnitResult carrier::Carrier::set_adc_channels(const std::array<int8_t, 8> &channels) {
438 // Check that all inputs are in a valid range
439 uint8_t channel_idx = 0;
440 for (auto channel : channels) {
441 TRY(set_adc_channel(channel_idx, channel));
442 ++channel_idx;
443 }
444 return UnitResult::ok();
445}
446
447UnitResult carrier::Carrier::set_adc_channel(uint8_t adc_channel, ADCChannel src_channel) {
448 if (adc_channel >= m_adc_channels.size())
449 return UnitResult::err_fmt("Error carrier channel out of range: %d", adc_channel);
450
451 m_adc_channels[adc_channel] = src_channel;
452 return UnitResult::ok();
453}
454
455[[nodiscard]] UnitResult carrier::Carrier::set_adc_channel(uint8_t adc_channel, int8_t src_idx) {
456 return set_adc_channel(adc_channel, ADCChannel{
457 .src = src_idx,
458 });
459}
460
461UnitResult carrier::Carrier::set_adc_channel(uint8_t adc_channel, int8_t src_idx, uint8_t cluster_idx) {
462 return set_adc_channel(adc_channel, static_cast<int8_t>(src_idx + cluster_idx * 16));
463}
464
465void carrier::Carrier::reset_adc_channels() {
466 m_adc_channels.fill(ADCChannel());
467}
468
469UnitResult carrier::Carrier::measure_all_signals(std::array<std::array<float, 8>, 6> &data) {
470 auto old_adc_channels = get_adc_channels();
471 reset_adc_channels();
472 size_t idx = static_cast<size_t>(-1);
473 for (const auto &cluster : clusters) {
474 for (const auto mblock : {cluster.m0block, cluster.m1block}) {
475 ++idx;
476 if (!mblock) continue;
477
478 for (auto slot : blocks::MBlock::SLOT_OUTPUT_IDX_RANGE())
479 TRY(set_adc_channel(slot, mblock->slot_to_global_io_index(slot), cluster.get_cluster_idx()));
480
481 TRY_TRUE(write_to_hardware());
482 data[idx] = daq::average();
483 }
484 }
485 TRY(set_adc_channels(old_adc_channels));
486 return UnitResult::ok();
487}
488
489UnitResult carrier::Carrier::write_adcs_to_hardware(const std::array<ADCChannel, 8>& channels) {
490 if (ctrl_block)
491 TRY_TRUE(ctrl_block->write_to_hardware());
492
493 if (!hardware->write_adc_bus_mux(channels))
494 return UnitResult::err("ADC Bus write failed.");
495
496 return UnitResult::ok();
497}
498
499UnitResult carrier::Carrier::calibrate(const pb_CalibrationConfig &item) {
500#ifdef ANABRID_DEBUG_COMMS
501 Serial.println(__PRETTY_FUNCTION__);
502#endif
503
504 if(item.math != pb_CalibrationConfig_Kind_Disabled) {
505 //following calibrations are not configuration preserving
506 entities::Setup setup;
507 entities::ExtractSettings settings{
508 .include_configuration = true
509 };
510 setup.extract(this, settings);
511 reset(entities::ResetAction::CIRCUIT_RESET);
512 TRY_TRUE(write_to_hardware());
513 TRY(calibrate_m_blocks());
514
515 TRY(setup.apply(this, true));
516 }
517
518 if (item.offset != pb_CalibrationConfig_Kind_Disabled)
519 TRY(calibrate_offsets());
520
521 return UnitResult::ok();
522}
523
524UnitResult carrier::Carrier::user_get_overload_status(pb_OverloadStatus &overload_status) {
525 entities::OverloadVisitor visitor;
526 visitor.visit(this, true);
527 visitor.to(overload_status);
528 return UnitResult::ok();
529}
530
531UnitResult carrier::Carrier::user_calibrate(const pb_CalibrationConfig &item) {
532 return calibrate(item);
533}
534
535static Result<uint32_t> parse_uint(std::string_view view)
536{
537 char* eptr = nullptr;
538 auto result = std::strtol(view.begin(), &eptr, 10);
539 if(eptr - view.begin() != view.length())
540 return Result<uint32_t>::err("Invalid path: " + std::string(view));
541
542 return Result<uint32_t>::ok(result);
543}
544
545
546PathResult Routing::index2path(uint32_t node) const {
547 if (m_idx2path.size() <= node)
548 return PathResult::err_fmt("Unable to find path of entity idx: %d", node);
549 return PathResult::ok(m_idx2path.at(node));
550}
551
552U32Result Routing::path2index(Path path) const {
553 auto it = m_path2idx.find(path);
554 if (it == m_path2idx.end())
555 return LaneResult::err_fmt("Unable to find entity idx of path %s", std::string(path).c_str());
556
557 return U32Result::ok(m_path2idx.at(path));
558}
559
560LaneResult Routing::cluster2lane(uint32_t cluster_idx, uint32_t lane_idx) const {
561 if (!m_self_idx.has_value())
562 return LaneResult::err_fmt("Invalid self index for %s", carrier::Carrier::get().get_entity_id().c_str());
563 return LaneResult::ok(Lane(*m_self_idx, cluster_idx, lane_idx));
564}
565
566UnitResult Routing::config_entity_idx(const pb_EntityId* carrier_indices, uint32_t count) {
567 m_idx2path.resize(count);
568 m_self_idx = std::nullopt;
569 for (auto carrier_idx = 0; carrier_idx < count; ++carrier_idx) {
570 auto& carrier_path = carrier_indices[carrier_idx];
571 Path path = std::string_view(carrier_path.path);
572 if (path.size() != 1)
573 return ConfigResult::err("Expected cluster path in trace config");
574 if (path.segment(0) == m_self) {
575 m_self_idx = carrier_idx;
576 }
577
578 m_path2idx.emplace(path, carrier_idx);
579 m_idx2path[carrier_idx] = path;
580 }
581 return UnitResult::ok();
582}
583
584UnitResult Routing::config_trace_config(const pb_DependencyInfo& dep_info) {
585 clear();
586
587 TRY(config_entity_idx(dep_info.entity_ids, dep_info.entity_ids_count));
588
589 for (auto idx = 0; idx < dep_info.traces_count; ++idx) {
590 auto& trace = dep_info.traces[idx];
591 Lane src_lane(trace.source.carrier, trace.source.cluster, trace.source.lane);
592 Lane sink_lane(trace.sink.carrier, trace.sink.cluster, trace.sink.lane);
593 m_src2uses[src_lane]++;
594 if (trace.sink_upscaled) {
595 m_src_is_upscaled.insert(src_lane);
596 m_sink_is_upscaled.insert(sink_lane);
597 }
598 m_sink2src.emplace(sink_lane, src_lane);
599 m_sink_is_present.insert(sink_lane);
600 }
601
602 return UnitResult::ok();
603}
604
605
606ConfigResult Routing::config(const pb_Item &item){
607 if (item.which_kind == pb_Item_dependency_info_tag) {
608 TRY(config_trace_config(item.kind.dependency_info));
609 return ConfigResult::ok(true);
610 }
611
612 if (item.which_kind == pb_Item_ip_lookup_table_tag) {
613 auto& ip_lookup_table = item.kind.ip_lookup_table;
614 for (size_t idx = 0; idx < ip_lookup_table.entries_count; ++idx) {
615 auto& entity = ip_lookup_table.entries[idx];
616 if (!entity.has_address || !entity.has_entity_id) continue;
617 auto& data = entity.address.data.bytes;
618 IPAddress address(data[0], data[1], data[2], data[3]);
619 set_path_address(std::string_view(entity.entity_id.path), address);
620 }
621 }
622
623 return ConfigResult::ok(false);
624}
625
626bool Routing::is_sink_upscaled(Lane lane) const {
627 auto it = m_sink_is_upscaled.find(lane);
628 return it != m_sink_is_upscaled.end();
629}
630
631bool Routing::is_source_upscaled(Lane lane) const {
632 auto it = m_src_is_upscaled.find(lane);
633 return it != m_src_is_upscaled.end();
634}
635
636uint32_t Routing::use_count(Lane lane) const {
637 auto it = m_src2uses.find(lane);
638 if (it == m_src2uses.end())
639 return 0;
640 return it->second;
641}
642
643LaneResult Routing::source(Lane lane) const {
644 auto it = m_sink2src.find(lane);
645 if (it == m_sink2src.end())
646 return LaneResult::err("Not found source");
647 return LaneResult::ok(it->second);
648}
649
650bool Routing::is_source_used(Lane lane) const {
651 return use_count(lane) > 0;
652}
653
654bool Routing::is_sink_present(Lane lane) const {
655 auto it = m_sink_is_present.find(lane);
656 return it != m_sink_is_present.end();
657}
658
659IPAddressResult Routing::ip_address(Path path) const {
660 auto it = m_path2ip.find(path);
661 if (it != m_path2ip.end())
662 return IPAddressResult::ok(it->second);
663 return UnitResult::err_fmt("Ip adress of %s not found", std::string(path).c_str());
664}
665
666
667LaneResult Routing::source(uint32_t cluster_idx, uint32_t lane) const {
668 return source(TRY(cluster2lane(cluster_idx, lane)));
669}
670
671BoolResult Routing::is_source_upscaled(uint32_t cluster_idx, uint32_t lane) const {
672 return BoolResult::ok(is_source_upscaled(TRY(cluster2lane(cluster_idx, lane))));
673}
674
675BoolResult Routing::is_sink_upscaled(uint32_t cluster_idx, uint32_t lane) const {
676 return BoolResult::ok(is_sink_upscaled(TRY(cluster2lane(cluster_idx, lane))));
677}
678
679U32Result Routing::use_count(uint32_t cluster_idx, uint32_t lane) const {
680 return U32Result::ok(use_count(TRY(cluster2lane(cluster_idx, lane))));
681}
682
683PathResult Routing::source_path(uint32_t cluster_idx, uint32_t lane) const {
684 return index2path(TRY(source(TRY(cluster2lane(cluster_idx, lane)))).m_carrier);
685}
686
687BoolResult Routing::is_sink_present(uint32_t cluster_idx, uint32_t lane) const {
688 return BoolResult::ok(is_sink_present(TRY(cluster2lane(cluster_idx, lane))));
689}
690
691BoolResult Routing::is_source_used(uint32_t cluster_idx, uint32_t lane) const {
692 return BoolResult::ok(is_source_used(TRY(cluster2lane(cluster_idx, lane))));
693}
static Result< uint32_t > parse_uint(std::string_view view)
Definition carrier.cpp:535
void setup()
FASTRUN uint32_t size
Definition flasher.cpp:77