WIP: trying to enhance layout layer lookup performance.

This commit is contained in:
Matthias Koefferlein 2022-12-13 23:35:11 +01:00
parent 199dea536a
commit ad27c9a51d
6 changed files with 802 additions and 473 deletions

View File

@ -39,6 +39,7 @@ SOURCES = \
dbLayerMapping.cc \ dbLayerMapping.cc \
dbLayerProperties.cc \ dbLayerProperties.cc \
dbLayout.cc \ dbLayout.cc \
dbLayoutLayers.cc \
dbLayoutContextHandler.cc \ dbLayoutContextHandler.cc \
dbLayoutDiff.cc \ dbLayoutDiff.cc \
dbLayoutQuery.cc \ dbLayoutQuery.cc \
@ -138,85 +139,85 @@ SOURCES = \
gsiDeclDbVector.cc \ gsiDeclDbVector.cc \
gsiDeclDbLayoutDiff.cc \ gsiDeclDbLayoutDiff.cc \
gsiDeclDbGlyphs.cc \ gsiDeclDbGlyphs.cc \
dbConverters.cc \ dbConverters.cc \
dbAsIfFlatRegion.cc \ dbAsIfFlatRegion.cc \
dbEmptyRegion.cc \ dbEmptyRegion.cc \
dbFlatRegion.cc \ dbFlatRegion.cc \
dbOriginalLayerRegion.cc \ dbOriginalLayerRegion.cc \
dbRegionDelegate.cc \ dbRegionDelegate.cc \
dbEdgesDelegate.cc \ dbEdgesDelegate.cc \
dbEmptyEdges.cc \ dbEmptyEdges.cc \
dbAsIfFlatEdges.cc \ dbAsIfFlatEdges.cc \
dbFlatEdges.cc \ dbFlatEdges.cc \
dbEdgeBoolean.cc \ dbEdgeBoolean.cc \
dbOriginalLayerEdges.cc \ dbOriginalLayerEdges.cc \
dbAsIfFlatEdgePairs.cc \ dbAsIfFlatEdgePairs.cc \
dbEmptyEdgePairs.cc \ dbEmptyEdgePairs.cc \
dbFlatEdgePairs.cc \ dbFlatEdgePairs.cc \
dbOriginalLayerEdgePairs.cc \ dbOriginalLayerEdgePairs.cc \
dbEdgePairsDelegate.cc \ dbEdgePairsDelegate.cc \
dbDeepShapeStore.cc \ dbDeepShapeStore.cc \
dbHierarchyBuilder.cc \ dbHierarchyBuilder.cc \
dbLocalOperation.cc \ dbLocalOperation.cc \
dbHierProcessor.cc \ dbHierProcessor.cc \
dbDeepRegion.cc \ dbDeepRegion.cc \
dbHierNetworkProcessor.cc \ dbHierNetworkProcessor.cc \
dbNetlist.cc \ dbNetlist.cc \
gsiDeclDbNetlist.cc \ gsiDeclDbNetlist.cc \
dbNetlistDeviceClasses.cc \ dbNetlistDeviceClasses.cc \
dbNetlistDeviceExtractor.cc \ dbNetlistDeviceExtractor.cc \
dbNetlistExtractor.cc \ dbNetlistExtractor.cc \
gsiDeclDbNetlistDeviceClasses.cc \ gsiDeclDbNetlistDeviceClasses.cc \
gsiDeclDbNetlistDeviceExtractor.cc \ gsiDeclDbNetlistDeviceExtractor.cc \
gsiDeclDbHierNetworkProcessor.cc \ gsiDeclDbHierNetworkProcessor.cc \
dbNetlistDeviceExtractorClasses.cc \ dbNetlistDeviceExtractorClasses.cc \
dbLayoutToNetlist.cc \ dbLayoutToNetlist.cc \
gsiDeclDbLayoutToNetlist.cc \ gsiDeclDbLayoutToNetlist.cc \
dbCircuit.cc \ dbCircuit.cc \
dbDevice.cc \ dbDevice.cc \
dbDeviceClass.cc \ dbDeviceClass.cc \
dbNet.cc \ dbNet.cc \
dbSubCircuit.cc \ dbSubCircuit.cc \
dbPin.cc \ dbPin.cc \
dbLayoutToNetlistReader.cc \ dbLayoutToNetlistReader.cc \
dbLayoutToNetlistWriter.cc \ dbLayoutToNetlistWriter.cc \
dbLayoutToNetlistFormatDefs.cc \ dbLayoutToNetlistFormatDefs.cc \
dbDeviceAbstract.cc \ dbDeviceAbstract.cc \
dbLocalOperationUtils.cc \ dbLocalOperationUtils.cc \
gsiDeclDbDeepShapeStore.cc \ gsiDeclDbDeepShapeStore.cc \
dbNetlistSpiceWriter.cc \ dbNetlistSpiceWriter.cc \
dbNetlistWriter.cc \ dbNetlistWriter.cc \
dbCellVariants.cc \ dbCellVariants.cc \
dbDeepEdges.cc \ dbDeepEdges.cc \
dbDeepEdgePairs.cc \ dbDeepEdgePairs.cc \
dbRegionUtils.cc \ dbRegionUtils.cc \
dbEdgesUtils.cc \ dbEdgesUtils.cc \
dbRegionProcessors.cc \ dbRegionProcessors.cc \
dbNetlistCompare.cc \ dbNetlistCompare.cc \
dbNetlistReader.cc \ dbNetlistReader.cc \
dbNetlistSpiceReader.cc \ dbNetlistSpiceReader.cc \
gsiDeclDbNetlistCompare.cc \ gsiDeclDbNetlistCompare.cc \
dbNetlistCrossReference.cc \ dbNetlistCrossReference.cc \
dbLayoutVsSchematicWriter.cc \ dbLayoutVsSchematicWriter.cc \
dbLayoutVsSchematicReader.cc \ dbLayoutVsSchematicReader.cc \
dbLayoutVsSchematicFormatDefs.cc \ dbLayoutVsSchematicFormatDefs.cc \
dbLayoutVsSchematic.cc \ dbLayoutVsSchematic.cc \
gsiDeclDbNetlistCrossReference.cc \ gsiDeclDbNetlistCrossReference.cc \
gsiDeclDbLayoutVsSchematic.cc \ gsiDeclDbLayoutVsSchematic.cc \
dbNetlistObject.cc \ dbNetlistObject.cc \
gsiDeclDbTexts.cc \ gsiDeclDbTexts.cc \
dbTexts.cc \ dbTexts.cc \
dbDeepTexts.cc \ dbDeepTexts.cc \
dbAsIfFlatTexts.cc \ dbAsIfFlatTexts.cc \
dbTextsDelegate.cc \ dbTextsDelegate.cc \
dbEmptyTexts.cc \ dbEmptyTexts.cc \
dbFlatTexts.cc \ dbFlatTexts.cc \
dbTextsUtils.cc \ dbTextsUtils.cc \
dbOriginalLayerTexts.cc \ dbOriginalLayerTexts.cc \
dbNetShape.cc \ dbNetShape.cc \
dbShapeCollection.cc \ dbShapeCollection.cc \
gsiDeclDbShapeCollection.cc \ gsiDeclDbShapeCollection.cc \
dbShapeCollectionUtils.cc dbShapeCollectionUtils.cc
HEADERS = \ HEADERS = \
dbArray.h \ dbArray.h \
@ -256,6 +257,7 @@ HEADERS = \
dbLayerProperties.h \ dbLayerProperties.h \
dbLayoutDiff.h \ dbLayoutDiff.h \
dbLayout.h \ dbLayout.h \
dbLayoutLayers.h \
dbLayoutQuery.h \ dbLayoutQuery.h \
dbLayoutStateModel.h \ dbLayoutStateModel.h \
dbLayoutUtils.h \ dbLayoutUtils.h \
@ -321,76 +323,76 @@ HEADERS = \
dbForceLink.h \ dbForceLink.h \
dbPlugin.h \ dbPlugin.h \
dbInit.h \ dbInit.h \
dbConverters.h \ dbConverters.h \
dbAsIfFlatRegion.h \ dbAsIfFlatRegion.h \
dbEmptyRegion.h \ dbEmptyRegion.h \
dbFlatRegion.h \ dbFlatRegion.h \
dbOriginalLayerRegion.h \ dbOriginalLayerRegion.h \
dbRegionDelegate.h \ dbRegionDelegate.h \
dbEdgesDelegate.h \ dbEdgesDelegate.h \
dbEmptyEdges.h \ dbEmptyEdges.h \
dbAsIfFlatEdges.h \ dbAsIfFlatEdges.h \
dbFlatEdges.h \ dbFlatEdges.h \
dbEdgeBoolean.h \ dbEdgeBoolean.h \
dbOriginalLayerEdges.h \ dbOriginalLayerEdges.h \
dbAsIfFlatEdgePairs.h \ dbAsIfFlatEdgePairs.h \
dbEmptyEdgePairs.h \ dbEmptyEdgePairs.h \
dbFlatEdgePairs.h \ dbFlatEdgePairs.h \
dbOriginalLayerEdgePairs.h \ dbOriginalLayerEdgePairs.h \
dbEdgePairsDelegate.h \ dbEdgePairsDelegate.h \
dbDeepShapeStore.h \ dbDeepShapeStore.h \
dbHierarchyBuilder.h \ dbHierarchyBuilder.h \
dbLocalOperation.h \ dbLocalOperation.h \
dbHierProcessor.h \ dbHierProcessor.h \
dbNetlist.h \ dbNetlist.h \
dbNetlistDeviceClasses.h \ dbNetlistDeviceClasses.h \
dbNetlistDeviceExtractor.h \ dbNetlistDeviceExtractor.h \
dbNetlistExtractor.h \ dbNetlistExtractor.h \
dbNetlistDeviceExtractorClasses.h \ dbNetlistDeviceExtractorClasses.h \
dbLayoutToNetlist.h \ dbLayoutToNetlist.h \
dbHierNetworkProcessor.h \ dbHierNetworkProcessor.h \
dbNetlistUtils.h \ dbNetlistUtils.h \
dbNet.h \ dbNet.h \
dbCircuit.h \ dbCircuit.h \
dbDevice.h \ dbDevice.h \
dbDeviceClass.h \ dbDeviceClass.h \
dbPin.h \ dbPin.h \
dbSubCircuit.h \ dbSubCircuit.h \
dbLayoutToNetlistReader.h \ dbLayoutToNetlistReader.h \
dbLayoutToNetlistWriter.h \ dbLayoutToNetlistWriter.h \
dbLayoutToNetlistFormatDefs.h \ dbLayoutToNetlistFormatDefs.h \
dbDeviceAbstract.h \ dbDeviceAbstract.h \
dbLocalOperationUtils.h \ dbLocalOperationUtils.h \
dbDeepRegion.h \ dbDeepRegion.h \
dbNetlistSpiceWriter.h \ dbNetlistSpiceWriter.h \
dbNetlistWriter.h \ dbNetlistWriter.h \
dbCellVariants.h \ dbCellVariants.h \
dbDeepEdges.h \ dbDeepEdges.h \
dbDeepEdgePairs.h \ dbDeepEdgePairs.h \
dbRegionUtils.h \ dbRegionUtils.h \
dbEdgesUtils.h \ dbEdgesUtils.h \
dbRegionProcessors.h \ dbRegionProcessors.h \
gsiDeclDbHelpers.h \ gsiDeclDbHelpers.h \
dbNetlistCompare.h \ dbNetlistCompare.h \
dbNetlistReader.h \ dbNetlistReader.h \
dbNetlistSpiceReader.h \ dbNetlistSpiceReader.h \
dbNetlistCrossReference.h \ dbNetlistCrossReference.h \
dbLayoutVsSchematicWriter.h \ dbLayoutVsSchematicWriter.h \
dbLayoutVsSchematicReader.h \ dbLayoutVsSchematicReader.h \
dbLayoutVsSchematicFormatDefs.h \ dbLayoutVsSchematicFormatDefs.h \
dbLayoutVsSchematic.h \ dbLayoutVsSchematic.h \
dbNetlistObject.h \ dbNetlistObject.h \
dbTexts.h \ dbTexts.h \
dbDeepTexts.h \ dbDeepTexts.h \
dbAsIfFlatTexts.h \ dbAsIfFlatTexts.h \
dbTextsDelegate.h \ dbTextsDelegate.h \
dbEmptyTexts.h \ dbEmptyTexts.h \
dbFlatTexts.h \ dbFlatTexts.h \
dbTextsUtils.h \ dbTextsUtils.h \
dbOriginalLayerTexts.h \ dbOriginalLayerTexts.h \
dbNetShape.h \ dbNetShape.h \
dbShapeCollection.h \ dbShapeCollection.h \
dbShapeCollectionUtils.h dbShapeCollectionUtils.h
!equals(HAVE_QT, "0") || !equals(HAVE_PYTHON, "0") { !equals(HAVE_QT, "0") || !equals(HAVE_PYTHON, "0") {

View File

@ -255,92 +255,6 @@ private:
bool m_insert; 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<unsigned int, const db::LayerProperties *>
LayerIterator::operator*() const
{
return std::pair<unsigned int, const db::LayerProperties *> (m_layer_index, &m_layout.get_properties (m_layer_index));
}
// -----------------------------------------------------------------
// Implementation of the ProxyContextInfo class
ProxyContextInfo
ProxyContextInfo::deserialize (std::vector<std::string>::const_iterator from, std::vector<std::string>::const_iterator to)
{
ProxyContextInfo info;
for (std::vector<std::string>::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<std::string, tl::Variant> 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<std::string> &strings)
{
if (! lib_name.empty ()) {
strings.push_back ("LIB=" + lib_name);
}
for (std::map<std::string, tl::Variant> ::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 // Implementation of the Layout class
@ -353,9 +267,6 @@ Layout::Layout (db::Manager *manager)
m_dbu (0.001), m_dbu (0.001),
m_prop_id (0), m_prop_id (0),
m_properties_repository (this), m_properties_repository (this),
m_guiding_shape_layer (-1),
m_waste_layer (-1),
m_error_layer (-1),
m_do_cleanup (false), m_do_cleanup (false),
m_editable (db::default_editable_mode ()) m_editable (db::default_editable_mode ())
{ {
@ -371,9 +282,6 @@ Layout::Layout (bool editable, db::Manager *manager)
m_dbu (0.001), m_dbu (0.001),
m_prop_id (0), m_prop_id (0),
m_properties_repository (this), m_properties_repository (this),
m_guiding_shape_layer (-1),
m_waste_layer (-1),
m_error_layer (-1),
m_do_cleanup (false), m_do_cleanup (false),
m_editable (editable) m_editable (editable)
{ {
@ -393,9 +301,6 @@ Layout::Layout (const db::Layout &layout)
m_dbu (0.001), m_dbu (0.001),
m_prop_id (0), m_prop_id (0),
m_properties_repository (this), m_properties_repository (this),
m_guiding_shape_layer (-1),
m_waste_layer (-1),
m_error_layer (-1),
m_do_cleanup (false), m_do_cleanup (false),
m_editable (layout.m_editable) m_editable (layout.m_editable)
{ {
@ -437,8 +342,7 @@ Layout::clear ()
m_top_down_list.clear (); m_top_down_list.clear ();
m_free_indices.clear (); m_layers.clear ();
m_layer_states.clear ();
for (std::vector<const char *>::const_iterator p = m_cell_names.begin (); p != m_cell_names.end (); ++p) { for (std::vector<const char *>::const_iterator p = m_cell_names.begin (); p != m_cell_names.end (); ++p) {
if (*p) { if (*p) {
@ -459,10 +363,6 @@ Layout::clear ()
m_pcells.clear (); m_pcells.clear ();
m_pcell_ids.clear (); m_pcell_ids.clear ();
m_guiding_shape_layer = -1;
m_waste_layer = -1;
m_error_layer = -1;
m_lib_proxy_map.clear (); m_lib_proxy_map.clear ();
m_meta_info.clear (); m_meta_info.clear ();
} }
@ -476,9 +376,8 @@ Layout::operator= (const Layout &d)
clear (); clear ();
m_guiding_shape_layer = d.m_guiding_shape_layer; m_layers = d.m_layers;
m_waste_layer = d.m_waste_layer;
m_error_layer = d.m_error_layer;
m_editable = d.m_editable; m_editable = d.m_editable;
m_pcell_ids = d.m_pcell_ids; 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_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_down_list = d.m_top_down_list;
m_top_cells = d.m_top_cells; 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); 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_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_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_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_names, true, (void *) this);
db::mem_stat (stat, purpose, cat, m_cell_map, 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_pcells, true, (void *) this);
db::mem_stat (stat, purpose, cat, m_pcell_ids, 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); 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 void
Layout::swap_layers (unsigned int a, unsigned int b) Layout::swap_layers (unsigned int a, unsigned int b)
{ {
tl_assert (a < layers () && m_layer_states [a] != Free); tl_assert (m_layers.layer_state (a) != LayoutLayers::Free);
tl_assert (b < layers () && m_layer_states [b] != Free); tl_assert (m_layers.layer_state (b) != LayoutLayers::Free);
// clear the shapes // clear the shapes
for (iterator c = begin (); c != end (); ++c) { for (iterator c = begin (); c != end (); ++c) {
@ -1851,8 +1746,8 @@ Layout::swap_layers (unsigned int a, unsigned int b)
void void
Layout::move_layer (unsigned int src, unsigned int dest) Layout::move_layer (unsigned int src, unsigned int dest)
{ {
tl_assert (src < layers () && m_layer_states [src] != Free); tl_assert (m_layers.layer_state (src) != LayoutLayers::Free);
tl_assert (dest < layers () && m_layer_states [dest] != Free); tl_assert (m_layers.layer_state (dest) != LayoutLayers::Free);
// move the shapes // move the shapes
for (iterator c = begin (); c != end (); ++c) { for (iterator c = begin (); c != end (); ++c) {
@ -1863,8 +1758,8 @@ Layout::move_layer (unsigned int src, unsigned int dest)
void void
Layout::copy_layer (unsigned int src, unsigned int dest) Layout::copy_layer (unsigned int src, unsigned int dest)
{ {
tl_assert (src < layers () && m_layer_states [src] != Free); tl_assert (m_layers.layer_state (src) != LayoutLayers::Free);
tl_assert (dest < layers () && m_layer_states [dest] != Free); tl_assert (m_layers.layer_state (dest) != LayoutLayers::Free);
// copy the shapes // copy the shapes
for (iterator c = begin (); c != end (); ++c) { for (iterator c = begin (); c != end (); ++c) {
@ -1875,7 +1770,7 @@ Layout::copy_layer (unsigned int src, unsigned int dest)
void void
Layout::clear_layer (unsigned int n) 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 // clear the shapes
for (iterator c = begin (); c != end (); ++c) { for (iterator c = begin (); c != end (); ++c) {
@ -1886,14 +1781,13 @@ Layout::clear_layer (unsigned int n)
void void
Layout::delete_layer (unsigned int n) 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 ()) { 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_layers.delete_layer (n);
m_layer_states [n] = Free;
// clear the shapes // clear the shapes
for (iterator c = begin (); c != end (); ++c) { for (iterator c = begin (); c != end (); ++c) {
@ -1906,11 +1800,7 @@ Layout::delete_layer (unsigned int n)
unsigned int unsigned int
Layout::insert_layer (const LayerProperties &props) Layout::insert_layer (const LayerProperties &props)
{ {
unsigned int i = do_insert_layer (); unsigned int i = m_layers.insert_layer (props);
while (m_layer_props.size () <= i) {
m_layer_props.push_back (LayerProperties ());
}
m_layer_props [i] = props;
if (manager () && manager ()->transacting ()) { if (manager () && manager ()->transacting ()) {
manager ()->queue (this, new InsertRemoveLayerOp (i, props, true/*insert*/)); manager ()->queue (this, new InsertRemoveLayerOp (i, props, true/*insert*/));
@ -1924,11 +1814,7 @@ Layout::insert_layer (const LayerProperties &props)
void void
Layout::insert_layer (unsigned int index, const LayerProperties &props) Layout::insert_layer (unsigned int index, const LayerProperties &props)
{ {
do_insert_layer (index); m_layers.insert_layer (index, props);
while (m_layer_props.size () <= index) {
m_layer_props.push_back (LayerProperties ());
}
m_layer_props [index] = props;
if (manager () && manager ()->transacting ()) { if (manager () && manager ()->transacting ()) {
manager ()->queue (this, new InsertRemoveLayerOp (index, props, true/*insert*/)); manager ()->queue (this, new InsertRemoveLayerOp (index, props, true/*insert*/));
@ -1940,68 +1826,13 @@ Layout::insert_layer (unsigned int index, const LayerProperties &props)
unsigned int unsigned int
Layout::get_layer (const db::LayerProperties &lp) Layout::get_layer (const db::LayerProperties &lp)
{ {
if (lp.is_null ()) { return m_layers.get_layer (lp);
// 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<db::Layout *> (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<db::Layout *> (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<db::Layout *> (this);
self->m_guiding_shape_layer = (int) self->insert_special_layer (db::LayerProperties ("GUIDING_SHAPES"));
}
return (unsigned int) m_guiding_shape_layer;
} }
unsigned int unsigned int
Layout::insert_special_layer (const LayerProperties &props) Layout::insert_special_layer (const LayerProperties &props)
{ {
unsigned int i = do_insert_layer (true /*special*/); unsigned int i = m_layers.insert_special_layer (props);
while (m_layer_props.size () <= i) {
m_layer_props.push_back (LayerProperties ());
}
m_layer_props [i] = props;
if (manager () && manager ()->transacting ()) { if (manager () && manager ()->transacting ()) {
manager ()->queue (this, new InsertRemoveLayerOp (i, props, true/*insert*/)); manager ()->queue (this, new InsertRemoveLayerOp (i, props, true/*insert*/));
@ -2013,13 +1844,13 @@ Layout::insert_special_layer (const LayerProperties &props)
void void
Layout::set_properties (unsigned int i, const LayerProperties &props) 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 ()) { 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 (); layer_properties_changed ();
@ -2029,60 +1860,13 @@ Layout::set_properties (unsigned int i, const LayerProperties &props)
void void
Layout::insert_special_layer (unsigned int index, const LayerProperties &props) Layout::insert_special_layer (unsigned int index, const LayerProperties &props)
{ {
do_insert_layer (index, true /*special*/); m_layers.insert_special_layer (index, props);
while (m_layer_props.size () <= index) {
m_layer_props.push_back (LayerProperties ());
}
m_layer_props [index] = props;
if (manager () && manager ()->transacting ()) { if (manager () && manager ()->transacting ()) {
manager ()->queue (this, new InsertRemoveLayerOp (index, props, true/*insert*/)); 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<tl::Variant> &gauge_parameters (const std::vector<tl::Variant> &p, const db::PCellDeclaration *pcell_decl, std::vector<tl::Variant> &buffer) static const std::vector<tl::Variant> &gauge_parameters (const std::vector<tl::Variant> &p, const db::PCellDeclaration *pcell_decl, std::vector<tl::Variant> &buffer)
{ {
const std::vector<db::PCellParameterDeclaration> &pcp = pcell_decl->parameter_declarations (); const std::vector<db::PCellParameterDeclaration> &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); new_cell.set_cell_index (ret_ci);
// remove guiding shapes. // remove guiding shapes.
if (m_guiding_shape_layer >= 0) { if (m_layers.guiding_shape_layer_maybe () >= 0) {
new_cell.shapes (m_guiding_shape_layer).clear (); new_cell.shapes (m_layers.guiding_shape_layer_maybe ()).clear ();
} }
} }

View File

@ -32,6 +32,7 @@
#include "dbText.h" #include "dbText.h"
#include "dbCell.h" #include "dbCell.h"
#include "dbLayoutStateModel.h" #include "dbLayoutStateModel.h"
#include "dbLayoutLayers.h"
#include "dbLayerProperties.h" #include "dbLayerProperties.h"
#include "dbMetaInfo.h" #include "dbMetaInfo.h"
#include "dbCellInst.h" #include "dbCellInst.h"
@ -393,50 +394,6 @@ private:
cell_type *mp_first, *mp_last; 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<unsigned int, const db::LayerProperties *> 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 * @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 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 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 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 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 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 layer_iterator end_layers () const
{ {
return layer_iterator (layers (), *this); return m_layers.end_layers ();
} }
/** /**
* @brief Reserve space for n 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 * @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 * 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 * @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. * 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 * @brief Gets the error layer
* *
* The error layer is used to display error messages. * 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 * @brief Set the properties for a specified layer
@ -1731,7 +1700,7 @@ public:
*/ */
const LayerProperties &get_properties (unsigned int i) const 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 (); virtual void do_update ();
private: private:
enum LayerState { Normal, Free, Special };
db::Library *mp_library; db::Library *mp_library;
cell_list m_cells; cell_list m_cells;
size_t m_cells_size; size_t m_cells_size;
@ -1887,11 +1854,9 @@ private:
mutable unsigned int m_invalid; mutable unsigned int m_invalid;
cell_index_vector m_top_down_list; cell_index_vector m_top_down_list;
size_t m_top_cells; size_t m_top_cells;
std::vector<unsigned int> m_free_indices; LayoutLayers m_layers;
std::vector<LayerState> m_layer_states;
std::vector<const char *> m_cell_names; std::vector<const char *> m_cell_names;
cell_map_type m_cell_map; cell_map_type m_cell_map;
std::vector<LayerProperties> m_layer_props;
double m_dbu; double m_dbu;
db::properties_id_type m_prop_id; db::properties_id_type m_prop_id;
StringRepository m_string_repository; StringRepository m_string_repository;
@ -1901,9 +1866,6 @@ private:
std::vector<pcell_header_type *> m_pcells; std::vector<pcell_header_type *> m_pcells;
pcell_name_map m_pcell_ids; pcell_name_map m_pcell_ids;
lib_proxy_map m_lib_proxy_map; 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_do_cleanup;
bool m_editable; bool m_editable;
meta_info m_meta_info; meta_info m_meta_info;
@ -1937,21 +1899,6 @@ private:
*/ */
cell_index_type allocate_new_cell (); 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 * @brief Implementation of prune_cell and prune_subcells
*/ */

318
src/db/db/dbLayoutLayers.cc Normal file
View File

@ -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<unsigned int, const db::LayerProperties *>
LayerIterator::operator*() const
{
return std::pair<unsigned int, const db::LayerProperties *> (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<db::LayoutLayers *> (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<db::LayoutLayers *> (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<db::LayoutLayers *> (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));
}
}
}

282
src/db/db/dbLayoutLayers.h Normal file
View File

@ -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 <vector>
#include <map>
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<unsigned int, const db::LayerProperties *> 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<unsigned int> m_free_indices;
std::vector<LayerState> m_layer_states;
std::vector<LayerProperties> m_layer_props;
std::multimap<LayerProperties, unsigned int, db::LPLogicalLessFunc> 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

View File

@ -629,11 +629,7 @@ LayerProperties::do_realize (const LayoutViewBase *view) const
// lookup the layer with the given name/layer/datatype // lookup the layer with the given name/layer/datatype
if (m_layer_index < 0 && ! m_source_real.is_wildcard_layer ()) { 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) { m_layer_index = cv->layout ().get_layer_maybe (m_source_real.layer_props ());
if (cv->layout ().is_valid_layer (i) && m_source_real.match (cv->layout ().get_properties (i))) {
m_layer_index = int (i);
}
}
} }
} }