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
4 changes: 3 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,9 @@ target_sources(
include
FILES
include/log/catalog/catalog.hpp
include/log/catalog/mipi_encoder.hpp)
include/log/catalog/mipi_builder.hpp
include/log/catalog/mipi_encoder.hpp
include/log/catalog/mipi_messages.hpp)

add_library(cib_nexus INTERFACE)
target_compile_features(cib_nexus INTERFACE cxx_std_20)
Expand Down
116 changes: 116 additions & 0 deletions include/log/catalog/mipi_builder.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
#pragma once

#include <log/catalog/catalog.hpp>
#include <log/catalog/mipi_messages.hpp>

#include <stdx/compiler.hpp>
#include <stdx/utility.hpp>

#include <array>
#include <concepts>
#include <cstdint>
#include <cstring>
#include <utility>

namespace logging::mipi {
template <typename> struct builder;

template <> struct builder<defn::short32_msg_t> {
template <auto Level, std::same_as<std::uint32_t>... Ts>
ALWAYS_INLINE static auto build(string_id id, module_id, Ts...) {
using namespace msg;
return owning<defn::short32_msg_t>{"payload"_field = id};
}
};

template <typename Storage> struct catalog_builder {
template <auto Level, std::same_as<std::uint32_t>... Ts>
ALWAYS_INLINE static auto build(string_id id, module_id m, Ts... msg_data) {
using namespace msg;
defn::catalog_msg_t::owner_t<Storage> message{"severity"_field = Level,
"module_id"_field = m};

constexpr auto header_size =
defn::catalog_msg_t::size<typename Storage::value_type>::value;
constexpr auto copy_arg = [](std::uint32_t arg, auto &dest) {
std::memcpy(dest, &arg, sizeof(std::uint32_t));
dest += sizeof(std::uint32_t);
};
auto dest = &message.data()[header_size];
copy_arg(stdx::to_le(id), dest);
(copy_arg(stdx::to_le(msg_data), dest), ...);

return message;
}
};

template <typename Storage>
requires std::same_as<typename Storage::value_type, std::uint32_t>
struct catalog_builder<Storage> {
template <auto Level, std::same_as<std::uint32_t>... Ts>
ALWAYS_INLINE static auto build(string_id id, module_id m, Ts... msg_data) {
using namespace msg;
defn::catalog_msg_t::owner_t<Storage> message{"severity"_field = Level,
"module_id"_field = m};

constexpr auto header_size =
defn::catalog_msg_t::size<std::uint32_t>::value;
auto dest = &message.data()[header_size];
*dest++ = stdx::to_le(id);
((*dest++ = stdx::to_le(msg_data)), ...);

return message;
}
};

template <> struct builder<defn::catalog_msg_t> {
template <auto Level, std::same_as<std::uint32_t>... Ts>
ALWAYS_INLINE static auto build(string_id id, module_id m, Ts... msg_data) {
using namespace msg;
if constexpr (sizeof...(Ts) <= 2u) {
constexpr auto header_size =
defn::catalog_msg_t::size<std::uint32_t>::value;
constexpr auto payload_len = 1 + sizeof...(Ts);
using storage_t =
std::array<std::uint32_t, header_size + payload_len>;
return catalog_builder<storage_t>{}.template build<Level>(
id, m, msg_data...);
} else {
constexpr auto header_size =
defn::catalog_msg_t::size<std::uint8_t>::value;
constexpr auto payload_len = (sizeof(id) + ... + sizeof(Ts));
using storage_t =
std::array<std::uint8_t, header_size + payload_len>;
return catalog_builder<storage_t>{}.template build<Level>(
id, m, msg_data...);
}
}
};

struct default_builder {
template <auto Level, std::same_as<std::uint32_t>... Ts>
ALWAYS_INLINE static auto build(string_id id, module_id m, Ts... msg_data) {
if constexpr (sizeof...(Ts) == 0u) {
return builder<defn::short32_msg_t>{}.template build<Level>(
id, m, msg_data...);
} else {
return builder<defn::catalog_msg_t>{}.template build<Level>(
id, m, msg_data...);
}
}
};

[[maybe_unused]] constexpr inline struct get_builder_t {
template <typename T>
requires true
CONSTEVAL auto operator()(T &&t) const noexcept(
noexcept(std::forward<T>(t).query(std::declval<get_builder_t>())))
-> decltype(std::forward<T>(t).query(*this)) {
return std::forward<T>(t).query(*this);
}

CONSTEVAL auto operator()(auto &&) const {
return stdx::ct<default_builder{}>();
}
} get_builder;
} // namespace logging::mipi
139 changes: 23 additions & 116 deletions include/log/catalog/mipi_encoder.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@

