Skip to content

Commit faedd52

Browse files
authored
Merge pull request #688 from elbeno/log-message-control
✨ Allow overriding the mipi message type
2 parents 0556202 + bddece0 commit faedd52

File tree

5 files changed

+253
-133
lines changed

5 files changed

+253
-133
lines changed

CMakeLists.txt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,9 @@ target_sources(
207207
include
208208
FILES
209209
include/log/catalog/catalog.hpp
210-
include/log/catalog/mipi_encoder.hpp)
210+
include/log/catalog/mipi_builder.hpp
211+
include/log/catalog/mipi_encoder.hpp
212+
include/log/catalog/mipi_messages.hpp)
211213

212214
add_library(cib_nexus INTERFACE)
213215
target_compile_features(cib_nexus INTERFACE cxx_std_20)
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
#pragma once
2+
3+
#include <log/catalog/catalog.hpp>
4+
#include <log/catalog/mipi_messages.hpp>
5+
6+
#include <stdx/compiler.hpp>
7+
#include <stdx/utility.hpp>
8+
9+
#include <array>
10+
#include <concepts>
11+
#include <cstdint>
12+
#include <cstring>
13+
#include <utility>
14+
15+
namespace logging::mipi {
16+
template <typename> struct builder;
17+
18+
template <> struct builder<defn::short32_msg_t> {
19+
template <auto Level, std::same_as<std::uint32_t>... Ts>
20+
ALWAYS_INLINE static auto build(string_id id, module_id, Ts...) {
21+
using namespace msg;
22+
return owning<defn::short32_msg_t>{"payload"_field = id};
23+
}
24+
};
25+
26+
template <typename Storage> struct catalog_builder {
27+
template <auto Level, std::same_as<std::uint32_t>... Ts>
28+
ALWAYS_INLINE static auto build(string_id id, module_id m, Ts... msg_data) {
29+
using namespace msg;
30+
defn::catalog_msg_t::owner_t<Storage> message{"severity"_field = Level,
31+
"module_id"_field = m};
32+
33+
constexpr auto header_size =
34+
defn::catalog_msg_t::size<typename Storage::value_type>::value;
35+
constexpr auto copy_arg = [](std::uint32_t arg, auto &dest) {
36+
std::memcpy(dest, &arg, sizeof(std::uint32_t));
37+
dest += sizeof(std::uint32_t);
38+
};
39+
auto dest = &message.data()[header_size];
40+
copy_arg(stdx::to_le(id), dest);
41+
(copy_arg(stdx::to_le(msg_data), dest), ...);
42+
43+
return message;
44+
}
45+
};
46+
47+
template <typename Storage>
48+
requires std::same_as<typename Storage::value_type, std::uint32_t>
49+
struct catalog_builder<Storage> {
50+
template <auto Level, std::same_as<std::uint32_t>... Ts>
51+
ALWAYS_INLINE static auto build(string_id id, module_id m, Ts... msg_data) {
52+
using namespace msg;
53+
defn::catalog_msg_t::owner_t<Storage> message{"severity"_field = Level,
54+
"module_id"_field = m};
55+
56+
constexpr auto header_size =
57+
defn::catalog_msg_t::size<std::uint32_t>::value;
58+
auto dest = &message.data()[header_size];
59+
*dest++ = stdx::to_le(id);
60+
((*dest++ = stdx::to_le(msg_data)), ...);
61+
62+
return message;
63+
}
64+
};
65+
66+
template <> struct builder<defn::catalog_msg_t> {
67+
template <auto Level, std::same_as<std::uint32_t>... Ts>
68+
ALWAYS_INLINE static auto build(string_id id, module_id m, Ts... msg_data) {
69+
using namespace msg;
70+
if constexpr (sizeof...(Ts) <= 2u) {
71+
constexpr auto header_size =
72+
defn::catalog_msg_t::size<std::uint32_t>::value;
73+
constexpr auto payload_len = 1 + sizeof...(Ts);
74+
using storage_t =
75+
std::array<std::uint32_t, header_size + payload_len>;
76+
return catalog_builder<storage_t>{}.template build<Level>(
77+
id, m, msg_data...);
78+
} else {
79+
constexpr auto header_size =
80+
defn::catalog_msg_t::size<std::uint8_t>::value;
81+
constexpr auto payload_len = (sizeof(id) + ... + sizeof(Ts));
82+
using storage_t =
83+
std::array<std::uint8_t, header_size + payload_len>;
84+
return catalog_builder<storage_t>{}.template build<Level>(
85+
id, m, msg_data...);
86+
}
87+
}
88+
};
89+
90+
struct default_builder {
91+
template <auto Level, std::same_as<std::uint32_t>... Ts>
92+
ALWAYS_INLINE static auto build(string_id id, module_id m, Ts... msg_data) {
93+
if constexpr (sizeof...(Ts) == 0u) {
94+
return builder<defn::short32_msg_t>{}.template build<Level>(
95+
id, m, msg_data...);
96+
} else {
97+
return builder<defn::catalog_msg_t>{}.template build<Level>(
98+
id, m, msg_data...);
99+
}
100+
}
101+
};
102+
103+
[[maybe_unused]] constexpr inline struct get_builder_t {
104+
template <typename T>
105+
requires true
106+
CONSTEVAL auto operator()(T &&t) const noexcept(
107+
noexcept(std::forward<T>(t).query(std::declval<get_builder_t>())))
108+
-> decltype(std::forward<T>(t).query(*this)) {
109+
return std::forward<T>(t).query(*this);
110+
}
111+
112+
CONSTEVAL auto operator()(auto &&) const {
113+
return stdx::ct<default_builder{}>();
114+
}
115+
} get_builder;
116+
} // namespace logging::mipi

