Merge branch 'koriakin/xc7nocarrymux' into xaig
[yosys.git] / kernel / rtlil.cc
index d4aebcda9cabf6b9303af9fda34b83207359e84c..502b45cfdb691dc88a887ecf39a53d15613c23bc 100644 (file)
@@ -33,6 +33,8 @@ std::vector<int> RTLIL::IdString::global_refcount_storage_;
 std::vector<char*> RTLIL::IdString::global_id_storage_;
 dict<char*, int, hash_cstr_ops> RTLIL::IdString::global_id_index_;
 std::vector<int> RTLIL::IdString::global_free_idx_list_;
+int RTLIL::IdString::last_created_idx_[8];
+int RTLIL::IdString::last_created_idx_ptr_;
 
 RTLIL::Const::Const()
 {
@@ -74,6 +76,13 @@ RTLIL::Const::Const(const std::vector<bool> &bits)
                this->bits.push_back(b ? RTLIL::S1 : RTLIL::S0);
 }
 
+RTLIL::Const::Const(const RTLIL::Const &c)
+{
+       flags = c.flags;
+       for (auto b : c.bits)
+               this->bits.push_back(b);
+}
+
 bool RTLIL::Const::operator <(const RTLIL::Const &other) const
 {
        if (bits.size() != other.bits.size())
@@ -205,16 +214,23 @@ bool RTLIL::Const::is_fully_undef() const
        return true;
 }
 
-void RTLIL::AttrObject::set_bool_attribute(RTLIL::IdString id)
+void RTLIL::AttrObject::set_bool_attribute(RTLIL::IdString id, bool value)
 {
-       attributes[id] = RTLIL::Const(1);
+       if (value)
+               attributes[id] = RTLIL::Const(1);
+       else {
+                const auto it = attributes.find(id);
+                if (it != attributes.end())
+                       attributes.erase(it);
+       }
 }
 
 bool RTLIL::AttrObject::get_bool_attribute(RTLIL::IdString id) const
 {
-       if (attributes.count(id) == 0)
+       const auto it = attributes.find(id);
+       if (it == attributes.end())
                return false;
-       return attributes.at(id).as_bool();
+       return it->second.as_bool();
 }
 
 void RTLIL::AttrObject::set_strpool_attribute(RTLIL::IdString id, const pool<string> &data)
@@ -358,6 +374,10 @@ RTLIL::Design::Design()
 
        refcount_modules_ = 0;
        selection_stack.push_back(RTLIL::Selection());
+
+#ifdef WITH_PYTHON
+       RTLIL::Design::get_all_designs()->insert(std::pair<unsigned int, RTLIL::Design*>(hashidx_, this));
+#endif
 }
 
 RTLIL::Design::~Design()
@@ -368,8 +388,19 @@ RTLIL::Design::~Design()
                delete n;
        for (auto n : verilog_globals)
                delete n;
+#ifdef WITH_PYTHON
+       RTLIL::Design::get_all_designs()->erase(hashidx_);
+#endif
 }
 
+#ifdef WITH_PYTHON
+static std::map<unsigned int, RTLIL::Design*> all_designs;
+std::map<unsigned int, RTLIL::Design*> *RTLIL::Design::get_all_designs(void)
+{
+       return &all_designs;
+}
+#endif
+
 RTLIL::ObjRange<RTLIL::Module*> RTLIL::Design::modules()
 {
        return RTLIL::ObjRange<RTLIL::Module*>(&modules_, &refcount_modules_);
@@ -587,7 +618,7 @@ std::vector<RTLIL::Module*> RTLIL::Design::selected_modules() const
        std::vector<RTLIL::Module*> result;
        result.reserve(modules_.size());
        for (auto &it : modules_)
-               if (selected_module(it.first) && !it.second->get_bool_attribute("\\blackbox"))
+               if (selected_module(it.first) && !it.second->get_blackbox_attribute())
                        result.push_back(it.second);
        return result;
 }
@@ -597,7 +628,7 @@ std::vector<RTLIL::Module*> RTLIL::Design::selected_whole_modules() const
        std::vector<RTLIL::Module*> result;
        result.reserve(modules_.size());
        for (auto &it : modules_)
-               if (selected_whole_module(it.first) && !it.second->get_bool_attribute("\\blackbox"))
+               if (selected_whole_module(it.first) && !it.second->get_blackbox_attribute())
                        result.push_back(it.second);
        return result;
 }
@@ -607,7 +638,7 @@ std::vector<RTLIL::Module*> RTLIL::Design::selected_whole_modules_warn() const
        std::vector<RTLIL::Module*> result;
        result.reserve(modules_.size());
        for (auto &it : modules_)
