Merge pull request #210 from rakeshm75/ffs_map_update

Modified ffs map file
diff --git a/uhdm-plugin/UhdmAst.cc b/uhdm-plugin/UhdmAst.cc
index 9ec5c49..b6b541b 100644
--- a/uhdm-plugin/UhdmAst.cc
+++ b/uhdm-plugin/UhdmAst.cc
@@ -220,12 +220,17 @@
         }
         if (!wire_node->multirange_swapped.empty()) {
             bool is_swapped = wire_node->multirange_swapped[wire_node->multirange_swapped.size() - i - 1];
+            auto right_idx = wire_node->multirange_dimensions.size() - (i * 2) - 2;
             if (is_swapped) {
                 auto left_idx = wire_node->multirange_dimensions.size() - (i * 2) - 1;
-                auto right_idx = wire_node->multirange_dimensions.size() - (i * 2) - 2;
                 auto elem_size = wire_node->multirange_dimensions[left_idx] - wire_node->multirange_dimensions[right_idx];
                 range_left = new AST::AstNode(AST::AST_SUB, AST::AstNode::mkconst_int(elem_size - 1, false), range_left->clone());
                 range_right = new AST::AstNode(AST::AST_SUB, AST::AstNode::mkconst_int(elem_size - 1, false), range_right->clone());
+            } else if (wire_node->multirange_dimensions[right_idx] != 0) {
+                range_left =
+                  new AST::AstNode(AST::AST_SUB, range_left, AST::AstNode::mkconst_int(wire_node->multirange_dimensions[right_idx], false));
+                range_right =
+                  new AST::AstNode(AST::AST_SUB, range_right, AST::AstNode::mkconst_int(wire_node->multirange_dimensions[right_idx], false));
             }
         }
         range_left =
@@ -1279,13 +1284,16 @@
 void UhdmAst::process_design()
 {
     current_node = make_ast_node(AST::AST_DESIGN);
-    visit_one_to_many(
-      {UHDM::uhdmallInterfaces, UHDM::uhdmallPackages, UHDM::uhdmallModules, UHDM::uhdmtopModules, vpiTypedef, vpiParameter, vpiParamAssign}, obj_h,
-      [&](AST::AstNode *node) {
-          if (node) {
-              shared.top_nodes[node->str] = node;
-          }
-      });
+    visit_one_to_many({UHDM::uhdmallInterfaces, UHDM::uhdmallPackages, UHDM::uhdmallModules, UHDM::uhdmtopModules}, obj_h, [&](AST::AstNode *node) {
+        if (node) {
+            shared.top_nodes[node->str] = node;
+        }
+    });
+    visit_one_to_many({vpiParameter, vpiParamAssign}, obj_h, [&](AST::AstNode *node) {});
+    visit_one_to_many({vpiTypedef}, obj_h, [&](AST::AstNode *node) {
+        if (node)
+            move_type_to_new_typedef(current_node, node);
+    });
     for (auto pair : shared.top_nodes) {
         if (!pair.second)
             continue;
@@ -1323,6 +1331,8 @@
     visitEachDescendant(shared.current_top_node, [&](AST::AstNode *current_scope_node) {
         if (current_scope_node->type == AST::AST_TYPEDEF || current_scope_node->type == AST::AST_PARAMETER ||
             current_scope_node->type == AST::AST_LOCALPARAM) {
+            if (current_scope_node->type == AST::AST_TYPEDEF)
+                simplify(current_scope_node, nullptr);
             AST_INTERNAL::current_scope[current_scope_node->str] = current_scope_node;
         }
     });
@@ -1330,6 +1340,8 @@
         visitEachDescendant(module_node, [&](AST::AstNode *current_scope_node) {
             if (current_scope_node->type == AST::AST_TYPEDEF || current_scope_node->type == AST::AST_PARAMETER ||
                 current_scope_node->type == AST::AST_LOCALPARAM) {
+                if (current_scope_node->type == AST::AST_TYPEDEF)
+                    simplify(current_scope_node, nullptr);
                 AST_INTERNAL::current_scope[current_scope_node->str] = current_scope_node;
             }
         });
@@ -1536,6 +1548,28 @@
     });
 }
 
+void UhdmAst::process_union_typespec()
+{
+    current_node = make_ast_node(AST::AST_UNION);
+    visit_one_to_many({vpiTypespecMember}, obj_h, [&](AST::AstNode *node) {
+        if (node->children.size() > 0 && node->children[0]->type == AST::AST_ENUM) {
+            log_assert(node->children.size() == 1);
+            log_assert(!node->children[0]->children.empty());
+            log_assert(!node->children[0]->children[0]->children.empty());
+            // TODO: add missing enum_type attribute
+            auto range = make_range(0, 0);
+            // check if single enum element is larger than 1 bit
+            if (node->children[0]->children[0]->children.size() == 2) {
+                range = node->children[0]->children[0]->children[1]->clone();
+            }
+            delete node->children[0];
+            node->children.clear();
+            node->children.push_back(range);
+        }
+        current_node->children.push_back(node);
+    });
+}
+
 void UhdmAst::process_array_typespec()
 {
     current_node = make_ast_node(AST::AST_WIRE);
@@ -1547,9 +1581,6 @@
             node->cloneInto(current_node);
             current_node->str = str;
             delete node;
-        } else if (node) {
-            current_node->str = node->str;
-            delete node;
         }
     });
     visit_one_to_many({vpiRange}, obj_h, [&](AST::AstNode *node) { unpacked_ranges.push_back(node); });
