Skip to content

Commit

Permalink
Blocks and connections refactor
Browse files Browse the repository at this point in the history
* Reimplemented graph connection mechanism
* Don't instantiate types in typelist's for_each
* Low level support for hier-blocks

Signed-off-by: Ivan Čukić <[email protected]>
  • Loading branch information
ivan-cukic authored Jul 23, 2024
1 parent 6ff9b10 commit 2c60a4b
Show file tree
Hide file tree
Showing 16 changed files with 577 additions and 298 deletions.
8 changes: 4 additions & 4 deletions blocks/basic/test/qa_PythonBlock.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -187,8 +187,8 @@ def process_bulk(ins, outs):
auto& block = graph.emplaceBlock<PythonBlock<int32_t>>({{"n_inputs", 1U}, {"n_outputs", 1U}, {"pythonScript", pythonScript}});
auto& sink = graph.emplaceBlock<TagSink<int32_t, ProcessFunction::USE_PROCESS_BULK>>({{"n_samples_expected", 5U}, {"verbose_console", true}});

expect(gr::ConnectionResult::SUCCESS == graph.connect(src, {"out", gr::meta::invalid_index}, block, {"inputs", 0U}));
expect(gr::ConnectionResult::SUCCESS == graph.connect(block, {"outputs", 0U}, sink, {"in", gr::meta::invalid_index}));
expect(gr::ConnectionResult::SUCCESS == graph.connect(src, "out"s, block, "inputs#0"s));
expect(gr::ConnectionResult::SUCCESS == graph.connect(block, "outputs#0"s, sink, "in"s));

scheduler::Simple sched{std::move(graph)};
bool throws = false;
Expand Down Expand Up @@ -248,8 +248,8 @@ def process_bulk(ins, outs):
auto& block = graph.emplaceBlock<PythonBlock<float>>({{"n_inputs", 1U}, {"n_outputs", 1U}, {"pythonScript", pythonScript}});
auto& sink = graph.emplaceBlock<TagSink<float, ProcessFunction::USE_PROCESS_BULK>>({{"n_samples_expected", 5U}, {"verbose_console", true}});

expect(gr::ConnectionResult::SUCCESS == graph.connect(src, {"out", gr::meta::invalid_index}, block, {"inputs", 0U}));
expect(gr::ConnectionResult::SUCCESS == graph.connect(block, {"outputs", 0U}, sink, {"in", gr::meta::invalid_index}));
expect(gr::ConnectionResult::SUCCESS == graph.connect(src, "out"s, block, "inputs#0"s));
expect(gr::ConnectionResult::SUCCESS == graph.connect(block, "outputs#0"s, sink, "in"s));

scheduler::Simple sched{std::move(graph)};
block.pause(); // simplified calling
Expand Down
6 changes: 4 additions & 2 deletions blocks/basic/test/qa_Selector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
#include <gnuradio-4.0/basic/Selector.hpp>
#include <gnuradio-4.0/testing/TagMonitors.hpp>

using namespace std::string_literals;

struct TestParams {
gr::Size_t nSamples;
std::vector<std::pair<gr::Size_t, gr::Size_t>> mapping;
Expand Down Expand Up @@ -49,13 +51,13 @@ void execute_selector_test(TestParams params) {
for (gr::Size_t i = 0; i < nSources; ++i) {
sources.push_back(std::addressof(graph.emplaceBlock<TagSource<double>>({{"n_samples_max", params.nSamples}, {"values", params.inValues[i]}})));
expect(sources[i]->settings().applyStagedParameters().forwardParameters.empty());
expect(gr::ConnectionResult::SUCCESS == graph.connect(*sources[i], {"out", gr::meta::invalid_index}, *selector, {"inputs", i}));
expect(gr::ConnectionResult::SUCCESS == graph.connect(*sources[i], "out"s, *selector, "inputs#"s + std::to_string(i)));
}

for (gr::Size_t i = 0; i < nSinks; ++i) {
sinks.push_back(std::addressof(graph.emplaceBlock<TagSink<double, ProcessFunction::USE_PROCESS_ONE>>()));
expect(sinks[i]->settings().applyStagedParameters().forwardParameters.empty());
expect(gr::ConnectionResult::SUCCESS == graph.connect(*selector, {"outputs", i}, *sinks[i], {"in"}));
expect(gr::ConnectionResult::SUCCESS == graph.connect(*selector, "outputs#"s + std::to_string(i), *sinks[i], "in"s));
}

TagSink<double, ProcessFunction::USE_PROCESS_ONE>* monitorSink = std::addressof(graph.emplaceBlock<TagSink<double, ProcessFunction::USE_PROCESS_ONE>>());
Expand Down
1 change: 1 addition & 0 deletions cmake/CompilerWarnings.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ function(set_project_warnings project_name)
-Wuseless-cast # warn if you perform a cast to the same type
-Wno-interference-size # suppress ABI compatibility warnings for hardware inferred size
-Wno-maybe-uninitialized # false positives if asan is enabled: https://gcc.gnu.org/bugzilla//show_bug.cgi?id=1056h6
-Wno-tautological-compare # fmt has always true comparisons
-fconcepts-diagnostics-depth=3
-Wno-missing-field-initializers # confusing warning which is not what most users expect: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96868#c3
)
Expand Down
22 changes: 17 additions & 5 deletions core/include/gnuradio-4.0/Block.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,14 @@ inline static const char* kStoreDefaults = "StoreDefaults"; ///< store present s
inline static const char* kResetDefaults = "ResetDefaults"; ///< retrieve and reset to default setting, for counterpart @see kStoreDefaults
} // namespace block::property

