Added RTLIL::ObjIterator and RTLIL::ObjRange
authorClifford Wolf <clifford@clifford.at>
Sun, 27 Jul 2014 08:13:22 +0000 (10:13 +0200)
committerClifford Wolf <clifford@clifford.at>
Sun, 27 Jul 2014 09:18:30 +0000 (11:18 +0200)
kernel/rtlil.cc
kernel/rtlil.h

index f307be43e3e7c19f82392f4a56d1be2b35020d40..5fdcb025affe05a95df2aecbd6aaa1bc35275a3a 100644 (file)
@@ -274,6 +274,12 @@ bool RTLIL::Design::selected_member(RTLIL::IdString mod_name, RTLIL::IdString me
        return selection_stack.back().selected_member(mod_name, memb_name);
 }
 
+RTLIL::Module::Module()
+{
+       refcount_wires_ = 0;
+       refcount_cells_ = 0;
+}
+
 RTLIL::Module::~Module()
 {
        for (auto it = wires_.begin(); it != wires_.end(); it++)
@@ -772,6 +778,9 @@ void RTLIL::Module::optimize()
 
 void RTLIL::Module::cloneInto(RTLIL::Module *new_mod) const
 {
+       log_assert(new_mod->refcount_wires_ == 0);
+       log_assert(new_mod->refcount_cells_ == 0);
+
        new_mod->name = name;
        new_mod->connections_ = connections_;
        new_mod->attributes = attributes;
@@ -815,15 +824,17 @@ RTLIL::Module *RTLIL::Module::clone() const
 
 void RTLIL::Module::add(RTLIL::Wire *wire)
 {
-       assert(!wire->name.empty());
-       assert(count_id(wire->name) == 0);
+       log_assert(!wire->name.empty());
+       log_assert(count_id(wire->name) == 0);
+       log_assert(refcount_wires_ == 0);
        wires_[wire->name] = wire;
 }
 
 void RTLIL::Module::add(RTLIL::Cell *cell)
 {
-       assert(!cell->name.empty());
-       assert(count_id(cell->name) == 0);
+       log_assert(!cell->name.empty());
+       log_assert(count_id(cell->name) == 0);
+       log_assert(refcount_cells_ == 0);
        cells_[cell->name] = cell;
 }
 
@@ -856,20 +867,24 @@ void RTLIL::Module::remove(RTLIL::Wire *wire)
 
 void RTLIL::Module::remove(const std::set<RTLIL::Wire*> &wires)
 {
+       log_assert(refcount_wires_ == 0);
+
        DeleteWireWorker delete_wire_worker;
        delete_wire_worker.module = this;
        delete_wire_worker.wires_p = &wires;
        rewrite_sigspecs(delete_wire_worker);
 
        for (auto &it : wires) {
-               this->wires_.erase(it->name);
+               log_assert(wires_.count(it->name) != 0);
+               wires_.erase(it->name);
                delete it;
        }
 }
 
 void RTLIL::Module::remove(RTLIL::Cell *cell)
 {
-       assert(cells_.count(cell->name) != 0);
+       log_assert(cells_.count(cell->name) != 0);
+       log_assert(refcount_cells_ == 0);
        cells_.erase(cell->name);
        delete cell;
 }
@@ -877,6 +892,7 @@ void RTLIL::Module::remove(RTLIL::Cell *cell)
 void RTLIL::Module::rename(RTLIL::Wire *wire, RTLIL::IdString new_name)
 {
        assert(wires_[wire->name] == wire);
+       log_assert(refcount_wires_ == 0);
        wires_.erase(wire->name);
        wire->name = new_name;
        add(wire);
@@ -885,6 +901,7 @@ void RTLIL::Module::rename(RTLIL::Wire *wire, RTLIL::IdString new_name)
 void RTLIL::Module::rename(RTLIL::Cell *cell, RTLIL::IdString new_name)
 {
        assert(cells_[cell->name] == cell);
+       log_assert(refcount_wires_ == 0);
        cells_.erase(cell->name);
        cell->name = new_name;
        add(cell);
index 91c9a1baa01391eca1d51195bfd6a583e2632772..be2822706a0bfd670372c8028075ec0b539696dc 100644 (file)
@@ -189,6 +189,86 @@ namespace RTLIL
        RTLIL::Const const_pos         (const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len);
        RTLIL::Const const_bu0         (const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len);
        RTLIL::Const const_neg         (const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len);
+
+
+       // This iterator-range-pair is used for Design::modules(), Module::wires() and Module::cells().
+       // It maintains a reference counter that is used to make sure that the container is not modified while being iterated over.
+
+       template<typename T>
+       struct ObjIterator
+       {
+               typename std::map<RTLIL::IdString, T>::iterator it;
+               std::map<RTLIL::IdString, T> *list_p;
+               int *refcount_p;
+
+               ObjIterator() : list_p(nullptr), refcount_p(nullptr) {
+               }
+
+               ObjIterator(decltype(list_p) list_p, int *refcount_p) : list_p(list_p), refcount_p(refcount_p) {
+                       if (list_p->empty()) {
+                               this->list_p = nullptr;
+                               this->refcount_p = nullptr;
+                       } else {
+                               it = list_p->begin();
+                               (*refcount_p)++;
+                       }
+               }
+
+               ObjIterator(const RTLIL::ObjIterator<T> &other) {
+                       it = other.it;
+                       list_p = other.list_p;
+                       refcount_p = other.refcount_p;
+                       if (refcount_p)
+                               (*refcount_p)++;
+               }
+
+               ObjIterator &operator=(const RTLIL::ObjIterator<T> &other) {
+                       if (refcount_p)
+                               (*refcount_p)--;
+                       it = other.it;
+                       list_p = other.list_p;
+                       refcount_p = other.refcount_p;
+                       if (refcount_p)
+                               (*refcount_p)++;
+                       return *this;
+               }
+
+               ~ObjIterator() {
+                       if (refcount_p)
+                               (*refcount_p)--;
+               }
+
+               inline T operator*() const {
+                       assert(list_p != nullptr);
+                       return it->second;
+               }
+
+               inline bool operator!=(const RTLIL::ObjIterator<T> &other) const {
+                       if (list_p == nullptr || other.list_p == nullptr)
+                               return list_p != other.list_p;
+                       return it != other.it;
+               }
+
+               inline void operator++() {
+                       assert(list_p != nullptr);
+                       if (++it == list_p->end()) {
+                               (*refcount_p)--;
+                               list_p = nullptr;
+                               refcount_p = nullptr;
+                       }
+               }
+       };
+
+       template<typename T>
+       struct ObjRange
+       {
+               std::map<RTLIL::IdString, T> *list_p;
+               int *refcount_p;
+
+               ObjRange(decltype(list_p) list_p, int *refcount_p) : list_p(list_p), refcount_p(refcount_p) { }
+               RTLIL::ObjIterator<T> begin() { return RTLIL::ObjIterator<T>(list_p, refcount_p); }
+               RTLIL::ObjIterator<T> end() { return RTLIL::ObjIterator<T>(); }
+       };
 };
 
 struct RTLIL::Const
@@ -298,6 +378,9 @@ protected:
        void add(RTLIL::Cell *cell);
 
 public:
+       int refcount_wires_;
+       int refcount_cells_;
+
        std::map<RTLIL::IdString, RTLIL::Wire*> wires_;
        std::map<RTLIL::IdString, RTLIL::Cell*> cells_;
        std::vector<RTLIL::SigSig> connections_;
@@ -308,6 +391,7 @@ public:
        std::map<RTLIL::IdString, RTLIL::Process*> processes;
        RTLIL_ATTRIBUTE_MEMBERS
 
+       Module();
        virtual ~Module();
        virtual RTLIL::IdString derive(RTLIL::Design *design, std::map<RTLIL::IdString, RTLIL::Const> parameters);
        virtual size_t count_id(RTLIL::IdString id);
@@ -323,6 +407,9 @@ public:
        void cloneInto(RTLIL::Module *new_mod) const;
        virtual RTLIL::Module *clone() const;
 
+       RTLIL::ObjRange<RTLIL::Wire*> wires() { return RTLIL::ObjRange<RTLIL::Wire*>(&wires_, &refcount_wires_); }
+       RTLIL::ObjRange<RTLIL::Cell*> cells() { return RTLIL::ObjRange<RTLIL::Cell*>(&cells_, &refcount_cells_); }
+
        // Removing wires is expensive. If you have to remove wires, remove them all at once.
        void remove(const std::set<RTLIL::Wire*> &wires);
        void remove(RTLIL::Cell *cell);
@@ -583,7 +670,7 @@ struct RTLIL::SigSpecIterator
        int index;
 
        inline RTLIL::SigBit &operator*() const;
-       inline bool operator!=(const RTLIL::SigSpecIterator &other) { return index != other.index; }
+       inline bool operator!=(const RTLIL::SigSpecIterator &other) const { return index != other.index; }
        inline void operator++() { index++; }
 };