Skip to content
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
25 changes: 25 additions & 0 deletions include/interrupt/concepts.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
#include <interrupt/fwd.hpp>
#include <interrupt/policies.hpp>

#include <stdx/ct_conversions.hpp>
#include <stdx/ct_string.hpp>
#include <stdx/tuple.hpp>
#include <stdx/type_traits.hpp>

Expand Down Expand Up @@ -61,4 +63,27 @@ concept nexus_for = requires {
T::template service<Flow>();
{ T::template service<Flow>.active } -> std::same_as<bool const &>;
};

namespace detail {
template <typename T> constexpr auto config_string1() {
if constexpr (requires {
[]<auto N>(stdx::ct_string<N>) {}(T::config());
}) {
return stdx::ct<T::config()>();
} else if constexpr (requires {
[]<auto N>(stdx::ct_string<N>) {}(T::name);
}) {
return stdx::ct<T::name>();
} else {
constexpr auto s = stdx::type_as_string<T>();
return stdx::ct<stdx::ct_string<s.size() + 1>{s}>();
}
}

template <typename... Ts> constexpr auto config_string_for() {
using namespace stdx::literals;
return stdx::tuple{config_string1<Ts>()...}.join(
""_ctst, [](auto lhs, auto rhs) { return lhs + ", "_ctst + rhs; });
}
} // namespace detail
} // namespace interrupt
36 changes: 36 additions & 0 deletions include/interrupt/config.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@
#include <interrupt/impl.hpp>
#include <interrupt/policies.hpp>

#include <stdx/ct_format.hpp>
#include <stdx/tuple.hpp>
#include <stdx/tuple_algorithms.hpp>
#include <stdx/utility.hpp>

namespace interrupt {
namespace detail {
Expand Down Expand Up @@ -96,6 +98,13 @@ struct irq : detail::policy_config<Policies>,
detail::super_config<Number, Priority>,
detail::flow_config<Flows...> {
template <typename... Nexi> using built_t = irq_impl<irq, Nexi...>;

constexpr static auto config() {
using namespace stdx::literals;
return +stdx::ct_format<"interrupt::irq<{}_irq, {}, {}>">(
stdx::ct<stdx::to_underlying(Number)>(), stdx::ct<Priority>(),
detail::config_string_for<Policies, Flows...>());
}
};

template <typename EnableField, typename StatusField, typename Policies,
Expand All @@ -105,6 +114,13 @@ struct sub_irq : detail::policy_config<Policies>,
detail::sub_config<EnableField, StatusField>,
detail::flow_config<Flows...> {
template <typename... Nexi> using built_t = sub_irq_impl<sub_irq, Nexi...>;

constexpr static auto config() {
using namespace stdx::literals;
return +stdx::ct_format<"interrupt::sub_irq<{}>">(
detail::config_string_for<EnableField, StatusField, Policies,
Flows...>());
}
};

template <typename EnableField, typename Policies>
Expand All @@ -113,6 +129,12 @@ struct id_irq : detail::policy_config<Policies>,
detail::sub_config<EnableField, status_t<>> {
template <typename...> using built_t = id_irq_impl<id_irq>;
template <typename> constexpr static bool triggers_flow = false;

constexpr static auto config() {
using namespace stdx::literals;
return +stdx::ct_format<"interrupt::id_irq<{}>">(
detail::config_string_for<EnableField, Policies>());
}
};

template <irq_num_t Number, priority_t Priority, typename Policies,
Expand All @@ -131,6 +153,13 @@ struct shared_irq : detail::policy_config<Policies>,
template <typename Flow>
constexpr static bool triggers_flow =
(... or Cfgs::template triggers_flow<Flow>);

constexpr static auto config() {
using namespace stdx::literals;
return +stdx::ct_format<"interrupt::shared_irq<{}_irq, {}, {}>">(
stdx::ct<stdx::to_underlying(Number)>(), stdx::ct<Priority>(),
detail::config_string_for<Policies, Cfgs...>());
}
};

template <typename EnableField, typename StatusField, typename Policies,
Expand All @@ -149,5 +178,12 @@ struct shared_sub_irq : detail::policy_config<Policies>,
template <typename Flow>
constexpr static bool triggers_flow =
(... or Cfgs::template triggers_flow<Flow>);

constexpr static auto config() {
using namespace stdx::literals;
return +stdx::ct_format<"interrupt::shared_sub_irq<{}>">(
detail::config_string_for<EnableField, StatusField, Policies,
Cfgs...>());
}
};
} // namespace interrupt
9 changes: 7 additions & 2 deletions include/interrupt/manager.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
#include <interrupt/dynamic_controller.hpp>
#include <interrupt/hal.hpp>

