Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Message-based API for block and edge creation and deletion #357

Merged
merged 2 commits into from
Jun 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 16 additions & 10 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,30 @@ set(CMAKE_CXX_STANDARD 23)
set(CMAKE_CXX_VISIBILITY_PRESET hidden)
set(CMAKE_VISIBILITY_INLINES_HIDDEN 1)

option(NOPLUGINS "Disable plugins" OFF)
if (CMAKE_CXX_COMPILER MATCHES "/em\\+\\+(-[a-zA-Z0-9.])?$") # if this hasn't been set before via e.g. emcmake
message(" Transpiling to WASM: using: Emscripten (${CMAKE_CXX_COMPILER})")
set(EMSCRIPTEN ON)
endif ()

option(ENABLE_BLOCK_PLUGINS "Enable building the plugin system" ON)
option(ENABLE_BLOCK_REGISTRY "Enable building the block registry" ON)
option(EMBEDDED "Enable embedded mode" OFF)
option(TIMETRACE "Enable clang's -ftime-trace" OFF)
option(ADDRESS_SANITIZER "Enable address sanitizer" OFF)
option(UB_SANITIZER "Enable undefined behavior sanitizer" OFF)
option(THREAD_SANITIZER "Enable thread sanitizer" OFF)

if (NOPLUGINS)
set(NOPLUGINS ON)
add_compile_definitions(NOPLUGINS)
message(STATUS "disable plugin system (faster compile-times and when runtime or Python wrapping APIs are not required): ${NOPLUGINS}")
if (EMSCRIPTEN)
set(ENABLE_BLOCK_PLUGINS OFF)
endif ()

if (ENABLE_BLOCK_PLUGINS)
set(ENABLE_BLOCK_REGISTRY ON)
endif ()

message(STATUS "Is block registry enabled? (faster compile-times and when runtime or Python wrapping APIs are not required) ${ENABLE_BLOCK_REGISTRY}")
message(STATUS "Is plugin system enabled? ${ENABLE_BLOCK_PLUGINS}")

# Determine if fmt is built as a subproject (using add_subdirectory) or if it is the master project.
if (NOT DEFINED GR_TOPLEVEL_PROJECT)
set(GR_TOPLEVEL_PROJECT OFF)
Expand Down Expand Up @@ -136,11 +147,6 @@ add_library(gnuradio-options INTERFACE)
include(cmake/CompilerWarnings.cmake)
set_project_warnings(gnuradio-options)

if (CMAKE_CXX_COMPILER MATCHES "/em\\+\\+(-[a-zA-Z0-9.])?$") # if this hasn't been set before via e.g. emcmake
message(" Transpiling to WASM: using: Emscripten (${CMAKE_CXX_COMPILER})")
set(EMSCRIPTEN true)
endif ()

if (EMSCRIPTEN)
set(CMAKE_EXECUTABLE_SUFFIX ".js")
add_compile_options(
Expand Down
87 changes: 40 additions & 47 deletions blocks/testing/include/gnuradio-4.0/testing/NullSources.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,7 @@ Ideal for scenarios that require a simple, low-overhead source of consistent val

gr::PortOut<T> out;

[[nodiscard]] constexpr T
processOne() const noexcept {
return T{};
}
[[nodiscard]] constexpr T processOne() const noexcept { return T{}; }
};

static_assert(gr::BlockLike<NullSource<float>>);
Expand All @@ -36,13 +33,9 @@ Commonly used for testing and simulations where consistent output and finite exe
Annotated<gr::Size_t, "max samples", Doc<"count>n_samples_max -> signal DONE (0: infinite)">> n_samples_max = 0U;
Annotated<gr::Size_t, "count", Doc<"sample count (diagnostics only)">> count = 0U;

void
reset() {
count = 0U;
}
void reset() { count = 0U; }