-               if (it.second->get_bool_attribute("\\blackbox"))
+               if (it.second->get_blackbox_attribute())
                        continue;
                else if (selected_whole_module(it.first))
                        result.push_back(it.second);
@@ -625,6 +656,10 @@ RTLIL::Module::Module()
        design = nullptr;
        refcount_wires_ = 0;
        refcount_cells_ = 0;
+
+#ifdef WITH_PYTHON
+       RTLIL::Module::get_all_modules()->insert(std::pair<unsigned int, RTLIL::Module*>(hashidx_, this));
+#endif
 }
 
 RTLIL::Module::~Module()
@@ -637,6 +672,41 @@ RTLIL::Module::~Module()
                delete it->second;
        for (auto it = processes.begin(); it != processes.end(); ++it)
                delete it->second;
+#ifdef WITH_PYTHON
+       RTLIL::Module::get_all_modules()->erase(hashidx_);
+#endif
+}
+
+#ifdef WITH_PYTHON
+static std::map<unsigned int, RTLIL::Module*> all_modules;
+std::map<unsigned int, RTLIL::Module*> *RTLIL::Module::get_all_modules(void)
+{
+       return &all_modules;
+}
+#endif
+
+void RTLIL::Module::makeblackbox()
+{
+       pool<RTLIL::Wire*> delwires;
+
+       for (auto it = wires_.begin(); it != wires_.end(); ++it)
+               if (!it->second->port_input && !it->second->port_output)
+                       delwires.insert(it->second);
+
+       for (auto it = memories.begin(); it != memories.end(); ++it)
+               delete it->second;
+       memories.clear();
+
+       for (auto it = cells_.begin(); it != cells_.end(); ++it)
+               delete it->second;
+       cells_.clear();
+
+       for (auto it = processes.begin(); it != processes.end(); ++it)
+               delete it->second;
+       processes.clear();
+
+       remove(delwires);
+       set_bool_attribute("\\blackbox");
 }
 
 void RTLIL::Module::reprocess_module(RTLIL::Design *, dict<RTLIL::IdString, RTLIL::Module *>)