#include <conc/concurrency.hpp>
#include <log/catalog/catalog.hpp>
#include <log/catalog/mipi_builder.hpp>
#include <log/catalog/mipi_messages.hpp>
#include <log/log.hpp>
#include <log/module.hpp>
#include <msg/message.hpp>

#include <stdx/bit.hpp>
#include <stdx/compiler.hpp>
Expand Down Expand Up @@ -37,68 +38,6 @@ template <stdx::ct_string S> constexpr auto to_module() {
}
} // namespace detail

namespace defn {
using msg::at;
using msg::dword_index_t;
using msg::field;
using msg::message;
using msg::operator""_msb;
using msg::operator""_lsb;

enum struct type : uint8_t { Build = 0, Short32 = 1, Catalog = 3 };
enum struct build_subtype : uint8_t { Compact32 = 0, Compact64 = 1, Long = 2 };
enum struct catalog_subtype : uint8_t { Id32_Pack32 = 1 };

using type_f = field<"type", type>::located<at{dword_index_t{0}, 3_msb, 0_lsb}>;
using opt_len_f =
field<"opt_len", bool>::located<at{dword_index_t{0}, 9_msb, 9_lsb}>;
using payload_len_f =
field<"payload_len",
std::uint16_t>::located<at{dword_index_t{1}, 15_msb, 0_lsb}>;

using build_subtype_f =
field<"subtype",
build_subtype>::located<at{dword_index_t{0}, 29_msb, 24_lsb}>;
using compact32_build_id_f = field<"build_id", std::uint32_t>::located<
at{dword_index_t{0}, 31_msb, 30_lsb}, at{dword_index_t{0}, 23_msb, 4_lsb}>;
using compact64_build_id_f = field<"build_id", std::uint64_t>::located<
at{dword_index_t{1}, 31_msb, 0_lsb}, at{dword_index_t{0}, 31_msb, 30_lsb},
at{dword_index_t{0}, 23_msb, 4_lsb}>;

using normal_build_msg_t =
message<"normal_build", type_f::with_required<type::Build>,
opt_len_f::with_required<true>,
build_subtype_f::with_required<build_subtype::Long>, payload_len_f>;
using compact32_build_msg_t =
message<"compact32_build", type_f::with_required<type::Build>,
build_subtype_f::with_required<build_subtype::Compact32>,
compact32_build_id_f>;
using compact64_build_msg_t =
message<"compact64_build", type_f::with_required<type::Build>,
build_subtype_f::with_required<build_subtype::Compact64>,
compact64_build_id_f>;

using short32_payload_f =
field<"payload",
std::uint32_t>::located<at{dword_index_t{0}, 31_msb, 4_lsb}>;
using short32_msg_t =
message<"short32", type_f::with_required<type::Short32>, short32_payload_f>;

using catalog_subtype_f =
field<"subtype",
catalog_subtype>::located<at{dword_index_t{0}, 29_msb, 24_lsb}>;
using severity_f = field<"severity", std::uint8_t>::located<at{dword_index_t{0},
6_msb, 4_lsb}>;
using module_id_f =
field<"module_id",
std::uint8_t>::located<at{dword_index_t{0}, 22_msb, 16_lsb}>;

using catalog_msg_t =
message<"catalog", type_f::with_required<type::Catalog>, severity_f,
module_id_f,
catalog_subtype_f::with_required<catalog_subtype::Id32_Pack32>>;
} // namespace defn

