From 1c8fdaeef86d6e33668e325556380bfa67ec0a6f Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sun, 27 Jul 2014 10:13:22 +0200 Subject: Added RTLIL::ObjIterator and RTLIL::ObjRange --- kernel/rtlil.cc | 29 +++++++++++++++---- kernel/rtlil.h | 89 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 111 insertions(+), 7 deletions(-) diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index f307be43..5fdcb025 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -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 &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); diff --git a/kernel/rtlil.h b/kernel/rtlil.h index 91c9a1ba..be282270 100644 --- a/kernel/rtlil.h +++ b/kernel/rtlil.h @@ -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 + struct ObjIterator + { + typename std::map::iterator it; + std::map *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 &other) { + it = other.it; + list_p = other.list_p; + refcount_p = other.refcount_p; + if (refcount_p) + (*refcount_p)++; + } + + ObjIterator &operator=(const RTLIL::ObjIterator &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 &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 + struct ObjRange + { + std::map *list_p; + int *refcount_p; + + ObjRange(decltype(list_p) list_p, int *refcount_p) : list_p(list_p), refcount_p(refcount_p) { } + RTLIL::ObjIterator begin() { return RTLIL::ObjIterator(list_p, refcount_p); } + RTLIL::ObjIterator end() { return RTLIL::ObjIterator(); } + }; }; struct RTLIL::Const @@ -298,6 +378,9 @@ protected: void add(RTLIL::Cell *cell); public: + int refcount_wires_; + int refcount_cells_; + std::map wires_; std::map cells_; std::vector connections_; @@ -308,6 +391,7 @@ public: std::map processes; RTLIL_ATTRIBUTE_MEMBERS + Module(); virtual ~Module(); virtual RTLIL::IdString derive(RTLIL::Design *design, std::map 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 wires() { return RTLIL::ObjRange(&wires_, &refcount_wires_); } + RTLIL::ObjRange cells() { return RTLIL::ObjRange(&cells_, &refcount_cells_); } + // Removing wires is expensive. If you have to remove wires, remove them all at once. void remove(const std::set &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++; } }; -- cgit v1.2.3