1#include <entity/visitor.h>
2#include <proto/main.pb.h>
4#include <redac/tblock.h>
8TBlock::TBlock(TBlockHAL *hardware) : FunctionBlock(
"T", hardware), hardware(hardware) { classifier.class_enum = CLASS_; }
10ConfigResult TBlock::config(
const pb_Config &cfg) {
11 if (cfg.which_kind == pb_Config_switch_config_tag) {
12 auto &switch_config = cfg.kind.switch_config;
13 return apply_muxes(switch_config.muxes);
16 if (cfg.which_kind == pb_UseConfig_uses_tag) {
17 auto &use_config = cfg.kind.use_config;
18 return apply_uses(use_config.uses);
22 return ConfigResult::ok(
false);
25ConfigResult TBlock::apply_muxes(
const pb_Mux (&muxes)[TBlockHAL::NUM_SWITCHES]) {
27 for (
auto &mux : muxes) {
34 auto mux_value = mux.state;
35 if (mux_value < 0 || 4 <= mux_value)
36 return ConfigResult::err(
"TBlock: Mux must be interval [0, 3]");
37 connections[idx] = mux_value;
40 return ConfigResult::ok(
true);
43ConfigResult TBlock::apply_uses(
const pb_Use (&uses)[TBlockHAL::NUM_SWITCHES]) {
44 for (
auto &use : uses) {
45 external_signal_sources[use.idx] = use.has_source ?
static_cast<int32_t
>(use.source) : -1;
46 external_target_upscaling[use.idx] = use.upscaled;
49 return ConfigResult::ok(
true);
52std::array<uint8_t, TBlockHAL::NUM_SWITCHES> TBlock::get_connections()
const {
return connections; }
54void TBlock::set_connections(
const std::array<uint8_t, TBlockHAL::NUM_SWITCHES> &connections) { this->connections = connections; }
56void TBlock::extract(entities::ExtractVisitor &collector) {
57 auto &cfg = collector.create(pb_Config_switch_config_tag);
58 auto &switch_config = cfg.kind.switch_config = pb_SwitchConfig_init_default;
60 auto &idx = switch_config.muxes_count = 0;
61 for (; idx < connections.size(); ++idx) {
62 switch_config.muxes[idx] = {
64 .state = connections[idx],
69status TBlock::connect(Sector src_sector, Sector dst_sector, uint8_t lane_idx) {
71 return status(
"Invalid lane. Remember that TBlock lanes are allways counted from 0 to 23");
73 connections[lane_idx * 4 + dst_sector] = src_sector;
75 return status::success();
78TBlock::Sector TBlock::src_of_signal(Sector dst_sector, uint8_t lane_idx)
const {
82 return static_cast<Sector
>(connections[lane_idx * 4 + dst_sector]);
87void TBlock::reset(entities::ResetAction action) {
88 Entity::reset(action);
89 if (action.has(entities::ResetAction::CIRCUIT_RESET)) {
93 if (action.has(entities::ResetAction::EVERYTHING))
97void TBlock::reset_external_signal_infos() {
98 external_signal_sources = {};
99 external_target_upscaling = {};
102void TBlock::reset_connections() {
105 connections = {Sector::BPL, Sector::CL0, Sector::CL1, Sector::CL2, Sector::BPL, Sector::CL0, Sector::CL1, Sector::CL2, Sector::BPL, Sector::CL0,
106 Sector::CL1, Sector::CL2, Sector::BPL, Sector::CL0, Sector::CL1, Sector::CL2, Sector::BPL, Sector::CL0, Sector::CL1, Sector::CL2,
107 Sector::BPL, Sector::CL0, Sector::CL1, Sector::CL2, Sector::BPL, Sector::CL0, Sector::CL1, Sector::CL2, Sector::BPL, Sector::CL0,
108 Sector::CL1, Sector::CL2, Sector::BPL, Sector::CL0, Sector::CL1, Sector::CL2, Sector::BPL, Sector::CL0, Sector::CL1, Sector::CL2,
109 Sector::BPL, Sector::CL0, Sector::CL1, Sector::CL2, Sector::BPL, Sector::CL0, Sector::CL1, Sector::CL2, Sector::BPL, Sector::CL0,
110 Sector::CL1, Sector::CL2, Sector::BPL, Sector::CL0, Sector::CL1, Sector::CL2, Sector::BPL, Sector::CL0, Sector::CL1, Sector::CL2,
111 Sector::BPL, Sector::CL0, Sector::CL1, Sector::CL2, Sector::BPL, Sector::CL0, Sector::CL1, Sector::CL2, Sector::BPL, Sector::CL0,
112 Sector::CL1, Sector::CL2, Sector::BPL, Sector::CL0, Sector::CL1, Sector::CL2, Sector::BPL, Sector::CL0, Sector::CL1, Sector::CL2,
113 Sector::BPL, Sector::CL0, Sector::CL1, Sector::CL2, Sector::BPL, Sector::CL0, Sector::CL1, Sector::CL2, Sector::BPL, Sector::CL0,
114 Sector::CL1, Sector::CL2, Sector::BPL, Sector::CL0, Sector::CL1, Sector::CL2};
117status TBlock::write_to_hardware() {
118 RETURN_IF_FAILED(Entity::write_to_hardware());
119 if (!hardware->write_muxes(connections))
120 return status(
"Error writing mux settings to hardware.");
122 hardware->reset_mux_disable();
124 hardware->set_mux_disable();
125 return status::success();
128bool TBlock::is_enabled()
const {
return enabled; }
130void TBlock::set_enabled(
bool enabled_) { enabled = enabled_; }
132int32_t TBlock::get_external_signal_source_entity_id(Sector dst_sector, uint8_t lane_idx) {
136 return external_signal_sources[lane_idx * 4 + dst_sector];
139bool TBlock::is_external_target_upscaled(uint8_t lane) {
142 return external_target_upscaling[lane];
145TBlockBackplane::TBlockBackplane(TBlockBackplaneHAL *hardware) : FunctionBlock(
"T_BPL", hardware), hardware(hardware) {
146 classifier.class_enum = CLASS_;
149utils::status TBlockBackplane::connect(Sector src_sector, Sector dst_sector, uint8_t lane_idx) {
151 return "lane_idx is invalid! Maximum is 7!";
153 if (src_sector == dst_sector)
154 return "src_sector is equal to dst_sector! This connection is impossible!";
157 uint8_t switch_setting = src_sector;
158 if (src_sector == Sector::EXT0)
159 switch_setting = dst_sector;
161 connections[dst_sector + lane_idx * 9] = switch_setting;
163 return status::success();
166TBlockBackplane::Sector TBlockBackplane::src_of_signal(Sector dst_sector, uint8_t lane_idx)
const {
170 uint8_t switch_setting = connections[dst_sector + lane_idx * 9];
171 if (switch_setting == dst_sector)
174 return static_cast<Sector
>(switch_setting);
177void TBlockBackplane::reset(entities::ResetAction action) {
178 Entity::reset(action);
179 if (action.has(entities::ResetAction::CIRCUIT_RESET)) {
182 if (action.has(entities::ResetAction::EVERYTHING))
186void TBlockBackplane::reset_connections() {
190 std::fill(connections.begin(), connections.end(), random() % 9);
193status TBlockBackplane::write_to_hardware() {
194 RETURN_IF_FAILED(Entity::write_to_hardware());
195 if (!hardware->write_muxes(connections))
196 return status(
"Error writing mux settings to hardware.");
198 hardware->reset_mux_disable();
200 hardware->set_mux_disable();
201 return status::success();
204std::array<uint8_t, TBlockBackplaneHAL::NUM_SWITCHES> TBlockBackplane::get_connections()
const {
return connections; }
206void TBlockBackplane::set_connections(
const std::array<uint8_t, TBlockBackplaneHAL::NUM_SWITCHES> &connections_) { connections = connections_; }
208bool TBlockBackplane::is_enabled()
const {
return enabled; }
210void TBlockBackplane::set_enabled(
bool enabled_) { enabled = enabled_; }
212ConfigResult TBlockBackplane::config(
const pb_Config &cfg) {
213 if (cfg.which_kind == pb_Config_bpl_switch_config_tag) {
214 auto &switch_config = cfg.kind.bpl_switch_config;
215 return apply_muxes(switch_config.muxes);
218 return ConfigResult::ok(
false);
221ConfigResult TBlockBackplane::apply_muxes(
const pb_Mux (&muxes)[TBlockBackplaneHAL::NUM_SWITCHES]) {
222 for (
size_t i = 0; i < TBlockBackplaneHAL::NUM_SWITCHES; i++) {
223 if (!muxes[i].has_state)
226 auto mux_value = muxes[i].state;
228 return ConfigResult::err(
"TBlockBackplane::apply_muxes: mux value is invalid, must be between [0, 7]!");
229 connections[i] = mux_value;
232 return ConfigResult::ok(
true);
235void TBlockBackplane::extract(entities::ExtractVisitor &collector) {
236 auto &cfg = collector.create(pb_Config_bpl_switch_config_tag);
237 auto &switch_config = cfg.kind.bpl_switch_config = pb_BPLSwitchConfig_init_default;
239 auto &idx = switch_config.muxes_count = 0;
240 for (; idx < connections.size(); ++idx) {
241 switch_config.muxes[idx] = {.has_state =
true, .state = connections[idx]};
void reset_external_signal_infos()