From fbe58198740e84f259b021ff9ae9a94af995e6e1 Mon Sep 17 00:00:00 2001 From: Thomas Watson Date: Sat, 20 Jul 2024 10:41:12 -0500 Subject: [PATCH 1/2] add level of indirection to _encode and _decode This allows the entry point to be inlined at the caller site, paving the way for various optimizations. _encode now calls the non-inlined __encode function in the .c file which does the preliminary work then calls ___encode to encode the actual type, if compound (or e.g. canardEncodeScalar). --- templates/msg.c.em | 8 ++++---- templates/msg.h.em | 38 +++++++++++++++++++++++++++----------- 2 files changed, 31 insertions(+), 15 deletions(-) diff --git a/templates/msg.c.em b/templates/msg.c.em index 1b7d9cd..aa3f57e 100644 --- a/templates/msg.c.em +++ b/templates/msg.c.em @@ -11,14 +11,14 @@ #include #endif -uint32_t @(msg_underscored_name)_encode(@(msg_c_type)* msg, uint8_t* buffer +uint32_t _@(msg_underscored_name)_encode(@(msg_c_type)* msg, uint8_t* buffer #if CANARD_ENABLE_TAO_OPTION , bool tao #endif ) { uint32_t bit_ofs = 0; memset(buffer, 0, @(msg_define_name.upper())_MAX_SIZE); - _@(msg_underscored_name)_encode(buffer, &bit_ofs, msg, + __@(msg_underscored_name)_encode(buffer, &bit_ofs, msg, #if CANARD_ENABLE_TAO_OPTION tao #else @@ -31,14 +31,14 @@ uint32_t @(msg_underscored_name)_encode(@(msg_c_type)* msg, uint8_t* buffer /* return true if the decode is invalid */ -bool @(msg_underscored_name)_decode(const CanardRxTransfer* transfer, @(msg_c_type)* msg) { +bool _@(msg_underscored_name)_decode(const CanardRxTransfer* transfer, @(msg_c_type)* msg) { #if CANARD_ENABLE_TAO_OPTION if (transfer->tao && (transfer->payload_len > @(msg_define_name.upper())_MAX_SIZE)) { return true; /* invalid payload length */ } #endif uint32_t bit_ofs = 0; - if (_@(msg_underscored_name)_decode(transfer, &bit_ofs, msg, + if (__@(msg_underscored_name)_decode(transfer, &bit_ofs, msg, #if CANARD_ENABLE_TAO_OPTION transfer->tao #else diff --git a/templates/msg.h.em b/templates/msg.h.em index cb43c67..2ca435f 100644 --- a/templates/msg.h.em +++ b/templates/msg.h.em @@ -69,18 +69,34 @@ extern "C" { #endif -uint32_t @(msg_underscored_name)_encode(@(msg_c_type)* msg, uint8_t* buffer +uint32_t _@(msg_underscored_name)_encode(@(msg_c_type)* msg, uint8_t* buffer #if CANARD_ENABLE_TAO_OPTION , bool tao #endif ); -bool @(msg_underscored_name)_decode(const CanardRxTransfer* transfer, @(msg_c_type)* msg); +bool _@(msg_underscored_name)_decode(const CanardRxTransfer* transfer, @(msg_c_type)* msg); + +static inline uint32_t @(msg_underscored_name)_encode(@(msg_c_type)* msg, uint8_t* buffer +#if CANARD_ENABLE_TAO_OPTION + , bool tao +#endif +) { + return _@(msg_underscored_name)_encode(msg, buffer +#if CANARD_ENABLE_TAO_OPTION + , tao +#endif + ); +} + +static inline bool @(msg_underscored_name)_decode(const CanardRxTransfer* transfer, @(msg_c_type)* msg) { + return _@(msg_underscored_name)_decode(transfer, msg); +} #if defined(CANARD_DSDLC_INTERNAL) @{indent = 0}@{ind = ' '*indent}@ -static inline void _@(msg_underscored_name)_encode(uint8_t* buffer, uint32_t* bit_ofs, @(msg_c_type)* msg, bool tao); -static inline bool _@(msg_underscored_name)_decode(const CanardRxTransfer* transfer, uint32_t* bit_ofs, @(msg_c_type)* msg, bool tao); -void _@(msg_underscored_name)_encode(uint8_t* buffer, uint32_t* bit_ofs, @(msg_c_type)* msg, bool tao) { +static inline void __@(msg_underscored_name)_encode(uint8_t* buffer, uint32_t* bit_ofs, @(msg_c_type)* msg, bool tao); +static inline bool __@(msg_underscored_name)_decode(const CanardRxTransfer* transfer, uint32_t* bit_ofs, @(msg_c_type)* msg, bool tao); +void __@(msg_underscored_name)_encode(uint8_t* buffer, uint32_t* bit_ofs, @(msg_c_type)* msg, bool tao) { @{indent += 1}@{ind = ' '*indent}@ @(ind)(void)buffer; @(ind)(void)bit_ofs; @@ -101,7 +117,7 @@ void _@(msg_underscored_name)_encode(uint8_t* buffer, uint32_t* bit_ofs, @(msg_c @{indent += 1}@{ind = ' '*indent}@ @[ end if]@ @[ if field.type.category == field.type.CATEGORY_COMPOUND]@ -@(ind)_@(underscored_name(field.type))_encode(buffer, bit_ofs, &msg->@(field.name), @('tao' if (field == msg_fields[-1] or msg_union) else 'false')); +@(ind)__@(underscored_name(field.type))_encode(buffer, bit_ofs, &msg->@(field.name), @('tao' if (field == msg_fields[-1] or msg_union) else 'false')); @[ elif field.type.category == field.type.CATEGORY_PRIMITIVE]@ @[ if field.type.kind == field.type.KIND_FLOAT and field.type.bitlen == 16]@ @(ind){ @@ -144,7 +160,7 @@ void _@(msg_underscored_name)_encode(uint8_t* buffer, uint32_t* bit_ofs, @(msg_c @[ end if]@ @(ind)*bit_ofs += @(field.type.value_type.bitlen); @[ elif field.type.value_type.category == field.type.value_type.CATEGORY_COMPOUND]@ -@(ind)_@(underscored_name(field.type.value_type))_encode(buffer, bit_ofs, &msg->@(field_get_data(field))[i], @[if field == msg_fields[-1] and field.type.value_type.get_min_bitlen() < 8]tao && i==msg->@(field.name).len@[else]false@[end if]); +@(ind)__@(underscored_name(field.type.value_type))_encode(buffer, bit_ofs, &msg->@(field_get_data(field))[i], @[if field == msg_fields[-1] and field.type.value_type.get_min_bitlen() < 8]tao && i==msg->@(field.name).len@[else]false@[end if]); @[ end if]@ @{indent -= 1}@{ind = ' '*indent}@ @(ind)} @@ -167,7 +183,7 @@ void _@(msg_underscored_name)_encode(uint8_t* buffer, uint32_t* bit_ofs, @(msg_c /* decode @(msg_underscored_name), return true on failure, false on success */ -bool _@(msg_underscored_name)_decode(const CanardRxTransfer* transfer, uint32_t* bit_ofs, @(msg_c_type)* msg, bool tao) { +bool __@(msg_underscored_name)_decode(const CanardRxTransfer* transfer, uint32_t* bit_ofs, @(msg_c_type)* msg, bool tao) { @{indent += 1}@{ind = ' '*indent}@ @(ind)(void)transfer; @(ind)(void)bit_ofs; @@ -194,7 +210,7 @@ bool _@(msg_underscored_name)_decode(const CanardRxTransfer* transfer, uint32_t* @{indent += 1}@{ind = ' '*indent}@ @[ end if]@ @[ if field.type.category == field.type.CATEGORY_COMPOUND]@ -@(ind)if (_@(underscored_name(field.type))_decode(transfer, bit_ofs, &msg->@(field.name), @('tao' if (field == msg_fields[-1] or msg_union) else 'false'))) {return true;} +@(ind)if (__@(underscored_name(field.type))_decode(transfer, bit_ofs, &msg->@(field.name), @('tao' if (field == msg_fields[-1] or msg_union) else 'false'))) {return true;} @[ elif field.type.category == field.type.CATEGORY_PRIMITIVE]@ @[ if field.type.kind == field.type.KIND_FLOAT and field.type.bitlen == 16]@ @(ind){ @@ -235,7 +251,7 @@ bool _@(msg_underscored_name)_decode(const CanardRxTransfer* transfer, uint32_t* @(ind)uint32_t max_bits = (transfer->payload_len*8)-7; // TAO elements must be >= 8 bits @(ind)while (max_bits > *bit_ofs) { @{indent += 1}@{ind = ' '*indent}@ -@(ind)if (!max_len-- || _@(underscored_name(field.type.value_type))_decode(transfer, bit_ofs, &msg->@(field_get_data(field))[msg->@(field.name).len], @[if field == msg_fields[-1] and field.type.value_type.get_min_bitlen() < 8]tao && i==msg->@(field.name).len@[else]false@[end if])) {return true;} +@(ind)if (!max_len-- || __@(underscored_name(field.type.value_type))_decode(transfer, bit_ofs, &msg->@(field_get_data(field))[msg->@(field.name).len], @[if field == msg_fields[-1] and field.type.value_type.get_min_bitlen() < 8]tao && i==msg->@(field.name).len@[else]false@[end if])) {return true;} @(ind)msg->@(field.name).len++; @{indent -= 1}@{ind = ' '*indent}@ @(ind)} @@ -269,7 +285,7 @@ bool _@(msg_underscored_name)_decode(const CanardRxTransfer* transfer, uint32_t* @[ end if]@ @(ind)*bit_ofs += @(field.type.value_type.bitlen); @[ elif field.type.value_type.category == field.type.value_type.CATEGORY_COMPOUND]@ -@(ind)if (_@(underscored_name(field.type.value_type))_decode(transfer, bit_ofs, &msg->@(field_get_data(field))[i], @[if field == msg_fields[-1] and field.type.value_type.get_min_bitlen() < 8]tao && i==msg->@(field.name).len@[else]false@[end if])) {return true;} +@(ind)if (__@(underscored_name(field.type.value_type))_decode(transfer, bit_ofs, &msg->@(field_get_data(field))[i], @[if field == msg_fields[-1] and field.type.value_type.get_min_bitlen() < 8]tao && i==msg->@(field.name).len@[else]false@[end if])) {return true;} @[ end if]@ @{indent -= 1}@{ind = ' '*indent}@ @(ind)} From 436bc22977ce03046e83132c30e45c354c5cdd42 Mon Sep 17 00:00:00 2001 From: Thomas Watson Date: Sat, 20 Jul 2024 10:59:47 -0500 Subject: [PATCH 2/2] inline coding of 0-length messages Allows the processing of 0-length messages (which is true of some important ones in the DSDL) to be optimized away. --- templates/msg.h.em | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/templates/msg.h.em b/templates/msg.h.em index 2ca435f..52feae1 100644 --- a/templates/msg.h.em +++ b/templates/msg.h.em @@ -81,15 +81,32 @@ static inline uint32_t @(msg_underscored_name)_encode(@(msg_c_type)* msg, uint8_ , bool tao #endif ) { +@[if msg_max_bitlen == 0] + (void)msg; + (void)buffer; +#if CANARD_ENABLE_TAO_OPTION + (void)tao; +#endif + + return 0; // 0-length message encodes to 0 bytes +@[else] return _@(msg_underscored_name)_encode(msg, buffer #if CANARD_ENABLE_TAO_OPTION , tao #endif ); +@[end if] } static inline bool @(msg_underscored_name)_decode(const CanardRxTransfer* transfer, @(msg_c_type)* msg) { +@[if msg_max_bitlen == 0] + (void)msg; + + // all transports accurately convey a payload length of 0 bytes so any payload is an error + return transfer->payload_len != 0; +@[else] return _@(msg_underscored_name)_decode(transfer, msg); +@[end if] } #if defined(CANARD_DSDLC_INTERNAL)