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.
This commit is contained in:
Catherine 2024-02-13 12:15:59 +00:00
parent 606bbef30c
commit ae1a67ba47
2 changed files with 16 additions and 9 deletions

View File

@ -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;

View File

@ -1176,7 +1176,7 @@ struct debug_item : ::cxxrtl_object {
template<size_t Bits>
debug_item(value<Bits> &item, size_t lsb_offset = 0, uint32_t flags_ = 0) {
static_assert(sizeof(item) == value<Bits>::chunks * sizeof(chunk_t),
static_assert(Bits == 0 || sizeof(item) == value<Bits>::chunks * sizeof(chunk_t),
"value<Bits> is not compatible with C layout");
type = VALUE;
flags = flags_;
@ -1192,7 +1192,7 @@ struct debug_item : ::cxxrtl_object {
template<size_t Bits>
debug_item(const value<Bits> &item, size_t lsb_offset = 0) {
static_assert(sizeof(item) == value<Bits>::chunks * sizeof(chunk_t),
static_assert(Bits == 0 || sizeof(item) == value<Bits>::chunks * sizeof(chunk_t),
"value<Bits> is not compatible with C layout");
type = VALUE;
flags = DRIVEN_COMB;
@ -1208,8 +1208,9 @@ struct debug_item : ::cxxrtl_object {
template<size_t Bits>
debug_item(wire<Bits> &item, size_t lsb_offset = 0, uint32_t flags_ = 0) {
static_assert(sizeof(item.curr) == value<Bits>::chunks * sizeof(chunk_t) &&
sizeof(item.next) == value<Bits>::chunks * sizeof(chunk_t),
static_assert(Bits == 0 ||
(sizeof(item.curr) == value<Bits>::chunks * sizeof(chunk_t) &&
sizeof(item.next) == value<Bits>::chunks * sizeof(chunk_t)),
"wire<Bits> is not compatible with C layout");
type = WIRE;
flags = flags_;
@ -1225,7 +1226,7 @@ struct debug_item : ::cxxrtl_object {
template<size_t Width>
debug_item(memory<Width> &item, size_t zero_offset = 0) {
static_assert(sizeof(item.data[0]) == value<Width>::chunks * sizeof(chunk_t),
static_assert(Width == 0 || sizeof(item.data[0]) == value<Width>::chunks * sizeof(chunk_t),
"memory<Width> is not compatible with C layout");
type = MEMORY;
flags = 0;
@ -1241,7 +1242,7 @@ struct debug_item : ::cxxrtl_object {
template<size_t Bits>
debug_item(debug_alias, const value<Bits> &item, size_t lsb_offset = 0) {
static_assert(sizeof(item) == value<Bits>::chunks * sizeof(chunk_t),
static_assert(Bits == 0 || sizeof(item) == value<Bits>::chunks * sizeof(chunk_t),
"value<Bits> is not compatible with C layout");
type = ALIAS;
flags = DRIVEN_COMB;
@ -1257,8 +1258,9 @@ struct debug_item : ::cxxrtl_object {
template<size_t Bits>
debug_item(debug_alias, const wire<Bits> &item, size_t lsb_offset = 0) {
static_assert(sizeof(item.curr) == value<Bits>::chunks * sizeof(chunk_t) &&
sizeof(item.next) == value<Bits>::chunks * sizeof(chunk_t),
static_assert(Bits == 0 ||
(sizeof(item.curr) == value<Bits>::chunks * sizeof(chunk_t) &&
sizeof(item.next) == value<Bits>::chunks * sizeof(chunk_t)),
"wire<Bits> is not compatible with C layout");
type = ALIAS;
flags = DRIVEN_COMB;
@ -1274,7 +1276,7 @@ struct debug_item : ::cxxrtl_object {
template<size_t Bits>
debug_item(debug_outline &group, const value<Bits> &item, size_t lsb_offset = 0) {
static_assert(sizeof(item) == value<Bits>::chunks * sizeof(chunk_t),
static_assert(Bits == 0 || sizeof(item) == value<Bits>::chunks * sizeof(chunk_t),
"value<Bits> is not compatible with C layout");
type = OUTLINE;
flags = DRIVEN_COMB;