Merge branch 'koriakin/xc7nocarrymux' into xaig
[yosys.git] / kernel / rtlil.cc
index 4522b0a085bbf2fc7d04e9b91b8ba54510360c0b..502b45cfdb691dc88a887ecf39a53d15613c23bc 100644 (file)
@@ -218,15 +218,19 @@ void RTLIL::AttrObject::set_bool_attribute(RTLIL::IdString id, bool value)
 {
        if (value)
                attributes[id] = RTLIL::Const(1);
-       else if (attributes.count(id))
-               attributes.erase(id);
+       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)
@@ -1218,6 +1222,22 @@ namespace {
                                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; }
@@ -1361,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_) {
@@ -1494,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;
@@ -1509,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);
@@ -1530,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)
@@ -3480,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();