Merge pull request #435 from antmicro/signed-wire

systemverilog: Fix signed wire handling
diff --git a/systemverilog-plugin/UhdmAst.cc b/systemverilog-plugin/UhdmAst.cc
index 3737d9a..ee19809 100644
--- a/systemverilog-plugin/UhdmAst.cc
+++ b/systemverilog-plugin/UhdmAst.cc
@@ -67,6 +67,11 @@
     static const IdString id("\\is_imported");
     return id;
 }
+/*static*/ const IdString &UhdmAst::is_simplified_wire()
+{
+    static const IdString id("\\is_simplified_wire");
+    return id;
+}
 
 static void sanitize_symbol_name(std::string &name)
 {
@@ -944,6 +949,8 @@
         AST_INTERNAL::current_scope[current_node->str] = current_node;
         break;
     case AST::AST_WIRE:
+        current_node->attributes[UhdmAst::is_simplified_wire()] = AST::AstNode::mkconst_int(1, true);
+        [[fallthrough]];
     case AST::AST_PARAMETER:
     case AST::AST_LOCALPARAM:
         AST_INTERNAL::current_scope[current_node->str] = current_node;
@@ -956,7 +963,11 @@
                 break;
             }
             AST::AstNode *wire_node = AST_INTERNAL::current_scope[current_node->str];
-            simplify(wire_node, nullptr);
+
+            // if a wire is simplified multiple times, its ranges may be added multiple times and be redundant as a result
+            if (!wire_node->attributes.count(UhdmAst::is_simplified_wire())) {
+                simplify(wire_node, nullptr);
+            }
             const std::vector<AST::AstNode *> packed_ranges = wire_node->attributes.count(UhdmAst::packed_ranges())
                                                                 ? wire_node->attributes[UhdmAst::packed_ranges()]->children
                                                                 : std::vector<AST::AstNode *>();
@@ -1181,7 +1192,8 @@
         default: {
             const uhdm_handle *const handle = (const uhdm_handle *)obj_h;
             const UHDM::BaseClass *const object = (const UHDM::BaseClass *)handle->object;
-            report_error("%s:%d: Encountered unhandled constant format %d\n", object->VpiFile().c_str(), object->VpiLineNo(), val.format);
+            report_error("%.*s:%d: Encountered unhandled constant format %d\n", (int)object->VpiFile().length(), object->VpiFile().data(),
+                         object->VpiLineNo(), val.format);
         }
         }
         // handle vpiBinStrVal, vpiDecStrVal and vpiHexStrVal
@@ -1633,6 +1645,10 @@
         visitEachDescendant(current_node, [&](AST::AstNode *node) {
             node->attributes.erase(UhdmAst::packed_ranges());
             node->attributes.erase(UhdmAst::unpacked_ranges());
+            if (node->attributes.count(UhdmAst::is_simplified_wire())) {
+                delete node->attributes[UhdmAst::is_simplified_wire()];
+                node->attributes.erase(UhdmAst::is_simplified_wire());
+            }
         });
     }
 }
@@ -2013,16 +2029,18 @@
         });
         break;
     case vpiVoidTypespec: {
-        report_error("%s:%d: Void typespecs are currently unsupported", object->VpiFile().c_str(), object->VpiLineNo());
+        report_error("%.*s:%d: Void typespecs are currently unsupported", (int)object->VpiFile().length(), object->VpiFile().data(),
+                     object->VpiLineNo());
         break;
     }
     case vpiClassTypespec: {
-        report_error("%s:%d: Class typespecs are unsupported", object->VpiFile().c_str(), object->VpiLineNo());
+        report_error("%.*s:%d: Class typespecs are unsupported", (int)object->VpiFile().length(), object->VpiFile().data(), object->VpiLineNo());
         break;
     }
     default: {
-        report_error("%s:%d: Encountered unhandled typespec in process_typespec_member: '%s' of type '%s'\n", object->VpiFile().c_str(),
-                     object->VpiLineNo(), object->VpiName().c_str(), UHDM::VpiTypeName(typespec_h).c_str());
+        report_error("%.*s:%d: Encountered unhandled typespec in process_typespec_member: '%.*s' of type '%s'\n", (int)object->VpiFile().length(),
+                     object->VpiFile().data(), object->VpiLineNo(), (int)object->VpiName().length(), object->VpiName().data(),
+                     UHDM::VpiTypeName(typespec_h).c_str());
         break;
     }
     }
@@ -2429,8 +2447,8 @@
         default:
             delete current_node;
             current_node = nullptr;
