From ae1a67ba47ce5d9d531a1fd89c4e687ed558994e Mon Sep 17 00:00:00 2001 From: Catherine Date: Tue, 13 Feb 2024 12:15:59 +0000 Subject: [PATCH] cxxrtl: fix debug information for zero-width items. Because all objects in C++ must have non-zero size, a `value<0>` has a size of 4 despite consisting of a `uint32_t chunks[0]`. The debug item assertions were not written expecting that and prevent any debug items for such values from compiling. The C API does not define exactly what happens for a zero-width debug item, but it seems OK to say that they should refer to some unique pointer that cannot be, in actuality, read or written. This allows some techniques or optimizations that use `curr` pointers as keys and assume they correspond 1-to-1 to simulation objects. --- .../cxxrtl/runtime/cxxrtl/capi/cxxrtl_capi.h | 5 +++++ backends/cxxrtl/runtime/cxxrtl/cxxrtl.h | 20 ++++++++++--------- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/backends/cxxrtl/runtime/cxxrtl/capi/cxxrtl_capi.h b/backends/cxxrtl/runtime/cxxrtl/capi/cxxrtl_capi.h index e5c84bf65..c2a9d37e1 100644 --- a/backends/cxxrtl/runtime/cxxrtl/capi/cxxrtl_capi.h +++ b/backends/cxxrtl/runtime/cxxrtl/capi/cxxrtl_capi.h @@ -240,6 +240,11 @@ struct cxxrtl_object { // through wires, the bits are double buffered. To avoid race conditions, user code should // always read from `curr` and write to `next`. The `curr` pointer is always valid; for objects // that cannot be modified, or cannot be modified in a race-free way, `next` is NULL. + // + // In case where `width == 0`, `curr` is a non-NULL pointer unique for the wire. That is, + // there is a 1-to-1 correspondence between simulation objects and `curr` pointers, regardless + // of whether they have storage or not. (Aliases' `curr` pointer equals that of some other + // simulated object.) uint32_t *curr; uint32_t *next; diff --git a/backends/cxxrtl/runtime/cxxrtl/cxxrtl.h b/backends/cxxrtl/runtime/cxxrtl/cxxrtl.h index ee55011e8..8b7cf4da8 100644 --- a/backends/cxxrtl/runtime/cxxrtl/cxxrtl.h +++ b/backends/cxxrtl/runtime/cxxrtl/cxxrtl.h @@ -1176,7 +1176,7 @@ struct debug_item : ::cxxrtl_object { template debug_item(value &item, size_t lsb_offset = 0, uint32_t flags_ = 0) { - static_assert(sizeof(item) == value::chunks * sizeof(chunk_t), + static_assert(Bits == 0 || sizeof(item) == value::chunks * sizeof(chunk_t), "value is not compatible with C layout"); type = VALUE; flags = flags_; @@ -1192,7 +1192,7 @@ struct debug_item : ::cxxrtl_object { template debug_item(const value &item, size_t lsb_offset = 0) { - static_assert(sizeof(item) == value::chunks * sizeof(chunk_t), + static_assert(Bits == 0 || sizeof(item) == value::chunks * sizeof(chunk_t), "value is not compatible with C layout"); type = VALUE; flags = DRIVEN_COMB; @@ -1208,8 +1208,9 @@ struct debug_item : ::cxxrtl_object { template debug_item(wire &item, size_t lsb_offset = 0, uint32_t flags_ = 0) { - static_assert(sizeof(item.curr) == value::chunks * sizeof(chunk_t) && - sizeof(item.next) == value::chunks * sizeof(chunk_t), + static_assert(Bits == 0 || + (sizeof(item.curr) == value::chunks * sizeof(chunk_t) && + sizeof(item.next) == value::chunks * sizeof(chunk_t)), "wire is not compatible with C layout"); type = WIRE; flags = flags_; @@ -1225,7 +1226,7 @@ struct debug_item : ::cxxrtl_object { template debug_item(memory &item, size_t zero_offset = 0) { - static_assert(sizeof(item.data[0]) == value::chunks * sizeof(chunk_t), + static_assert(Width == 0 || sizeof(item.data[0]) == value::chunks * sizeof(chunk_t), "memory is not compatible with C layout"); type = MEMORY; flags = 0; @@ -1241,7 +1242,7 @@ struct debug_item : ::cxxrtl_object { template debug_item(debug_alias, const value &item, size_t lsb_offset = 0) { - static_assert(sizeof(item) == value::chunks * sizeof(chunk_t), + static_assert(Bits == 0 || sizeof(item) == value::chunks * sizeof(chunk_t), "value is not compatible with C layout"); type = ALIAS; flags = DRIVEN_COMB; @@ -1257,8 +1258,9 @@ struct debug_item : ::cxxrtl_object { template debug_item(debug_alias, const wire &item, size_t lsb_offset = 0) { - static_assert(sizeof(item.curr) == value::chunks * sizeof(chunk_t) && - sizeof(item.next) == value::chunks * sizeof(chunk_t), + static_assert(Bits == 0 || + (sizeof(item.curr) == value::chunks * sizeof(chunk_t) && + sizeof(item.next) == value::chunks * sizeof(chunk_t)), "wire is not compatible with C layout"); type = ALIAS; flags = DRIVEN_COMB; @@ -1274,7 +1276,7 @@ struct debug_item : ::cxxrtl_object { template debug_item(debug_outline &group, const value &item, size_t lsb_offset = 0) { - static_assert(sizeof(item) == value::chunks * sizeof(chunk_t), + static_assert(Bits == 0 || sizeof(item) == value::chunks * sizeof(chunk_t), "value is not compatible with C layout"); type = OUTLINE; flags = DRIVEN_COMB;