From: whitequark Date: Wed, 2 Sep 2020 15:18:44 +0000 (+0000) Subject: cxxrtl: expose port direction in debug information. X-Git-Tag: working-ls180~278^2~2 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=b025ee0aa646268747c121c97cf0673eb06e632b;p=yosys.git cxxrtl: expose port direction in debug information. This can be useful to distinguish e.g. a combinatorially driven wire with type `CXXRTL_VALUE` from a module input with the same type, as well as general introspection. --- diff --git a/backends/cxxrtl/cxxrtl.h b/backends/cxxrtl/cxxrtl.h index e3c96d422..df42f5807 100644 --- a/backends/cxxrtl/cxxrtl.h +++ b/backends/cxxrtl/cxxrtl.h @@ -452,7 +452,7 @@ struct value : public expr_base> { bool carry = CarryIn; for (size_t n = 0; n < result.chunks; n++) { result.data[n] = data[n] + (Invert ? ~other.data[n] : other.data[n]) + carry; - if (result.chunks - 1 == n) + if (result.chunks - 1 == n) result.data[result.chunks - 1] &= result.msb_mask; carry = (result.data[n] < data[n]) || (result.data[n] == data[n] && carry); @@ -824,6 +824,7 @@ struct debug_alias {}; // To avoid violating strict aliasing rules, this structure has to be a subclass of the one used // in the C API, or it would not be possible to cast between the pointers to these. struct debug_item : ::cxxrtl_object { + // Object types. enum : uint32_t { VALUE = CXXRTL_VALUE, WIRE = CXXRTL_WIRE, @@ -831,13 +832,21 @@ struct debug_item : ::cxxrtl_object { ALIAS = CXXRTL_ALIAS, }; + // Object flags. + enum : uint32_t { + INPUT = CXXRTL_INPUT, + OUTPUT = CXXRTL_OUTPUT, + INOUT = CXXRTL_INOUT, + }; + debug_item(const ::cxxrtl_object &object) : cxxrtl_object(object) {} template - debug_item(value &item, size_t lsb_offset = 0) { + debug_item(value &item, size_t lsb_offset = 0, uint32_t flags_ = 0) { static_assert(sizeof(item) == value::chunks * sizeof(chunk_t), "value is not compatible with C layout"); type = VALUE; + flags = flags_; width = Bits; lsb_at = lsb_offset; depth = 1; @@ -847,10 +856,11 @@ struct debug_item : ::cxxrtl_object { } template - debug_item(const value &item, size_t lsb_offset = 0) { + debug_item(const value &item, size_t lsb_offset = 0, uint32_t flags_ = 0) { static_assert(sizeof(item) == value::chunks * sizeof(chunk_t), "value is not compatible with C layout"); type = VALUE; + flags = flags_; width = Bits; lsb_at = lsb_offset; depth = 1; @@ -860,11 +870,12 @@ struct debug_item : ::cxxrtl_object { } template - debug_item(wire &item, size_t lsb_offset = 0) { + 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), "wire is not compatible with C layout"); type = WIRE; + flags = flags_; width = Bits; lsb_at = lsb_offset; depth = 1; @@ -878,6 +889,7 @@ struct debug_item : ::cxxrtl_object { static_assert(sizeof(item.data[0]) == value::chunks * sizeof(chunk_t), "memory is not compatible with C layout"); type = MEMORY; + flags = 0; width = Width; lsb_at = 0; depth = item.data.size(); @@ -891,6 +903,7 @@ struct debug_item : ::cxxrtl_object { static_assert(sizeof(item) == value::chunks * sizeof(chunk_t), "value is not compatible with C layout"); type = ALIAS; + flags = 0; width = Bits; lsb_at = lsb_offset; depth = 1; @@ -905,6 +918,7 @@ struct debug_item : ::cxxrtl_object { sizeof(item.next) == value::chunks * sizeof(chunk_t), "wire is not compatible with C layout"); type = ALIAS; + flags = 0; width = Bits; lsb_at = lsb_offset; depth = 1; diff --git a/backends/cxxrtl/cxxrtl_backend.cc b/backends/cxxrtl/cxxrtl_backend.cc index c045af692..07f42d375 100644 --- a/backends/cxxrtl/cxxrtl_backend.cc +++ b/backends/cxxrtl/cxxrtl_backend.cc @@ -1662,7 +1662,14 @@ struct CxxrtlWorker { // Member wire f << indent << "items.add(path + " << escape_cxx_string(get_hdl_name(wire)); f << ", debug_item(" << mangle(wire) << ", "; - f << wire->start_offset << "));\n"; + f << wire->start_offset; + if (wire->port_input && wire->port_output) + f << ", debug_item::INOUT"; + else if (wire->port_input) + f << ", debug_item::INPUT"; + else if (wire->port_output) + f << ", debug_item::OUTPUT"; + f << "));\n"; count_member_wires++; } else { count_skipped_wires++; diff --git a/backends/cxxrtl/cxxrtl_capi.h b/backends/cxxrtl/cxxrtl_capi.h index 447c9e1f3..d2e9787dd 100644 --- a/backends/cxxrtl/cxxrtl_capi.h +++ b/backends/cxxrtl/cxxrtl_capi.h @@ -112,6 +112,28 @@ enum cxxrtl_type { // More object types may be added in the future, but the existing ones will never change. }; +// Flags of a simulated object. +enum cxxrtl_flag { + // Node is a module input port. + // + // This flag can be set on objects of type `CXXRTL_VALUE` and `CXXRTL_WIRE`. It may be combined + // with `CXXRTL_OUTPUT`, as well as other flags. + CXXRTL_INPUT = 1 << 0, + + // Node is a module output port. + // + // This flag can be set on objects of type `CXXRTL_WIRE`. It may be combined with `CXXRTL_INPUT`, + // as well as other flags. + CXXRTL_OUTPUT = 1 << 1, + + // Node is a module inout port. + // + // This flag can be set on objects of type `CXXRTL_WIRE`. It may be combined with other flags. + CXXRTL_INOUT = (CXXRTL_INPUT|CXXRTL_OUTPUT), + + // More object flags may be added in the future, but the existing ones will never change. +}; + // Description of a simulated object. // // The `data` array can be accessed directly to inspect and, if applicable, modify the bits @@ -123,6 +145,9 @@ struct cxxrtl_object { // determines all other properties of the object. uint32_t type; // actually `enum cxxrtl_type` + // Flags of the object. + uint32_t flags; // actually bit mask of `enum cxxrtl_flags` + // Width of the object in bits. size_t width;