#include <stdx/ct_format.hpp>
#include <stdx/tuple.hpp>
#include <stdx/type_traits.hpp>
#include <stdx/utility.hpp>

Expand All @@ -14,13 +16,16 @@ namespace interrupt {
namespace detail {
template <typename Dynamic, irq_interface... Impls> struct manager {
void init() const {
// TODO: log exact interrupt manager configuration
// (should be a single compile-time string with no arguments)
hal::init();
init_mcu_interrupts();
init_sub_interrupts();
}

constexpr static auto config() {
return +stdx::ct_format<"interrupt::root<{}>">(
detail::config_string_for<Impls...>());
}

void init_mcu_interrupts() const { (Impls::init_mcu_interrupts(), ...); }

void init_sub_interrupts() const {
Expand Down
1 change: 1 addition & 0 deletions test/interrupt/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
add_tests(
FILES
dynamic_controller
id_irq_impl
irq_impl
manager
shared_irq_impl
Expand Down
6 changes: 2 additions & 4 deletions test/interrupt/common.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,16 +34,15 @@ struct test_hal {
} // namespace
template <> inline auto interrupt::injected_hal<> = test_hal{};

namespace {
template <typename T> inline bool flow_run{};

template <typename T> struct flow {
template <typename T> struct flow_t {
auto operator()() const { flow_run<T> = true; }
constexpr static bool active{T::value};
};

struct test_nexus {
template <typename T> constexpr static auto service = flow<T>{};
template <typename T> constexpr static auto service = flow_t<T>{};
};

template <auto> struct enable_field_t {
Expand All @@ -64,4 +63,3 @@ template <typename Field> constexpr auto clear(Field) {
template <typename... Ops> constexpr auto apply(Ops... ops) {
return (ops(), ...);
}
} // namespace
28 changes: 28 additions & 0 deletions test/interrupt/id_irq_impl.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#include "common.hpp"

#include <interrupt/concepts.hpp>

#include <catch2/catch_test_macros.hpp>

#include <type_traits>

namespace {
using config_t = interrupt::id_irq<enable_field_t<0>, interrupt::policies<>>;
} // namespace

TEST_CASE("config models concept", "[id_irq_impl]") {
STATIC_REQUIRE(interrupt::sub_irq_config<config_t>);
}

TEST_CASE("impl models concept", "[id_irq_impl]") {
using impl_t = interrupt::id_irq_impl<config_t>;
STATIC_REQUIRE(interrupt::sub_irq_interface<impl_t>);
}

TEST_CASE("impl can dump config", "[id_irq_impl]") {
using namespace stdx::literals;
using impl_t = interrupt::id_irq_impl<config_t>;
constexpr auto s = impl_t::config();
STATIC_REQUIRE(
s == "interrupt::id_irq<enable_field_t<0>, interrupt::policies<>>"_cts);
}
20 changes: 20 additions & 0 deletions test/interrupt/irq_impl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

#include <interrupt/concepts.hpp>

#include <stdx/ct_string.hpp>

#include <catch2/catch_test_macros.hpp>

#include <type_traits>
Expand Down Expand Up @@ -46,11 +48,29 @@ TEST_CASE("impl models concept", "[irq_impl]") {
STATIC_REQUIRE(interrupt::irq_interface<impl_t>);
}

TEST_CASE("impl can dump config (no flows)", "[irq_impl]") {
using namespace stdx::literals;
using impl_t = interrupt::irq_impl<no_flows_config_t, test_nexus>;
constexpr auto s = impl_t::config();
STATIC_REQUIRE(s ==
"interrupt::irq<42_irq, 17, interrupt::policies<>>"_cts);
}

namespace {
template <typename T>
using flow_config_t = interrupt::irq<17_irq, 42, interrupt::policies<>, T>;
} // namespace

TEST_CASE("impl can dump config (some flows)", "[irq_impl]") {
using namespace stdx::literals;
using impl_t =
interrupt::irq_impl<flow_config_t<std::true_type>, test_nexus>;
constexpr auto s = impl_t::config();
STATIC_REQUIRE(
s ==
"interrupt::irq<17_irq, 42, interrupt::policies<>, std::integral_constant<bool, true>>"_cts);
}

TEST_CASE("impl runs a flow", "[irq_impl]") {
using impl_t =
interrupt::irq_impl<flow_config_t<std::true_type>, test_nexus>;
Expand Down
16 changes: 14 additions & 2 deletions test/interrupt/manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@

#include <type_traits>

namespace {
struct flow_1 : std::true_type {};
struct flow_2 : std::true_type {};

namespace {
using config_a =
interrupt::root<interrupt::irq<17_irq, 42, interrupt::policies<>, flow_1>>;
using config_b = interrupt::root<
Expand All @@ -30,6 +30,18 @@ TEST_CASE("init enables interrupts", "[manager]") {
CHECK(priority<17_irq> == 42);
}

TEST_CASE("manager can dump config", "[manager]") {
using namespace stdx::literals;
constexpr auto s1 = interrupt::manager<config_a, test_nexus>::config();
STATIC_REQUIRE(
s1 ==
"interrupt::root<interrupt::irq<17_irq, 42, interrupt::policies<>, flow_1>>"_cts);
constexpr auto s2 = interrupt::manager<config_b, test_nexus>::config();
STATIC_REQUIRE(
s2 ==
"interrupt::root<interrupt::irq<17_irq, 42, interrupt::policies<>, flow_1, flow_2>>"_cts);
}

TEST_CASE("run single flow", "[manager]") {
auto m = interrupt::manager<config_a, test_nexus>{};
flow_run<flow_1> = false;
Expand All @@ -54,7 +66,7 @@ namespace {
template <typename Flow> struct alt_flow : Flow {};

struct alt_nexus {
template <typename T> constexpr static auto service = flow<alt_flow<T>>{};
template <typename T> constexpr static auto service = flow_t<alt_flow<T>>{};
};
} // namespace

Expand Down
17 changes: 17 additions & 0 deletions test/interrupt/shared_irq_impl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,14 @@ TEST_CASE("impl models concept", "[shared_irq_impl]") {
STATIC_REQUIRE(interrupt::irq_interface<impl_t>);
}

TEST_CASE("impl can dump config (no subs)", "[shared_irq_impl]") {
using namespace stdx::literals;
using impl_t = interrupt::shared_irq_impl<no_flows_config_t>;
constexpr auto s = impl_t::config();
STATIC_REQUIRE(
s == "interrupt::shared_irq<42_irq, 17, interrupt::policies<>>"_cts);
}

namespace {
template <typename T, auto N>
using sub_config_t = interrupt::sub_irq<enable_field_t<N>, status_field_t<N>,
Expand All @@ -56,6 +64,15 @@ using flow_config_t = interrupt::shared_irq<17_irq, 42, interrupt::policies<>,
sub_config_t<T, 0>>;
} // namespace

TEST_CASE("impl can dump config (some subs)", "[shared_irq_impl]") {
using namespace stdx::literals;
using impl_t = interrupt::shared_irq_impl<flow_config_t<std::true_type>>;
constexpr auto s = impl_t::config();
STATIC_REQUIRE(
s ==
"interrupt::shared_irq<17_irq, 42, interrupt::policies<>, interrupt::sub_irq<enable_field_t<0>, status_field_t<0>, interrupt::policies<>, std::integral_constant<bool, true>>>"_cts);
}

TEST_CASE("impl runs a flow", "[shared_irq_impl]") {
using sub_impl_t =
interrupt::sub_irq_impl<sub_config_t<std::true_type, 0>, test_nexus>;
Expand Down
18 changes: 18 additions & 0 deletions test/interrupt/shared_sub_irq_impl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,15 @@ TEST_CASE("impl models concept", "[shared_sub_irq_impl]") {
STATIC_REQUIRE(interrupt::sub_irq_interface<impl_t>);
}

TEST_CASE("impl can dump config (no flows)", "[shared_sub_irq_impl]") {
using namespace stdx::literals;
using impl_t = interrupt::shared_sub_irq_impl<no_flows_config_t>;
constexpr auto s = impl_t::config();
STATIC_REQUIRE(
s ==
"interrupt::shared_sub_irq<enable_field_t<0>, status_field_t<0>, interrupt::policies<>>"_cts);
}

namespace {
template <typename T, auto N>
using sub_config_t = interrupt::sub_irq<enable_field_t<N>, status_field_t<N>,
Expand All @@ -46,6 +55,15 @@ using flow_config_t =
interrupt::policies<>, sub_config_t<T, 1>>;
} // namespace

TEST_CASE("impl can dump config (some flows)", "[shared_sub_irq_impl]") {
using namespace stdx::literals;
using impl_t = interrupt::sub_irq_impl<flow_config_t<std::true_type>>;
constexpr auto s = impl_t::config();
STATIC_REQUIRE(
s ==
"interrupt::shared_sub_irq<enable_field_t<0>, status_field_t<0>, interrupt::policies<>, interrupt::sub_irq<enable_field_t<1>, status_field_t<1>, interrupt::policies<>, std::integral_constant<bool, true>>>"_cts);
}

TEST_CASE("impl runs a flow", "[shared_sub_irq_impl]") {
using sub_impl_t =
interrupt::sub_irq_impl<sub_config_t<std::true_type, 1>, test_nexus>;
Expand Down
19 changes: 19 additions & 0 deletions test/interrupt/sub_irq_impl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,31 @@ TEST_CASE("impl models concept", "[sub_irq_impl]") {
STATIC_REQUIRE(interrupt::sub_irq_interface<impl_t>);
}

TEST_CASE("impl can dump config (no flows)", "[sub_irq_impl]") {
using namespace stdx::literals;
using impl_t = interrupt::sub_irq_impl<no_flows_config_t, test_nexus>;
constexpr auto s = impl_t::config();
STATIC_REQUIRE(
s ==
"interrupt::sub_irq<enable_field_t<0>, status_field_t<0>, interrupt::policies<>>"_cts);
}

namespace {
template <typename T>
using flow_config_t = interrupt::sub_irq<enable_field_t<0>, status_field_t<0>,
interrupt::policies<>, T>;
}

TEST_CASE("impl can dump config (some flows)", "[sub_irq_impl]") {
using namespace stdx::literals;
using impl_t =
interrupt::sub_irq_impl<flow_config_t<std::true_type>, test_nexus>;
constexpr auto s = impl_t::config();
STATIC_REQUIRE(
s ==
"interrupt::sub_irq<enable_field_t<0>, status_field_t<0>, interrupt::policies<>, std::integral_constant<bool, true>>"_cts);
}

TEST_CASE("impl runs a flow when enabled and status", "[sub_irq_impl]") {
using impl_t =
interrupt::sub_irq_impl<flow_config_t<std::true_type>, test_nexus>;
Expand Down
Loading