Extract missing module support in hierarchy.cc to a helper function
authorRupert Swarbrick <rswarbrick@gmail.com>
Wed, 27 May 2020 09:42:37 +0000 (10:42 +0100)
committerZachary Snow <zachary.j.snow@gmail.com>
Thu, 15 Jul 2021 02:54:50 +0000 (22:54 -0400)
I think the code is now a bit easier to follow (and has lost some
levels of indentation!).

The only non-trivial change is that I removed the check for
cell->type[0] != '$' when deciding whether to complain if we couldn't
find a module. This will always be true because of the early exit
earlier in the function.

passes/hierarchy/hierarchy.cc

index dadae04a46db4c565f33d5726d7f4d93ec922125..2f7fc6d8a2f58cabe126ed253dea2d7e61545588 100644 (file)
@@ -318,6 +318,64 @@ struct IFExpander
        }
 };
 
+// Get a module needed by a cell, either by deriving an abstract module or by
+// loading one from a directory in libdirs.
+//
+// If the module can't be found and check is true then exit with an error
+// message. Otherwise, return a pointer to the module if we derived or loaded
+// something. or null otherwise (the module should be blackbox or we couldn't
+// find it and check is not set).
+RTLIL::Module *get_module(RTLIL::Design                  &design,
+                          RTLIL::Cell                    &cell,
+                          RTLIL::Module                  &parent,
+                          bool                            check,
+                          const std::vector<std::string> &libdirs)
+{
+       std::string cell_type = cell.type.str();
+       RTLIL::Module *abs_mod = design.module("$abstract" + cell_type);
+       if (abs_mod) {
+               cell.type = abs_mod->derive(&design, cell.parameters);
+               cell.parameters.clear();
+               RTLIL::Module *mod = design.module(cell.type);
+               log_assert(mod);
+               return mod;
+       }
+
+       // If the cell type starts with '$' and isn't '$abstract', we should
+       // treat it as a black box and skip.
+       if (cell_type[0] == '$')
+               return nullptr;
+
+       for (auto &dir : libdirs) {
+               static const vector<pair<string, string>> extensions_list =
+                       {
+                        {".v", "verilog"},
+                        {".sv", "verilog -sv"},
+                        {".il", "rtlil"}
+                       };
+
+               for (auto &ext : extensions_list) {
+                       std::string filename = dir + "/" + RTLIL::unescape_id(cell.type) + ext.first;
+                       if (!check_file_exists(filename))
+                               continue;
+
+                       Frontend::frontend_call(&design, NULL, filename, ext.second);
+                       RTLIL::Module *mod = design.module(cell.type);
+                       if (!mod)
+                               log_error("File `%s' from libdir does not declare module `%s'.\n",
+                                         filename.c_str(), cell_type.c_str());
+                       return mod;
+               }
+       }
+
+       // We couldn't find the module anywhere. Complain if check is set.
+       if (check)
+               log_error("Module `%s' referenced in module `%s' in cell `%s' is not part of the design.\n",
+                         cell_type.c_str(), parent.name.c_str(), cell.name.c_str());
+
+       return nullptr;
+}
+
 bool expand_module(RTLIL::Design *design, RTLIL::Module *module, bool flag_check, bool flag_simcheck, std::vector<std::string> &libdirs)
 {
        bool did_something = false;
@@ -354,49 +412,21 @@ bool expand_module(RTLIL::Design *design, RTLIL::Module *module, bool flag_check
                }
 
                RTLIL::Module *mod = design->module(cell->type);
-               if (mod == nullptr)
+               if (!mod)
                {
-                       if (design->module("$abstract" + cell->type.str()) != nullptr)
-                       {
-                               cell->type = design->module("$abstract" + cell->type.str())->derive(design, cell->parameters);
-                               cell->parameters.clear();
-                               did_something = true;
-                               continue;
-                       }
+                       mod = get_module(*design, *cell, *module, flag_check || flag_simcheck, libdirs);
 
-                       if (cell->type[0] == '$')
-                               continue;
-
-                       for (auto &dir : libdirs)
-                       {
-                               static const vector<pair<string, string>> extensions_list =
-                               {
-                                       {".v", "verilog"},
-                                       {".sv", "verilog -sv"},
-                                       {".il", "rtlil"}
-                               };
-
-                               for (auto &ext : extensions_list)
-                               {
-                                       filename = dir + "/" + RTLIL::unescape_id(cell->type) + ext.first;
-                                       if (check_file_exists(filename)) {
-                                               Frontend::frontend_call(design, NULL, filename, ext.second);
-                                               goto loaded_module;
-                                       }
-                               }
-                       }
+                       // If we still don't have a module, treat the cell as a black box and skip
+                       // it. Otherwise, we either loaded or derived something so should set the
+                       // did_something flag before returning (to ensure we come back and expand
+                       // the thing we just loaded).
+                       if (mod)
+                               did_something = true;
 
-                       if ((flag_check || flag_simcheck) && cell->type[0] != '$')
-                               log_error("Module `%s' referenced in module `%s' in cell `%s' is not part of the design.\n",
-                                               cell->type.c_str(), module->name.c_str(), cell->name.c_str());
                        continue;
+               }
 
-               loaded_module:
-                       mod = design->module(cell->type);
-                       if (mod == nullptr)
-                               log_error("File `%s' from libdir does not declare module `%s'.\n", filename.c_str(), cell->type.c_str());
-                       did_something = true;
-               } else {
+               log_assert(mod);
 
                // Go over all connections and check if any of them are SV
                // interfaces.
@@ -426,12 +456,6 @@ bool expand_module(RTLIL::Design *design, RTLIL::Module *module, bool flag_check
                        }
 
                }
-               }
-
-               // If we make it out of the if/else block above without leaving
-               // this iteration, mod will equal design->module(cell->type) and
-               // will be non-null.
-               log_assert(mod);
 
                if (mod->get_blackbox_attribute()) {
                        if (flag_simcheck)