@@ -1579,9 +1610,10 @@
         break;
     }
     case vpiStructTypespec:
+    case vpiUnionTypespec:
     case vpiEnumTypespec: {
         visit_one_to_one({vpiTypespec}, obj_h, [&](AST::AstNode *node) {
-            if (typespec_type == vpiStructTypespec) {
+            if (typespec_type == vpiStructTypespec || typespec_type == vpiUnionTypespec) {
                 auto str = current_node->str;
                 node->cloneInto(current_node);
                 current_node->str = str;
@@ -1684,6 +1716,21 @@
             shared.report.mark_handled(typespec_h);
             break;
         }
+        case vpiBitTypespec: {
+            bool has_range = false;
+            visit_range(typespec_h, [&](AST::AstNode *node) {
+                has_range = true;
+                for (auto child : current_node->children) {
+                    child->children.push_back(node->clone());
+                }
+                delete node;
+            });
+            if (!has_range) // range is needed for simplify
+                for (auto child : current_node->children)
+                    child->children.push_back(make_ast_node(AST::AST_RANGE, {AST::AstNode::mkconst_int(0, true)}));
+            shared.report.mark_handled(typespec_h);
+            break;
+        }
         default: {
             const uhdm_handle *const handle = (const uhdm_handle *)typespec_h;
             const UHDM::BaseClass *const object = (const UHDM::BaseClass *)handle->object;
@@ -2167,7 +2214,7 @@
             current_node->is_output = true;
         }
     }
-    add_multirange_wire(current_node, packed_ranges, unpacked_ranges);
+    add_multirange_wire(current_node, packed_ranges, unpacked_ranges, false);
 }
 
 void UhdmAst::process_always()
@@ -3072,11 +3119,26 @@
 void UhdmAst::process_sys_func_call()
 {
     current_node = make_ast_node(AST::AST_FCALL);
+
+    // skip unsupported simulation functions
+    std::string to_skip[] = {
+      "\\$value$plusargs", "\\$test$plusargs", "\\$displayb", "\\$displayh",  "\\$displayo",  "\\$strobeb",  "\\$strobeh",       "\\$strobeo",
+      "\\$writeb",         "\\$writeh",        "\\$writeo",   "\\$dumplimit", "\\$dumpflush", "\\$fdisplay", "\\$fdisplayb",     "\\$fdisplayh",
+      "\\$fdisplayo",      "\\$fmonitor",      "\\$fstrobe",  "\\$fstrobeb",  "\\$fstrobeh",  "\\$fstrobeo", "\\$fwrite",        "\\$fwriteb",
+      "\\$fwriteh",        "\\$fwriteo",       "\\$ungetc",   "\\$fgetc",     "\\$fgets",     "\\$ftell",    "\\$printtimescale"};
+
+    if (std::find(std::begin(to_skip), std::end(to_skip), current_node->str) != std::end(to_skip)) {
+        log_warning("System function %s was skipped\n", current_node->str.substr(1).c_str());
+        delete current_node;
+        current_node = nullptr;
+        return;
+    }
+
     if (current_node->str == "\\$signed") {
         current_node->type = AST::AST_TO_SIGNED;
     } else if (current_node->str == "\\$unsigned") {
         current_node->type = AST::AST_TO_UNSIGNED;
-    } else if (current_node->str == "\\$display" || current_node->str == "\\$time") {
+    } else if (current_node->str == "\\$display" || current_node->str == "\\$time" || current_node->str == "\\$monitor") {
         current_node->type = AST::AST_TCALL;
         current_node->str = current_node->str.substr(1);
     } else if (current_node->str == "\\$readmemh") {
@@ -3088,12 +3150,6 @@
             current_node->children.push_back(node);
         }
     });
-
-    // skip $value$plusargs function, as it is simulation function
-    if (current_node->str == "\\$value$plusargs") {
-        delete current_node;
-        current_node = nullptr;
-    }
 }
 
 void UhdmAst::process_func_call()
@@ -3579,6 +3635,9 @@
     case vpiStructTypespec:
         process_struct_typespec();
         break;
+    case vpiUnionTypespec:
+        process_union_typespec();
+        break;
     case vpiPackedArrayTypespec:
         process_packed_array_typespec();
         break;
diff --git a/uhdm-plugin/UhdmAst.h b/uhdm-plugin/UhdmAst.h
index 6d2cf5b..538ec3b 100644
--- a/uhdm-plugin/UhdmAst.h
+++ b/uhdm-plugin/UhdmAst.h
@@ -72,6 +72,7 @@
     void process_port();
     void process_module();
     void process_struct_typespec();
+    void process_union_typespec();
     void process_packed_array_typespec();
     void process_array_typespec();
     void process_typespec_member();