Merge pull request #466 from antmicro/kr/process_module

systemverilog-plugin: update module parameters processing
diff --git a/systemverilog-plugin/UhdmAst.cc b/systemverilog-plugin/UhdmAst.cc
index 20959a8..2dc7f0c 100644
--- a/systemverilog-plugin/UhdmAst.cc
+++ b/systemverilog-plugin/UhdmAst.cc
@@ -1902,53 +1902,44 @@
     } else {
         // Not a top module, create instance
         current_node = make_ast_node(AST::AST_CELL);
-        std::string module_parameters;
+        std::vector<std::pair<RTLIL::IdString, RTLIL::Const>> parameters;
         visit_one_to_many({vpiParamAssign}, obj_h, [&](AST::AstNode *node) {
             if (node && node->type == AST::AST_PARAMETER) {
+                log_assert(!node->children.empty());
                 if (node->children[0]->type != AST::AST_CONSTANT) {
                     if (shared.top_nodes.count(type)) {
                         simplify_parameter(node, shared.top_nodes[type]);
-                        log_assert(node->children[0]->type == AST::AST_CONSTANT || node->children[0]->type == AST::AST_REALVALUE);
+                    } else {
+                        simplify_parameter(node, nullptr);
                     }
                 }
-                if (shared.top_nodes.count(type)) {
-                    if (!node->children[0]->str.empty())
-                        module_parameters += node->str + "=" + node->children[0]->str;
-                    else
-                        module_parameters +=
-                          node->str + "=" + std::to_string(node->children[0]->bits.size()) + "'d" + std::to_string(node->children[0]->integer);
-                }
+                log_assert(node->children[0]->type == AST::AST_CONSTANT || node->children[0]->type == AST::AST_REALVALUE);
+                parameters.push_back(std::make_pair(node->str, node->children[0]->asParaConst()));
                 delete node;
             }
         });
-        // rename module in same way yosys do
-        std::string module_name;
-        if (module_parameters.size() > 60)
-            module_name = "$paramod$" + sha1(module_parameters) + type;
-        else if (!module_parameters.empty())
-            module_name = "$paramod" + type + module_parameters;
-        else
-            module_name = type;
+        // We need to rename module to prevent name collision with the same module, but with different parameters
+        std::string module_name = !parameters.empty() ? AST::derived_module_name(type, parameters).c_str() : type;
         auto module_node = shared.top_nodes[module_name];
-        auto cell_instance = vpi_get(vpiCellInstance, obj_h);
+        // true, when Surelog don't have definition of module while parsing design
+        // if so, we leaving module parameters to yosys and don't rename module
+        // as it will be done by yosys
+        bool isPrimitive = false;
         if (!module_node) {
             module_node = shared.top_nodes[type];
             if (!module_node) {
                 module_node = new AST::AstNode(AST::AST_MODULE);
                 module_node->str = type;
                 module_node->attributes[UhdmAst::partial()] = AST::AstNode::mkconst_int(2, false, 1);
-                cell_instance = 1;
-                module_name = type;
+                module_node->attributes[ID::whitebox] = AST::AstNode::mkconst_int(1, false, 1);
             }
-            if (!module_parameters.empty()) {
+            isPrimitive = module_node->attributes.count(UhdmAst::partial()) && module_node->attributes[UhdmAst::partial()]->integer == 2;
+            if (!parameters.empty() && !isPrimitive) {
                 module_node = module_node->clone();
+                module_node->str = module_name;
             }
         }
-        module_node->str = module_name;
         shared.top_nodes[module_node->str] = module_node;
-        if (cell_instance) {
-            module_node->attributes[ID::whitebox] = AST::AstNode::mkconst_int(1, false, 1);
-        }
         visit_one_to_many({vpiParamAssign}, obj_h, [&](AST::AstNode *node) {
             if (node) {
                 if (node->children[0]->type != AST::AST_CONSTANT) {
@@ -1957,39 +1948,14 @@
                         log_assert(node->children[0]->type == AST::AST_CONSTANT || node->children[0]->type == AST::AST_REALVALUE);
                     }
                 }
-                auto parent_node = std::find_if(module_node->children.begin(), module_node->children.end(), [&](AST::AstNode *child) -> bool {
-                    return ((child->type == AST::AST_PARAMETER) || (child->type == AST::AST_LOCALPARAM)) && child->str == node->str &&
-                           // skip real parameters as they are currently not working: https://github.com/alainmarcel/Surelog/issues/1035
-                           child->type != AST::AST_REALVALUE;
-                });
-                if (parent_node != module_node->children.end()) {
-                    if ((*parent_node)->type == AST::AST_PARAMETER) {
-                        if (cell_instance ||
-                            (!node->children.empty() &&
-                             node->children[0]->type !=
-                               AST::AST_CONSTANT)) { // if cell is a blackbox or we need to simplify parameter first, left setting parameters to yosys
-                            // We only want to add AST_PARASET for parameters that is different than already set
-                            // to match the name yosys gives to the module.
-                            // Note: this should also be applied for other (not only cell_instance) modules
-                            // but as we are using part of the modules parsed by sv2v and other
-                            // part by uhdm, we need to always rename module if it is parametrized,
-                            // Otherwise, verilog frontend can use module parsed by uhdm and try to set
-                            // parameters, but this module would be already parametrized
-                            if ((node->children[0]->integer != (*parent_node)->children[0]->integer ||
-                                 node->children[0]->str != (*parent_node)->children[0]->str)) {
-                                node->type = AST::AST_PARASET;
-                                current_node->children.push_back(node);
-                            }
-                        } else {
-                            add_or_replace_child(module_node, node);
-                        }
-                    } else {
-                        add_or_replace_child(module_node, node);
-                    }
-                } else if ((module_node->attributes.count(UhdmAst::partial()) && module_node->attributes[UhdmAst::partial()]->integer == 2)) {
-                    // When module definition is not parsed by Surelog, left setting parameters to yosys
+                // if module is primitive
+                // Surelog doesn't have definition of this module,
+                // so we need to left setting of parameters to yosys
+                if (isPrimitive) {
                     node->type = AST::AST_PARASET;
                     current_node->children.push_back(node);
+                } else {
+                    add_or_replace_child(module_node, node);
                 }
             }
         });
@@ -2006,16 +1972,12 @@
         current_node->children.insert(current_node->children.begin(), typeNode);
         auto old_top = shared.current_top_node;
         shared.current_top_node = module_node;
-        visit_one_to_many({vpiVariables, vpiNet, vpiArrayNet}, obj_h, [&](AST::AstNode *node) {
-            if (node) {
-                add_or_replace_child(module_node, node);
-            }
-        });
-        visit_one_to_many({vpiInterface, vpiModule, vpiPort, vpiGenScopeArray, vpiContAssign, vpiTaskFunc}, obj_h, [&](AST::AstNode *node) {
-            if (node) {
-                add_or_replace_child(module_node, node);
-            }
-        });
+        visit_one_to_many({vpiVariables, vpiNet, vpiArrayNet, vpiInterface, vpiModule, vpiPort, vpiGenScopeArray, vpiContAssign, vpiTaskFunc}, obj_h,
+                          [&](AST::AstNode *node) {
+                              if (node) {
+                                  add_or_replace_child(module_node, node);
+                              }
+                          });
         make_cell(obj_h, current_node, module_node);
         shared.current_top_node = old_top;
     }