include/log/catalog/mipi_encoder.hpp

Lines changed: 23 additions & 116 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,10 @@
22

33
#include <conc/concurrency.hpp>
44
#include <log/catalog/catalog.hpp>
5+
#include <log/catalog/mipi_builder.hpp>
6+
#include <log/catalog/mipi_messages.hpp>
57
#include <log/log.hpp>
68
#include <log/module.hpp>
7-
#include <msg/message.hpp>
89

910
#include <stdx/bit.hpp>
1011
#include <stdx/compiler.hpp>
@@ -37,68 +38,6 @@ template <stdx::ct_string S> constexpr auto to_module() {
3738
}
3839
} // namespace detail
3940

40-
namespace defn {
41-
using msg::at;
42-
using msg::dword_index_t;
43-
using msg::field;
44-
using msg::message;
45-
using msg::operator""_msb;
46-
using msg::operator""_lsb;
47-
48-
enum struct type : uint8_t { Build = 0, Short32 = 1, Catalog = 3 };
49-
enum struct build_subtype : uint8_t { Compact32 = 0, Compact64 = 1, Long = 2 };
50-
enum struct catalog_subtype : uint8_t { Id32_Pack32 = 1 };
51-
52-
using type_f = field<"type", type>::located<at{dword_index_t{0}, 3_msb, 0_lsb}>;
53-
using opt_len_f =
54-
field<"opt_len", bool>::located<at{dword_index_t{0}, 9_msb, 9_lsb}>;
55-
using payload_len_f =
56-
field<"payload_len",
57-
std::uint16_t>::located<at{dword_index_t{1}, 15_msb, 0_lsb}>;
58-
59-
using build_subtype_f =
60-
field<"subtype",
61-
build_subtype>::located<at{dword_index_t{0}, 29_msb, 24_lsb}>;
62-
using compact32_build_id_f = field<"build_id", std::uint32_t>::located<
63-
at{dword_index_t{0}, 31_msb, 30_lsb}, at{dword_index_t{0}, 23_msb, 4_lsb}>;
64-
using compact64_build_id_f = field<"build_id", std::uint64_t>::located<
65-
at{dword_index_t{1}, 31_msb, 0_lsb}, at{dword_index_t{0}, 31_msb, 30_lsb},
66-
at{dword_index_t{0}, 23_msb, 4_lsb}>;
67-
68-
using normal_build_msg_t =
69-
message<"normal_build", type_f::with_required<type::Build>,
70-
opt_len_f::with_required<true>,
71-
build_subtype_f::with_required<build_subtype::Long>, payload_len_f>;
72-
using compact32_build_msg_t =
73-
message<"compact32_build", type_f::with_required<type::Build>,
74-
build_subtype_f::with_required<build_subtype::Compact32>,
75-
compact32_build_id_f>;
76-
using compact64_build_msg_t =
77-
message<"compact64_build", type_f::with_required<type::Build>,
78-
build_subtype_f::with_required<build_subtype::Compact64>,
79-
compact64_build_id_f>;
80-
81-
using short32_payload_f =
82-
field<"payload",
83-
std::uint32_t>::located<at{dword_index_t{0}, 31_msb, 4_lsb}>;
84-
using short32_msg_t =
85-
message<"short32", type_f::with_required<type::Short32>, short32_payload_f>;
86-
87-
using catalog_subtype_f =
88-
field<"subtype",
89-
catalog_subtype>::located<at{dword_index_t{0}, 29_msb, 24_lsb}>;
90-
using severity_f = field<"severity", std::uint8_t>::located<at{dword_index_t{0},
91-
6_msb, 4_lsb}>;
92-
using module_id_f =
93-
field<"module_id",
94-
std::uint8_t>::located<at{dword_index_t{0}, 22_msb, 16_lsb}>;
95-
96-
using catalog_msg_t =
97-
message<"catalog", type_f::with_required<type::Catalog>, severity_f,
98-
module_id_f,
99-
catalog_subtype_f::with_required<catalog_subtype::Id32_Pack32>>;
100-
} // namespace defn
101-
10241
template <typename TDestinations> struct log_handler {
10342
constexpr explicit log_handler(TDestinations &&ds) : dests{std::move(ds)} {}
10443

@@ -116,8 +55,10 @@ template <typename TDestinations> struct log_handler {
11655
using Message = decltype(detail::to_message<S, Args...>());
11756
using Module =
11857
decltype(detail::to_module<get_module(Env{}).value>());
119-
dispatch_message<L>(catalog<Message>(), module<Module>(),
120-
static_cast<std::uint32_t>(args)...);
58+
auto builder = get_builder(Env{}).value;
59+
write(
60+
builder.template build<L>(catalog<Message>(), module<Module>(),
61+
static_cast<std::uint32_t>(args)...));
12162
});
12263
}
12364