@@ -758,7 +828,7 @@ namespace {
 
                void check()
                {
-                       if (cell->type.substr(0, 1) != "$" || cell->type.substr(0, 3) == "$__" || cell->type.substr(0, 8) == "$paramod" ||
+                       if (cell->type.substr(0, 1) != "$" || cell->type.substr(0, 3) == "$__" || cell->type.substr(0, 8) == "$paramod" || cell->type.substr(0,10) == "$fmcombine" ||
                                        cell->type.substr(0, 9) == "$verific$" || cell->type.substr(0, 7) == "$array:" || cell->type.substr(0, 8) == "$extern:")
                                return;
 
@@ -1128,6 +1198,46 @@ namespace {
                                return;
                        }
 
+                       if (cell->type.in("$specify2", "$specify3")) {
+                               param_bool("\\FULL");
+                               param_bool("\\SRC_DST_PEN");
+                               param_bool("\\SRC_DST_POL");
+                               param("\\T_RISE_MIN");
+                               param("\\T_RISE_TYP");
+                               param("\\T_RISE_MAX");
+                               param("\\T_FALL_MIN");
+                               param("\\T_FALL_TYP");
+                               param("\\T_FALL_MAX");
+                               port("\\EN", 1);
+                               port("\\SRC", param("\\SRC_WIDTH"));
+                               port("\\DST", param("\\DST_WIDTH"));
+                               if (cell->type == "$specify3") {
+                                       param_bool("\\EDGE_EN");
+                                       param_bool("\\EDGE_POL");
+                                       param_bool("\\DAT_DST_PEN");
+                                       param_bool("\\DAT_DST_POL");
+                                       port("\\DAT", param("\\DST_WIDTH"));
+                               }
+                               check_expected();
+                               return;
+                       }
+
+                       if (cell->type == "$specrule") {
+                               param("\\TYPE");
+                               param_bool("\\SRC_PEN");
+                               param_bool("\\SRC_POL");
+                               param_bool("\\DST_PEN");
+                               param_bool("\\DST_POL");
+                               param("\\T_LIMIT");
+                               param("\\T_LIMIT2");
+                               port("\\SRC_EN", 1);
+                               port("\\DST_EN", 1);
+                               port("\\SRC", param("\\SRC_WIDTH"));
+                               port("\\DST", param("\\DST_WIDTH"));
+                               check_expected();
+                               return;
+                       }
+
                        if (cell->type == "$_BUF_")    { check_gate("AY"); return; }
                        if (cell->type == "$_NOT_")    { check_gate("AY"); return; }
                        if (cell->type == "$_AND_")    { check_gate("ABY"); return; }
@@ -1271,7 +1381,34 @@ void RTLIL::Module::check()
        for (auto &it : processes) {
                log_assert(it.first == it.second->name);
                log_assert(!it.first.empty());
-               // FIXME: More checks here..
+               log_assert(it.second->root_case.compare.empty());
+               std::vector<CaseRule*> all_cases = {&it.second->root_case};
+               for (size_t i = 0; i < all_cases.size(); i++) {
+                       for (auto &switch_it : all_cases[i]->switches) {
+                               for (auto &case_it : switch_it->cases) {
+                                       for (auto &compare_it : case_it->compare) {
+                                               log_assert(switch_it->signal.size() == compare_it.size());
+                                       }
+                                       all_cases.push_back(case_it);
+                               }
+                       }
+               }
+               for (auto &sync_it : it.second->syncs) {
+                       switch (sync_it->type) {
+                               case SyncType::ST0:
+                               case SyncType::ST1:
+                               case SyncType::STp:
+                               case SyncType::STn:
+                               case SyncType::STe:
+                                       log_assert(!sync_it->signal.empty());
+                                       break;
+                               case SyncType::STa:
+                               case SyncType::STg:
+                               case SyncType::STi:
+                                       log_assert(sync_it->signal.empty());
+                                       break;
+                       }
+               }
        }
 
        for (auto &it : connections_) {
@@ -1404,7 +1541,10 @@ void RTLIL::Module::add(RTLIL::Cell *cell)
        cell->module = this;
 }
 
-namespace {
+void RTLIL::Module::remove(const pool<RTLIL::Wire*> &wires)
+{
+       log_assert(refcount_wires_ == 0);
+
        struct DeleteWireWorker
        {
                RTLIL::Module *module;
@@ -1419,17 +1559,29 @@ namespace {
                                }
                        sig = chunks;
                }
-       };
-}
 
-void RTLIL::Module::remove(const pool<RTLIL::Wire*> &wires)
-{
-       log_assert(refcount_wires_ == 0);
+               void operator()(RTLIL::SigSpec &lhs, RTLIL::SigSpec &rhs) {
+                       log_assert(GetSize(lhs) == GetSize(rhs));
+                       RTLIL::SigSpec new_lhs, new_rhs;
+                       for (int i = 0; i < GetSize(lhs); i++) {
+                               RTLIL::SigBit lhs_bit = lhs[i];
+                               if (lhs_bit.wire != nullptr && wires_p->count(lhs_bit.wire))
+                                       continue;
+                               RTLIL::SigBit rhs_bit = rhs[i];
+                               if (rhs_bit.wire != nullptr && wires_p->count(rhs_bit.wire))
+                                       continue;
+                               new_lhs.append(lhs_bit);
+                               new_rhs.append(rhs_bit);
+                       }
+                       lhs = new_lhs;
+                       rhs = new_rhs;
+               }
+       };
 
        DeleteWireWorker delete_wire_worker;
        delete_wire_worker.module = this;
        delete_wire_worker.wires_p = &wires;
-       rewrite_sigspecs(delete_wire_worker);
+       rewrite_sigspecs2(delete_wire_worker);
 
        for (auto &it : wires) {
                log_assert(wires_.count(it->name) != 0);
@@ -1440,13 +1592,21 @@ void RTLIL::Module::remove(const pool<RTLIL::Wire*> &wires)
 
 void RTLIL::Module::remove(RTLIL::Cell *cell)
 {
+       auto it = cells_.find(cell->name);
+       log_assert(it != cells_.end());
+       remove(it);
+}
+
+dict<RTLIL::IdString, RTLIL::Cell*>::iterator RTLIL::Module::remove(dict<RTLIL::IdString, RTLIL::Cell*>::iterator it)
+{
+       RTLIL::Cell *cell = it->second;
        while (!cell->connections_.empty())
                cell->unsetPort(cell->connections_.begin()->first);
 
-       log_assert(cells_.count(cell->name) != 0);
        log_assert(refcount_cells_ == 0);
-       cells_.erase(cell->name);
+       it = cells_.erase(it);
        delete cell;
+       return it;
 }
 
 void RTLIL::Module::rename(RTLIL::Wire *wire, RTLIL::IdString new_name)
@@ -2200,8 +2360,27 @@ RTLIL::Wire::Wire()
        port_input = false;
        port_output = false;
        upto = false;
+
+#ifdef WITH_PYTHON
+       RTLIL::Wire::get_all_wires()->insert(std::pair<unsigned int, RTLIL::Wire*>(hashidx_, this));
+#endif
+}
+
+RTLIL::Wire::~Wire()
+{
+#ifdef WITH_PYTHON
+       RTLIL::Wire::get_all_wires()->erase(hashidx_);
+#endif
 }
 
+#ifdef WITH_PYTHON
+static std::map<unsigned int, RTLIL::Wire*> all_wires;
+std::map<unsigned int, RTLIL::Wire*> *RTLIL::Wire::get_all_wires(void)
+{
+       return &all_wires;
+}
+#endif
+
 RTLIL::Memory::Memory()
 {
        static unsigned int hashidx_count = 123456789;
@@ -2211,6 +2390,9 @@ RTLIL::Memory::Memory()
        width = 1;
        start_offset = 0;
        size = 0;
+#ifdef WITH_PYTHON
+       RTLIL::Memory::get_all_memorys()->insert(std::pair<unsigned int, RTLIL::Memory*>(hashidx_, this));
+#endif
 }
 
 RTLIL::Cell::Cell() : module(nullptr)
@@ -2221,7 +2403,26 @@ RTLIL::Cell::Cell() : module(nullptr)
 
        // log("#memtrace# %p\n", this);
        memhasher();
+
+#ifdef WITH_PYTHON
+       RTLIL::Cell::get_all_cells()->insert(std::pair<unsigned int, RTLIL::Cell*>(hashidx_, this));
+#endif
+}
+
+RTLIL::Cell::~Cell()
+{
+#ifdef WITH_PYTHON
+       RTLIL::Cell::get_all_cells()->erase(hashidx_);
+#endif
+}
+
+#ifdef WITH_PYTHON
+static std::map<unsigned int, RTLIL::Cell*> all_cells;
+std::map<unsigned int, RTLIL::Cell*> *RTLIL::Cell::get_all_cells(void)
+{
+       return &all_cells;
 }
+#endif
 
 bool RTLIL::Cell::hasPort(RTLIL::IdString portname) const
 {
@@ -2358,7 +2559,7 @@ void RTLIL::Cell::check()
 
 void RTLIL::Cell::fixup_parameters(bool set_a_signed, bool set_b_signed)
 {
-       if (type.substr(0, 1) != "$" || type.substr(0, 2) == "$_" || type.substr(0, 8) == "$paramod" ||
+       if (type.substr(0, 1) != "$" || type.substr(0, 2) == "$_" || type.substr(0, 8) == "$paramod" || type.substr(0,10) == "$fmcombine" ||
                        type.substr(0, 9) == "$verific$" || type.substr(0, 7) == "$array:" || type.substr(0, 8) == "$extern:")
                return;
 
@@ -2482,6 +2683,14 @@ RTLIL::SigChunk::SigChunk(RTLIL::SigBit bit)
        width = 1;
 }
 
+RTLIL::SigChunk::SigChunk(const RTLIL::SigChunk &sigchunk) : data(sigchunk.data)
+{
+       wire = sigchunk.wire;
+       data = sigchunk.data;
+       width = sigchunk.width;
+       offset = sigchunk.offset;
+}
+
 RTLIL::SigChunk RTLIL::SigChunk::extract(int offset, int length) const
 {
        RTLIL::SigChunk ret;
@@ -3235,7 +3444,7 @@ void RTLIL::SigSpec::extend_u0(int width, bool is_signed)
                remove(width, width_ - width);
 
        if (width_ < width) {
-               RTLIL::SigBit padding = width_ > 0 ? (*this)[width_ - 1] : RTLIL::State::S0;
+               RTLIL::SigBit padding = width_ > 0 ? (*this)[width_ - 1] : RTLIL::State::Sx;
                if (!is_signed)
                        padding = RTLIL::State::S0;
                while (width_ < width)
@@ -3341,7 +3550,7 @@ bool RTLIL::SigSpec::operator ==(const RTLIL::SigSpec &other) const
        pack();
        other.pack();
 
-       if (chunks_.size() != chunks_.size())
+       if (chunks_.size() != other.chunks_.size())
                return false;
 
        updhash();
@@ -3866,5 +4075,15 @@ RTLIL::Process *RTLIL::Process::clone() const
        return new_proc;
 }
 
+#ifdef WITH_PYTHON
+RTLIL::Memory::~Memory()
+{
+       RTLIL::Memory::get_all_memorys()->erase(hashidx_);
+}
+static std::map<unsigned int, RTLIL::Memory*> all_memorys;
+std::map<unsigned int, RTLIL::Memory*> *RTLIL::Memory::get_all_memorys(void)
+{
+       return &all_memorys;
+}
+#endif
 YOSYS_NAMESPACE_END
-