-            report_error("%s:%d: Encountered unhandled compound assignment with operation type %d\n", object->VpiFile().c_str(), object->VpiLineNo(),
-                         op_type);
+            report_error("%.*s:%d: Encountered unhandled compound assignment with operation type %d\n", (int)object->VpiFile().length(),
+                         object->VpiFile().data(), object->VpiLineNo(), op_type);
             return;
         }
         log_assert(current_node->children.size() == 2);
@@ -2674,7 +2692,8 @@
         if (node) {
             auto process_node = find_ancestor({AST::AST_ALWAYS});
             if (!process_node) {
-                log_error("%s:%d: Currently supports only event control stmts inside 'always'\n", object->VpiFile().c_str(), object->VpiLineNo());
+                log_error("%.*s:%d: Currently supports only event control stmts inside 'always'\n", (int)object->VpiFile().length(),
+                          object->VpiFile().data(), object->VpiLineNo());
             }
             process_node->children.push_back(node);
         }
@@ -2773,7 +2792,8 @@
         break;
     case vpiWildEqOp:
     case vpiWildNeqOp: {
-        report_error("%s:%d: Wildcard operators are not supported yet\n", object->VpiFile().c_str(), object->VpiLineNo());
+        report_error("%.*s:%d: Wildcard operators are not supported yet\n", (int)object->VpiFile().length(), object->VpiFile().data(),
+                     object->VpiLineNo());
         break;
     }
     default: {
@@ -2931,7 +2951,8 @@
             break;
         case vpiPostIncOp: {
             // TODO: Make this an actual post-increment op (currently it's a pre-increment)
-            log_warning("%s:%d: Post-incrementation operations are handled as pre-incrementation.\n", object->VpiFile().c_str(), object->VpiLineNo());
+            log_warning("%.*s:%d: Post-incrementation operations are handled as pre-incrementation.\n", (int)object->VpiFile().length(),
+                        object->VpiFile().data(), object->VpiLineNo());
             [[fallthrough]];
         }
         case vpiPreIncOp: {
@@ -2945,7 +2966,8 @@
         }
         case vpiPostDecOp: {
             // TODO: Make this an actual post-decrement op (currently it's a pre-decrement)
-            log_warning("%s:%d: Post-decrementation operations are handled as pre-decrementation.\n", object->VpiFile().c_str(), object->VpiLineNo());
+            log_warning("%.*s:%d: Post-decrementation operations are handled as pre-decrementation.\n", (int)object->VpiFile().length(),
+                        object->VpiFile().data(), object->VpiLineNo());
             [[fallthrough]];
         }
         case vpiPreDecOp: {
@@ -2995,7 +3017,8 @@
         default: {
             delete current_node;
             current_node = nullptr;
-            report_error("%s:%d: Encountered unhandled operation type %d\n", object->VpiFile().c_str(), object->VpiLineNo(), operation);
+            report_error("%.*s:%d: Encountered unhandled operation type %d\n", (int)object->VpiFile().length(), object->VpiFile().data(),
+                         object->VpiLineNo(), operation);
         }
         }
     }
@@ -3438,12 +3461,14 @@
     visit_one_to_one({vpiLeftRange, vpiRightRange}, obj_h, [&](AST::AstNode *node) { current_node->children.push_back(node); });
     if (current_node->children.size() > 0) {
         if (current_node->children[0]->str == "unsized") {
-            log_error("%s:%d: Currently not supported object of type 'unsized range'\n", object->VpiFile().c_str(), object->VpiLineNo());
+            log_error("%.*s:%d: Currently not supported object of type 'unsized range'\n", (int)object->VpiFile().length(), object->VpiFile().data(),
+                      object->VpiLineNo());
         }
     }
     if (current_node->children.size() > 1) {
         if (current_node->children[1]->str == "unsized") {
-            log_error("%s:%d: Currently not supported object of type 'unsized range'\n", object->VpiFile().c_str(), object->VpiLineNo());
+            log_error("%.*s:%d: Currently not supported object of type 'unsized range'\n", (int)object->VpiFile().length(), object->VpiFile().data(),
+                      object->VpiLineNo());
         }
     }
 }
@@ -3945,8 +3970,8 @@
         default: {
             const uhdm_handle *const handle = (const uhdm_handle *)actual_h;
             const UHDM::BaseClass *const object = (const UHDM::BaseClass *)handle->object;
-            report_error("%s:%d: Encountered unhandled type in process_port: %s\n", object->VpiFile().c_str(), object->VpiLineNo(),
-                         UHDM::VpiTypeName(actual_h).c_str());
+            report_error("%.*s:%d: Encountered unhandled type in process_port: %s\n", (int)object->VpiFile().length(), object->VpiFile().data(),
+                         object->VpiLineNo(), UHDM::VpiTypeName(actual_h).c_str());
             break;
         }
         }