@@ -126,11 +67,11 @@ template <typename TDestinations> struct log_handler {
12667
if constexpr (S.empty() and stdx::bit_width(Version) <= 22) {
12768
owning<defn::compact32_build_msg_t> message{"build_id"_field =
12869
Version};
129-
dispatch_pass_by_args(message.data()[0]);
70+
write(message);
13071
} else if constexpr (S.empty() and stdx::bit_width(Version) <= 54) {
13172
owning<defn::compact64_build_msg_t> message{"build_id"_field =
13273
Version};
133-
dispatch_pass_by_args(message.data()[0], message.data()[1]);
74+
write(message);
13475
} else {
13576
constexpr auto header_size =
13677
defn::normal_build_msg_t::size<std::uint8_t>::value;
@@ -146,25 +87,13 @@ template <typename TDestinations> struct log_handler {
14687
dest = std::copy_n(stdx::bit_cast<std::uint8_t const *>(&ver),
14788
sizeof(std::uint64_t), dest);
14889
std::copy_n(std::cbegin(S.value), S.size(), dest);
149-
dispatch_pass_by_buffer(message.data());
90+
write(message);
15091
}
15192
}
15293

15394
private:
154-
template <typename... MsgDataTypes>
155-
NEVER_INLINE auto
156-
dispatch_pass_by_args(MsgDataTypes &&...msg_data) -> void {
157-
stdx::for_each(
158-
[&]<typename Dest>(Dest &dest) {
159-
conc::call_in_critical_section<Dest>([&] {
160-
dest.log_by_args(std::forward<MsgDataTypes>(msg_data)...);
161-
});
162-
},
163-
dests);
164-
}
165-
166-
NEVER_INLINE auto
167-
dispatch_pass_by_buffer(stdx::span<std::uint8_t const> msg) -> void {
95+
template <std::size_t N>
96+
NEVER_INLINE auto write(stdx::span<std::uint8_t const, N> msg) -> void {
16897
stdx::for_each(
16998
[&]<typename Dest>(Dest &dest) {
17099
conc::call_in_critical_section<Dest>(
@@ -173,42 +102,20 @@ template <typename TDestinations> struct log_handler {
173102
dests);
174103
}
175104

176-
template <auto Level, std::same_as<std::uint32_t>... MsgDataTypes>
177-
ALWAYS_INLINE auto dispatch_message(string_id id,
178-
[[maybe_unused]] module_id m,
179-
MsgDataTypes... msg_data) -> void {
180-
using namespace msg;
181-
if constexpr (sizeof...(msg_data) == 0u) {
182-
owning<defn::short32_msg_t> message{"payload"_field = id};
183-
dispatch_pass_by_args(message.data()[0]);
184-
} else if constexpr (sizeof...(MsgDataTypes) <= 2u) {
185-
owning<defn::catalog_msg_t> message{"severity"_field = Level,
186-
"module_id"_field = m};
187-
dispatch_pass_by_args(
188-
message.data()[0], stdx::to_le(id),
189-
stdx::to_le(std::forward<MsgDataTypes>(msg_data))...);
190-
} else {
191-
constexpr auto header_size =
192-
defn::catalog_msg_t::size<std::uint8_t>::value;
193-
constexpr auto payload_len =
194-
(sizeof(id) + ... + sizeof(MsgDataTypes));
195-
using storage_t =
196-
std::array<std::uint8_t, header_size + payload_len>;
197-
198-
defn::catalog_msg_t::owner_t<storage_t> message{
199-
"severity"_field = Level, "module_id"_field = m};
200-
201-
constexpr auto copy_arg = [](std::uint32_t arg, auto &dest) {
202-
std::memcpy(dest, &arg, sizeof(std::uint32_t));
203-
dest += sizeof(std::uint32_t);
204-
};
205-
auto dest = &message.data()[header_size];
206-
copy_arg(stdx::to_le(id), dest);
207-
(copy_arg(stdx::to_le(msg_data), dest), ...);
208-
dispatch_pass_by_buffer(message.data());
209-
}
105+
template <std::size_t N>
106+
NEVER_INLINE auto write(stdx::span<std::uint32_t const, N> msg) -> void {
107+
[&]<std::size_t... Is>(std::index_sequence<Is...>) {
108+
stdx::for_each(
109+
[&]<typename Dest>(Dest &dest) {
110+
conc::call_in_critical_section<Dest>(
111+
[&] { dest.log_by_args(msg[Is]...); });
112+
},
113+
dests);
114+
}(std::make_index_sequence<N>{});
210115
}
211116

117+
auto write(auto const &msg) -> void { write(msg.as_const_view().data()); }
118+
212119
TDestinations dests;
213120
};
214121

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
#pragma once
2+
3+
#include <msg/message.hpp>
4+
5+
namespace logging::mipi {
6+
namespace defn {
7+
using msg::at;
8+
using msg::dword_index_t;
9+
using msg::field;
10+
using msg::message;
11+
using msg::operator""_msb;
12+
using msg::operator""_lsb;
13+
14+
enum struct type : uint8_t { Build = 0, Short32 = 1, Catalog = 3 };
15+
enum struct build_subtype : uint8_t { Compact32 = 0, Compact64 = 1, Long = 2 };
16+
enum struct catalog_subtype : uint8_t { Id32_Pack32 = 1 };
17+
18+
using type_f = field<"type", type>::located<at{dword_index_t{0}, 3_msb, 0_lsb}>;
19+
using opt_len_f =
20+
field<"opt_len", bool>::located<at{dword_index_t{0}, 9_msb, 9_lsb}>;
21+
using payload_len_f =
22+
field<"payload_len",
23+
std::uint16_t>::located<at{dword_index_t{1}, 15_msb, 0_lsb}>;
24+
25+
using build_subtype_f =
26+
field<"subtype",
27+
build_subtype>::located<at{dword_index_t{0}, 29_msb, 24_lsb}>;
28+
using compact32_build_id_f = field<"build_id", std::uint32_t>::located<
29+
at{dword_index_t{0}, 31_msb, 30_lsb}, at{dword_index_t{0}, 23_msb, 4_lsb}>;
30+
using compact64_build_id_f = field<"build_id", std::uint64_t>::located<
31+
at{dword_index_t{1}, 31_msb, 0_lsb}, at{dword_index_t{0}, 31_msb, 30_lsb},
32+
at{dword_index_t{0}, 23_msb, 4_lsb}>;
33+
34+
using normal_build_msg_t =
35+
message<"normal_build", type_f::with_required<type::Build>,
36+
opt_len_f::with_required<true>,
37+
build_subtype_f::with_required<build_subtype::Long>, payload_len_f>;
38+
using compact32_build_msg_t =
39+
message<"compact32_build", type_f::with_required<type::Build>,
40+
build_subtype_f::with_required<build_subtype::Compact32>,
41+
compact32_build_id_f>;
42+
using compact64_build_msg_t =
43+
message<"compact64_build", type_f::with_required<type::Build>,
44+
build_subtype_f::with_required<build_subtype::Compact64>,
45+
compact64_build_id_f>;
46+
47+
using short32_payload_f =
48+
field<"payload",
49+
std::uint32_t>::located<at{dword_index_t{0}, 31_msb, 4_lsb}>;
50+
using short32_msg_t =
51+
message<"short32", type_f::with_required<type::Short32>, short32_payload_f>;
52+
53+
using catalog_subtype_f =
54+
field<"subtype",
55+
catalog_subtype>::located<at{dword_index_t{0}, 29_msb, 24_lsb}>;
56+
using severity_f = field<"severity", std::uint8_t>::located<at{dword_index_t{0},
57+
6_msb, 4_lsb}>;
58+
using module_id_f =
59+
field<"module_id",
60+
std::uint8_t>::located<at{dword_index_t{0}, 22_msb, 16_lsb}>;
61+
62+
using catalog_msg_t =
63+
message<"catalog", type_f::with_required<type::Catalog>, severity_f,
64+
module_id_f,
65+
catalog_subtype_f::with_required<catalog_subtype::Id32_Pack32>>;
66+
} // namespace defn
67+
} // namespace logging::mipi

0 commit comments

Comments
 (0)