Merge pull request #2295 from epfl-vlsc/firrtl_blackbox_generic_parameters
[yosys.git] / kernel / modtools.h
index 113b0918d591b42c8aa7a394b44fd882e6e82e3c..29c510059ffc4f5e0220ffdeb6e9bea8eacffe0d 100644 (file)
@@ -1,12 +1,12 @@
-/*
+/* -*- c++ -*-
  *  yosys -- Yosys Open SYnthesis Suite
  *
  *  Copyright (C) 2012  Clifford Wolf <clifford@clifford.at>
- *  
+ *
  *  Permission to use, copy, modify, and/or distribute this software for any
  *  purpose with or without fee is hereby granted, provided that the above
  *  copyright notice and this permission notice appear in all copies.
- *  
+ *
  *  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  *  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  *  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
@@ -60,6 +60,10 @@ struct ModIndex : public RTLIL::Monitor
 
                SigBitInfo() : is_input(false), is_output(false) { }
 
+               bool operator==(const SigBitInfo &other) const {
+                       return is_input == other.is_input && is_output == other.is_output && ports == other.ports;
+               }
+
                void merge(const SigBitInfo &other)
                {
                        is_input = is_input || other.is_input;
@@ -71,6 +75,7 @@ struct ModIndex : public RTLIL::Monitor
        SigMap sigmap;
        RTLIL::Module *module;
        std::map<RTLIL::SigBit, SigBitInfo> database;
+       int auto_reload_counter;
        bool auto_reload_module;
 
        void port_add(RTLIL::Cell *cell, RTLIL::IdString port, const RTLIL::SigSpec &sig)
@@ -96,10 +101,12 @@ struct ModIndex : public RTLIL::Monitor
                return database[sigmap(bit)];
        }
 
-       void reload_module()
+       void reload_module(bool reset_sigmap = true)
        {
-               sigmap.clear();
-               sigmap.set(module);
+               if (reset_sigmap) {
+                       sigmap.clear();
+                       sigmap.set(module);
+               }
 
                database.clear();
                for (auto wire : module->wires())
@@ -115,11 +122,43 @@ struct ModIndex : public RTLIL::Monitor
                        for (auto &conn : cell->connections())
                                port_add(cell, conn.first, conn.second);
 
-               auto_reload_module = false;
-               // log("Auto-reload in ModIndex -- possible performance bug!\n");
+               if (auto_reload_module) {
+                       if (++auto_reload_counter > 2)
+                               log_warning("Auto-reload in ModIndex -- possible performance bug!\n");
+                       auto_reload_module = false;
+               }
        }
 
-       virtual void notify_connect(RTLIL::Cell *cell, const RTLIL::IdString &port, const RTLIL::SigSpec &old_sig, RTLIL::SigSpec &sig) YS_OVERRIDE
+       void check()
+       {
+#ifndef NDEBUG
+               if (auto_reload_module)
+                       return;
+
+               for (auto it : database)
+                       log_assert(it.first == sigmap(it.first));
+
+               auto database_bak = std::move(database);
+               reload_module(false);
+
+               if (!(database == database_bak))
+               {
+                       for (auto &it : database_bak)
+                               if (!database.count(it.first))
+                                       log("ModuleIndex::check(): Only in database_bak, not database: %s\n", log_signal(it.first));
+
+                       for (auto &it : database)
+                               if (!database_bak.count(it.first))
+                                       log("ModuleIndex::check(): Only in database, not database_bak: %s\n", log_signal(it.first));
+                               else if (!(it.second == database_bak.at(it.first)))
+                                       log("ModuleIndex::check(): Different content for database[%s].\n", log_signal(it.first));
+
+                       log_assert(database == database_bak);
+               }
+#endif
+       }
+
+       void notify_connect(RTLIL::Cell *cell, const RTLIL::IdString &port, const RTLIL::SigSpec &old_sig, const RTLIL::SigSpec &sig) override
        {
                log_assert(module == cell->module);
 
@@ -130,7 +169,7 @@ struct ModIndex : public RTLIL::Monitor
                port_add(cell, port, sig);
        }
 
-       virtual void notify_connect(RTLIL::Module *mod, const RTLIL::SigSig &sigsig) YS_OVERRIDE
+       void notify_connect(RTLIL::Module *mod, const RTLIL::SigSig &sigsig) override
        {
                log_assert(module == mod);
 
@@ -141,8 +180,8 @@ struct ModIndex : public RTLIL::Monitor
                {
                        RTLIL::SigBit lhs = sigmap(sigsig.first[i]);
                        RTLIL::SigBit rhs = sigmap(sigsig.second[i]);
-                       bool has_lhs = database.count(lhs);
-                       bool has_rhs = database.count(rhs);
+                       bool has_lhs = database.count(lhs) != 0;
+                       bool has_rhs = database.count(rhs) != 0;
 
                        if (!has_lhs && !has_rhs) {
                                sigmap.add(lhs, rhs);
@@ -151,43 +190,45 @@ struct ModIndex : public RTLIL::Monitor
                                SigBitInfo new_info = database.at(lhs);
                                database.erase(lhs);
                                sigmap.add(lhs, rhs);
-                               database[sigmap(lhs)] = new_info;
+                               lhs = sigmap(lhs);
+                               if (lhs.wire)
+                                       database[lhs] = new_info;
                        } else
                        if (!has_lhs) {
                                SigBitInfo new_info = database.at(rhs);
                                database.erase(rhs);
                                sigmap.add(lhs, rhs);
-                               database[sigmap(rhs)] = new_info;
+                               rhs = sigmap(rhs);
+                               if (rhs.wire)
+                                       database[rhs] = new_info;
                        } else {
-               #if 1
-                               auto_reload_module = true;
-                               return;
-               #else
                                SigBitInfo new_info = database.at(lhs);
                                new_info.merge(database.at(rhs));
                                database.erase(lhs);
                                database.erase(rhs);
                                sigmap.add(lhs, rhs);
-                               database[sigmap(rhs)] = new_info;
-               #endif
+                               rhs = sigmap(rhs);
+                               if (rhs.wire)
+                                       database[rhs] = new_info;
                        }
                }
        }
 
-       virtual void notify_connect(RTLIL::Module *mod, const std::vector<RTLIL::SigSig>&) YS_OVERRIDE
+       void notify_connect(RTLIL::Module *mod, const std::vector<RTLIL::SigSig>&) override
        {
                log_assert(module == mod);
                auto_reload_module = true;
        }
 
-       virtual void notify_blackout(RTLIL::Module *mod) YS_OVERRIDE
+       void notify_blackout(RTLIL::Module *mod) override
        {
                log_assert(module == mod);
                auto_reload_module = true;
        }
 
-       ModIndex(RTLIL::Module *_m) : module(_m)
+       ModIndex(RTLIL::Module *_m) : sigmap(_m), module(_m)
        {
+               auto_reload_counter = 0;
                auto_reload_module = true;
                module->monitors.insert(this);
        }
@@ -233,6 +274,27 @@ struct ModIndex : public RTLIL::Monitor
                        return empty_result_set;
                return info->ports;
        }
+
+       void dump_db()
+       {
+               log("--- ModIndex Dump ---\n");
+
+               if (auto_reload_module) {
+                       log("AUTO-RELOAD\n");
+                       reload_module();
+               }
+
+               for (auto &it : database) {
+                       log("BIT %s:\n", log_signal(it.first));
+                       if (it.second.is_input)
+                               log("  PRIMARY INPUT\n");
+                       if (it.second.is_output)
+                               log("  PRIMARY OUTPUT\n");
+                       for (auto &port : it.second.ports)
+                               log("  PORT: %s.%s[%d] (%s)\n", log_id(port.cell),
+                                               log_id(port.port), port.offset, log_id(port.cell->type));
+               }
+       }
 };
 
 struct ModWalker
@@ -318,22 +380,15 @@ struct ModWalker
                }
        }
 
-       ModWalker() : design(NULL), module(NULL)
-       {
-       }
-
-       ModWalker(RTLIL::Design *design, RTLIL::Module *module, CellTypes *filter_ct = NULL)
+       ModWalker(RTLIL::Design *design) : design(design), module(NULL)
        {
-               setup(design, module, filter_ct);
+            ct.setup(design);
        }
 
-       void setup(RTLIL::Design *design, RTLIL::Module *module, CellTypes *filter_ct = NULL)
+       void setup(RTLIL::Module *module, CellTypes *filter_ct = NULL)
        {
-               this->design = design;
                this->module = module;
 
-               ct.clear();
-               ct.setup(design);
                sigmap.set(module);
 
                signal_drivers.clear();