From ad27c9a51d02f2e1462a58937d4af34b76bbfd8e Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Tue, 13 Dec 2022 23:35:11 +0100 Subject: [PATCH] WIP: trying to enhance layout layer lookup performance. --- src/db/db/db.pro | 300 +++++++++--------- src/db/db/dbLayout.cc | 266 ++-------------- src/db/db/dbLayout.h | 103 ++----- src/db/db/dbLayoutLayers.cc | 318 ++++++++++++++++++++ src/db/db/dbLayoutLayers.h | 282 +++++++++++++++++ src/laybasic/laybasic/layLayerProperties.cc | 6 +- 6 files changed, 802 insertions(+), 473 deletions(-) create mode 100644 src/db/db/dbLayoutLayers.cc create mode 100644 src/db/db/dbLayoutLayers.h diff --git a/src/db/db/db.pro b/src/db/db/db.pro index 16f2caffb..dc634cd78 100644 --- a/src/db/db/db.pro +++ b/src/db/db/db.pro @@ -39,6 +39,7 @@ SOURCES = \ dbLayerMapping.cc \ dbLayerProperties.cc \ dbLayout.cc \ + dbLayoutLayers.cc \ dbLayoutContextHandler.cc \ dbLayoutDiff.cc \ dbLayoutQuery.cc \ @@ -138,85 +139,85 @@ SOURCES = \ gsiDeclDbVector.cc \ gsiDeclDbLayoutDiff.cc \ gsiDeclDbGlyphs.cc \ - dbConverters.cc \ - dbAsIfFlatRegion.cc \ - dbEmptyRegion.cc \ - dbFlatRegion.cc \ - dbOriginalLayerRegion.cc \ - dbRegionDelegate.cc \ - dbEdgesDelegate.cc \ - dbEmptyEdges.cc \ - dbAsIfFlatEdges.cc \ - dbFlatEdges.cc \ - dbEdgeBoolean.cc \ - dbOriginalLayerEdges.cc \ - dbAsIfFlatEdgePairs.cc \ - dbEmptyEdgePairs.cc \ - dbFlatEdgePairs.cc \ - dbOriginalLayerEdgePairs.cc \ - dbEdgePairsDelegate.cc \ - dbDeepShapeStore.cc \ - dbHierarchyBuilder.cc \ - dbLocalOperation.cc \ - dbHierProcessor.cc \ - dbDeepRegion.cc \ - dbHierNetworkProcessor.cc \ - dbNetlist.cc \ - gsiDeclDbNetlist.cc \ - dbNetlistDeviceClasses.cc \ - dbNetlistDeviceExtractor.cc \ - dbNetlistExtractor.cc \ - gsiDeclDbNetlistDeviceClasses.cc \ - gsiDeclDbNetlistDeviceExtractor.cc \ - gsiDeclDbHierNetworkProcessor.cc \ - dbNetlistDeviceExtractorClasses.cc \ - dbLayoutToNetlist.cc \ - gsiDeclDbLayoutToNetlist.cc \ - dbCircuit.cc \ - dbDevice.cc \ - dbDeviceClass.cc \ - dbNet.cc \ - dbSubCircuit.cc \ - dbPin.cc \ - dbLayoutToNetlistReader.cc \ - dbLayoutToNetlistWriter.cc \ - dbLayoutToNetlistFormatDefs.cc \ - dbDeviceAbstract.cc \ - dbLocalOperationUtils.cc \ - gsiDeclDbDeepShapeStore.cc \ - dbNetlistSpiceWriter.cc \ - dbNetlistWriter.cc \ - dbCellVariants.cc \ - dbDeepEdges.cc \ - dbDeepEdgePairs.cc \ - dbRegionUtils.cc \ - dbEdgesUtils.cc \ - dbRegionProcessors.cc \ - dbNetlistCompare.cc \ - dbNetlistReader.cc \ - dbNetlistSpiceReader.cc \ - gsiDeclDbNetlistCompare.cc \ - dbNetlistCrossReference.cc \ - dbLayoutVsSchematicWriter.cc \ - dbLayoutVsSchematicReader.cc \ - dbLayoutVsSchematicFormatDefs.cc \ - dbLayoutVsSchematic.cc \ - gsiDeclDbNetlistCrossReference.cc \ - gsiDeclDbLayoutVsSchematic.cc \ - dbNetlistObject.cc \ - gsiDeclDbTexts.cc \ - dbTexts.cc \ - dbDeepTexts.cc \ - dbAsIfFlatTexts.cc \ - dbTextsDelegate.cc \ - dbEmptyTexts.cc \ - dbFlatTexts.cc \ - dbTextsUtils.cc \ - dbOriginalLayerTexts.cc \ - dbNetShape.cc \ - dbShapeCollection.cc \ - gsiDeclDbShapeCollection.cc \ - dbShapeCollectionUtils.cc + dbConverters.cc \ + dbAsIfFlatRegion.cc \ + dbEmptyRegion.cc \ + dbFlatRegion.cc \ + dbOriginalLayerRegion.cc \ + dbRegionDelegate.cc \ + dbEdgesDelegate.cc \ + dbEmptyEdges.cc \ + dbAsIfFlatEdges.cc \ + dbFlatEdges.cc \ + dbEdgeBoolean.cc \ + dbOriginalLayerEdges.cc \ + dbAsIfFlatEdgePairs.cc \ + dbEmptyEdgePairs.cc \ + dbFlatEdgePairs.cc \ + dbOriginalLayerEdgePairs.cc \ + dbEdgePairsDelegate.cc \ + dbDeepShapeStore.cc \ + dbHierarchyBuilder.cc \ + dbLocalOperation.cc \ + dbHierProcessor.cc \ + dbDeepRegion.cc \ + dbHierNetworkProcessor.cc \ + dbNetlist.cc \ + gsiDeclDbNetlist.cc \ + dbNetlistDeviceClasses.cc \ + dbNetlistDeviceExtractor.cc \ + dbNetlistExtractor.cc \ + gsiDeclDbNetlistDeviceClasses.cc \ + gsiDeclDbNetlistDeviceExtractor.cc \ + gsiDeclDbHierNetworkProcessor.cc \ + dbNetlistDeviceExtractorClasses.cc \ + dbLayoutToNetlist.cc \ + gsiDeclDbLayoutToNetlist.cc \ + dbCircuit.cc \ + dbDevice.cc \ + dbDeviceClass.cc \ + dbNet.cc \ + dbSubCircuit.cc \ + dbPin.cc \ + dbLayoutToNetlistReader.cc \ + dbLayoutToNetlistWriter.cc \ + dbLayoutToNetlistFormatDefs.cc \ + dbDeviceAbstract.cc \ + dbLocalOperationUtils.cc \ + gsiDeclDbDeepShapeStore.cc \ + dbNetlistSpiceWriter.cc \ + dbNetlistWriter.cc \ + dbCellVariants.cc \ + dbDeepEdges.cc \ + dbDeepEdgePairs.cc \ + dbRegionUtils.cc \ + dbEdgesUtils.cc \ + dbRegionProcessors.cc \ + dbNetlistCompare.cc \ + dbNetlistReader.cc \ + dbNetlistSpiceReader.cc \ + gsiDeclDbNetlistCompare.cc \ + dbNetlistCrossReference.cc \ + dbLayoutVsSchematicWriter.cc \ + dbLayoutVsSchematicReader.cc \ + dbLayoutVsSchematicFormatDefs.cc \ + dbLayoutVsSchematic.cc \ + gsiDeclDbNetlistCrossReference.cc \ + gsiDeclDbLayoutVsSchematic.cc \ + dbNetlistObject.cc \ + gsiDeclDbTexts.cc \ + dbTexts.cc \ + dbDeepTexts.cc \ + dbAsIfFlatTexts.cc \ + dbTextsDelegate.cc \ + dbEmptyTexts.cc \ + dbFlatTexts.cc \ + dbTextsUtils.cc \ + dbOriginalLayerTexts.cc \ + dbNetShape.cc \ + dbShapeCollection.cc \ + gsiDeclDbShapeCollection.cc \ + dbShapeCollectionUtils.cc HEADERS = \ dbArray.h \ @@ -256,6 +257,7 @@ HEADERS = \ dbLayerProperties.h \ dbLayoutDiff.h \ dbLayout.h \ + dbLayoutLayers.h \ dbLayoutQuery.h \ dbLayoutStateModel.h \ dbLayoutUtils.h \ @@ -321,76 +323,76 @@ HEADERS = \ dbForceLink.h \ dbPlugin.h \ dbInit.h \ - dbConverters.h \ - dbAsIfFlatRegion.h \ - dbEmptyRegion.h \ - dbFlatRegion.h \ - dbOriginalLayerRegion.h \ - dbRegionDelegate.h \ - dbEdgesDelegate.h \ - dbEmptyEdges.h \ - dbAsIfFlatEdges.h \ - dbFlatEdges.h \ - dbEdgeBoolean.h \ - dbOriginalLayerEdges.h \ - dbAsIfFlatEdgePairs.h \ - dbEmptyEdgePairs.h \ - dbFlatEdgePairs.h \ - dbOriginalLayerEdgePairs.h \ - dbEdgePairsDelegate.h \ - dbDeepShapeStore.h \ - dbHierarchyBuilder.h \ - dbLocalOperation.h \ - dbHierProcessor.h \ - dbNetlist.h \ - dbNetlistDeviceClasses.h \ - dbNetlistDeviceExtractor.h \ - dbNetlistExtractor.h \ - dbNetlistDeviceExtractorClasses.h \ - dbLayoutToNetlist.h \ - dbHierNetworkProcessor.h \ - dbNetlistUtils.h \ - dbNet.h \ - dbCircuit.h \ - dbDevice.h \ - dbDeviceClass.h \ - dbPin.h \ - dbSubCircuit.h \ - dbLayoutToNetlistReader.h \ - dbLayoutToNetlistWriter.h \ - dbLayoutToNetlistFormatDefs.h \ - dbDeviceAbstract.h \ - dbLocalOperationUtils.h \ - dbDeepRegion.h \ - dbNetlistSpiceWriter.h \ - dbNetlistWriter.h \ - dbCellVariants.h \ - dbDeepEdges.h \ - dbDeepEdgePairs.h \ - dbRegionUtils.h \ - dbEdgesUtils.h \ - dbRegionProcessors.h \ - gsiDeclDbHelpers.h \ - dbNetlistCompare.h \ - dbNetlistReader.h \ - dbNetlistSpiceReader.h \ - dbNetlistCrossReference.h \ - dbLayoutVsSchematicWriter.h \ - dbLayoutVsSchematicReader.h \ - dbLayoutVsSchematicFormatDefs.h \ - dbLayoutVsSchematic.h \ - dbNetlistObject.h \ - dbTexts.h \ - dbDeepTexts.h \ - dbAsIfFlatTexts.h \ - dbTextsDelegate.h \ - dbEmptyTexts.h \ - dbFlatTexts.h \ - dbTextsUtils.h \ - dbOriginalLayerTexts.h \ - dbNetShape.h \ - dbShapeCollection.h \ - dbShapeCollectionUtils.h + dbConverters.h \ + dbAsIfFlatRegion.h \ + dbEmptyRegion.h \ + dbFlatRegion.h \ + dbOriginalLayerRegion.h \ + dbRegionDelegate.h \ + dbEdgesDelegate.h \ + dbEmptyEdges.h \ + dbAsIfFlatEdges.h \ + dbFlatEdges.h \ + dbEdgeBoolean.h \ + dbOriginalLayerEdges.h \ + dbAsIfFlatEdgePairs.h \ + dbEmptyEdgePairs.h \ + dbFlatEdgePairs.h \ + dbOriginalLayerEdgePairs.h \ + dbEdgePairsDelegate.h \ + dbDeepShapeStore.h \ + dbHierarchyBuilder.h \ + dbLocalOperation.h \ + dbHierProcessor.h \ + dbNetlist.h \ + dbNetlistDeviceClasses.h \ + dbNetlistDeviceExtractor.h \ + dbNetlistExtractor.h \ + dbNetlistDeviceExtractorClasses.h \ + dbLayoutToNetlist.h \ + dbHierNetworkProcessor.h \ + dbNetlistUtils.h \ + dbNet.h \ + dbCircuit.h \ + dbDevice.h \ + dbDeviceClass.h \ + dbPin.h \ + dbSubCircuit.h \ + dbLayoutToNetlistReader.h \ + dbLayoutToNetlistWriter.h \ + dbLayoutToNetlistFormatDefs.h \ + dbDeviceAbstract.h \ + dbLocalOperationUtils.h \ + dbDeepRegion.h \ + dbNetlistSpiceWriter.h \ + dbNetlistWriter.h \ + dbCellVariants.h \ + dbDeepEdges.h \ + dbDeepEdgePairs.h \ + dbRegionUtils.h \ + dbEdgesUtils.h \ + dbRegionProcessors.h \ + gsiDeclDbHelpers.h \ + dbNetlistCompare.h \ + dbNetlistReader.h \ + dbNetlistSpiceReader.h \ + dbNetlistCrossReference.h \ + dbLayoutVsSchematicWriter.h \ + dbLayoutVsSchematicReader.h \ + dbLayoutVsSchematicFormatDefs.h \ + dbLayoutVsSchematic.h \ + dbNetlistObject.h \ + dbTexts.h \ + dbDeepTexts.h \ + dbAsIfFlatTexts.h \ + dbTextsDelegate.h \ + dbEmptyTexts.h \ + dbFlatTexts.h \ + dbTextsUtils.h \ + dbOriginalLayerTexts.h \ + dbNetShape.h \ + dbShapeCollection.h \ + dbShapeCollectionUtils.h !equals(HAVE_QT, "0") || !equals(HAVE_PYTHON, "0") { diff --git a/src/db/db/dbLayout.cc b/src/db/db/dbLayout.cc index 51f249d58..458f2eda9 100644 --- a/src/db/db/dbLayout.cc +++ b/src/db/db/dbLayout.cc @@ -255,92 +255,6 @@ private: bool m_insert; }; -// ----------------------------------------------------------------- -// Implementation of the LayerIterator class - -LayerIterator::LayerIterator (unsigned int layer_index, const db::Layout &layout) - : m_layer_index (layer_index), m_layout (layout) -{ - while (m_layer_index < m_layout.layers () && ! m_layout.is_valid_layer (m_layer_index)) { - ++m_layer_index; - } -} - -LayerIterator & -LayerIterator::operator++() -{ - do { - ++m_layer_index; - } while (m_layer_index < m_layout.layers () && ! m_layout.is_valid_layer (m_layer_index)); - - return *this; -} - -std::pair -LayerIterator::operator*() const -{ - return std::pair (m_layer_index, &m_layout.get_properties (m_layer_index)); -} - -// ----------------------------------------------------------------- -// Implementation of the ProxyContextInfo class - -ProxyContextInfo -ProxyContextInfo::deserialize (std::vector::const_iterator from, std::vector::const_iterator to) -{ - ProxyContextInfo info; - - for (std::vector::const_iterator i = from; i != to; ++i) { - - tl::Extractor ex (i->c_str ()); - - if (ex.test ("LIB=")) { - - info.lib_name = ex.skip (); - - } else if (ex.test ("P(")) { - - std::pair vv; - - ex.read_word_or_quoted (vv.first); - ex.test (")"); - ex.test ("="); - ex.read (vv.second); - - info.pcell_parameters.insert (vv); - - } else if (ex.test ("PCELL=")) { - - info.pcell_name = ex.skip (); - - } else if (ex.test ("CELL=")) { - - info.cell_name = ex.skip (); - - } - - } - - return info; -} - -void -ProxyContextInfo::serialize (std::vector &strings) -{ - if (! lib_name.empty ()) { - strings.push_back ("LIB=" + lib_name); - } - for (std::map ::const_iterator p = pcell_parameters.begin (); p != pcell_parameters.end (); ++p) { - strings.push_back ("P(" + tl::to_word_or_quoted_string (p->first) + ")=" + p->second.to_parsable_string ()); - } - if (! pcell_name.empty ()) { - strings.push_back ("PCELL=" + pcell_name); - } - if (! cell_name.empty ()) { - strings.push_back ("CELL=" + cell_name); - } -} - // ----------------------------------------------------------------- // Implementation of the Layout class @@ -353,9 +267,6 @@ Layout::Layout (db::Manager *manager) m_dbu (0.001), m_prop_id (0), m_properties_repository (this), - m_guiding_shape_layer (-1), - m_waste_layer (-1), - m_error_layer (-1), m_do_cleanup (false), m_editable (db::default_editable_mode ()) { @@ -371,9 +282,6 @@ Layout::Layout (bool editable, db::Manager *manager) m_dbu (0.001), m_prop_id (0), m_properties_repository (this), - m_guiding_shape_layer (-1), - m_waste_layer (-1), - m_error_layer (-1), m_do_cleanup (false), m_editable (editable) { @@ -393,9 +301,6 @@ Layout::Layout (const db::Layout &layout) m_dbu (0.001), m_prop_id (0), m_properties_repository (this), - m_guiding_shape_layer (-1), - m_waste_layer (-1), - m_error_layer (-1), m_do_cleanup (false), m_editable (layout.m_editable) { @@ -437,8 +342,7 @@ Layout::clear () m_top_down_list.clear (); - m_free_indices.clear (); - m_layer_states.clear (); + m_layers.clear (); for (std::vector::const_iterator p = m_cell_names.begin (); p != m_cell_names.end (); ++p) { if (*p) { @@ -459,10 +363,6 @@ Layout::clear () m_pcells.clear (); m_pcell_ids.clear (); - m_guiding_shape_layer = -1; - m_waste_layer = -1; - m_error_layer = -1; - m_lib_proxy_map.clear (); m_meta_info.clear (); } @@ -476,9 +376,8 @@ Layout::operator= (const Layout &d) clear (); - m_guiding_shape_layer = d.m_guiding_shape_layer; - m_waste_layer = d.m_waste_layer; - m_error_layer = d.m_error_layer; + m_layers = d.m_layers; + m_editable = d.m_editable; m_pcell_ids = d.m_pcell_ids; @@ -504,9 +403,6 @@ Layout::operator= (const Layout &d) } m_properties_repository = d.m_properties_repository; // because the cell assign operator does not map property ID's .. - m_free_indices = d.m_free_indices; - m_layer_states = d.m_layer_states; - m_layer_props = d.m_layer_props; m_top_down_list = d.m_top_down_list; m_top_cells = d.m_top_cells; @@ -720,14 +616,13 @@ Layout::mem_stat (MemStatistics *stat, MemStatistics::purpose_t purpose, int cat stat->add (typeid (*this), (void *) this, sizeof (*this), sizeof (*this), parent, purpose, cat); } + m_layers.mem_stat (stat, purpose, cat, true, (void *) this); + db::mem_stat (stat, purpose, cat, m_cell_ptrs, true, (void *) this); db::mem_stat (stat, purpose, cat, m_free_cell_indices, true, (void *) this); db::mem_stat (stat, purpose, cat, m_top_down_list, true, (void *) this); - db::mem_stat (stat, purpose, cat, m_free_indices, true, (void *) this); - db::mem_stat (stat, purpose, cat, m_layer_states, true, (void *) this); db::mem_stat (stat, purpose, cat, m_cell_names, true, (void *) this); db::mem_stat (stat, purpose, cat, m_cell_map, true, (void *) this); - db::mem_stat (stat, purpose, cat, m_layer_props, true, (void *) this); db::mem_stat (stat, purpose, cat, m_pcells, true, (void *) this); db::mem_stat (stat, purpose, cat, m_pcell_ids, true, (void *) this); db::mem_stat (stat, purpose, cat, m_lib_proxy_map, true, (void *) this); @@ -1839,8 +1734,8 @@ Layout::meta_info_value (const std::string &name) const void Layout::swap_layers (unsigned int a, unsigned int b) { - tl_assert (a < layers () && m_layer_states [a] != Free); - tl_assert (b < layers () && m_layer_states [b] != Free); + tl_assert (m_layers.layer_state (a) != LayoutLayers::Free); + tl_assert (m_layers.layer_state (b) != LayoutLayers::Free); // clear the shapes for (iterator c = begin (); c != end (); ++c) { @@ -1851,8 +1746,8 @@ Layout::swap_layers (unsigned int a, unsigned int b) void Layout::move_layer (unsigned int src, unsigned int dest) { - tl_assert (src < layers () && m_layer_states [src] != Free); - tl_assert (dest < layers () && m_layer_states [dest] != Free); + tl_assert (m_layers.layer_state (src) != LayoutLayers::Free); + tl_assert (m_layers.layer_state (dest) != LayoutLayers::Free); // move the shapes for (iterator c = begin (); c != end (); ++c) { @@ -1863,8 +1758,8 @@ Layout::move_layer (unsigned int src, unsigned int dest) void Layout::copy_layer (unsigned int src, unsigned int dest) { - tl_assert (src < layers () && m_layer_states [src] != Free); - tl_assert (dest < layers () && m_layer_states [dest] != Free); + tl_assert (m_layers.layer_state (src) != LayoutLayers::Free); + tl_assert (m_layers.layer_state (dest) != LayoutLayers::Free); // copy the shapes for (iterator c = begin (); c != end (); ++c) { @@ -1875,7 +1770,7 @@ Layout::copy_layer (unsigned int src, unsigned int dest) void Layout::clear_layer (unsigned int n) { - tl_assert (n < layers () && m_layer_states [n] != Free); + tl_assert (m_layers.layer_state (n) != LayoutLayers::Free); // clear the shapes for (iterator c = begin (); c != end (); ++c) { @@ -1886,14 +1781,13 @@ Layout::clear_layer (unsigned int n) void Layout::delete_layer (unsigned int n) { - tl_assert (n < layers () && m_layer_states [n] != Free); + tl_assert (m_layers.layer_state (n) != LayoutLayers::Free); if (manager () && manager ()->transacting ()) { - manager ()->queue (this, new InsertRemoveLayerOp (n, m_layer_props [n], false /*delete*/)); + manager ()->queue (this, new InsertRemoveLayerOp (n, m_layers.get_properties (n), false /*delete*/)); } - m_free_indices.push_back (n); - m_layer_states [n] = Free; + m_layers.delete_layer (n); // clear the shapes for (iterator c = begin (); c != end (); ++c) { @@ -1906,11 +1800,7 @@ Layout::delete_layer (unsigned int n) unsigned int Layout::insert_layer (const LayerProperties &props) { - unsigned int i = do_insert_layer (); - while (m_layer_props.size () <= i) { - m_layer_props.push_back (LayerProperties ()); - } - m_layer_props [i] = props; + unsigned int i = m_layers.insert_layer (props); if (manager () && manager ()->transacting ()) { manager ()->queue (this, new InsertRemoveLayerOp (i, props, true/*insert*/)); @@ -1924,11 +1814,7 @@ Layout::insert_layer (const LayerProperties &props) void Layout::insert_layer (unsigned int index, const LayerProperties &props) { - do_insert_layer (index); - while (m_layer_props.size () <= index) { - m_layer_props.push_back (LayerProperties ()); - } - m_layer_props [index] = props; + m_layers.insert_layer (index, props); if (manager () && manager ()->transacting ()) { manager ()->queue (this, new InsertRemoveLayerOp (index, props, true/*insert*/)); @@ -1940,68 +1826,13 @@ Layout::insert_layer (unsigned int index, const LayerProperties &props) unsigned int Layout::get_layer (const db::LayerProperties &lp) { - if (lp.is_null ()) { - // for a null layer info always create a layer - return insert_layer (); - } else { - // if we have a layer with the requested properties already, return this. - for (db::Layout::layer_iterator li = begin_layers (); li != end_layers (); ++li) { - if ((*li).second->log_equal (lp)) { - return (*li).first; - } - } - // otherwise create a new layer - return insert_layer (lp); - } -} - -unsigned int -Layout::error_layer () const -{ - if (m_error_layer < 0) { - // create the waste layer (since that layer is cached we can do - // this in a "const" fashion. - db::Layout *self = const_cast (this); - self->m_error_layer = (int) self->insert_special_layer (db::LayerProperties ("WASTE")); - } - - return (unsigned int) m_error_layer; -} - -unsigned int -Layout::waste_layer () const -{ - if (m_waste_layer < 0) { - // create the waste layer (since that layer is cached we can do - // this in a "const" fashion. - db::Layout *self = const_cast (this); - self->m_waste_layer = (int) self->insert_special_layer (db::LayerProperties ("WASTE")); - } - - return (unsigned int) m_waste_layer; -} - -unsigned int -Layout::guiding_shape_layer () const -{ - if (m_guiding_shape_layer < 0) { - // create the guiding shape layer (since that layer is cached we can do - // this in a "const" fashion. - db::Layout *self = const_cast (this); - self->m_guiding_shape_layer = (int) self->insert_special_layer (db::LayerProperties ("GUIDING_SHAPES")); - } - - return (unsigned int) m_guiding_shape_layer; + return m_layers.get_layer (lp); } unsigned int Layout::insert_special_layer (const LayerProperties &props) { - unsigned int i = do_insert_layer (true /*special*/); - while (m_layer_props.size () <= i) { - m_layer_props.push_back (LayerProperties ()); - } - m_layer_props [i] = props; + unsigned int i = m_layers.insert_special_layer (props); if (manager () && manager ()->transacting ()) { manager ()->queue (this, new InsertRemoveLayerOp (i, props, true/*insert*/)); @@ -2013,13 +1844,13 @@ Layout::insert_special_layer (const LayerProperties &props) void Layout::set_properties (unsigned int i, const LayerProperties &props) { - if (m_layer_props [i] != props) { + if (m_layers.get_properties (i) != props) { if (manager () && manager ()->transacting ()) { - manager ()->queue (this, new SetLayerPropertiesOp (i, props, m_layer_props [i])); + manager ()->queue (this, new SetLayerPropertiesOp (i, props, m_layers.get_properties (i))); } - m_layer_props [i] = props; + m_layers.set_properties (i, props); layer_properties_changed (); @@ -2029,60 +1860,13 @@ Layout::set_properties (unsigned int i, const LayerProperties &props) void Layout::insert_special_layer (unsigned int index, const LayerProperties &props) { - do_insert_layer (index, true /*special*/); - while (m_layer_props.size () <= index) { - m_layer_props.push_back (LayerProperties ()); - } - m_layer_props [index] = props; + m_layers.insert_special_layer (index, props); if (manager () && manager ()->transacting ()) { manager ()->queue (this, new InsertRemoveLayerOp (index, props, true/*insert*/)); } } -unsigned int -Layout::do_insert_layer (bool special) -{ - if (m_free_indices.size () > 0) { - unsigned int i = m_free_indices.back (); - m_free_indices.pop_back (); - m_layer_states [i] = special ? Special : Normal; - return i; - } else { - m_layer_states.push_back (special ? Special : Normal); - unsigned int i = layers () - 1; - return i; - } -} - -void -Layout::do_insert_layer (unsigned int index, bool special) -{ - if (index >= layers ()) { - - // add layer to the end of the list. - // add as may freelist entries as required. - while (index > layers ()) { - m_free_indices.push_back (layers ()); - m_layer_states.push_back (Free); - } - m_layer_states.push_back (special ? Special : Normal); - - } else { - - tl_assert (m_layer_states [index] == Free); - m_layer_states [index] = special ? Special : Normal; - - } - -} - -void -Layout::reserve_layers (unsigned int n) -{ - m_layer_states.reserve (n); -} - static const std::vector &gauge_parameters (const std::vector &p, const db::PCellDeclaration *pcell_decl, std::vector &buffer) { const std::vector &pcp = pcell_decl->parameter_declarations (); @@ -2354,8 +2138,8 @@ Layout::convert_cell_to_static (db::cell_index_type ci) new_cell.set_cell_index (ret_ci); // remove guiding shapes. - if (m_guiding_shape_layer >= 0) { - new_cell.shapes (m_guiding_shape_layer).clear (); + if (m_layers.guiding_shape_layer_maybe () >= 0) { + new_cell.shapes (m_layers.guiding_shape_layer_maybe ()).clear (); } } diff --git a/src/db/db/dbLayout.h b/src/db/db/dbLayout.h index 79337f3b0..99ab11d5e 100644 --- a/src/db/db/dbLayout.h +++ b/src/db/db/dbLayout.h @@ -32,6 +32,7 @@ #include "dbText.h" #include "dbCell.h" #include "dbLayoutStateModel.h" +#include "dbLayoutLayers.h" #include "dbLayerProperties.h" #include "dbMetaInfo.h" #include "dbCellInst.h" @@ -393,50 +394,6 @@ private: cell_type *mp_first, *mp_last; }; -/** - * @brief A layer iterator (for valid layers) - * - * The layer iterator delivers layer indices and layer properties of layer layers. - */ -class DB_PUBLIC LayerIterator -{ -public: - /** - * @brief Constructor - */ - LayerIterator (unsigned int layer_index, const db::Layout &layout); - - /** - * @brief Increment operator - */ - LayerIterator &operator++(); - - /** - * @brief Equality - */ - bool operator== (const LayerIterator &i) - { - return i.m_layer_index == m_layer_index; - } - - /** - * @brief Inequality - */ - bool operator!= (const LayerIterator &i) - { - return i.m_layer_index != m_layer_index; - } - - /** - * @brief Access operator - */ - std::pair operator*() const; - -private: - unsigned int m_layer_index; - const db::Layout &m_layout; -}; - /** * @brief An interface that is used to map layer between libraries and PCells and the layout */ @@ -1426,7 +1383,7 @@ public: */ bool is_valid_layer (unsigned int n) const { - return (n < layers () && m_layer_states [n] == Normal); + return m_layers.layer_state (n) == db::LayoutLayers::Normal; } /** @@ -1434,7 +1391,7 @@ public: */ bool is_free_layer (unsigned int n) const { - return (n >= layers () || m_layer_states [n] == Free); + return m_layers.layer_state (n) == db::LayoutLayers::Free; } /** @@ -1442,7 +1399,7 @@ public: */ bool is_special_layer (unsigned int n) const { - return (n < layers () && m_layer_states [n] == Special); + return m_layers.layer_state (n) == db::LayoutLayers::Special; } /** @@ -1454,7 +1411,7 @@ public: */ unsigned int layers () const { - return (cell_index_type) m_layer_states.size (); + return m_layers.layers (); } /** @@ -1462,7 +1419,7 @@ public: */ layer_iterator begin_layers () const { - return layer_iterator (0, *this); + return m_layers.begin_layers (); } /** @@ -1470,13 +1427,16 @@ public: */ layer_iterator end_layers () const { - return layer_iterator (layers (), *this); + return m_layers.end_layers (); } /** * @brief Reserve space for n layers */ - void reserve_layers (unsigned int n); + void reserve_layers (unsigned int n) + { + m_layers.reserve_layers (n); + } /** * @brief begin iterator of the unsorted cell list @@ -1705,21 +1665,30 @@ public: * * The guiding shape layer is used to store the guiding shapes of PCells */ - unsigned int guiding_shape_layer () const; + unsigned int guiding_shape_layer () const + { + return m_layers.guiding_shape_layer (); + } /** * @brief Gets the waste layer * * The waste layer is used to store shapes that should not be visible and can be cleared at any time. */ - unsigned int waste_layer () const; + unsigned int waste_layer () const + { + return m_layers.waste_layer (); + } /** * @brief Gets the error layer * * The error layer is used to display error messages. */ - unsigned int error_layer () const; + unsigned int error_layer () const + { + return m_layers.error_layer (); + } /** * @brief Set the properties for a specified layer @@ -1731,7 +1700,7 @@ public: */ const LayerProperties &get_properties (unsigned int i) const { - return m_layer_props [i]; + return m_layers.get_properties (i); } /** @@ -1877,8 +1846,6 @@ protected: virtual void do_update (); private: - enum LayerState { Normal, Free, Special }; - db::Library *mp_library; cell_list m_cells; size_t m_cells_size; @@ -1887,11 +1854,9 @@ private: mutable unsigned int m_invalid; cell_index_vector m_top_down_list; size_t m_top_cells; - std::vector m_free_indices; - std::vector m_layer_states; + LayoutLayers m_layers; std::vector m_cell_names; cell_map_type m_cell_map; - std::vector m_layer_props; double m_dbu; db::properties_id_type m_prop_id; StringRepository m_string_repository; @@ -1901,9 +1866,6 @@ private: std::vector m_pcells; pcell_name_map m_pcell_ids; lib_proxy_map m_lib_proxy_map; - int m_guiding_shape_layer; - int m_waste_layer; - int m_error_layer; bool m_do_cleanup; bool m_editable; meta_info m_meta_info; @@ -1937,21 +1899,6 @@ private: */ cell_index_type allocate_new_cell (); - /** - * @brief Insert a new layer - * - * This creates a new index number, either from the free list - * of by creating a new one. - */ - unsigned int do_insert_layer (bool special = false); - - /** - * @brief Insert a new layer at the given index - * - * If the index is unused, create a new layer there. - */ - void do_insert_layer (unsigned int index, bool special = false); - /** * @brief Implementation of prune_cell and prune_subcells */ diff --git a/src/db/db/dbLayoutLayers.cc b/src/db/db/dbLayoutLayers.cc new file mode 100644 index 000000000..e6f8eb251 --- /dev/null +++ b/src/db/db/dbLayoutLayers.cc @@ -0,0 +1,318 @@ + +/* + + KLayoutLayers LayoutLayers Viewer + Copyright (C) 2006-2022 Matthias Koefferlein + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + + +#include "dbLayoutLayers.h" + +namespace db +{ + +// ----------------------------------------------------------------- +// Implementation of the LayerIterator class + +LayerIterator::LayerIterator (unsigned int layer_index, const db::LayoutLayers &layout) + : m_layer_index (layer_index), m_layout (layout) +{ + while (m_layer_index < m_layout.layers () && m_layout.layer_state (m_layer_index) != db::LayoutLayers::Normal) { + ++m_layer_index; + } +} + +LayerIterator & +LayerIterator::operator++() +{ + do { + ++m_layer_index; + } while (m_layer_index < m_layout.layers () && m_layout.layer_state (m_layer_index) != db::LayoutLayers::Normal); + + return *this; +} + +std::pair +LayerIterator::operator*() const +{ + return std::pair (m_layer_index, &m_layout.get_properties (m_layer_index)); +} + +// ----------------------------------------------------------------- +// Implementation of the LayoutLayers class + +LayoutLayers::LayoutLayers () + : m_guiding_shape_layer (-1), + m_waste_layer (-1), + m_error_layer (-1) +{ + // .. nothing yet .. +} + +LayoutLayers::LayoutLayers (const db::LayoutLayers &layout) + : m_guiding_shape_layer (-1), + m_waste_layer (-1), + m_error_layer (-1) +{ + *this = layout; +} + +LayoutLayers::~LayoutLayers () +{ + // .. nothing yet .. +} + +void +LayoutLayers::clear () +{ + m_free_indices.clear (); + m_layer_states.clear (); + m_layer_props.clear (); + m_layers_by_props.clear (); + + m_guiding_shape_layer = -1; + m_waste_layer = -1; + m_error_layer = -1; +} + +LayoutLayers & +LayoutLayers::operator= (const LayoutLayers &d) +{ + if (&d != this) { + + m_guiding_shape_layer = d.m_guiding_shape_layer; + m_waste_layer = d.m_waste_layer; + m_error_layer = d.m_error_layer; + + m_free_indices = d.m_free_indices; + m_layer_states = d.m_layer_states; + m_layer_props = d.m_layer_props; + m_layers_by_props = d.m_layers_by_props; + + } + return *this; +} + +void +LayoutLayers::mem_stat (MemStatistics *stat, MemStatistics::purpose_t purpose, int cat, bool no_self, void *parent) const +{ + if (!no_self) { + stat->add (typeid (*this), (void *) this, sizeof (*this), sizeof (*this), parent, purpose, cat); + } + + db::mem_stat (stat, purpose, cat, m_free_indices, true, (void *) this); + db::mem_stat (stat, purpose, cat, m_layer_states, true, (void *) this); + db::mem_stat (stat, purpose, cat, m_layer_props, true, (void *) this); + db::mem_stat (stat, purpose, cat, m_layers_by_props, true, (void *) this); +} + +void +LayoutLayers::delete_layer (unsigned int n) +{ + const db::LayerProperties &lp = m_layer_props [n]; + if (! lp.is_null ()) { + for (auto i = m_layers_by_props.find (lp); i != m_layers_by_props.end () && i->first.log_equal (lp); ++i) { + if (i->second == n) { + m_layers_by_props.erase (i); + break; + } + } + } + + m_free_indices.push_back (n); + m_layer_props [n] = db::LayerProperties (); + m_layer_states [n] = Free; +} + +unsigned int +LayoutLayers::insert_layer (const LayerProperties &props) +{ + unsigned int i = do_insert_layer (); + set_properties (i, props); + return i; +} + +void +LayoutLayers::insert_layer (unsigned int index, const LayerProperties &props) +{ + if (layer_state (index) == Normal) { + delete_layer (index); + } + do_insert_layer (index); + set_properties (index, props); +} + +unsigned int +LayoutLayers::get_layer (const db::LayerProperties &lp) +{ + if (lp.is_null ()) { + // for a null layer info always create a layer + return insert_layer (); + } else { + auto i = m_layers_by_props.find (lp); + if (i != m_layers_by_props.end () && i->first.log_equal (lp)) { + return i->second; + } else { + // otherwise create a new layer + return insert_layer (lp); + } + } +} + +int +LayoutLayers::get_layer_maybe (const db::LayerProperties &lp) +{ + if (lp.is_null ()) { + return -1; + } else { + auto i = m_layers_by_props.find (lp); + if (i != m_layers_by_props.end () && i->first.log_equal (lp)) { + return int (i->second); + } else { + return -1; + } + } +} + +unsigned int +LayoutLayers::error_layer () const +{ + if (m_error_layer < 0) { + // create the waste layer (since that layer is cached we can do + // this in a "const" fashion. + db::LayoutLayers *self = const_cast (this); + self->m_error_layer = (int) self->insert_special_layer (db::LayerProperties ("WASTE")); + } + + return (unsigned int) m_error_layer; +} + +unsigned int +LayoutLayers::waste_layer () const +{ + if (m_waste_layer < 0) { + // create the waste layer (since that layer is cached we can do + // this in a "const" fashion. + db::LayoutLayers *self = const_cast (this); + self->m_waste_layer = (int) self->insert_special_layer (db::LayerProperties ("WASTE")); + } + + return (unsigned int) m_waste_layer; +} + +unsigned int +LayoutLayers::guiding_shape_layer () const +{ + if (m_guiding_shape_layer < 0) { + // create the guiding shape layer (since that layer is cached we can do + // this in a "const" fashion. + db::LayoutLayers *self = const_cast (this); + self->m_guiding_shape_layer = (int) self->insert_special_layer (db::LayerProperties ("GUIDING_SHAPES")); + } + + return (unsigned int) m_guiding_shape_layer; +} + +unsigned int +LayoutLayers::insert_special_layer (const LayerProperties &props) +{ + unsigned int i = do_insert_layer (true /*special*/); + set_properties (i, props); + return i; +} + +void +LayoutLayers::insert_special_layer (unsigned int index, const LayerProperties &props) +{ + if (layer_state (index) == Normal) { + delete_layer (index); + } + + do_insert_layer (index, true /*special*/); + set_properties (index, props); +} + +unsigned int +LayoutLayers::do_insert_layer (bool special) +{ + if (m_free_indices.size () > 0) { + unsigned int i = m_free_indices.back (); + m_free_indices.pop_back (); + m_layer_states [i] = special ? Special : Normal; + return i; + } else { + m_layer_states.push_back (special ? Special : Normal); + unsigned int i = layers () - 1; + return i; + } +} + +void +LayoutLayers::do_insert_layer (unsigned int index, bool special) +{ + if (index >= layers ()) { + + // add layer to the end of the list. + // add as may freelist entries as required. + while (index > layers ()) { + m_free_indices.push_back (layers ()); + m_layer_states.push_back (Free); + } + m_layer_states.push_back (special ? Special : Normal); + + } else { + + tl_assert (m_layer_states [index] == Free); + m_layer_states [index] = special ? Special : Normal; + + } + +} + +void +LayoutLayers::reserve_layers (unsigned int n) +{ + m_layer_states.reserve (n); +} + +void +LayoutLayers::set_properties (unsigned int n, const LayerProperties &props) +{ + while (m_layer_props.size () <= n) { + m_layer_props.push_back (LayerProperties ()); + } + + const db::LayerProperties &lp = m_layer_props [n]; + if (! lp.is_null ()) { + for (auto i = m_layers_by_props.find (lp); i != m_layers_by_props.end () && i->first.log_equal (lp); ++i) { + if (i->second == n) { + m_layers_by_props.erase (i); + break; + } + } + } + + m_layer_props [n] = props; + + if (! props.is_null ()) { + m_layers_by_props.insert (std::make_pair (props, n)); + } +} + +} + diff --git a/src/db/db/dbLayoutLayers.h b/src/db/db/dbLayoutLayers.h new file mode 100644 index 000000000..fb0046144 --- /dev/null +++ b/src/db/db/dbLayoutLayers.h @@ -0,0 +1,282 @@ + +/* + + KLayout Layout Viewer + Copyright (C) 2006-2022 Matthias Koefferlein + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + + +#ifndef HDR_dbLayoutLayers +#define HDR_dbLayoutLayers + +#include "dbCommon.h" + +#include "dbLayerProperties.h" +#include "dbMemStatistics.h" + +#include +#include + +namespace db +{ + +class MemStatistics; +class LayoutLayers; + +/** + * @brief A layer iterator (for valid layers) + * + * The layer iterator delivers layer indices and layer properties of layer layers. + */ +class DB_PUBLIC LayerIterator +{ +public: + /** + * @brief Constructor + */ + LayerIterator (unsigned int layer_index, const db::LayoutLayers &layout); + + /** + * @brief Increment operator + */ + LayerIterator &operator++(); + + /** + * @brief Equality + */ + bool operator== (const LayerIterator &i) + { + return i.m_layer_index == m_layer_index; + } + + /** + * @brief Inequality + */ + bool operator!= (const LayerIterator &i) + { + return i.m_layer_index != m_layer_index; + } + + /** + * @brief Access operator + */ + std::pair operator*() const; + +private: + unsigned int m_layer_index; + const db::LayoutLayers &m_layout; +}; + +/** + * @brief The layoutLayers object + * + * This object wraps the layer list and manages layer properties, + * layer states and the free layer list. + */ + +class DB_PUBLIC LayoutLayers +{ +public: + typedef LayerIterator layer_iterator; + enum LayerState { Normal, Free, Special }; + + /** + * @brief Standard constructor + */ + LayoutLayers (); + + /** + * @brief The copy ctor + */ + LayoutLayers (const LayoutLayers &d); + + /** + * @brief Destructor + */ + ~LayoutLayers (); + + /** + * @brief Assignment operator + */ + LayoutLayers &operator= (const LayoutLayers &d); + + /** + * @brief Clears the layout layers + */ + void clear (); + + /** + * @brief Deletes a layer + */ + void delete_layer (unsigned int n); + + /** + * @brief Gets the layer's state + */ + LayerState layer_state (unsigned int l) const + { + return l < (unsigned int) m_layer_states.size () ? m_layer_states [l] : Free; + } + + /** + * @brief Gets the number of layers defined so far + * + * TODO: the list of 0 to nlayers-1 also contains the free layers - + * we should get a vector containing the layers that are actually + * allocated. + */ + unsigned int layers () const + { + return (unsigned int) m_layer_states.size (); + } + + /** + * @brief The iterator of valid layers: begin + */ + layer_iterator begin_layers () const + { + return layer_iterator (0, *this); + } + + /** + * @brief The iterator of valid layers: end + */ + layer_iterator end_layers () const + { + return layer_iterator (layers (), *this); + } + + /** + * @brief Reserve space for n layers + */ + void reserve_layers (unsigned int n); + + /** + * @brief Inserts a new layer with the given properties + */ + unsigned int insert_layer (const LayerProperties &props = LayerProperties ()); + + /** + * @brief Inserts a new layer with the given properties at the given index + */ + void insert_layer (unsigned int index, const LayerProperties &props = LayerProperties ()); + + /** + * @brief Gets or creates a layer with the given properties + * + * If there already is a layer matching the given properties, it's index will be + * returned. Otherwise a new layer with these properties is created. + */ + unsigned int get_layer (const db::LayerProperties &props); + + /** + * @brief Gets or creates a layer with the given properties or -1 if such a layer does not exist. + */ + int get_layer_maybe (const db::LayerProperties &props); + + /** + * @brief Insert a new special layer with the given properties + * + * A special layers is used for example to represent rulers. + */ + unsigned int insert_special_layer (const LayerProperties &props = LayerProperties ()); + + /** + * @brief Insert a new layer with the given properties at the given index + * + * A special layers is used for example to represent rulers. + */ + void insert_special_layer (unsigned int index, const LayerProperties &props = LayerProperties ()); + + /** + * @brief Gets the guiding shape layer or -1 if none is set yet. + */ + int guiding_shape_layer_maybe () const + { + return m_guiding_shape_layer; + } + + /** + * @brief Gets the guiding shape layer + * + * The guiding shape layer is used to store the guiding shapes of PCells + */ + unsigned int guiding_shape_layer () const; + + /** + * @brief Gets the waste layer + * + * The waste layer is used to store shapes that should not be visible and can be cleared at any time. + */ + unsigned int waste_layer () const; + + /** + * @brief Gets the error layer + * + * The error layer is used to display error messages. + */ + unsigned int error_layer () const; + + /** + * @brief Sets the properties for a specified layer + */ + void set_properties (unsigned int i, const LayerProperties &props); + + /** + * @brief Gets the properties for a specified layer + */ + const LayerProperties &get_properties (unsigned int i) const + { + return m_layer_props [i]; + } + + /** + * @brief Collects memory statistics + */ + void mem_stat (MemStatistics *stat, MemStatistics::purpose_t purpose, int cat, bool no_self = false, void *parent = 0) const; + +private: + std::vector m_free_indices; + std::vector m_layer_states; + std::vector m_layer_props; + std::multimap m_layers_by_props; + int m_guiding_shape_layer; + int m_waste_layer; + int m_error_layer; + + /** + * @brief Insert a new layer + * + * This creates a new index number, either from the free list + * of by creating a new one. + */ + unsigned int do_insert_layer (bool special = false); + + /** + * @brief Insert a new layer at the given index + * + * If the index is unused, create a new layer there. + */ + void do_insert_layer (unsigned int index, bool special = false); +}; + +} + +#endif + + diff --git a/src/laybasic/laybasic/layLayerProperties.cc b/src/laybasic/laybasic/layLayerProperties.cc index 7ee412e6c..61dc43359 100644 --- a/src/laybasic/laybasic/layLayerProperties.cc +++ b/src/laybasic/laybasic/layLayerProperties.cc @@ -629,11 +629,7 @@ LayerProperties::do_realize (const LayoutViewBase *view) const // lookup the layer with the given name/layer/datatype if (m_layer_index < 0 && ! m_source_real.is_wildcard_layer ()) { - for (unsigned int i = 0; i < cv->layout ().layers () && m_layer_index < 0; ++i) { - if (cv->layout ().is_valid_layer (i) && m_source_real.match (cv->layout ().get_properties (i))) { - m_layer_index = int (i); - } - } + m_layer_index = cv->layout ().get_layer_maybe (m_source_real.layer_props ()); } }