cxxrtl: expose port direction in debug information.
authorwhitequark <whitequark@whitequark.org>
Wed, 2 Sep 2020 15:18:44 +0000 (15:18 +0000)
committerwhitequark <whitequark@whitequark.org>
Wed, 2 Sep 2020 17:19:11 +0000 (17:19 +0000)
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.

backends/cxxrtl/cxxrtl.h
backends/cxxrtl/cxxrtl_backend.cc
backends/cxxrtl/cxxrtl_capi.h

index e3c96d422b98a42e661ed13671dcb4fbbdc30763..df42f5807ced2b29f8d529d35808b74dbc658515 100644 (file)
@@ -452,7 +452,7 @@ struct value : public expr_base<value<Bits>> {
                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<size_t Bits>
-       debug_item(value<Bits> &item, size_t lsb_offset = 0) {
+       debug_item(value<Bits> &item, size_t lsb_offset = 0, uint32_t flags_ = 0) {
                static_assert(sizeof(item) == value<Bits>::chunks * sizeof(chunk_t),
                              "value<Bits> 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<size_t Bits>
-       debug_item(const value<Bits> &item, size_t lsb_offset = 0) {
+       debug_item(const value<Bits> &item, size_t lsb_offset = 0, uint32_t flags_ = 0) {
                static_assert(sizeof(item) == value<Bits>::chunks * sizeof(chunk_t),
                              "value<Bits> 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<size_t Bits>
-       debug_item(wire<Bits> &item, size_t lsb_offset = 0) {
+       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),
                              "wire<Bits> 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<Width>::chunks * sizeof(chunk_t),
                              "memory<Width> 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<Bits>::chunks * sizeof(chunk_t),
                              "value<Bits> 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<Bits>::chunks * sizeof(chunk_t),
                              "wire<Bits> is not compatible with C layout");
                type    = ALIAS;
+               flags   = 0;
                width   = Bits;
                lsb_at  = lsb_offset;
                depth   = 1;
index c045af69211ee5a9c662defb57d23e32e3f4d5c4..07f42d3750e6311be354adf1d0a8189eeb34aa92 100644 (file)
@@ -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++;
index 447c9e1f383d427223bebee909e93ba6e3c2f8d3..d2e9787dd4d1adeda79122519728f121a387b004 100644 (file)
@@ -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;