diff --git a/src/db/db/dbBoxScanner.h b/src/db/db/dbBoxScanner.h index eefd7df5a..95b1270ec 100644 --- a/src/db/db/dbBoxScanner.h +++ b/src/db/db/dbBoxScanner.h @@ -415,11 +415,15 @@ private: } while (f != future && bc (*f->first).left () == xx); } while (f != future && f - c < min_box_size); + if (m_report_progress) { + // Note: there is no better estimation of the progress than "current" ... + progress->set (current - m_pp.begin ()); + } + for (iterator_type i = f0; i != f; ++i) { for (iterator_type j = c; j < i; ++j) { if (bs_boxes_overlap (bc (*i->first), bc (*j->first), enl)) { if (seen.insert (std::make_pair (i->first, j->first)).second) { - seen.insert (std::make_pair (j->first, i->first)); rec.add (i->first, i->second, j->first, j->second); if (rec.stop ()) { return false; @@ -431,10 +435,6 @@ private: x = xx; - if (m_report_progress) { - progress->set (f - m_pp.begin ()); - } - } y = yy; diff --git a/src/db/db/dbHierNetworkProcessor.cc b/src/db/db/dbHierNetworkProcessor.cc index c19f12dc1..1bb053cbc 100644 --- a/src/db/db/dbHierNetworkProcessor.cc +++ b/src/db/db/dbHierNetworkProcessor.cc @@ -1023,15 +1023,21 @@ connected_clusters::join_cluster_with (typename local_cluster::id_type id, // handle the connections by translating - const connections_type &to_join = connections_for_cluster (with_id); - connections_type &target = m_connections [id]; - target.insert (target.end (), to_join.begin (), to_join.end ()); + typename std::map::id_type, connections_type>::iterator tc = m_connections.find (with_id); + if (tc != m_connections.end ()) { + + connections_type &to_join = tc->second; + + for (connections_type::const_iterator c = to_join.begin (); c != to_join.end (); ++c) { + m_rev_connections [*c] = id; + } + + connections_type &target = m_connections [id]; + target.splice (target.end (), to_join, to_join.begin (), to_join.end ()); + + m_connections.erase (tc); - for (connections_type::const_iterator c = to_join.begin (); c != to_join.end (); ++c) { - m_rev_connections [*c] = id; } - - m_connections.erase (with_id); } template @@ -1161,6 +1167,11 @@ public: : cluster_id (_cluster_id), other_ci (_other_ci) { } + bool operator== (const ClusterInstanceInteraction &other) const + { + return cluster_id == other.cluster_id && other_ci == other.other_ci; + } + size_t cluster_id; ClusterInstance other_ci; }; @@ -1205,6 +1216,7 @@ public: db::ICplxTrans t; consider_cluster_instance_pair (*c1, *i2, t, ic); + ic.unique (); m_ci_interactions.splice (m_ci_interactions.end (), ic, ic.begin (), ic.end ()); } @@ -1405,6 +1417,8 @@ private: for (std::list >::iterator i = ii_interactions.begin (); i != ii_interactions.end (); ++i) { propagate_cluster_inst (i->second, i2.cell_index (), i2t, i2.prop_id ()); } + + ii_interactions.unique (); interacting_clusters.splice (interacting_clusters.end (), ii_interactions, ii_interactions.begin (), ii_interactions.end ()); } @@ -1430,6 +1444,8 @@ private: for (std::list >::iterator i = ii_interactions.begin (); i != ii_interactions.end (); ++i) { propagate_cluster_inst (i->first, i1.cell_index (), i1t, i1.prop_id ()); } + + ii_interactions.unique (); interacting_clusters.splice (interacting_clusters.end (), ii_interactions, ii_interactions.begin (), ii_interactions.end ()); } @@ -1442,15 +1458,28 @@ private: } - cluster_instance_pair_list_type &cached = (*mp_instance_interaction_cache) [ii_key]; - cached = interacting_clusters; + // remove duplicates (after doing a quick unique before) + // NOTE: duplicates may happen due to manifold child/child interactions which boil down to + // identical parent cluster interactions. + std::vector > sorted_interactions; + sorted_interactions.reserve (interacting_clusters.size ()); + sorted_interactions.insert (sorted_interactions.end (), interacting_clusters.begin (), interacting_clusters.end ()); + interacting_clusters.clear (); + std::sort (sorted_interactions.begin (), sorted_interactions.end ()); + sorted_interactions.erase (std::unique (sorted_interactions.begin (), sorted_interactions.end ()), sorted_interactions.end ()); + + // return the list of unique interactions + interacting_clusters.insert (interacting_clusters.end (), sorted_interactions.begin (), sorted_interactions.end ()); // normalize transformations in cache db::ICplxTrans i1ti = i1t.inverted (), i2ti = i2t.inverted (); - for (std::list >::iterator i = cached.begin (); i != cached.end (); ++i) { + for (std::vector >::iterator i = sorted_interactions.begin (); i != sorted_interactions.end (); ++i) { i->first.transform (i1ti); i->second.transform (i2ti); } + + cluster_instance_pair_list_type &cached = (*mp_instance_interaction_cache) [ii_key]; + cached.insert (cached.end (), sorted_interactions.begin (), sorted_interactions.end ()); } /** @@ -1773,11 +1802,8 @@ private: const ClusterInstance &k2 = ic->second; // Note: "with_self" is false as we're going to create a connected cluster anyway - mp_tree->propagate_cluster_inst (*mp_layout, *mp_cell, k1, mp_cell->cell_index (), false); - mp_tree->propagate_cluster_inst (*mp_layout, *mp_cell, k2, mp_cell->cell_index (), false); - - id_type x1 = mp_cell_clusters->find_cluster_with_connection (k1); - id_type x2 = mp_cell_clusters->find_cluster_with_connection (k2); + id_type x1 = mp_tree->propagate_cluster_inst (*mp_layout, *mp_cell, k1, mp_cell->cell_index (), false); + id_type x2 = mp_tree->propagate_cluster_inst (*mp_layout, *mp_cell, k2, mp_cell->cell_index (), false); if (x1 == 0) { @@ -2228,9 +2254,8 @@ hier_clusters::build_hier_connections (cell_clusters_box_converter &cbc, c } else { // ensures the cluster is propagated so we can connect it with another - propagate_cluster_inst (layout, cell, *i, cell.cell_index (), false); + size_t other_id = propagate_cluster_inst (layout, cell, *i, cell.cell_index (), false); - size_t other_id = local.find_cluster_with_connection (*i); if (other_id == gcid) { // shouldn't happen, but duplicate instances may trigger this } else if (other_id) { diff --git a/src/lay/lay/layMainWindow.cc b/src/lay/lay/layMainWindow.cc index 0a3924964..682f20c84 100644 --- a/src/lay/lay/layMainWindow.cc +++ b/src/lay/lay/layMainWindow.cc @@ -136,19 +136,9 @@ public: } } - void set_can_cancel (bool f) + void set_progress (tl::Progress *progress) { - mp_progress_widget->set_can_cancel (f); - } - - void set_text (const std::string &text) - { - mp_progress_widget->set_text (text); - } - - void set_value (double v, const std::string &value) - { - mp_progress_widget->set_value (v, value); + mp_progress_widget->set_progress (progress); } void add_widget (QWidget *widget) @@ -4732,23 +4722,14 @@ MainWindow::progress_get_widget () const bool MainWindow::update_progress (tl::Progress *progress) { - bool can_cancel = progress->can_cancel (); - std::string text = progress->desc (); - std::string value = progress->formatted_value (); - double v = progress->value (); - if (mp_progress_dialog) { - mp_progress_dialog->set_can_cancel (can_cancel); - mp_progress_dialog->set_text (text); - mp_progress_dialog->set_value (v, value); + mp_progress_dialog->set_progress (progress); return true; } else if (isVisible () && mp_progress_widget) { - mp_progress_widget->set_can_cancel (can_cancel); - mp_progress_widget->set_text (text); - mp_progress_widget->set_value (v, value); + mp_progress_widget->set_progress (progress); return true; } else { diff --git a/src/lay/lay/layProgressWidget.cc b/src/lay/lay/layProgressWidget.cc index 09ce42b5a..58d8306c9 100644 --- a/src/lay/lay/layProgressWidget.cc +++ b/src/lay/lay/layProgressWidget.cc @@ -25,6 +25,7 @@ #include #include +#include #include @@ -34,22 +35,15 @@ namespace lay // -------------------------------------------------------------------- class ProgressBarWidget - : public QWidget + : public QWidget { public: ProgressBarWidget (QWidget *parent, const char *name = ""); void set_value (double v, const std::string &value); - QSize sizeHint () const - { - return QSize (m_width, 1); - } - - QSize minimumSizeHint () const - { - return QSize (m_width, 1); - } + QSize sizeHint () const; + QSize minimumSizeHint () const; private: double m_value; @@ -69,6 +63,7 @@ ProgressBarWidget::ProgressBarWidget (QWidget *parent, const char *name) { setObjectName (QString::fromUtf8 (name)); setMinimumSize (64, 10); + setSizePolicy (QSizePolicy::Expanding, QSizePolicy::Expanding); } void @@ -90,6 +85,19 @@ ProgressBarWidget::set_value (double v, const std::string &value) } } +QSize +ProgressBarWidget::sizeHint () const +{ + QFontMetrics fm (font ()); + return QSize (m_width, fm.height () + 2); +} + +QSize +ProgressBarWidget::minimumSizeHint () const +{ + return QSize (m_width, 1); +} + void ProgressBarWidget::paintEvent (QPaintEvent *) { @@ -161,16 +169,21 @@ ProgressWidget::ProgressWidget (ProgressReporter *pr, QWidget *parent, bool full QFrame *progress_bar_frame = new QFrame (bar_frame); progress_bar_frame->setFrameStyle (QFrame::Box | QFrame::Plain); - progress_bar_frame->setSizePolicy (QSizePolicy::Expanding, QSizePolicy::Preferred); + progress_bar_frame->setSizePolicy (QSizePolicy::Expanding, QSizePolicy::Expanding); layout->addWidget (progress_bar_frame, 0, col, 1, 1); layout->setColumnStretch(col++, 2); - QHBoxLayout *pbf_layout = new QHBoxLayout (progress_bar_frame); + QGridLayout *pbf_layout = new QGridLayout (progress_bar_frame); progress_bar_frame->setLayout (pbf_layout); pbf_layout->setMargin (0); + pbf_layout->setSpacing (0); - mp_progress_bar = new ProgressBarWidget (progress_bar_frame); - pbf_layout->addWidget (mp_progress_bar); + mp_progress_bar1 = new ProgressBarWidget (progress_bar_frame); + pbf_layout->addWidget (mp_progress_bar1, 0, 0, 1, 1); + mp_progress_bar2 = new ProgressBarWidget (progress_bar_frame); + pbf_layout->addWidget (mp_progress_bar2, 1, 0, 1, 1); + mp_progress_bar3 = new ProgressBarWidget (progress_bar_frame); + pbf_layout->addWidget (mp_progress_bar3, 2, 0, 1, 1); layout->addItem (new QSpacerItem (8, 8, QSizePolicy::Fixed, QSizePolicy::Fixed), 0, col++, 1, 1); @@ -218,21 +231,43 @@ ProgressWidget::remove_widget () } void -ProgressWidget::set_can_cancel (bool f) +ProgressWidget::set_progress (tl::Progress *progress) { - mp_cancel_button->setEnabled (f); -} + bool can_cancel = false; + std::string text; -void -ProgressWidget::set_text (const std::string &text) -{ + if (progress) { + can_cancel = progress->can_cancel (); + text = progress->desc (); + } + + mp_cancel_button->setEnabled (can_cancel); mp_label->setText (tl::to_qstring (text)); -} -void -ProgressWidget::set_value (double v, const std::string &value) -{ - mp_progress_bar->set_value (v, value); + lay::ProgressBarWidget *progress_bars[] = { mp_progress_bar1, mp_progress_bar2, mp_progress_bar3 }; + + for (size_t i = 0; i < sizeof (progress_bars) / sizeof (progress_bars[0]); ++i) { + + lay::ProgressBarWidget *pb = progress_bars[i]; + + if (progress) { + + pb->show (); + + std::string value = progress->formatted_value (); + double v = progress->value (); + pb->set_value (v, value); + + progress = progress->next (); + + } else { + pb->hide (); + } + + } + + // according to the doc this should not be required, but without, the progress bar does not resize + mp_progress_bar1->parentWidget ()->updateGeometry (); } void diff --git a/src/lay/lay/layProgressWidget.h b/src/lay/lay/layProgressWidget.h index 976e799fd..66446cea5 100644 --- a/src/lay/lay/layProgressWidget.h +++ b/src/lay/lay/layProgressWidget.h @@ -37,6 +37,11 @@ class QLabel; class QToolButton; class QGridLayout; +namespace tl +{ + class Progress; +} + namespace lay { @@ -50,9 +55,7 @@ Q_OBJECT public: ProgressWidget (ProgressReporter *pr, QWidget *parent, bool full_width = false); - void set_text (const std::string &text); - void set_value (double v, const std::string &value); - void set_can_cancel (bool f); + void set_progress (tl::Progress *progress); void add_widget (QWidget *widget); void remove_widget (); QWidget *get_widget () const; @@ -64,7 +67,7 @@ public slots: private: QLabel *mp_label; - ProgressBarWidget *mp_progress_bar; + ProgressBarWidget *mp_progress_bar1, *mp_progress_bar2, *mp_progress_bar3; QWidget *mp_widget; int m_widget_col; QGridLayout *mp_layout; diff --git a/src/tl/tl/tlProgress.cc b/src/tl/tl/tlProgress.cc index 4a8fbf85e..031bf22f7 100644 --- a/src/tl/tl/tlProgress.cc +++ b/src/tl/tl/tlProgress.cc @@ -148,8 +148,7 @@ Progress::set_desc (const std::string &d) } } -void -Progress::test (bool force_yield) +bool Progress::test(bool force_yield) { if (++m_interval_count >= m_yield_interval || force_yield) { @@ -180,6 +179,10 @@ Progress::test (bool force_yield) throw tl::BreakException (); } + return true; + + } else { + return false; } } @@ -222,8 +225,9 @@ RelativeProgress & RelativeProgress::set (size_t count, bool force_yield) { m_count = count; - test (force_yield || m_count - m_last_count >= m_unit); - m_last_count = m_count; + if (test (force_yield || m_count - m_last_count >= m_unit)) { + m_last_count = m_count; + } return *this; } diff --git a/src/tl/tl/tlProgress.h b/src/tl/tl/tlProgress.h index d5a3fb2b8..40323dd94 100644 --- a/src/tl/tl/tlProgress.h +++ b/src/tl/tl/tlProgress.h @@ -203,7 +203,7 @@ protected: * This method must be called by the derived class. * If "force_yield" is true, the events are always processed. */ - void test (bool force_yield = false); + bool test (bool force_yield = false); /** * @brief This method needs to be called by all derived classes after initialization has happened diff --git a/testdata/algo/device_extract_au2_with_rec_nets.gds b/testdata/algo/device_extract_au2_with_rec_nets.gds index 89fccd17a..a92ab6744 100644 Binary files a/testdata/algo/device_extract_au2_with_rec_nets.gds and b/testdata/algo/device_extract_au2_with_rec_nets.gds differ diff --git a/testdata/algo/device_extract_au3_with_rec_nets.gds b/testdata/algo/device_extract_au3_with_rec_nets.gds index b8ed2a041..8e5c0cd09 100644 Binary files a/testdata/algo/device_extract_au3_with_rec_nets.gds and b/testdata/algo/device_extract_au3_with_rec_nets.gds differ diff --git a/testdata/algo/device_extract_au4_with_rec_nets.gds b/testdata/algo/device_extract_au4_with_rec_nets.gds index 95a6a3156..6ecb58431 100644 Binary files a/testdata/algo/device_extract_au4_with_rec_nets.gds and b/testdata/algo/device_extract_au4_with_rec_nets.gds differ diff --git a/testdata/algo/device_extract_au5_flattened_circuits.gds b/testdata/algo/device_extract_au5_flattened_circuits.gds index a0b32677e..18d0b794d 100644 Binary files a/testdata/algo/device_extract_au5_flattened_circuits.gds and b/testdata/algo/device_extract_au5_flattened_circuits.gds differ diff --git a/testdata/algo/device_extract_au5_with_rec_nets.gds b/testdata/algo/device_extract_au5_with_rec_nets.gds index 365498e93..1c310db0b 100644 Binary files a/testdata/algo/device_extract_au5_with_rec_nets.gds and b/testdata/algo/device_extract_au5_with_rec_nets.gds differ diff --git a/testdata/algo/hc_test_au11.gds b/testdata/algo/hc_test_au11.gds index f24149b23..51611f9e7 100644 Binary files a/testdata/algo/hc_test_au11.gds and b/testdata/algo/hc_test_au11.gds differ diff --git a/testdata/algo/hc_test_au12.gds b/testdata/algo/hc_test_au12.gds index 72d2f1097..fc350873c 100644 Binary files a/testdata/algo/hc_test_au12.gds and b/testdata/algo/hc_test_au12.gds differ diff --git a/testdata/algo/l2n_writer_au_2.gds b/testdata/algo/l2n_writer_au_2.gds index 975f2f836..37ba81471 100644 Binary files a/testdata/algo/l2n_writer_au_2.gds and b/testdata/algo/l2n_writer_au_2.gds differ diff --git a/testdata/python/dbLayoutToNetlist.py b/testdata/python/dbLayoutToNetlist.py index 11e395309..e417684c7 100644 --- a/testdata/python/dbLayoutToNetlist.py +++ b/testdata/python/dbLayoutToNetlist.py @@ -386,11 +386,11 @@ end; l2n.extract_netlist() self.assertEqual(str(l2n.netlist()), """circuit RINGO (); - subcircuit INV2PAIR $1 (BULK=VSS,$2=FB,$3=VDD,$4=VSS,$5=$I7,$6=OSC,$7=VDD); - subcircuit INV2PAIR $2 (BULK=VSS,$2=$I22,$3=VDD,$4=VSS,$5=FB,$6=$I13,$7=VDD); - subcircuit INV2PAIR $3 (BULK=VSS,$2=$I23,$3=VDD,$4=VSS,$5=$I13,$6=$I5,$7=VDD); - subcircuit INV2PAIR $4 (BULK=VSS,$2=$I24,$3=VDD,$4=VSS,$5=$I5,$6=$I6,$7=VDD); - subcircuit INV2PAIR $5 (BULK=VSS,$2=$I25,$3=VDD,$4=VSS,$5=$I6,$6=$I7,$7=VDD); + subcircuit INV2PAIR $1 (BULK=VSS,$2=FB,$3=VDD,$4=VSS,$5=$I11,$6=OSC,$7=VDD); + subcircuit INV2PAIR $2 (BULK=VSS,$2=$I22,$3=VDD,$4=VSS,$5=FB,$6=$I17,$7=VDD); + subcircuit INV2PAIR $3 (BULK=VSS,$2=$I23,$3=VDD,$4=VSS,$5=$I17,$6=$I9,$7=VDD); + subcircuit INV2PAIR $4 (BULK=VSS,$2=$I24,$3=VDD,$4=VSS,$5=$I9,$6=$I10,$7=VDD); + subcircuit INV2PAIR $5 (BULK=VSS,$2=$I25,$3=VDD,$4=VSS,$5=$I10,$6=$I11,$7=VDD); end; circuit INV2PAIR (BULK=BULK,$2=$I8,$3=$I6,$4=$I5,$5=$I3,$6=$I2,$7=$I1); subcircuit INV2 $1 ($1=$I1,IN=$I3,$3=$I7,OUT=$I4,VSS=$I5,VDD=$I6,BULK=BULK); @@ -415,11 +415,11 @@ end; l2n.netlist().purge() self.assertEqual(str(l2n.netlist()), """circuit RINGO (FB=FB,OSC=OSC,VDD=VDD,VSS=VSS); - subcircuit INV2PAIR $1 (BULK=VSS,$2=FB,$3=VDD,$4=VSS,$5=$I7,$6=OSC,$7=VDD); - subcircuit INV2PAIR $2 (BULK=VSS,$2=$I22,$3=VDD,$4=VSS,$5=FB,$6=$I13,$7=VDD); - subcircuit INV2PAIR $3 (BULK=VSS,$2=$I23,$3=VDD,$4=VSS,$5=$I13,$6=$I5,$7=VDD); - subcircuit INV2PAIR $4 (BULK=VSS,$2=$I24,$3=VDD,$4=VSS,$5=$I5,$6=$I6,$7=VDD); - subcircuit INV2PAIR $5 (BULK=VSS,$2=$I25,$3=VDD,$4=VSS,$5=$I6,$6=$I7,$7=VDD); + subcircuit INV2PAIR $1 (BULK=VSS,$2=FB,$3=VDD,$4=VSS,$5=$I11,$6=OSC,$7=VDD); + subcircuit INV2PAIR $2 (BULK=VSS,$2=$I22,$3=VDD,$4=VSS,$5=FB,$6=$I17,$7=VDD); + subcircuit INV2PAIR $3 (BULK=VSS,$2=$I23,$3=VDD,$4=VSS,$5=$I17,$6=$I9,$7=VDD); + subcircuit INV2PAIR $4 (BULK=VSS,$2=$I24,$3=VDD,$4=VSS,$5=$I9,$6=$I10,$7=VDD); + subcircuit INV2PAIR $5 (BULK=VSS,$2=$I25,$3=VDD,$4=VSS,$5=$I10,$6=$I11,$7=VDD); end; circuit INV2PAIR (BULK=BULK,$2=$I8,$3=$I6,$4=$I5,$5=$I3,$6=$I2,$7=$I1); subcircuit INV2 $1 ($1=$I1,IN=$I3,$3=$I7,OUT=$I4,VSS=$I5,VDD=$I6,BULK=BULK); diff --git a/testdata/ruby/dbLayoutToNetlist.rb b/testdata/ruby/dbLayoutToNetlist.rb index 727ab064a..41399f413 100644 --- a/testdata/ruby/dbLayoutToNetlist.rb +++ b/testdata/ruby/dbLayoutToNetlist.rb @@ -424,11 +424,11 @@ END assert_equal(l2n.netlist.to_s, <