diff --git a/src/db/db/dbHierNetworkProcessor.cc b/src/db/db/dbHierNetworkProcessor.cc index 1bb053cbc..621a4aea3 100644 --- a/src/db/db/dbHierNetworkProcessor.cc +++ b/src/db/db/dbHierNetworkProcessor.cc @@ -1347,30 +1347,37 @@ private: return; } - db::ICplxTrans i1t = i1.complex_trans (); - db::ICplxTrans tt1 = t1 * i1t; + InstanceToInstanceInteraction ii_key; + db::ICplxTrans i1t, i2t; - db::ICplxTrans i2t = i2.complex_trans (); - db::ICplxTrans tt2 = t2 * i2t; + { + i1t = i1element.at_end () ? i1.complex_trans () : i1.complex_trans (*i1element); + db::ICplxTrans tt1 = t1 * i1t; - db::ICplxTrans tt21 = tt1.inverted () * tt2; - InstanceToInstanceInteraction ii_key (i1.cell_index (), i1.cell_inst ().delegate (), i2.cell_index (), i2.cell_inst ().delegate (), tt21); + i2t = i2element.at_end () ? i2.complex_trans () : i2.complex_trans (*i2element); + db::ICplxTrans tt2 = t2 * i2t; - instance_interaction_cache_type::iterator ii = mp_instance_interaction_cache->find (ii_key); - if (ii != mp_instance_interaction_cache->end ()) { + db::ICplxTrans tt21 = tt1.inverted () * tt2; + ii_key = InstanceToInstanceInteraction (i1.cell_index (), (! i1element.at_end () || i1.size () == 1) ? 0 : i1.cell_inst ().delegate (), + i2.cell_index (), (! i2element.at_end () || i2.size () == 1) ? 0 : i2.cell_inst ().delegate (), + tt21); + + instance_interaction_cache_type::iterator ii = mp_instance_interaction_cache->find (ii_key); + if (ii != mp_instance_interaction_cache->end ()) { + + // use cached interactions + interacting_clusters = ii->second; + for (std::list >::iterator i = interacting_clusters.begin (); i != interacting_clusters.end (); ++i) { + // translate the property IDs + i->first.set_inst_prop_id (i1.prop_id ()); + i->first.transform (i1t); + i->second.set_inst_prop_id (i2.prop_id ()); + i->second.transform (i2t); + } + + return; - // use cached interactions - interacting_clusters = ii->second; - for (std::list >::iterator i = interacting_clusters.begin (); i != interacting_clusters.end (); ++i) { - // translate the property IDs - i->first.set_inst_prop_id (i1.prop_id ()); - i->first.transform (i1t); - i->second.set_inst_prop_id (i2.prop_id ()); - i->second.transform (i2t); } - - return; - } // array interactions diff --git a/src/db/db/dbHierNetworkProcessor.h b/src/db/db/dbHierNetworkProcessor.h index 057e2e649..49e9405fb 100644 --- a/src/db/db/dbHierNetworkProcessor.h +++ b/src/db/db/dbHierNetworkProcessor.h @@ -765,6 +765,10 @@ struct InstanceToInstanceInteraction : ci1 (_ci1), ci2 (_ci2), array1 (_array1), array2 (_array2), t21 (_t21) { } + InstanceToInstanceInteraction () + : ci1 (0), ci2 (0), array1 (0), array2 (0) + { } + bool operator== (const InstanceToInstanceInteraction &other) const { return ci1 == other.ci1 && ci2 == other.ci2 && t21.equal (other.t21) && diff --git a/src/db/db/gsiDeclDbLayoutToNetlist.cc b/src/db/db/gsiDeclDbLayoutToNetlist.cc index eab15bca5..dc65068cc 100644 --- a/src/db/db/gsiDeclDbLayoutToNetlist.cc +++ b/src/db/db/gsiDeclDbLayoutToNetlist.cc @@ -329,7 +329,7 @@ Class decl_dbLayoutToNetlist ("db", "LayoutToNetlist", gsi::method ("global_net_name", &db::LayoutToNetlist::global_net_name, gsi::arg ("global_net_id"), "@brief Gets the global net name for the given global net ID." ) + - gsi::method ("extract_netlist", &db::LayoutToNetlist::extract_netlist, gsi::arg ("join_net_names", std::string ()), gsi::arg ("include_floating_subcircuits", false), + gsi::method ("extract_netlist", &db::LayoutToNetlist::extract_netlist, gsi::arg ("join_net_names", std::string (), "\"\""), gsi::arg ("include_floating_subcircuits", false), "@brief Runs the netlist extraction\n" "'join_net_names' is a glob expression for labels. Nets on top level carrying the same label which matches this glob " "expression will be connected implicitly even if there is no physical connection. This feature is useful to simulate a connection " @@ -359,12 +359,14 @@ Class decl_dbLayoutToNetlist ("db", "LayoutToNetlist", "@brief Runs the netlist extraction\n" "This method runs the netlist extraction like the two-parameter version. In addition to the latter, this method " "can be given a per-cell net label joining specification in 'join_net_names_per_cell'. The keys of this array " - "are cell names or cell names or cell name match expressions (glob style). The values are lable match expressions.\n" + "are cell names or cell names or cell name match expressions (glob style). The values are label match expressions.\n" "\n" "If not an empty string, the 'join_net_names' label match expression is applied to the top cell. For all non-top cells " "the per-cell label match expression is applied and determines what labels are joined into single nets. " "As the keys of 'join_net_names_per_cell' are glob expressions, a single cell may fall into more than one category. In this " - "case, the label match pattern are combined. In any case, the 'join_net_names' has priority for the top cell." + "case, the label match pattern are combined. In any case, the 'join_net_names' has priority for the top cell.\n" + "\n" + "This variant of 'extract_netlist' has been introduced in version 0.26.2." ) + gsi::method_ext ("internal_layout", &l2n_internal_layout, "@brief Gets the internal layout\n" diff --git a/src/db/unit_tests/dbHierNetworkProcessorTests.cc b/src/db/unit_tests/dbHierNetworkProcessorTests.cc index 07ca63197..6f9743225 100644 --- a/src/db/unit_tests/dbHierNetworkProcessorTests.cc +++ b/src/db/unit_tests/dbHierNetworkProcessorTests.cc @@ -1275,3 +1275,9 @@ TEST(118_HierClustersMeanderArrays) run_hc_test (_this, "meander.gds.gz", "meander_au1.gds"); run_hc_test_with_backannotation (_this, "meander.gds.gz", "meander_au2.gds"); } + +TEST(119_HierClustersCombArrays) +{ + run_hc_test (_this, "comb.gds", "comb_au1.gds"); + run_hc_test_with_backannotation (_this, "comb.gds", "comb_au2.gds"); +} diff --git a/src/lay/lay/layGSIHelpProvider.cc b/src/lay/lay/layGSIHelpProvider.cc index ee14780c4..48121cd71 100644 --- a/src/lay/lay/layGSIHelpProvider.cc +++ b/src/lay/lay/layGSIHelpProvider.cc @@ -796,7 +796,6 @@ method_arguments (const gsi::MethodBase *method, const gsi::ClassBase *cls_obj, if (i > 0) { r += ","; r += sep; - r += " "; } r += escape_xml (doc.args [i]); } @@ -816,7 +815,6 @@ method_arguments (const gsi::MethodBase *method, const gsi::ClassBase *cls_obj, if (n > 0) { r += ","; r += sep; - r += " "; } r += type_to_s (*a, linked, false); r += " "; @@ -1312,7 +1310,7 @@ GSIHelpProvider::produce_class_doc (const std::string &cls) const if (! attr.empty ()) { os << "[" << escape_xml (attr) << "] "; } - os << method_return (i->second.first, method_doc, true) << " " << escape_xml (i->first) << " " << method_arguments (i->second.first, cls_obj, method_doc, true, ""); + os << method_return (i->second.first, method_doc, true) << " " << escape_xml (i->first) << " " << method_arguments (i->second.first, cls_obj, method_doc, true, " "); os << "

" << std::endl; os << "

" << tl::to_string (QObject::tr ("Description")) << ": " << replace_references (escape_xml (method_doc.brief_doc), cls_obj) << "

" << std::endl;