template <typename TDestinations> struct log_handler {
constexpr explicit log_handler(TDestinations &&ds) : dests{std::move(ds)} {}

Expand All @@ -116,8 +55,10 @@ template <typename TDestinations> struct log_handler {
using Message = decltype(detail::to_message<S, Args...>());
using Module =
decltype(detail::to_module<get_module(Env{}).value>());
dispatch_message<L>(catalog<Message>(), module<Module>(),
static_cast<std::uint32_t>(args)...);
auto builder = get_builder(Env{}).value;
write(
builder.template build<L>(catalog<Message>(), module<Module>(),
static_cast<std::uint32_t>(args)...));
});
}

Expand All @@ -126,11 +67,11 @@ template <typename TDestinations> struct log_handler {
if constexpr (S.empty() and stdx::bit_width(Version) <= 22) {
owning<defn::compact32_build_msg_t> message{"build_id"_field =
Version};
dispatch_pass_by_args(message.data()[0]);
write(message);
} else if constexpr (S.empty() and stdx::bit_width(Version) <= 54) {
owning<defn::compact64_build_msg_t> message{"build_id"_field =
Version};
dispatch_pass_by_args(message.data()[0], message.data()[1]);
write(message);
} else {
constexpr auto header_size =
defn::normal_build_msg_t::size<std::uint8_t>::value;
Expand All @@ -146,25 +87,13 @@ template <typename TDestinations> struct log_handler {
dest = std::copy_n(stdx::bit_cast<std::uint8_t const *>(&ver),
sizeof(std::uint64_t), dest);
std::copy_n(std::cbegin(S.value), S.size(), dest);
dispatch_pass_by_buffer(message.data());
write(message);
}
}

private:
template <typename... MsgDataTypes>
NEVER_INLINE auto
dispatch_pass_by_args(MsgDataTypes &&...msg_data) -> void {
stdx::for_each(
[&]<typename Dest>(Dest &dest) {
conc::call_in_critical_section<Dest>([&] {
dest.log_by_args(std::forward<MsgDataTypes>(msg_data)...);
});
},
dests);
}

NEVER_INLINE auto
dispatch_pass_by_buffer(stdx::span<std::uint8_t const> msg) -> void {
template <std::size_t N>
NEVER_INLINE auto write(stdx::span<std::uint8_t const, N> msg) -> void {
stdx::for_each(
[&]<typename Dest>(Dest &dest) {
conc::call_in_critical_section<Dest>(
Expand All @@ -173,42 +102,20 @@ template <typename TDestinations> struct log_handler {
dests);
}

template <auto Level, std::same_as<std::uint32_t>... MsgDataTypes>
ALWAYS_INLINE auto dispatch_message(string_id id,
[[maybe_unused]] module_id m,
MsgDataTypes... msg_data) -> void {
using namespace msg;
if constexpr (sizeof...(msg_data) == 0u) {
owning<defn::short32_msg_t> message{"payload"_field = id};
dispatch_pass_by_args(message.data()[0]);
} else if constexpr (sizeof...(MsgDataTypes) <= 2u) {
owning<defn::catalog_msg_t> message{"severity"_field = Level,
"module_id"_field = m};
dispatch_pass_by_args(
message.data()[0], stdx::to_le(id),
stdx::to_le(std::forward<MsgDataTypes>(msg_data))...);
} else {
constexpr auto header_size =
defn::catalog_msg_t::size<std::uint8_t>::value;
constexpr auto payload_len =
(sizeof(id) + ... + sizeof(MsgDataTypes));
using storage_t =
std::array<std::uint8_t, header_size + payload_len>;

defn::catalog_msg_t::owner_t<storage_t> message{
"severity"_field = Level, "module_id"_field = m};

constexpr auto copy_arg = [](std::uint32_t arg, auto &dest) {
std::memcpy(dest, &arg, sizeof(std::uint32_t));
dest += sizeof(std::uint32_t);
};
auto dest = &message.data()[header_size];
copy_arg(stdx::to_le(id), dest);
(copy_arg(stdx::to_le(msg_data), dest), ...);
dispatch_pass_by_buffer(message.data());
}
template <std::size_t N>
NEVER_INLINE auto write(stdx::span<std::uint32_t const, N> msg) -> void {
[&]<std::size_t... Is>(std::index_sequence<Is...>) {
stdx::for_each(
[&]<typename Dest>(Dest &dest) {
conc::call_in_critical_section<Dest>(
[&] { dest.log_by_args(msg[Is]...); });
},
dests);
}(std::make_index_sequence<N>{});
}

auto write(auto const &msg) -> void { write(msg.as_const_view().data()); }

TDestinations dests;
};

Expand Down
67 changes: 67 additions & 0 deletions include/log/catalog/mipi_messages.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
#pragma once

#include <msg/message.hpp>

namespace logging::mipi {
namespace defn {
using msg::at;
using msg::dword_index_t;
using msg::field;
using msg::message;
using msg::operator""_msb;
using msg::operator""_lsb;

enum struct type : uint8_t { Build = 0, Short32 = 1, Catalog = 3 };
enum struct build_subtype : uint8_t { Compact32 = 0, Compact64 = 1, Long = 2 };
enum struct catalog_subtype : uint8_t { Id32_Pack32 = 1 };

using type_f = field<"type", type>::located<at{dword_index_t{0}, 3_msb, 0_lsb}>;
using opt_len_f =
field<"opt_len", bool>::located<at{dword_index_t{0}, 9_msb, 9_lsb}>;
using payload_len_f =
field<"payload_len",
std::uint16_t>::located<at{dword_index_t{1}, 15_msb, 0_lsb}>;

using build_subtype_f =
field<"subtype",
build_subtype>::located<at{dword_index_t{0}, 29_msb, 24_lsb}>;
using compact32_build_id_f = field<"build_id", std::uint32_t>::located<
at{dword_index_t{0}, 31_msb, 30_lsb}, at{dword_index_t{0}, 23_msb, 4_lsb}>;
using compact64_build_id_f = field<"build_id", std::uint64_t>::located<
at{dword_index_t{1}, 31_msb, 0_lsb}, at{dword_index_t{0}, 31_msb, 30_lsb},
at{dword_index_t{0}, 23_msb, 4_lsb}>;

using normal_build_msg_t =
message<"normal_build", type_f::with_required<type::Build>,
opt_len_f::with_required<true>,
build_subtype_f::with_required<build_subtype::Long>, payload_len_f>;
using compact32_build_msg_t =
message<"compact32_build", type_f::with_required<type::Build>,
build_subtype_f::with_required<build_subtype::Compact32>,
compact32_build_id_f>;
using compact64_build_msg_t =
message<"compact64_build", type_f::with_required<type::Build>,
build_subtype_f::with_required<build_subtype::Compact64>,
compact64_build_id_f>;

using short32_payload_f =
field<"payload",
std::uint32_t>::located<at{dword_index_t{0}, 31_msb, 4_lsb}>;
using short32_msg_t =
message<"short32", type_f::with_required<type::Short32>, short32_payload_f>;

using catalog_subtype_f =
field<"subtype",
catalog_subtype>::located<at{dword_index_t{0}, 29_msb, 24_lsb}>;
using severity_f = field<"severity", std::uint8_t>::located<at{dword_index_t{0},
6_msb, 4_lsb}>;
using module_id_f =
field<"module_id",
std::uint8_t>::located<at{dword_index_t{0}, 22_msb, 16_lsb}>;

using catalog_msg_t =
message<"catalog", type_f::with_required<type::Catalog>, severity_f,
module_id_f,
catalog_subtype_f::with_required<catalog_subtype::Id32_Pack32>>;
} // namespace defn
} // namespace logging::mipi
Loading
Loading