[[nodiscard]] constexpr T
processOne() noexcept {
[[nodiscard]] constexpr T processOne() noexcept {
count++;
if (n_samples_max > 0 && count >= n_samples_max) {
this->requestStop();
Expand All @@ -54,7 +47,32 @@ Commonly used for testing and simulations where consistent output and finite exe
static_assert(gr::BlockLike<ConstantSource<float>>);

template<typename T>
requires(std::is_arithmetic_v<T>)
struct SlowSource : public gr::Block<SlowSource<T>> {
using Description = Doc<R""(A source block that emits a constant default value every n miliseconds)"">;

gr::PortOut<T> out;
Annotated<T, "default value", Visible, Doc<"default value for each sample">> default_value{};
Annotated<gr::Size_t, "delay", Doc<"how many milliseconds between each value">> n_delay = 100U;

std::optional<std::chrono::time_point<std::chrono::system_clock>> lastEventAt;

[[nodiscard]] gr::work::Status processBulk(PublishableSpan auto& output) {
if (!lastEventAt || std::chrono::system_clock::now() - *lastEventAt > std::chrono::milliseconds(n_delay)) {
lastEventAt = std::chrono::system_clock::now();

output[0] = default_value;
output.publish(1);
return gr::work::Status::OK;
}

return gr::work::Status::INSUFFICIENT_OUTPUT_ITEMS;
}
};

static_assert(gr::BlockLike<SlowSource<float>>);

template<typename T>
requires(std::is_arithmetic_v<T>)
struct CountingSource : public gr::Block<CountingSource<T>> {
using Description = Doc<R""(A source block that emits an increasing sequence starting from a specified default value.
This block counts the number of samples emitted and optionally halts after reaching a specified maximum.
Expand All @@ -66,13 +84,9 @@ Commonly used for testing and simulations where consistent output and finite exe
Annotated<gr::Size_t, "max samples", Doc<"count>n_samples_max -> signal DONE (0: infinite)">> n_samples_max = 0U;
Annotated<gr::Size_t, "count", Doc<"sample count (diagnostics only)">> count = 0U;

void
reset() {
count = 0U;
}
void reset() { count = 0U; }

[[nodiscard]] constexpr T
processOne() noexcept {
[[nodiscard]] constexpr T processOne() noexcept {
count++;
if (n_samples_max > 0 && count >= n_samples_max) {
this->requestStop();
Expand All @@ -92,8 +106,7 @@ Commonly used used to isolate parts of a flowgraph, manage buffer sizes, or simp
gr::PortOut<T> out;

template<gr::meta::t_or_simd<T> V>
[[nodiscard]] constexpr auto
processOne(V input) const noexcept {
[[nodiscard]] constexpr auto processOne(V input) const noexcept {
return input;
}
};
Expand All @@ -111,13 +124,9 @@ Commonly used to control data flow in systems where precise sample counts are cr
Annotated<gr::Size_t, "max samples", Doc<"count>n_samples_max -> signal DONE (0: infinite)">> n_samples_max = 0U;
Annotated<gr::Size_t, "count", Doc<"sample count (diagnostics only)">> count = 0U;

void
reset() {
count = 0U;
}
void reset() { count = 0U; }

[[nodiscard]] constexpr auto
processOne(T input) noexcept {
[[nodiscard]] constexpr auto processOne(T input) noexcept {
count++;
if (n_samples_max > 0 && count >= n_samples_max) {
this->requestStop();
Expand All @@ -137,8 +146,7 @@ Commonly used for testing, performance benchmarking, and in scenarios where sign
gr::PortIn<T> in;

template<gr::meta::t_or_simd<T> V>
void
processOne(V) const noexcept {}
void processOne(V) const noexcept {}
};

static_assert(gr::BlockLike<NullSink<float>>);
Expand All @@ -154,14 +162,10 @@ Commonly used for testing scenarios and signal termination where output is unnec
Annotated<gr::Size_t, "max samples", Doc<"count>n_samples_max -> signal DONE (0: infinite)">> n_samples_max = 0U;
Annotated<gr::Size_t, "count", Doc<"sample count (diagnostics only)">> count = 0U;

void
reset() {
count = 0U;
}
void reset() { count = 0U; }

template<gr::meta::t_or_simd<T> V>
void
processOne(V) noexcept {
void processOne(V) noexcept {
if constexpr (stdx::is_simd_v<V>) {
count += V::size();
} else {
Expand All @@ -180,24 +184,13 @@ static_assert(gr::BlockLike<CountingSink<float>>);
ENABLE_REFLECTION_FOR_TEMPLATE(gr::testing::NullSource, out);
ENABLE_REFLECTION_FOR_TEMPLATE(gr::testing::ConstantSource, out, n_samples_max, count);
ENABLE_REFLECTION_FOR_TEMPLATE(gr::testing::CountingSource, out, n_samples_max, count);
ENABLE_REFLECTION_FOR_TEMPLATE(gr::testing::SlowSource, out, n_delay);
ENABLE_REFLECTION_FOR_TEMPLATE(gr::testing::Copy, in, out);
ENABLE_REFLECTION_FOR_TEMPLATE(gr::testing::HeadBlock, in, out, n_samples_max, count);
ENABLE_REFLECTION_FOR_TEMPLATE(gr::testing::NullSink, in);
ENABLE_REFLECTION_FOR_TEMPLATE(gr::testing::CountingSink, in, n_samples_max, count);

const inline auto registerNullSources
= gr::registerBlock<gr::testing::NullSource, uint8_t, uint16_t, uint32_t, uint64_t, int8_t, int16_t, int32_t, int64_t, float, double, std::complex<float>, std::complex<double>, std::string,
gr::Packet<float>, gr::Packet<double>, gr::Tensor<float>, gr::Tensor<double>, gr::DataSet<float>, gr::DataSet<double>>(gr::globalBlockRegistry())
| gr::registerBlock<gr::testing::ConstantSource, uint8_t, uint16_t, uint32_t, uint64_t, int8_t, int16_t, int32_t, int64_t, float, double, std::complex<float>, std::complex<double>,
std::string, gr::Packet<float>, gr::Packet<double>, gr::Tensor<float>, gr::Tensor<double>, gr::DataSet<float>, gr::DataSet<double>>(gr::globalBlockRegistry())
| gr::registerBlock<gr::testing::CountingSource, uint8_t, uint16_t, uint32_t, uint64_t, int8_t, int16_t, int32_t, int64_t, float, double>(gr::globalBlockRegistry())
| gr::registerBlock<gr::testing::Copy, uint8_t, uint16_t, uint32_t, uint64_t, int8_t, int16_t, int32_t, int64_t, float, double, std::complex<float>, std::complex<double>, std::string,
gr::Packet<float>, gr::Packet<double>, gr::Tensor<float>, gr::Tensor<double>, gr::DataSet<float>, gr::DataSet<double>>(gr::globalBlockRegistry())
| gr::registerBlock<gr::testing::HeadBlock, uint8_t, uint16_t, uint32_t, uint64_t, int8_t, int16_t, int32_t, int64_t, float, double, std::complex<float>, std::complex<double>, std::string,
gr::Packet<float>, gr::Packet<double>, gr::Tensor<float>, gr::Tensor<double>, gr::DataSet<float>, gr::DataSet<double>>(gr::globalBlockRegistry())
| gr::registerBlock<gr::testing::NullSink, uint8_t, uint16_t, uint32_t, uint64_t, int8_t, int16_t, int32_t, int64_t, float, double, std::complex<float>, std::complex<double>, std::string,
gr::Packet<float>, gr::Packet<double>, gr::Tensor<float>, gr::Tensor<double>, gr::DataSet<float>, gr::DataSet<double>>(gr::globalBlockRegistry())
| gr::registerBlock<gr::testing::CountingSink, uint8_t, uint16_t, uint32_t, uint64_t, int8_t, int16_t, int32_t, int64_t, float, double, std::complex<float>, std::complex<double>, std::string,
gr::Packet<float>, gr::Packet<double>, gr::Tensor<float>, gr::Tensor<double>, gr::DataSet<float>, gr::DataSet<double>>(gr::globalBlockRegistry());
const inline auto registerNullSources = gr::registerBlock<gr::testing::NullSource, uint8_t, uint16_t, uint32_t, uint64_t, int8_t, int16_t, int32_t, int64_t, float, double, std::complex<float>, std::complex<double>, std::string, gr::Packet<float>, gr::Packet<double>, gr::Tensor<float>, gr::Tensor<double>, gr::DataSet<float>, gr::DataSet<double>>(gr::globalBlockRegistry()) | gr::registerBlock<gr::testing::ConstantSource, uint8_t, uint16_t, uint32_t, uint64_t, int8_t, int16_t, int32_t, int64_t, float, double, std::complex<float>, std::complex<double>, std::string, gr::Packet<float>, gr::Packet<double>, gr::Tensor<float>, gr::Tensor<double>, gr::DataSet<float>, gr::DataSet<double>>(gr::globalBlockRegistry()) | gr::registerBlock<gr::testing::CountingSource, uint8_t, uint16_t, uint32_t, uint64_t, int8_t, int16_t, int32_t, int64_t, float, double>(gr::globalBlockRegistry()) | gr::registerBlock<gr::testing::Copy, uint8_t, uint16_t, uint32_t, uint64_t, int8_t, int16_t, int32_t, int64_t, float, double, std::complex<float>, std::complex<double>, std::string, gr::Packet<float>, gr::Packet<double>, gr::Tensor<float>, gr::Tensor<double>, gr::DataSet<float>, gr::DataSet<double>>(gr::globalBlockRegistry()) | gr::registerBlock<gr::testing::HeadBlock, uint8_t, uint16_t, uint32_t, uint64_t, int8_t, int16_t, int32_t, int64_t, float, double, std::complex<float>, std::complex<double>, std::string, gr::Packet<float>, gr::Packet<double>, gr::Tensor<float>, gr::Tensor<double>, gr::DataSet<float>, gr::DataSet<double>>(gr::globalBlockRegistry()) | gr::registerBlock<gr::testing::NullSink, uint8_t, uint16_t, uint32_t, uint64_t, int8_t, int16_t, int32_t, int64_t, float, double, std::complex<float>, std::complex<double>, std::string, gr::Packet<float>, gr::Packet<double>, gr::Tensor<float>, gr::Tensor<double>, gr::DataSet<float>, gr::DataSet<double>>(gr::globalBlockRegistry()) |
gr::registerBlock<gr::testing::CountingSink, uint8_t, uint16_t, uint32_t, uint64_t, int8_t, int16_t, int32_t, int64_t, float, double, std::complex<float>, std::complex<double>, std::string, gr::Packet<float>, gr::Packet<double>, gr::Tensor<float>, gr::Tensor<double>, gr::DataSet<float>, gr::DataSet<double>>(gr::globalBlockRegistry());

#endif // GNURADIO_NULLSOURCES_HPP
10 changes: 0 additions & 10 deletions cmake/config.h.in

This file was deleted.

13 changes: 13 additions & 0 deletions cmake/config.hpp.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#ifndef GNURADIO_GRAPH_PROJECT_CONFIG
#define GNURADIO_GRAPH_PROJECT_CONFIG

#define CXX_COMPILER_PATH "@CMAKE_CXX_COMPILER@"
#define CXX_COMPILER_ARG1 "@CMAKE_CXX_COMPILER_ARG1@"
#define CXX_COMPILER_ID "@CMAKE_CXX_COMPILER_ID@"
#define CXX_COMPILER_VERSION "@CMAKE_CXX_COMPILER_VERSION@"
#define CXX_COMPILER_FLAGS "@ALL_COMPILER_FLAGS@"

#cmakedefine ENABLE_BLOCK_PLUGINS
#cmakedefine ENABLE_BLOCK_REGISTRY

#endif // GNURADIO_GRAPH_PROJECT_CONFIG
2 changes: 1 addition & 1 deletion core/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ target_include_directories(gnuradio-core INTERFACE $<BUILD_INTERFACE:${CMAKE_CUR
target_link_libraries(gnuradio-core INTERFACE gnuradio-options gnuradio-meta refl-cpp magic_enum pmtv vir)

# configure a header file to pass the CMake settings to the source code
configure_file("${PROJECT_SOURCE_DIR}/cmake/config.h.in" "${CMAKE_CURRENT_BINARY_DIR}/include/gnuradio-4.0/config.h" @ONLY)
configure_file("${PROJECT_SOURCE_DIR}/cmake/config.hpp.in" "${CMAKE_CURRENT_BINARY_DIR}/include/gnuradio-4.0/config.hpp" @ONLY)
# TODO: install configure file... but not really meaningful for header only library, since compile flags are defined by the user...

install(
Expand Down
Loading
Loading