namespace block {
enum class Category {
NormalBlock, ///< Block that does not contain children blocks
TransparentBlockGroup, ///< Block with children blocks which do not have a dedicated scheduler
ScheduledBlockGroup ///< Block with children that have a dedicated scheduler
};
}

/**
* @brief The 'Block<Derived>' is a base class for blocks that perform specific signal processing operations. It stores
* references to its input and output 'ports' that can be zero, one, or many, depending on the use case.
Expand Down Expand Up @@ -363,7 +371,9 @@ class Block : public lifecycle::StateMachine<Derived>, public std::tuple<Argumen
using StrideControl = ArgumentsTypeList::template find_or_default<is_stride, Stride<0UL, true>>;
using AllowIncompleteFinalUpdate = ArgumentsTypeList::template find_or_default<is_incompleteFinalUpdatePolicy, IncompleteFinalUpdatePolicy<IncompleteFinalUpdateEnum::DROP>>;
using DrawableControl = ArgumentsTypeList::template find_or_default<is_drawable, Drawable<UICategory::None, "">>;
constexpr static bool blockingIO = std::disjunction_v<std::is_same<BlockingIO<true>, Arguments>...> || std::disjunction_v<std::is_same<BlockingIO<false>, Arguments>...>;

constexpr static bool blockingIO = std::disjunction_v<std::is_same<BlockingIO<true>, Arguments>...> || std::disjunction_v<std::is_same<BlockingIO<false>, Arguments>...>;
constexpr static block::Category blockCategory = block::Category::NormalBlock;

template<typename T>
auto& getArgument() {
Expand Down Expand Up @@ -523,15 +533,15 @@ class Block : public lifecycle::StateMachine<Derived>, public std::tuple<Argumen
// Set names of port member variables
// TODO: Refactor the library not to assign names to ports. The
// block and the graph are the only things that need the port name
auto setPortName = [&]([[maybe_unused]] std::size_t index, auto&& t) {
using CurrentPortType = std::remove_cvref_t<decltype(t)>;
auto setPortName = [&]([[maybe_unused]] std::size_t index, auto* t) {
using CurrentPortType = std::remove_pointer_t<decltype(t)>;
if constexpr (traits::port::is_port_v<CurrentPortType>) {
using PortDescriptor = typename CurrentPortType::ReflDescriptor;
if constexpr (refl::trait::is_descriptor_v<PortDescriptor>) {
auto& port = (self().*(PortDescriptor::pointer));
port.name = CurrentPortType::Name;
}
} else {
} else if constexpr (traits::port::is_port_collection_v<CurrentPortType>) {
using PortCollectionDescriptor = typename CurrentPortType::value_type::ReflDescriptor;
if constexpr (refl::trait::is_descriptor_v<PortCollectionDescriptor>) {
auto& collection = (self().*(PortCollectionDescriptor::pointer));
Expand All @@ -540,6 +550,8 @@ class Block : public lifecycle::StateMachine<Derived>, public std::tuple<Argumen
port.name = collectionName;
}
}
} else {
meta::print_types<meta::message_type<"Not a port, not a collection of ports">, CurrentPortType>{};
}
};
traits::block::all_input_ports<Derived>::for_each(setPortName);
Expand Down Expand Up @@ -1986,7 +1998,6 @@ template<BlockLike TBlock>
}

namespace detail {
using namespace std::string_literals;

template<typename Type>
std::string reflFirstTypeName() {
Expand All @@ -2012,6 +2023,7 @@ std::string reflFirstTypeName() {

template<typename... Types>
std::string encodeListOfTypes() {
using namespace std::string_literals;
struct accumulator {
std::string value;

Expand Down
Loading

0 comments on commit 2c60a4b

Please sign in to comment.