@@ -4102,8 +4127,9 @@
         default: {
             const uhdm_handle *const handle = (const uhdm_handle *)typespec_h;
             const UHDM::BaseClass *const object = (const UHDM::BaseClass *)handle->object;
-            report_error("%s:%d: Encountered unhandled typespec in process_parameter: '%s' of type '%s'\n", object->VpiFile().c_str(),
-                         object->VpiLineNo(), object->VpiName().c_str(), UHDM::VpiTypeName(typespec_h).c_str());
+            report_error("%.*s:%d: Encountered unhandled typespec in process_parameter: '%.*s' of type '%s'\n", (int)object->VpiFile().length(),
+                         object->VpiFile().data(), object->VpiLineNo(), (int)object->VpiName().length(), object->VpiName().data(),
+                         UHDM::VpiTypeName(typespec_h).c_str());
             break;
         }
         }
@@ -4216,8 +4242,8 @@
 
 void UhdmAst::process_unsupported_stmt(const UHDM::BaseClass *object)
 {
-    log_error("%s:%d: Currently not supported object of type '%s'\n", object->VpiFile().c_str(), object->VpiLineNo(),
-              UHDM::VpiTypeName(obj_h).c_str());
+    log_error("%.*s:%d: Currently not supported object of type '%s'\n", (int)object->VpiFile().length(), object->VpiFile().data(),
+              object->VpiLineNo(), UHDM::VpiTypeName(obj_h).c_str());
 }
 
 AST::AstNode *UhdmAst::process_object(vpiHandle obj_handle)
@@ -4228,8 +4254,8 @@
     const UHDM::BaseClass *const object = (const UHDM::BaseClass *)handle->object;
     for (auto *obj : shared.nonSynthesizableObjects) {
         if (!object->Compare(obj)) {
-            log_warning("%s:%d: Skipping non-synthesizable object of type '%s'\n", object->VpiFile().c_str(), object->VpiLineNo(),
-                        UHDM::VpiTypeName(obj_h).c_str());
+            log_warning("%.*s:%d: Skipping non-synthesizable object of type '%s'\n", (int)object->VpiFile().length(), object->VpiFile().data(),
+                        object->VpiLineNo(), UHDM::VpiTypeName(obj_h).c_str());
             return nullptr;
         }
     }
@@ -4490,8 +4516,8 @@
         break;
     case vpiProgram:
     default:
-        report_error("%s:%d: Encountered unhandled object '%s' of type '%s'\n", object->VpiFile().c_str(), object->VpiLineNo(),
-                     object->VpiName().c_str(), UHDM::VpiTypeName(obj_h).c_str());
+        report_error("%.*s:%d: Encountered unhandled object '%.*s' of type '%s'\n", (int)object->VpiFile().length(), object->VpiFile().data(),
+                     object->VpiLineNo(), (int)object->VpiName().length(), object->VpiName().data(), UHDM::VpiTypeName(obj_h).c_str());
         break;
     }
 
diff --git a/systemverilog-plugin/UhdmAst.h b/systemverilog-plugin/UhdmAst.h
index f3b1017..6d6a8f6 100644
--- a/systemverilog-plugin/UhdmAst.h
+++ b/systemverilog-plugin/UhdmAst.h
@@ -174,6 +174,7 @@
     // set this attribute to force conversion of multirange wire to single range. It is useful to force-convert some memories.
     static const ::Yosys::IdString &force_convert();
     static const ::Yosys::IdString &is_imported();
+    static const ::Yosys::IdString &is_simplified_wire();
 };
 
 } // namespace systemverilog_plugin
diff --git a/systemverilog-plugin/uhdmastreport.cc b/systemverilog-plugin/uhdmastreport.cc
index 1df94b3..10d6a94 100644
--- a/systemverilog-plugin/uhdmastreport.cc
+++ b/systemverilog-plugin/uhdmastreport.cc
@@ -16,7 +16,7 @@
     auto it = unhandled.find(object);
     if (it != unhandled.end()) {
         unhandled.erase(it);
-        handled_count_per_file.at(object->VpiFile())++;
+        handled_count_per_file.at(std::string(object->VpiFile()))++;
     }
 }
 
@@ -43,7 +43,7 @@
     for (auto object : unhandled) {
         if (!object->VpiFile().empty() && object->VpiFile() != AST::current_filename) {
             unhandled_per_file.insert(std::make_pair(object->VpiFile(), std::unordered_set<unsigned>()));
-            unhandled_per_file.at(object->VpiFile()).insert(object->VpiLineNo());
+            unhandled_per_file.at(std::string(object->VpiFile())).insert(object->VpiLineNo());
             handled_count_per_file.insert(std::make_pair(object->VpiFile(), 0));
         }
     }